From f3b7874007e2f46439345cad1781f3e99a98fac8 Mon Sep 17 00:00:00 2001 From: Garen Torikian Date: Fri, 12 Apr 2013 15:54:56 -0500 Subject: [PATCH] Get a good chunk of Selection} --- src/app/buffer-marker.coffee | 5 +++ src/app/cursor.coffee | 2 + src/app/edit-session.coffee | 16 ++++--- src/app/selection.coffee | 86 ++++++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 6 deletions(-) diff --git a/src/app/buffer-marker.coffee b/src/app/buffer-marker.coffee index ebc843546..6aa013e01 100644 --- a/src/app/buffer-marker.coffee +++ b/src/app/buffer-marker.coffee @@ -24,6 +24,11 @@ class BufferMarker @setTailPosition(range.start) unless options.noTail @setHeadPosition(range.end) + # Public: Identifies if the ending position of a marker is greater than the starting position. + # + # This can happen when, for example, you highlight text "up" in a {Buffer}. + # + # Returns a {Boolean}. isReversed: -> @tailPosition? and @headPosition.isLessThan(@tailPosition) diff --git a/src/app/cursor.coffee b/src/app/cursor.coffee index 0c2be3f4f..3f5785fbc 100644 --- a/src/app/cursor.coffee +++ b/src/app/cursor.coffee @@ -4,6 +4,8 @@ EventEmitter = require 'event-emitter' _ = require 'underscore' # Public: The `Cursor` class represents the little blinking line identifying where text can be inserted. +# +# Cursors have some metadata attached in the form of a {BufferMarker}. module.exports = class Cursor screenPosition: null diff --git a/src/app/edit-session.coffee b/src/app/edit-session.coffee index 134632519..5369a1e34 100644 --- a/src/app/edit-session.coffee +++ b/src/app/edit-session.coffee @@ -381,10 +381,10 @@ class EditSession shouldAutoIndentPastedText: -> config.get("editor.autoIndentOnPaste") - # Public: Inserts text at the current cursor positions. + # Public: Inserts text at the current cursor positions # # text - A {String} representing the text to insert. - # options - A set of options equivalent to {Selection#insertText}. + # options - A set of options equivalent to {Selection#insertText} insertText: (text, options={}) -> options.autoIndent ?= @shouldAutoIndent() @mutateSelectedText (selection) -> selection.insertText(text, options) @@ -427,7 +427,7 @@ class EditSession backspaceToBeginningOfLine: -> @mutateSelectedText (selection) -> selection.backspaceToBeginningOfLine() - # Public: Performs a delete, removing the character found behind the cursor position. + # Public: Performs a delete, removing the character found ahead of the cursor position. delete: -> @mutateSelectedText (selection) -> selection.delete() @@ -435,7 +435,7 @@ class EditSession deleteToEndOfWord: -> @mutateSelectedText (selection) -> selection.deleteToEndOfWord() - # Public: Performs a delete to the end of the current line, removing characters found there. + # Public: Deletes the entire line. deleteLine: -> @mutateSelectedText (selection) -> selection.deleteLine() @@ -890,7 +890,11 @@ class EditSession clearMarkerTail: (args...) -> @displayBuffer.clearMarkerTail(args...) - # Internal: + # Public: Identifies if markers are reversed, that is, they are highlighting "up." + # + # args - {String}s specifying the id of a {BufferMarker} + # + # Returns a {Boolean}. isMarkerReversed: (args...) -> @displayBuffer.isMarkerReversed(args...) @@ -1211,7 +1215,7 @@ class EditSession fn(cursor) for cursor in @getCursors() @mergeCursors() - # Public: Selects the text from the current cursor position to a given position. + # Public: Selects the text from the current cursor position to a given screen position. # # position - An instance of {Point}, with a given `row` and `column`. selectToScreenPosition: (position) -> diff --git a/src/app/selection.coffee b/src/app/selection.coffee index c3f91eb69..8b12d66ac 100644 --- a/src/app/selection.coffee +++ b/src/app/selection.coffee @@ -2,6 +2,7 @@ Range = require 'range' EventEmitter = require 'event-emitter' _ = require 'underscore' +# Public: Represents a selection in the {EditSession}. module.exports = class Selection cursor: null @@ -12,6 +13,7 @@ class Selection wordwise: false needsAutoscroll: null + # Internal: constructor: ({@cursor, @marker, @editSession, @goalBufferRange}) -> @cursor.selection = this @editSession.observeMarker @marker, => @screenRangeChanged() @@ -19,6 +21,7 @@ class Selection @cursor = null @destroy() + # Internal: destroy: -> return if @destroyed @destroyed = true @@ -26,33 +29,60 @@ class Selection @trigger 'destroyed' unless @editSession.destroyed @cursor?.destroy() + # Internal: finalize: -> @initialScreenRange = null unless @initialScreenRange?.isEqual(@getScreenRange()) if @isEmpty() @wordwise = false @linewise = false + # Public: Identifies if the selection is highlighting anything. + # + # Returns a {Boolean}. isEmpty: -> @getBufferRange().isEmpty() + # Public: Identifies if the selection is reversed, that is, it is highlighting "up." + # + # Returns a {Boolean}. isReversed: -> @editSession.isMarkerReversed(@marker) + # Public: Identifies if the selection is a single line. + # + # Returns a {Boolean}. isSingleScreenLine: -> @getScreenRange().isSingleLine() + # Internal: clearAutoscroll: -> @needsAutoscroll = null + # Public: Retrieves the screen range for the selection. + # + # Returns a {Range}. getScreenRange: -> @editSession.getMarkerScreenRange(@marker) + # Public: Modifies the screen range for the selection. + # + # screenRange - The new {Range} to select + # options - A hash of options matching those found in {#setBufferRange} setScreenRange: (screenRange, options) -> @setBufferRange(@editSession.bufferRangeForScreenRange(screenRange), options) + # Public: Retrieves the buffer range for the selection. + # + # Returns a {Range}. getBufferRange: -> @editSession.getMarkerBufferRange(@marker) + # Public: Modifies the buffer range for the selection. + # + # screenRange - The new {Range} to select + # options - A hash of options with the following keys: + # :preserveFolds - if `true`, the fold settings are preserved after the selection moves + # :autoscroll - if `true`, the {EditSession} scrolls to the new selection setBufferRange: (bufferRange, options={}) -> bufferRange = Range.fromObject(bufferRange) @needsAutoscroll = options.autoscroll @@ -62,6 +92,9 @@ class Selection @cursor.needsAutoscroll = false if options.autoscroll? @editSession.setMarkerBufferRange(@marker, bufferRange, options) + # Public: Retrieves the starting and ending buffer rows the selection is highlighting. + # + # Returns an {Array} of two {Number}s: the starting row, and the ending row. getBufferRowRange: -> range = @getBufferRange() start = range.start.row @@ -69,16 +102,24 @@ class Selection end = Math.max(start, end - 1) if range.end.column == 0 [start, end] + # Internal: screenRangeChanged: -> screenRange = @getScreenRange() @trigger 'screen-range-changed', screenRange + # Public: Retrieves the text in the selection. + # + # Returns a {String}. getText: -> @editSession.buffer.getTextInRange(@getBufferRange()) + # Public: Clears the selection, moving the marker to move to the head. clear: -> @editSession.clearMarkerTail(@marker) + # Public: Modifies the selection to mark the current word. + # + # Returns a {Range}. selectWord: -> options = {} options.wordRegex = /[\t ]*/ if @cursor.isSurroundedByWhitespace() @@ -90,6 +131,9 @@ class Selection expandOverWord: -> @setBufferRange(@getBufferRange().union(@cursor.getCurrentWordBufferRange())) + # Public: Selects an entire line in the {Buffer}. + # + # row - The line {Number} to select (default: the row of the cursor) selectLine: (row=@cursor.getBufferPosition().row) -> range = @editSession.bufferRangeForBufferRow(row, includeNewline: true) @setBufferRange(range) @@ -101,6 +145,9 @@ class Selection range = @getBufferRange().union(@cursor.getCurrentLineBufferRange(includeNewline: true)) @setBufferRange(range) + # Public: Selects the text from the current cursor position to a given screen position. + # + # position - An instance of {Point}, with a given `row` and `column`. selectToScreenPosition: (position) -> @modifySelection => if @initialScreenRange @@ -116,45 +163,61 @@ class Selection else if @wordwise @expandOverWord() + # Public: Selects the text from the current cursor position to a given buffer position. + # + # position - An instance of {Point}, with a given `row` and `column`. selectToBufferPosition: (position) -> @modifySelection => @cursor.setBufferPosition(position) + # Public: Selects the text one position right of the cursor. selectRight: -> @modifySelection => @cursor.moveRight() + # Public: Selects the text one position left of the cursor. selectLeft: -> @modifySelection => @cursor.moveLeft() + # Public: Selects all the text one position above the cursor. selectUp: -> @modifySelection => @cursor.moveUp() + # Public: Selects all the text one position below the cursor. selectDown: -> @modifySelection => @cursor.moveDown() + # Public: Selects all the text from the current cursor position to the top of the buffer. selectToTop: -> @modifySelection => @cursor.moveToTop() + # Public: Selects all the text from the current cursor position to the bottom of the buffer. selectToBottom: -> @modifySelection => @cursor.moveToBottom() + # Public: Selects all the text in the buffer. selectAll: -> @setBufferRange(@editSession.buffer.getRange(), autoscroll: false) + # Public: Selects all the text from the current cursor position to the beginning of the line. selectToBeginningOfLine: -> @modifySelection => @cursor.moveToBeginningOfLine() + # Public: Selects all the text from the current cursor position to the end of the line. selectToEndOfLine: -> @modifySelection => @cursor.moveToEndOfLine() + # Public: Selects all the text from the current cursor position to the beginning of the word. selectToBeginningOfWord: -> @modifySelection => @cursor.moveToBeginningOfWord() + # Public: Selects all the text from the current cursor position to the end of the word. selectToEndOfWord: -> @modifySelection => @cursor.moveToEndOfWord() + # Public: Selects all the text from the current cursor position to the beginning of the next word. selectToBeginningOfNextWord: -> @modifySelection => @cursor.moveToBeginningOfNextWord() + # Public: Moves the selection down one row. addSelectionBelow: -> range = (@goalBufferRange ? @getBufferRange()).copy() nextRow = range.end.row + 1 @@ -172,6 +235,7 @@ class Selection @editSession.addSelectionForBufferRange(range, goalBufferRange: range, suppressMerge: true) break + # Public: Moves the selection up one row. addSelectionAbove: -> range = (@goalBufferRange ? @getBufferRange()).copy() previousRow = range.end.row - 1 @@ -189,6 +253,13 @@ class Selection @editSession.addSelectionForBufferRange(range, goalBufferRange: range, suppressMerge: true) break + # Public: Replaces text at the current selection. + # + # text - A {String} representing the text to add + # options - A hash containing the following options: + # :normalizeIndent - TODO + # :select - if `true`, selects the newly added text + # :autoIndent - if `true`, indents the newly added text appropriately insertText: (text, options={}) -> oldBufferRange = @getBufferRange() @editSession.destroyFoldsContainingBufferRow(oldBufferRange.end.row) @@ -210,6 +281,10 @@ class Selection newBufferRange + # Public: Indents the selection. + # + # options - A hash with one key, `autoIndent`. If `true`, the indentation is + # performed appropriately. Otherwise, {EditSession#getTabText} is used indent: ({ autoIndent }={})-> { row, column } = @cursor.getBufferPosition() @@ -225,6 +300,7 @@ class Selection else @indentSelectedRows() + # Public: If the selection spans multiple rows, indents all of them. indentSelectedRows: -> [start, end] = @getBufferRowRange() for row in [start..end] @@ -270,6 +346,7 @@ class Selection desiredIndentString = @editSession.buildIndentString(desiredIndentLevel) line.replace(/^[\t ]*/, desiredIndentString) + # Public: Performs a backspace, removing the character found behind the selection. backspace: -> if @isEmpty() and not @editSession.isFoldedAtScreenRow(@cursor.getScreenRow()) if @cursor.isAtBeginningOfLine() and @editSession.isFoldedAtScreenRow(@cursor.getScreenRow() - 1) @@ -279,10 +356,12 @@ class Selection @deleteSelectedText() + # Public: Performs a backspace to the beginning of the current word, removing characters found there. backspaceToBeginningOfWord: -> @selectToBeginningOfWord() if @isEmpty() @deleteSelectedText() + # Public: Performs a backspace to the beginning of the current line, removing characters found there. backspaceToBeginningOfLine: -> if @isEmpty() and @cursor.isAtBeginningOfLine() @selectLeft() @@ -290,6 +369,7 @@ class Selection @selectToBeginningOfLine() @deleteSelectedText() + # Public: Performs a delete, removing the character found ahead of the cursor position. delete: -> if @isEmpty() if @cursor.isAtEndOfLine() and fold = @editSession.largestFoldStartingAtScreenRow(@cursor.getScreenRow() + 1) @@ -298,10 +378,12 @@ class Selection @selectRight() @deleteSelectedText() + # Public: Performs a delete to the end of the current word, removing characters found there. deleteToEndOfWord: -> @selectToEndOfWord() if @isEmpty() @deleteSelectedText() + # Public: Deletes the selected text. deleteSelectedText: -> bufferRange = @getBufferRange() if fold = @editSession.largestFoldContainingBufferRow(bufferRange.end.row) @@ -311,6 +393,7 @@ class Selection @editSession.buffer.delete(bufferRange) unless bufferRange.isEmpty() @cursor?.setBufferPosition(bufferRange.start) + # Public: Deletes the line. deleteLine: -> if @isEmpty() start = @cursor.getScreenRow() @@ -327,6 +410,9 @@ class Selection end-- @editSession.buffer.deleteRows(start, end) + # Public: Joins the current line with the one below it. + # + # If there selection spans more than one line, all the lines are joined together. joinLine: -> selectedRange = @getBufferRange() if selectedRange.isEmpty()