mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-11-13 08:44:12 +03:00
merge dev, fix conflicts
This commit is contained in:
commit
dd7835faf4
7
.atom/config.cson
Normal file
7
.atom/config.cson
Normal file
@ -0,0 +1,7 @@
|
||||
'editor':
|
||||
'fontSize': 16
|
||||
'core':
|
||||
'themes': [
|
||||
'atom-dark-ui'
|
||||
'atom-dark-syntax'
|
||||
]
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"editor": {
|
||||
"fontSize": 16
|
||||
},
|
||||
"core": {
|
||||
"themes": [
|
||||
"atom-dark-ui",
|
||||
"atom-dark-syntax"
|
||||
]
|
||||
}
|
||||
}
|
@ -69,6 +69,7 @@
|
||||
[self initWithBootstrapScript:@"window-bootstrap" background:YES alwaysUseBundleResourcePath:stable];
|
||||
[self.window setFrame:NSMakeRect(0, 0, 0, 0) display:NO];
|
||||
[self.window setExcludedFromWindowsMenu:YES];
|
||||
[self.window setCollectionBehavior:NSWindowCollectionBehaviorStationary];
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -307,6 +307,9 @@ class EditSession
|
||||
fold.destroy()
|
||||
@setCursorBufferPosition([fold.startRow, 0])
|
||||
|
||||
isFoldedAtCursorRow: ->
|
||||
@isFoldedAtScreenRow(@getCursorScreenRow())
|
||||
|
||||
isFoldedAtBufferRow: (bufferRow) ->
|
||||
screenRow = @screenPositionForBufferPosition([bufferRow]).row
|
||||
@isFoldedAtScreenRow(screenRow)
|
||||
|
@ -277,6 +277,7 @@ class Editor extends View
|
||||
destroyFoldsContainingBufferRow: (bufferRow) -> @activeEditSession.destroyFoldsContainingBufferRow(bufferRow)
|
||||
isFoldedAtScreenRow: (screenRow) -> @activeEditSession.isFoldedAtScreenRow(screenRow)
|
||||
isFoldedAtBufferRow: (bufferRow) -> @activeEditSession.isFoldedAtBufferRow(bufferRow)
|
||||
isFoldedAtCursorRow: -> @activeEditSession.isFoldedAtCursorRow()
|
||||
|
||||
lineForScreenRow: (screenRow) -> @activeEditSession.lineForScreenRow(screenRow)
|
||||
linesForScreenRows: (start, end) -> @activeEditSession.linesForScreenRows(start, end)
|
||||
|
120
src/packages/bracket-matcher/index.coffee
Normal file
120
src/packages/bracket-matcher/index.coffee
Normal file
@ -0,0 +1,120 @@
|
||||
AtomPackage = require 'atom-package'
|
||||
_ = require 'underscore'
|
||||
{$$} = require 'space-pen'
|
||||
Range = require 'range'
|
||||
|
||||
module.exports =
|
||||
class BracketMatcher extends AtomPackage
|
||||
startPairMatches:
|
||||
'(': ')'
|
||||
'[': ']'
|
||||
'{': '}'
|
||||
|
||||
endPairMatches:
|
||||
')': '('
|
||||
']': '['
|
||||
'}': '{'
|
||||
|
||||
pairHighlighted: false
|
||||
|
||||
activate: (rootView) ->
|
||||
rootView.eachEditor (editor) => @subscribeToEditor(editor) if editor.attached
|
||||
|
||||
subscribeToEditor: (editor) ->
|
||||
editor.on 'cursor:moved.bracket-matcher', => @updateMatch(editor)
|
||||
editor.command 'editor:go-to-matching-bracket.bracket-matcher', =>
|
||||
@goToMatchingPair(editor)
|
||||
editor.on 'editor:will-be-removed', => editor.off('.bracket-matcher')
|
||||
|
||||
goToMatchingPair: (editor) ->
|
||||
return unless @pairHighlighted
|
||||
return unless underlayer = editor.pane()?.find('.underlayer')
|
||||
|
||||
position = editor.getCursorBufferPosition()
|
||||
previousPosition = position.translate([0, -1])
|
||||
startPosition = underlayer.find('.bracket-matcher:first').data('bufferPosition')
|
||||
endPosition = underlayer.find('.bracket-matcher:last').data('bufferPosition')
|
||||
|
||||
if position.isEqual(startPosition)
|
||||
editor.setCursorBufferPosition(endPosition.translate([0, 1]))
|
||||
else if previousPosition.isEqual(startPosition)
|
||||
editor.setCursorBufferPosition(endPosition)
|
||||
else if position.isEqual(endPosition)
|
||||
editor.setCursorBufferPosition(startPosition.translate([0, 1]))
|
||||
else if previousPosition.isEqual(endPosition)
|
||||
editor.setCursorBufferPosition(startPosition)
|
||||
|
||||
createView: (editor, bufferPosition) ->
|
||||
pixelPosition = editor.pixelPositionForBufferPosition(bufferPosition)
|
||||
view = $$ -> @div class: 'bracket-matcher'
|
||||
view.data('bufferPosition', bufferPosition)
|
||||
view.css('top', pixelPosition.top).css('left', pixelPosition.left)
|
||||
view.width(editor.charWidth).height(editor.charHeight)
|
||||
|
||||
findCurrentPair: (editor, buffer, matches) ->
|
||||
position = editor.getCursorBufferPosition()
|
||||
currentPair = buffer.getTextInRange(Range.fromPointWithDelta(position, 0, 1))
|
||||
unless matches[currentPair]
|
||||
position = position.translate([0, -1])
|
||||
currentPair = buffer.getTextInRange(Range.fromPointWithDelta(position, 0, 1))
|
||||
matchingPair = matches[currentPair]
|
||||
if matchingPair
|
||||
{position, currentPair, matchingPair}
|
||||
else
|
||||
{}
|
||||
|
||||
findMatchingEndPair: (buffer, startPairPosition, startPair, endPair) ->
|
||||
scanRange = new Range(startPairPosition.translate([0, 1]), buffer.getEofPosition())
|
||||
regex = new RegExp("[#{_.escapeRegExp(startPair + endPair)}]", 'g')
|
||||
endPairPosition = null
|
||||
unpairedCount = 0
|
||||
buffer.scanInRange regex, scanRange, (match, range, {stop}) =>
|
||||
if match[0] is startPair
|
||||
unpairedCount++
|
||||
else if match[0] is endPair
|
||||
unpairedCount--
|
||||
endPairPosition = range.start
|
||||
stop() if unpairedCount < 0
|
||||
endPairPosition
|
||||
|
||||
findMatchingStartPair: (buffer, endPairPosition, startPair, endPair) ->
|
||||
scanRange = new Range([0, 0], endPairPosition)
|
||||
regex = new RegExp("[#{_.escapeRegExp(startPair + endPair)}]", 'g')
|
||||
startPairPosition = null
|
||||
unpairedCount = 0
|
||||
scanner = (match, range, {stop}) =>
|
||||
if match[0] is endPair
|
||||
unpairedCount++
|
||||
else if match[0] is startPair
|
||||
unpairedCount--
|
||||
startPairPosition = range.start
|
||||
stop() if unpairedCount < 0
|
||||
buffer.scanInRange(regex, scanRange, scanner, true)
|
||||
startPairPosition
|
||||
|
||||
updateMatch: (editor) ->
|
||||
return unless underlayer = editor.pane()?.find('.underlayer')
|
||||
|
||||
underlayer.find('.bracket-matcher').remove() if @pairHighlighted
|
||||
@pairHighlighted = false
|
||||
|
||||
return unless editor.getSelection().isEmpty()
|
||||
return if editor.isFoldedAtCursorRow()
|
||||
|
||||
buffer = editor.getBuffer()
|
||||
{position, currentPair, matchingPair} = @findCurrentPair(editor, buffer, @startPairMatches)
|
||||
if position
|
||||
matchPosition = @findMatchingEndPair(buffer, position, currentPair, matchingPair)
|
||||
else
|
||||
{position, currentPair, matchingPair} = @findCurrentPair(editor, buffer, @endPairMatches)
|
||||
if position
|
||||
matchPosition = @findMatchingStartPair(buffer, position, matchingPair, currentPair)
|
||||
|
||||
if position? and matchPosition?
|
||||
if position.isLessThan(matchPosition)
|
||||
underlayer.append(@createView(editor, position))
|
||||
underlayer.append(@createView(editor, matchPosition))
|
||||
else
|
||||
underlayer.append(@createView(editor, matchPosition))
|
||||
underlayer.append(@createView(editor, position))
|
||||
@pairHighlighted = true
|
@ -0,0 +1,2 @@
|
||||
'.editor':
|
||||
'ctrl-j': 'editor:go-to-matching-bracket'
|
@ -0,0 +1,86 @@
|
||||
RootView = require 'root-view'
|
||||
|
||||
describe "bracket matching", ->
|
||||
[rootView, editor] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView = new RootView(require.resolve('fixtures/sample.js'))
|
||||
atom.loadPackage('bracket-matcher')
|
||||
rootView.attachToDom()
|
||||
editor = rootView.getActiveEditor()
|
||||
|
||||
afterEach ->
|
||||
rootView.deactivate()
|
||||
|
||||
describe "when the cursor is before a starting pair", ->
|
||||
it "highlights the starting pair and ending pair", ->
|
||||
editor.moveCursorToEndOfLine()
|
||||
editor.moveCursorLeft()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
expect(editor.underlayer.find('.bracket-matcher:first').position()).toEqual editor.pixelPositionForBufferPosition([0,28])
|
||||
expect(editor.underlayer.find('.bracket-matcher:last').position()).toEqual editor.pixelPositionForBufferPosition([12,0])
|
||||
|
||||
describe "when the cursor is after a starting pair", ->
|
||||
it "highlights the starting pair and ending pair", ->
|
||||
editor.moveCursorToEndOfLine()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
expect(editor.underlayer.find('.bracket-matcher:first').position()).toEqual editor.pixelPositionForBufferPosition([0,28])
|
||||
expect(editor.underlayer.find('.bracket-matcher:last').position()).toEqual editor.pixelPositionForBufferPosition([12,0])
|
||||
|
||||
describe "when the cursor is before an ending pair", ->
|
||||
it "highlights the starting pair and ending pair", ->
|
||||
editor.moveCursorToBottom()
|
||||
editor.moveCursorLeft()
|
||||
editor.moveCursorLeft()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
expect(editor.underlayer.find('.bracket-matcher:last').position()).toEqual editor.pixelPositionForBufferPosition([12,0])
|
||||
expect(editor.underlayer.find('.bracket-matcher:first').position()).toEqual editor.pixelPositionForBufferPosition([0,28])
|
||||
|
||||
describe "when the cursor is after an ending pair", ->
|
||||
it "highlights the starting pair and ending pair", ->
|
||||
editor.moveCursorToBottom()
|
||||
editor.moveCursorLeft()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
expect(editor.underlayer.find('.bracket-matcher:last').position()).toEqual editor.pixelPositionForBufferPosition([12,0])
|
||||
expect(editor.underlayer.find('.bracket-matcher:first').position()).toEqual editor.pixelPositionForBufferPosition([0,28])
|
||||
|
||||
describe "when the cursor is moved off a pair", ->
|
||||
it "removes the starting pair and ending pair highlights", ->
|
||||
editor.moveCursorToEndOfLine()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
editor.moveCursorToBeginningOfLine()
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 0
|
||||
|
||||
describe "pair balancing", ->
|
||||
describe "when a second starting pair preceeds the first ending pair", ->
|
||||
it "advances to the second ending pair", ->
|
||||
editor.setCursorBufferPosition([8,42])
|
||||
expect(editor.underlayer.find('.bracket-matcher').length).toBe 2
|
||||
expect(editor.underlayer.find('.bracket-matcher:first').position()).toEqual editor.pixelPositionForBufferPosition([8,42])
|
||||
expect(editor.underlayer.find('.bracket-matcher:last').position()).toEqual editor.pixelPositionForBufferPosition([8,54])
|
||||
|
||||
describe "when editor:go-to-matching-bracket is triggered", ->
|
||||
describe "when the cursor is before the starting pair", ->
|
||||
it "moves the cursor to after the ending pair", ->
|
||||
editor.moveCursorToEndOfLine()
|
||||
editor.moveCursorLeft()
|
||||
editor.trigger "editor:go-to-matching-bracket"
|
||||
expect(editor.getCursorBufferPosition()).toEqual [12, 1]
|
||||
|
||||
describe "when the cursor is after the starting pair", ->
|
||||
it "moves the cursor to before the ending pair", ->
|
||||
editor.moveCursorToEndOfLine()
|
||||
editor.trigger "editor:go-to-matching-bracket"
|
||||
expect(editor.getCursorBufferPosition()).toEqual [12, 0]
|
||||
|
||||
describe "when the cursor is before the ending pair", ->
|
||||
it "moves the cursor to after the starting pair", ->
|
||||
editor.setCursorBufferPosition([12, 0])
|
||||
editor.trigger "editor:go-to-matching-bracket"
|
||||
expect(editor.getCursorBufferPosition()).toEqual [0, 29]
|
||||
|
||||
describe "when the cursor is after the ending pair", ->
|
||||
it "moves the cursor to before the starting pair", ->
|
||||
editor.setCursorBufferPosition([12, 1])
|
||||
editor.trigger "editor:go-to-matching-bracket"
|
||||
expect(editor.getCursorBufferPosition()).toEqual [0, 28]
|
@ -0,0 +1,3 @@
|
||||
.bracket-matcher {
|
||||
position: absolute;
|
||||
}
|
5
themes/atom-dark-ui/bracket-matcher.css
Normal file
5
themes/atom-dark-ui/bracket-matcher.css
Normal file
@ -0,0 +1,5 @@
|
||||
.bracket-matcher {
|
||||
border-bottom: 1px solid #f8de7e;
|
||||
margin-top: -1px;
|
||||
opacity: .7;
|
||||
}
|
@ -10,5 +10,6 @@
|
||||
"command-panel.css",
|
||||
"command-logger.css",
|
||||
"blurred.css"
|
||||
"bracket-matcher.css"
|
||||
]
|
||||
}
|
||||
|
5
themes/atom-light-ui/bracket-matcher.css
Normal file
5
themes/atom-light-ui/bracket-matcher.css
Normal file
@ -0,0 +1,5 @@
|
||||
.bracket-matcher {
|
||||
border-bottom: 1px solid #f8de7e;
|
||||
margin-top: -1px;
|
||||
opacity: .7;
|
||||
}
|
@ -8,6 +8,7 @@
|
||||
"status-bar.css",
|
||||
"markdown-preview.css",
|
||||
"command-panel.css",
|
||||
"command-logger.css"
|
||||
"command-logger.css",
|
||||
"bracket-matcher.css"
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user