diff --git a/spec/app/buffer-spec.coffee b/spec/app/buffer-spec.coffee index b72374fd6..8b20595fd 100644 --- a/spec/app/buffer-spec.coffee +++ b/spec/app/buffer-spec.coffee @@ -691,7 +691,7 @@ describe 'Buffer', -> beforeEach -> marker = buffer.markRange([[4, 20], [4, 23]]) - it "allows a markers head and tail positions to be changed", -> + it "allows a marker's head and tail positions to be changed", -> buffer.setMarkerHeadPosition(marker, [5, 3]) expect(buffer.getMarkerRange(marker)).toEqual [[4, 20], [5, 3]] @@ -705,6 +705,14 @@ describe 'Buffer', -> buffer.setMarkerTailPosition(marker, [Infinity, Infinity]) expect(buffer.getMarkerRange(marker)).toEqual([[0, 0], [12, 2]]) + it "allows a marker's tail to be placed and cleared", -> + buffer.clearMarkerTail(marker) + expect(buffer.getMarkerRange(marker)).toEqual [[4, 23], [4, 23]] + buffer.placeMarkerTail(marker) + buffer.setMarkerHeadPosition(marker, [2, 0]) + expect(buffer.getMarkerRange(marker)).toEqual [[2, 0], [4, 23]] + expect(buffer.isMarkerReversed(marker)).toBeTruthy() + describe "marker observation", -> describe ".observeMarkerHeadPosition(marker, callback)", -> observeHandler = null diff --git a/spec/app/edit-session-spec.coffee b/spec/app/edit-session-spec.coffee index ba5b36e66..9767c243f 100644 --- a/spec/app/edit-session-spec.coffee +++ b/spec/app/edit-session-spec.coffee @@ -2,7 +2,7 @@ Project = require 'project' Buffer = require 'buffer' EditSession = require 'edit-session' -describe "EditSession", -> +fdescribe "EditSession", -> [buffer, editSession, lineLengths] = [] convertToHardTabs = (buffer) -> @@ -1635,7 +1635,7 @@ describe "EditSession", -> expect(buffer.lineForRow(7)).toBe " }" it "preserves selection emptiness", -> - editSession.setSelectedBufferRange([[4, 0], [4, 0]]) + editSession.setCursorBufferPosition([4, 0]) editSession.toggleLineCommentsInSelection() expect(editSession.getSelection().isEmpty()).toBeTruthy() @@ -1647,7 +1647,7 @@ describe "EditSession", -> expect(buffer.lineForRow(4)).toBe " while(items.length > 0) {" it "uncomments when the line lacks the trailing whitespace in the comment regex", -> - editSession.setSelectedBufferRange([[10, 0], [10, 0]]) + editSession.setCursorBufferPosition([10, 0]) editSession.toggleLineCommentsInSelection() expect(buffer.lineForRow(10)).toBe "// " @@ -1660,7 +1660,7 @@ describe "EditSession", -> expect(editSession.getSelectedBufferRange()).toEqual [[10, 0], [10, 0]] it "uncomments when the line has leading whitespace", -> - editSession.setSelectedBufferRange([[10, 0], [10, 0]]) + editSession.setCursorBufferPosition([10, 0]) editSession.toggleLineCommentsInSelection() expect(buffer.lineForRow(10)).toBe "// " @@ -1763,18 +1763,18 @@ describe "EditSession", -> expect(cursor2.getScreenPosition()).toEqual [0, 8] expect(cursor3.getScreenPosition()).toEqual [1, 0] - it "does not destroy cursor or selection anchors when a change encompasses them", -> + it "does not destroy cursors or selections when a change encompasses them", -> cursor = editSession.getCursor() cursor.setBufferPosition [3, 3] editSession.buffer.delete([[3, 1], [3, 5]]) expect(cursor.getBufferPosition()).toEqual [3, 1] - expect(editSession.getAnchors().indexOf(cursor.anchor)).not.toBe -1 + expect(editSession.getCursors().indexOf(cursor)).not.toBe -1 selection = editSession.getLastSelection() selection.setBufferRange [[3, 5], [3, 10]] editSession.buffer.delete [[3, 3], [3, 8]] expect(selection.getBufferRange()).toEqual [[3, 3], [3, 5]] - expect(editSession.getAnchors().indexOf(selection.anchor)).not.toBe -1 + expect(editSession.getSelections().indexOf(selection)).not.toBe -1 it "merges cursors when the change causes them to overlap", -> editSession.setCursorScreenPosition([0, 0]) diff --git a/src/app/buffer-change-operation.coffee b/src/app/buffer-change-operation.coffee index de64d0335..947f6f206 100644 --- a/src/app/buffer-change-operation.coffee +++ b/src/app/buffer-change-operation.coffee @@ -92,6 +92,7 @@ class BufferChangeOperation updateMarkers: (bufferChange) -> marker.handleBufferChange(bufferChange) for marker in @buffer.getMarkers() + @buffer.trigger 'markers-updated' restoreMarkers: (markersToRestore) -> for [id, previousRange] in markersToRestore diff --git a/src/app/buffer-marker.coffee b/src/app/buffer-marker.coffee index 61485dba6..f79cc5288 100644 --- a/src/app/buffer-marker.coffee +++ b/src/app/buffer-marker.coffee @@ -51,6 +51,12 @@ class BufferMarker getEndPosition: -> @getRange().end + placeTail: -> + @setTailPosition(@headPosition) unless @tailPosition + + clearTail: -> + @tailPosition = null + observeHeadPosition: (callback) -> @headPositionObservers.push(callback) cancel: => diff --git a/src/app/buffer.coffee b/src/app/buffer.coffee index 6dab55088..c05ac567a 100644 --- a/src/app/buffer.coffee +++ b/src/app/buffer.coffee @@ -308,6 +308,15 @@ class Buffer getMarkerRange: (id) -> @validMarkers[id]?.getRange() + setMarkerRange: (id, range, options) -> + @validMarkers[id]?.setRange(range, options) + + placeMarkerTail: (id) -> + @validMarkers[id]?.placeTail() + + clearMarkerTail: (id) -> + @validMarkers[id]?.clearTail() + isMarkerReversed: (id) -> @validMarkers[id]?.isReversed() diff --git a/src/app/display-buffer.coffee b/src/app/display-buffer.coffee index fcff6df24..f83db9db2 100644 --- a/src/app/display-buffer.coffee +++ b/src/app/display-buffer.coffee @@ -303,14 +303,14 @@ class DisplayBuffer markScreenRange: (screenRange) -> @markBufferRange(@bufferRangeForScreenRange(screenRange)) - markBufferRange: (bufferRange) -> - @buffer.markRange(bufferRange) + markBufferRange: (args...) -> + @buffer.markRange(args...) - markScreenPosition: (screenPosition) -> - @markBufferPosition(@bufferPositionForScreenPosition(screenPosition)) + markScreenPosition: (screenPosition, options) -> + @markBufferPosition(@bufferPositionForScreenPosition(screenPosition), options) - markBufferPosition: (bufferPosition) -> - @buffer.markPosition(bufferPosition) + markBufferPosition: (bufferPosition, options) -> + @buffer.markPosition(bufferPosition, options) destroyMarker: (id) -> @buffer.destroyMarker(id) @@ -320,9 +320,15 @@ class DisplayBuffer getMarkerScreenRange: (id) -> @screenRangeForBufferRange(@getMarkerBufferRange(id)) + setMarkerScreenRange: (id, screenRange, options) -> + @setMarkerBufferRange(id, @bufferRangeForScreenRange(screenRange), options) + getMarkerBufferRange: (id) -> @buffer.getMarkerRange(id) + setMarkerBufferRange: (id, bufferRange, options) -> + @buffer.setMarkerRange(id, bufferRange, options) + getMarkerScreenPosition: (id) -> @getMarkerHeadScreenPosition(id) @@ -355,6 +361,12 @@ class DisplayBuffer setMarkerTailBufferPosition: (id, bufferPosition) -> @buffer.setMarkerTailPosition(id, bufferPosition) + placeMarkerTail: (id) -> + @buffer.placeMarkerTail(id) + + clearMarkerTail: (id) -> + @buffer.clearMarkerTail(id) + isMarkerReversed: (id) -> @buffer.isMarkerReversed(id) diff --git a/src/app/edit-session.coffee b/src/app/edit-session.coffee index b3e1922b9..556f31eee 100644 --- a/src/app/edit-session.coffee +++ b/src/app/edit-session.coffee @@ -51,7 +51,7 @@ class EditSession @buffer.retain() @subscribe @buffer, "path-changed", => @trigger "path-changed" @subscribe @buffer, "contents-conflicted", => @trigger "contents-conflicted" - @subscribe @buffer, "anchors-updated", => @mergeCursors() + @subscribe @buffer, "markers-updated", => @mergeCursors() @preserveCursorPositionOnBufferReload() @@ -434,6 +434,12 @@ class EditSession getAnchorRanges: -> new Array(@anchorRanges...) + markScreenRange: (args...) -> + @displayBuffer.markScreenRange(args...) + + markBufferRange: (args...) -> + @displayBuffer.markBufferRange(args...) + markScreenPosition: (args...) -> @displayBuffer.markScreenPosition(args...) @@ -443,11 +449,17 @@ class EditSession destroyMarker: (args...) -> @displayBuffer.destroyMarker(args...) + getMarkerScreenRange: (args...) -> + @displayBuffer.getMarkerScreenRange(args...) + + setMarkerScreenRange: (args...) -> + @displayBuffer.setMarkerScreenRange(args...) + getMarkerBufferRange: (args...) -> @displayBuffer.getMarkerBufferRange(args...) - getMarkerScreenRange: (args...) -> - @displayBuffer.getMarkerScreenRange(args...) + setMarkerBufferRange: (args...) -> + @displayBuffer.setMarkerBufferRange(args...) getMarkerScreenPosition: (args...) -> @displayBuffer.getMarkerScreenPosition(args...) @@ -482,6 +494,15 @@ class EditSession observeMarkerHeadScreenPosition: (args...) -> @displayBuffer.observeMarkerHeadScreenPosition(args...) + placeMarkerTail: (args...) -> + @displayBuffer.placeMarkerTail(args...) + + clearMarkerTail: (args...) -> + @displayBuffer.clearMarkerTail(args...) + + isMarkerReversed: (args...) -> + @displayBuffer.isMarkerReversed(args...) + addAnchor: (options={}) -> anchor = @buffer.addAnchor(_.extend({editSession: this}, options)) @anchors.push(anchor) @@ -545,7 +566,8 @@ class EditSession selection addSelectionForBufferRange: (bufferRange, options={}) -> - marker = @markBufferRange(bufferRange, _.defaults({stayValid: true}, options)) + options = _.defaults({stayValid: true}, options) + marker = @markBufferRange(bufferRange, options) @addSelection(marker) setSelectedBufferRange: (bufferRange, options) -> @@ -741,7 +763,7 @@ class EditSession mergeCursors: -> positions = [] - for cursor in new Array(@getCursors()...) + for cursor in @getCursors() position = cursor.getBufferPosition().toString() if position in positions cursor.destroy() diff --git a/src/app/selection.coffee b/src/app/selection.coffee index de637d861..fcbf50fe3 100644 --- a/src/app/selection.coffee +++ b/src/app/selection.coffee @@ -5,12 +5,11 @@ _ = require 'underscore' module.exports = class Selection - anchor: null wordwise: false initialScreenRange: null needsAutoscroll: null - constructor: ({@cursor, @editSession}) -> + constructor: ({@cursor, @marker, @editSession}) -> @cursor.selection = this @cursor.on 'moved.selection', ({bufferChange}) => @@ -24,7 +23,6 @@ class Selection if @cursor @cursor.off('.selection') @cursor.destroy() - @anchor?.destroy() @editSession.removeSelection(this) @trigger 'destroyed' @@ -38,7 +36,7 @@ class Selection @getBufferRange().isEmpty() isReversed: -> - not @isEmpty() and @cursor.getBufferPosition().isLessThan(@anchor.getBufferPosition()) + @editSession.isMarkerReversed(@marker) isSingleScreenLine: -> @getScreenRange().isSingleLine() @@ -47,33 +45,21 @@ class Selection @needsAutoscroll = null getScreenRange: -> - if @anchor - new Range(@anchor.getScreenPosition(), @cursor.getScreenPosition()) - else - new Range(@cursor.getScreenPosition(), @cursor.getScreenPosition()) + @editSession.getMarkerScreenRange(@marker) setScreenRange: (screenRange, options) -> - bufferRange = editSession.bufferRangeForScreenRange(screenRange) - @setBufferRange(bufferRange, options) + @setBufferRange(@editSession.bufferRangeForScreenRange(screenRange), options) getBufferRange: -> - if @anchor - new Range(@anchor.getBufferPosition(), @cursor.getBufferPosition()) - else - new Range(@cursor.getBufferPosition(), @cursor.getBufferPosition()) + @editSession.getMarkerBufferRange(@marker) setBufferRange: (bufferRange, options={}) -> bufferRange = Range.fromObject(bufferRange) - { start, end } = bufferRange - [start, end] = [end, start] if options.reverse ? @isReversed() - @needsAutoscroll = options.autoscroll - + options.reverse ?= @isReversed() @editSession.destroyFoldsIntersectingBufferRange(bufferRange) unless options.preserveFolds - @placeAnchor() unless @anchor @modifySelection => - @anchor.setBufferPosition(start, autoscroll: false) - @cursor.setBufferPosition(end, autoscroll: false) + @editSession.setMarkerBufferRange(@marker, bufferRange, options) getBufferRowRange: -> range = @getBufferRange() @@ -91,9 +77,7 @@ class Selection @editSession.buffer.getTextInRange(@getBufferRange()) clear: -> - return unless @anchor - @anchor.destroy() - @anchor = null + @editSession.clearMarkerTail(@marker) @screenRangeChanged() selectWord: -> @@ -122,11 +106,9 @@ class Selection @modifySelection => if @initialScreenRange if position.isLessThan(@initialScreenRange.start) - @anchor.setScreenPosition(@initialScreenRange.end) - @cursor.setScreenPosition(position) + @editSession.setMarkerScreenRange(@marker, [position, @initialScreenRange.end], reverse: true) else - @anchor.setScreenPosition(@initialScreenRange.start) - @cursor.setScreenPosition(position) + @editSession.setMarkerScreenRange(@marker, [@initialScreenRange.start, position]) else @cursor.setScreenPosition(position) @@ -318,8 +300,7 @@ class Selection @editSession.autoIndentBufferRows(start, end) toggleLineComments: -> - @modifySelection => - @editSession.toggleLineCommentsForBufferRows(@getBufferRowRange()...) + @editSession.toggleLineCommentsForBufferRows(@getBufferRowRange()...) cutToEndOfLine: (maintainPasteboard) -> @selectToEndOfLine() if @isEmpty() @@ -353,18 +334,16 @@ class Selection modifySelection: (fn) -> @retainSelection = true - @placeAnchor() unless @anchor - @anchor.pauseEvents() - @cursor.pauseEvents() + @editSession.placeMarkerTail(@marker) +# @anchor.pauseEvents() +# @cursor.pauseEvents() fn() - @anchor.resumeEvents() - @cursor.resumeEvents() +# @anchor.resumeEvents() +# @cursor.resumeEvents() @retainSelection = false - placeAnchor: -> - @anchor = @editSession.addAnchor(strong: true) - @anchor.setScreenPosition(@cursor.getScreenPosition()) - @anchor.on 'moved.selection', => @screenRangeChanged() +# placeAnchor: -> +# @anchor.on 'moved.selection', => @screenRangeChanged() intersectsBufferRange: (bufferRange) -> @getBufferRange().intersectsWith(bufferRange)