mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-11-14 04:29:04 +03:00
After shift/arrow-key movement, merge overlapping selections
This commit is contained in:
parent
6b96251174
commit
81869ebf59
@ -1013,46 +1013,24 @@ describe "Editor", ->
|
||||
expect(cursor3.getBufferPosition()).toEqual [4, 0]
|
||||
|
||||
describe "selections", ->
|
||||
it "adds an additional selection upon clicking and dragging with the meta-key held down", ->
|
||||
editor.attachToDom()
|
||||
editor.lines.trigger mousedownEvent(editor: editor, point: [4, 10])
|
||||
editor.lines.trigger mousemoveEvent(editor: editor, point: [5, 27])
|
||||
editor.lines.trigger 'mouseup'
|
||||
describe "upon clicking and dragging with the meta-key held down", ->
|
||||
it "adds an additional selection upon clicking and dragging with the meta-key held down", ->
|
||||
editor.attachToDom()
|
||||
editor.lines.trigger mousedownEvent(editor: editor, point: [4, 10])
|
||||
editor.lines.trigger mousemoveEvent(editor: editor, point: [5, 27])
|
||||
editor.lines.trigger 'mouseup'
|
||||
|
||||
editor.lines.trigger mousedownEvent(editor: editor, point: [6, 10], metaKey: true)
|
||||
editor.lines.trigger mousemoveEvent(editor: editor, point: [8, 27], metaKey: true)
|
||||
editor.lines.trigger 'mouseup'
|
||||
editor.lines.trigger mousedownEvent(editor: editor, point: [6, 10], metaKey: true)
|
||||
editor.lines.trigger mousemoveEvent(editor: editor, point: [8, 27], metaKey: true)
|
||||
editor.lines.trigger 'mouseup'
|
||||
|
||||
selections = editor.compositeSelection.getSelections()
|
||||
expect(selections.length).toBe 2
|
||||
[selection1, selection2] = selections
|
||||
expect(selection1.getScreenRange()).toEqual [[4, 10], [5, 27]]
|
||||
expect(selection2.getScreenRange()).toEqual [[6, 10], [8, 27]]
|
||||
selections = editor.compositeSelection.getSelections()
|
||||
expect(selections.length).toBe 2
|
||||
[selection1, selection2] = selections
|
||||
expect(selection1.getScreenRange()).toEqual [[4, 10], [5, 27]]
|
||||
expect(selection2.getScreenRange()).toEqual [[6, 10], [8, 27]]
|
||||
|
||||
it "adjusts all selections based on keyboard movement", ->
|
||||
editor.setSelectionBufferRange [[0,9], [0,13]]
|
||||
editor.addSelectionForBufferRange [[3,16], [3,21]]
|
||||
[selection1, selection2] = editor.compositeSelection.getSelections()
|
||||
|
||||
editor.selectRight()
|
||||
expect(selection1.getBufferRange()).toEqual [[0,9], [0,14]]
|
||||
expect(selection2.getBufferRange()).toEqual [[3,16], [3,22]]
|
||||
|
||||
editor.selectLeft()
|
||||
editor.selectLeft()
|
||||
expect(selection1.getBufferRange()).toEqual [[0,9], [0,12]]
|
||||
expect(selection2.getBufferRange()).toEqual [[3,16], [3,20]]
|
||||
|
||||
editor.selectDown()
|
||||
expect(selection1.getBufferRange()).toEqual [[0,9], [1,12]]
|
||||
expect(selection2.getBufferRange()).toEqual [[3,16], [4,20]]
|
||||
|
||||
editor.selectUp()
|
||||
expect(selection1.getBufferRange()).toEqual [[0,9], [0,12]]
|
||||
expect(selection2.getBufferRange()).toEqual [[3,16], [3,20]]
|
||||
|
||||
describe "when multiple selctions intersect", ->
|
||||
it "merges a selection that is completely contained within another", ->
|
||||
it "merges selections when they intersect", ->
|
||||
editor.attachToDom()
|
||||
editor.lines.trigger mousedownEvent(editor: editor, point: [4, 10])
|
||||
editor.lines.trigger mousemoveEvent(editor: editor, point: [5, 27])
|
||||
@ -1067,6 +1045,71 @@ describe "Editor", ->
|
||||
[selection1] = selections
|
||||
expect(selection1.getScreenRange()).toEqual [[3, 10], [6, 27]]
|
||||
|
||||
describe "upon moving the cursor with the arrow keys with the shift key held down", ->
|
||||
it "resizes all selections", ->
|
||||
editor.setSelectionBufferRange [[0,9], [0,13]]
|
||||
editor.addSelectionForBufferRange [[3,16], [3,21]]
|
||||
[selection1, selection2] = editor.compositeSelection.getSelections()
|
||||
|
||||
editor.selectRight()
|
||||
expect(selection1.getBufferRange()).toEqual [[0,9], [0,14]]
|
||||
expect(selection2.getBufferRange()).toEqual [[3,16], [3,22]]
|
||||
|
||||
editor.selectLeft()
|
||||
editor.selectLeft()
|
||||
expect(selection1.getBufferRange()).toEqual [[0,9], [0,12]]
|
||||
expect(selection2.getBufferRange()).toEqual [[3,16], [3,20]]
|
||||
|
||||
editor.selectDown()
|
||||
expect(selection1.getBufferRange()).toEqual [[0,9], [1,12]]
|
||||
expect(selection2.getBufferRange()).toEqual [[3,16], [4,20]]
|
||||
|
||||
editor.selectUp()
|
||||
expect(selection1.getBufferRange()).toEqual [[0,9], [0,12]]
|
||||
expect(selection2.getBufferRange()).toEqual [[3,16], [3,20]]
|
||||
|
||||
it "merges selections when they intersect when moving down", ->
|
||||
editor.setSelectionBufferRange [[0,9], [0,13]]
|
||||
editor.addSelectionForBufferRange [[1,10], [1,20]]
|
||||
editor.addSelectionForBufferRange [[2,15], [3,25]]
|
||||
[selection1, selection2, selection3] = editor.compositeSelection.getSelections()
|
||||
|
||||
editor.selectDown()
|
||||
expect(editor.compositeSelection.getSelections()).toEqual [selection1]
|
||||
expect(selection1.getScreenRange()).toEqual([[0, 9], [4, 25]])
|
||||
expect(selection2.parent()).not.toExist()
|
||||
expect(selection3.parent()).not.toExist()
|
||||
|
||||
it "merges selections when they intersect when moving up", ->
|
||||
editor.setSelectionBufferRange [[0,9], [0,13]], reverse: true
|
||||
editor.addSelectionForBufferRange [[1,10], [1,20]], reverse: true
|
||||
[selection1, selection2] = editor.compositeSelection.getSelections()
|
||||
|
||||
editor.selectUp()
|
||||
expect(editor.compositeSelection.getSelections()).toEqual [selection1]
|
||||
expect(selection1.getScreenRange()).toEqual([[0, 0], [1, 20]])
|
||||
expect(selection2.parent()).not.toExist()
|
||||
|
||||
it "merges selections when they intersect when moving left", ->
|
||||
editor.setSelectionBufferRange [[0,9], [0,13]], reverse: true
|
||||
editor.addSelectionForBufferRange [[0,14], [1,20]], reverse: true
|
||||
[selection1, selection2] = editor.compositeSelection.getSelections()
|
||||
|
||||
editor.selectLeft()
|
||||
expect(editor.compositeSelection.getSelections()).toEqual [selection1]
|
||||
expect(selection1.getScreenRange()).toEqual([[0, 8], [1, 20]])
|
||||
expect(selection2.parent()).not.toExist()
|
||||
|
||||
it "merges selections when they intersect when moving right", ->
|
||||
editor.setSelectionBufferRange [[0,9], [0,13]]
|
||||
editor.addSelectionForBufferRange [[0,14], [1,20]]
|
||||
[selection1, selection2] = editor.compositeSelection.getSelections()
|
||||
|
||||
editor.selectRight()
|
||||
expect(editor.compositeSelection.getSelections()).toEqual [selection1]
|
||||
expect(selection1.getScreenRange()).toEqual([[0, 9], [1, 21]])
|
||||
expect(selection2.parent()).not.toExist()
|
||||
|
||||
describe "cursor merging", ->
|
||||
it "merges cursors when they overlap due to a buffer change", ->
|
||||
editor.setCursorScreenPosition([0, 0])
|
||||
|
@ -16,11 +16,13 @@ describe "Range", ->
|
||||
expect(new Range(new Point(1, 1), new Point(1, 2)).isEmpty()).toBeFalsy()
|
||||
|
||||
describe ".intersectsWith(otherRange)", ->
|
||||
it "returns true if the ranges intersect", ->
|
||||
it "returns true if the ranges intersect or share an endpoint", ->
|
||||
expect(new Range([1, 1], [2, 10]).intersectsWith(new Range([2, 1], [3, 10]))).toBeTruthy()
|
||||
expect(new Range([2, 1], [3, 10]).intersectsWith(new Range([1, 1], [2, 10]))).toBeTruthy()
|
||||
expect(new Range([2, 1], [3, 10]).intersectsWith(new Range([2, 5], [3, 1]))).toBeTruthy()
|
||||
expect(new Range([2, 5], [3, 1]).intersectsWith(new Range([2, 1], [3, 10]))).toBeTruthy()
|
||||
expect(new Range([2, 5], [3, 1]).intersectsWith(new Range([3, 1], [3, 10]))).toBeTruthy()
|
||||
expect(new Range([3, 1], [3, 10]).intersectsWith(new Range([2, 5], [3, 1]))).toBeTruthy()
|
||||
expect(new Range([2, 5], [3, 1]).intersectsWith(new Range([3, 2], [3, 10]))).toBeFalsy()
|
||||
expect(new Range([3, 2], [3, 10]).intersectsWith(new Range([2, 5], [3, 1]))).toBeFalsy()
|
||||
|
||||
|
@ -17,9 +17,9 @@ class CompositeSeleciton
|
||||
@selections.push(selection)
|
||||
@editor.lines.append(selection)
|
||||
|
||||
addSelectionForBufferRange: (bufferRange) ->
|
||||
addSelectionForBufferRange: (bufferRange, options) ->
|
||||
cursor = @editor.compositeCursor.addCursor()
|
||||
@selectionForCursor(cursor).setBufferRange(bufferRange)
|
||||
@selectionForCursor(cursor).setBufferRange(bufferRange, options)
|
||||
|
||||
removeSelectionForCursor: (cursor) ->
|
||||
_.remove(@selections, @selectionForCursor(cursor))
|
||||
@ -31,32 +31,36 @@ class CompositeSeleciton
|
||||
selection.handleBufferChange(e) for selection in @getSelections()
|
||||
|
||||
insertText: (text) ->
|
||||
@modifySelections (selection) ->
|
||||
@modifySelectedText (selection) ->
|
||||
selection.insertText(text)
|
||||
|
||||
backspace: ->
|
||||
@modifySelections (selection) -> selection.backspace()
|
||||
@modifySelectedText (selection) -> selection.backspace()
|
||||
|
||||
delete: ->
|
||||
@modifySelections (selection) -> selection.delete()
|
||||
@modifySelectedText (selection) -> selection.delete()
|
||||
|
||||
selectToScreenPosition: (position) ->
|
||||
@lastSelection().selectToScreenPosition(position)
|
||||
|
||||
selectRight: ->
|
||||
selection.selectRight() for selection in @getSelections()
|
||||
@mergeIntersectingSelections()
|
||||
|
||||
selectLeft: ->
|
||||
selection.selectLeft() for selection in @getSelections()
|
||||
@mergeIntersectingSelections()
|
||||
|
||||
selectUp: ->
|
||||
selection.selectUp() for selection in @getSelections()
|
||||
@mergeIntersectingSelections()
|
||||
|
||||
selectDown: ->
|
||||
selection.selectDown() for selection in @getSelections()
|
||||
@mergeIntersectingSelections()
|
||||
|
||||
setBufferRange: (bufferRange) ->
|
||||
@lastSelection().setBufferRange(bufferRange)
|
||||
setBufferRange: (bufferRange, options) ->
|
||||
@lastSelection().setBufferRange(bufferRange, options)
|
||||
|
||||
getBufferRange: (bufferRange) ->
|
||||
@lastSelection().getBufferRange()
|
||||
@ -77,7 +81,7 @@ class CompositeSeleciton
|
||||
@mergeIntersectingSelections()
|
||||
return
|
||||
|
||||
modifySelections: (fn) ->
|
||||
modifySelectedText: (fn) ->
|
||||
selection.retainSelection = true for selection in @getSelections()
|
||||
for selection in @getSelections()
|
||||
selection.retainSelection = false
|
||||
@ -85,7 +89,7 @@ class CompositeSeleciton
|
||||
|
||||
cut: ->
|
||||
maintainPasteboard = false
|
||||
@modifySelections (selection) ->
|
||||
@modifySelectedText (selection) ->
|
||||
selection.cut(maintainPasteboard)
|
||||
maintainPasteboard = true
|
||||
|
||||
|
@ -356,8 +356,8 @@ class Editor extends View
|
||||
|
||||
getSelection: (index) -> @compositeSelection.getSelection(index)
|
||||
getSelectedText: -> @compositeSelection.getSelection().getText()
|
||||
setSelectionBufferRange: (bufferRange) -> @compositeSelection.setBufferRange(bufferRange)
|
||||
addSelectionForBufferRange: (bufferRange) -> @compositeSelection.addSelectionForBufferRange(bufferRange)
|
||||
setSelectionBufferRange: (bufferRange, options) -> @compositeSelection.setBufferRange(bufferRange, options)
|
||||
addSelectionForBufferRange: (bufferRange, options) -> @compositeSelection.addSelectionForBufferRange(bufferRange, options)
|
||||
selectRight: -> @compositeSelection.selectRight()
|
||||
selectLeft: -> @compositeSelection.selectLeft()
|
||||
selectUp: -> @compositeSelection.selectUp()
|
||||
|
@ -42,7 +42,7 @@ class Range
|
||||
|
||||
intersectsWith: (otherRange) ->
|
||||
if @start.isLessThanOrEqual(otherRange.start)
|
||||
@end.isGreaterThan(otherRange.start)
|
||||
@end.isGreaterThanOrEqual(otherRange.start)
|
||||
else
|
||||
otherRange.intersectsWith(this)
|
||||
|
||||
|
@ -81,16 +81,20 @@ class Selection extends View
|
||||
else
|
||||
new Range(@cursor.getScreenPosition(), @cursor.getScreenPosition())
|
||||
|
||||
setScreenRange: (range) ->
|
||||
@cursor.setScreenPosition(range.start)
|
||||
setScreenRange: (range, options={}) ->
|
||||
{ reverse } = options
|
||||
{ start, end } = range
|
||||
[start, end] = [end, start] if reverse
|
||||
|
||||
@cursor.setScreenPosition(start)
|
||||
@modifySelection =>
|
||||
@cursor.setScreenPosition(range.end)
|
||||
@cursor.setScreenPosition(end)
|
||||
|
||||
getBufferRange: ->
|
||||
@editor.bufferRangeForScreenRange(@getScreenRange())
|
||||
|
||||
setBufferRange: (bufferRange) ->
|
||||
@setScreenRange(@editor.screenRangeForBufferRange(bufferRange))
|
||||
setBufferRange: (bufferRange, options) ->
|
||||
@setScreenRange(@editor.screenRangeForBufferRange(bufferRange), options)
|
||||
|
||||
getText: ->
|
||||
@editor.buffer.getTextInRange @getBufferRange()
|
||||
|
Loading…
Reference in New Issue
Block a user