`. If the
+ # file is brand new, the title is `untitled`.
+ #
+ # Returns a {String}.
+ getLongTitle: ->
+ if sessionPath = @getPath()
+ fileName = path.basename(sessionPath)
+ directory = path.basename(path.dirname(sessionPath))
+ "#{fileName} - #{directory}"
else
- @scrollView.scrollLeft()
+ 'untitled'
- scrollRight: (scrollRight) ->
- if scrollRight?
- @scrollView.scrollRight(scrollRight)
- @activeEditSession.setScrollLeft(@scrollLeft())
+ # Public: Compares two `Editor`s to determine equality.
+ #
+ # Equality is based on the condition that:
+ #
+ # * the two {TextBuffer}s are the same
+ # * the two `scrollTop` and `scrollLeft` property are the same
+ # * the two {Cursor} screen positions are the same
+ #
+ # Returns a {Boolean}.
+ isEqual: (other) ->
+ return false unless other instanceof Editor
+ @buffer == other.buffer and
+ @getScrollTop() == other.getScrollTop() and
+ @getScrollLeft() == other.getScrollLeft() and
+ @getCursorScreenPosition().isEqual(other.getCursorScreenPosition())
+
+ # Public: Controls visiblity based on the given Boolean.
+ setVisible: (visible) -> @displayBuffer.setVisible(visible)
+
+ # Public: FIXME: I don't understand this.
+ setScrollTop: (scrollTop) -> @state.set('scrollTop', scrollTop)
+
+ # Public: Returns the current `scrollTop` value
+ getScrollTop: -> @state.get('scrollTop') ? 0
+
+ # Public: FIXME: I don't understand this.
+ setScrollLeft: (scrollLeft) -> @state.set('scrollLeft', scrollLeft)
+
+ # Public: Returns the current `scrollLeft` value
+ getScrollLeft: -> @state.get('scrollLeft')
+
+ # Set the number of characters that can be displayed horizontally in the
+ # editor that contains this edit session.
+ #
+ # editorWidthInChars - A {Number} of characters
+ setEditorWidthInChars: (editorWidthInChars) ->
+ @displayBuffer.setEditorWidthInChars(editorWidthInChars)
+
+ # Public: Sets the column at which columsn will soft wrap
+ getSoftWrapColumn: -> @displayBuffer.getSoftWrapColumn()
+
+ # Public: Returns whether soft tabs are enabled or not.
+ getSoftTabs: -> @state.get('softTabs')
+
+ # Public: Controls whether soft tabs are enabled or not.
+ setSoftTabs: (softTabs) ->
+ @state.set('softTabs', softTabs)
+
+ # Public: Returns whether soft wrap is enabled or not.
+ getSoftWrap: -> @displayBuffer.getSoftWrap()
+
+ # Public: Controls whether soft tabs are enabled or not.
+ setSoftWrap: (softWrap) -> @displayBuffer.setSoftWrap(softWrap)
+
+ # Public: Returns that String used to indicate a tab.
+ #
+ # If soft tabs are enabled, this is a space (`" "`) times the {.getTabLength} value.
+ # Otherwise, it's a tab (`\t`).
+ getTabText: -> @buildIndentString(1)
+
+ # Public: Returns the current tab length.
+ getTabLength: -> @displayBuffer.getTabLength()
+
+ # Public: Sets the current tab length.
+ setTabLength: (tabLength) -> @displayBuffer.setTabLength(tabLength)
+
+ # Public: Given a position, this clips it to a real position.
+ #
+ # For example, if `position`'s row exceeds the row count of the buffer,
+ # or if its column goes beyond a line's length, this "sanitizes" the value
+ # to a real position.
+ #
+ # * position:
+ # The {Point} to clip
+ #
+ # Returns the new, clipped {Point}. Note that this could be the same as
+ # `position` if no clipping was performed.
+ clipBufferPosition: (bufferPosition) -> @buffer.clipPosition(bufferPosition)
+
+ # Public: Given a range, this clips it to a real range.
+ #
+ # For example, if `range`'s row exceeds the row count of the buffer,
+ # or if its column goes beyond a line's length, this "sanitizes" the value
+ # to a real range.
+ #
+ # * range:
+ # The {Range} to clip
+ #
+ # Returns the new, clipped {Range}. Note that this could be the same as
+ # `range` if no clipping was performed.
+ clipBufferRange: (range) -> @buffer.clipRange(range)
+
+ # Public: Returns the indentation level of the given a buffer row
+ #
+ # * bufferRow:
+ # A Number indicating the buffer row.
+ indentationForBufferRow: (bufferRow) ->
+ @indentLevelForLine(@lineForBufferRow(bufferRow))
+
+ # Public: Sets the indentation level for the given buffer row.
+ #
+ # * bufferRow:
+ # A {Number} indicating the buffer row.
+ # * newLevel:
+ # A {Number} indicating the new indentation level.
+ setIndentationForBufferRow: (bufferRow, newLevel) ->
+ currentLevel = @indentationForBufferRow(bufferRow)
+ currentIndentString = @buildIndentString(currentLevel)
+ newIndentString = @buildIndentString(newLevel)
+ @buffer.change([[bufferRow, 0], [bufferRow, currentIndentString.length]], newIndentString)
+
+ # Public: Returns the indentation level of the given line of text.
+ #
+ # * line:
+ # A {String} in the current buffer.
+ #
+ # Returns a {Number} or 0 if the text isn't found within the buffer.
+ indentLevelForLine: (line) ->
+ if match = line.match(/^[\t ]+/)
+ leadingWhitespace = match[0]
+ tabCount = leadingWhitespace.match(/\t/g)?.length ? 0
+ spaceCount = leadingWhitespace.match(/[ ]/g)?.length ? 0
+ tabCount + (spaceCount / @getTabLength())
else
- @scrollView.scrollRight()
+ 0
- ### Public ###
+ # Private: Constructs the string used for tabs.
+ buildIndentString: (number) ->
+ if @getSoftTabs()
+ _.multiplyString(" ", number * @getTabLength())
+ else
+ _.multiplyString("\t", Math.floor(number))
- # Retrieves the {EditSession}'s buffer.
+ # {Delegates to: TextBuffer.save}
+ save: -> @buffer.save()
+
+ # {Delegates to: TextBuffer.saveAs}
+ saveAs: (path) -> @buffer.saveAs(path)
+
+ # {Delegates to: TextBuffer.getExtension}
+ getFileExtension: -> @buffer.getExtension()
+
+ # {Delegates to: TextBuffer.getPath}
+ getPath: -> @buffer.getPath()
+
+ # {Delegates to: TextBuffer.getText}
+ getText: -> @buffer.getText()
+
+ # {Delegates to: TextBuffer.setText}
+ setText: (text) -> @buffer.setText(text)
+
+ # Private: Retrieves the current {TextBuffer}.
+ getBuffer: -> @buffer
+
+ # Public: Retrieves the current buffer's URI.
+ getUri: -> @buffer.getUri()
+
+ # {Delegates to: TextBuffer.isRowBlank}
+ isBufferRowBlank: (bufferRow) -> @buffer.isRowBlank(bufferRow)
+
+ # Public: Determine if the given row is entirely a comment
+ isBufferRowCommented: (bufferRow) ->
+ if match = @lineForBufferRow(bufferRow).match(/\S/)
+ scopes = @tokenForBufferPosition([bufferRow, match.index]).scopes
+ new TextMateScopeSelector('comment.*').matches(scopes)
+
+ # {Delegates to: TextBuffer.nextNonBlankRow}
+ nextNonBlankBufferRow: (bufferRow) -> @buffer.nextNonBlankRow(bufferRow)
+
+ # {Delegates to: TextBuffer.getEofPosition}
+ getEofBufferPosition: -> @buffer.getEofPosition()
+
+ # {Delegates to: TextBuffer.getLastRow}
+ getLastBufferRow: -> @buffer.getLastRow()
+
+ # {Delegates to: TextBuffer.rangeForRow}
+ bufferRangeForBufferRow: (row, options) -> @buffer.rangeForRow(row, options)
+
+ # {Delegates to: TextBuffer.lineForRow}
+ lineForBufferRow: (row) -> @buffer.lineForRow(row)
+
+ # {Delegates to: TextBuffer.lineLengthForRow}
+ lineLengthForBufferRow: (row) -> @buffer.lineLengthForRow(row)
+
+ # {Delegates to: TextBuffer.scan}
+ scan: (args...) -> @buffer.scan(args...)
+
+ # {Delegates to: TextBuffer.scanInRange}
+ scanInBufferRange: (args...) -> @buffer.scanInRange(args...)
+
+ # {Delegates to: TextBuffer.backwardsScanInRange}
+ backwardsScanInBufferRange: (args...) -> @buffer.backwardsScanInRange(args...)
+
+ # {Delegates to: TextBuffer.isModified}
+ isModified: -> @buffer.isModified()
+
+ # Public: Determines if the user should be prompted to save before closing.
+ shouldPromptToSave: -> @isModified() and not @buffer.hasMultipleEditors()
+
+ # {Delegates to: DisplayBuffer.screenPositionForBufferPosition}
+ screenPositionForBufferPosition: (bufferPosition, options) -> @displayBuffer.screenPositionForBufferPosition(bufferPosition, options)
+
+ # {Delegates to: DisplayBuffer.bufferPositionForScreenPosition}
+ bufferPositionForScreenPosition: (screenPosition, options) -> @displayBuffer.bufferPositionForScreenPosition(screenPosition, options)
+
+ # {Delegates to: DisplayBuffer.screenRangeForBufferRange}
+ screenRangeForBufferRange: (bufferRange) -> @displayBuffer.screenRangeForBufferRange(bufferRange)
+
+ # {Delegates to: DisplayBuffer.bufferRangeForScreenRange}
+ bufferRangeForScreenRange: (screenRange) -> @displayBuffer.bufferRangeForScreenRange(screenRange)
+
+ # {Delegates to: DisplayBuffer.clipScreenPosition}
+ clipScreenPosition: (screenPosition, options) -> @displayBuffer.clipScreenPosition(screenPosition, options)
+
+ # {Delegates to: DisplayBuffer.lineForRow}
+ lineForScreenRow: (row) -> @displayBuffer.lineForRow(row)
+
+ # {Delegates to: DisplayBuffer.linesForRows}
+ linesForScreenRows: (start, end) -> @displayBuffer.linesForRows(start, end)
+
+ # {Delegates to: DisplayBuffer.getLineCount}
+ getScreenLineCount: -> @displayBuffer.getLineCount()
+
+ # {Delegates to: DisplayBuffer.getMaxLineLength}
+ getMaxScreenLineLength: -> @displayBuffer.getMaxLineLength()
+
+ # {Delegates to: DisplayBuffer.getLastRow}
+ getLastScreenRow: -> @displayBuffer.getLastRow()
+
+ # {Delegates to: DisplayBuffer.bufferRowsForScreenRows}
+ bufferRowsForScreenRows: (startRow, endRow) -> @displayBuffer.bufferRowsForScreenRows(startRow, endRow)
+
+ # {Delegates to: DisplayBuffer.scopesForBufferPosition}
+ scopesForBufferPosition: (bufferPosition) -> @displayBuffer.scopesForBufferPosition(bufferPosition)
+
+ # Public: ?
+ bufferRangeForScopeAtCursor: (selector) ->
+ @displayBuffer.bufferRangeForScopeAtPosition(selector, @getCursorBufferPosition())
+
+ # {Delegates to: DisplayBuffer.tokenForBufferPosition}
+ tokenForBufferPosition: (bufferPosition) -> @displayBuffer.tokenForBufferPosition(bufferPosition)
+
+ # Public: Retrieves the grammar's token scopes for the line with the most
+ # recently added cursor.
#
- # Returns the current {TextBuffer}.
- getBuffer: -> @activeEditSession.buffer
+ # Returns an {Array} of {String}s.
+ getCursorScopes: -> @getCursor().getScopes()
- # Scrolls the editor to the bottom.
- scrollToBottom: ->
- @scrollBottom(@getScreenLineCount() * @lineHeight)
-
- # Scrolls the editor to the position of the most recently added cursor.
+ # Public: Inserts text at the current cursor positions
#
- # The editor is also centered.
- scrollToCursorPosition: ->
- @scrollToBufferPosition(@getCursorBufferPosition(), center: true)
+ # * text:
+ # A String representing the text to insert.
+ # * options:
+ # + A set of options equivalent to {Selection.insertText}
+ insertText: (text, options={}) ->
+ options.autoIndentNewline ?= @shouldAutoIndent()
+ options.autoDecreaseIndent ?= @shouldAutoIndent()
+ @mutateSelectedText (selection) -> selection.insertText(text, options)
- # Scrolls the editor to the given buffer position.
- #
- # bufferPosition - An object that represents a buffer position. It can be either
- # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
- # options - A hash matching the options available to {.scrollToPixelPosition}
- scrollToBufferPosition: (bufferPosition, options) ->
- @scrollToPixelPosition(@pixelPositionForBufferPosition(bufferPosition), options)
+ # Public: Inserts a new line at the current cursor positions.
+ insertNewline: ->
+ @insertText('\n')
- # Scrolls the editor to the given screen position.
- #
- # screenPosition - An object that represents a buffer position. It can be either
- # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
- # options - A hash matching the options available to {.scrollToPixelPosition}
- scrollToScreenPosition: (screenPosition, options) ->
- @scrollToPixelPosition(@pixelPositionForScreenPosition(screenPosition), options)
+ # Public: Inserts a new line below the current cursor positions.
+ insertNewlineBelow: ->
+ @transact =>
+ @moveCursorToEndOfLine()
+ @insertNewline()
- # Scrolls the editor to the given pixel position.
- #
- # pixelPosition - An object that represents a pixel position. It can be either
- # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
- # options - A hash with the following keys:
- # center: if `true`, the position is scrolled such that it's in the center of the editor
- scrollToPixelPosition: (pixelPosition, options) ->
- return unless @attached
- @scrollVertically(pixelPosition, options)
- @scrollHorizontally(pixelPosition)
+ # Public: Inserts a new line above the current cursor positions.
+ insertNewlineAbove: ->
+ @transact =>
+ onFirstLine = @getCursorBufferPosition().row is 0
+ @moveCursorToBeginningOfLine()
+ @moveCursorLeft()
+ @insertNewline()
+ @moveCursorUp() if onFirstLine
- # Highlight all the folds within the given buffer range.
+ # Public: Indents the current line.
#
- # "Highlighting" essentially just adds the `fold-selected` class to the line's
- # DOM element.
- #
- # bufferRange - The {Range} to check.
- highlightFoldsContainingBufferRange: (bufferRange) ->
- screenLines = @linesForScreenRows(@firstRenderedScreenRow, @lastRenderedScreenRow)
- for screenLine, i in screenLines
- if fold = screenLine.fold
- screenRow = @firstRenderedScreenRow + i
- element = @lineElementForScreenRow(screenRow)
+ # * options
+ # + A set of options equivalent to {Selection.indent}.
+ indent: (options={})->
+ options.autoIndent ?= @shouldAutoIndent()
+ @mutateSelectedText (selection) -> selection.indent(options)
- if bufferRange.intersectsWith(fold.getBufferRange())
- element.addClass('fold-selected')
+ # Public: Removes the character found behind the current cursor position.
+ #
+ # FIXME: Does this remove content from all cursors or the last one?
+ backspace: ->
+ @mutateSelectedText (selection) -> selection.backspace()
+
+ # Public: Removes all characters from the current cursor position until the
+ # beginging of the current word.
+ backspaceToBeginningOfWord: ->
+ @mutateSelectedText (selection) -> selection.backspaceToBeginningOfWord()
+
+ # Public: Removes all characters from the current cursor position to the start
+ # of the line.
+ backspaceToBeginningOfLine: ->
+ @mutateSelectedText (selection) -> selection.backspaceToBeginningOfLine()
+
+ # Public: Removes the current selection or the next character after the
+ # cursor.
+ delete: ->
+ @mutateSelectedText (selection) -> selection.delete()
+
+ # Public: Removes all characters from the cursor until the end of the current
+ # word.
+ deleteToEndOfWord: ->
+ @mutateSelectedText (selection) -> selection.deleteToEndOfWord()
+
+ # Public: Deletes the entire line.
+ deleteLine: ->
+ @mutateSelectedText (selection) -> selection.deleteLine()
+
+ # Public: Indents the currently selected rows.
+ #
+ # FIXME: what does this do if no selection?
+ indentSelectedRows: ->
+ @mutateSelectedText (selection) -> selection.indentSelectedRows()
+
+ # Public: Outdents the selected rows.
+ #
+ # FIXME: what does this do if no selection?
+ outdentSelectedRows: ->
+ @mutateSelectedText (selection) -> selection.outdentSelectedRows()
+
+ # Public: Wraps the lines within a selection in comments.
+ #
+ # If the language doesn't have comments, nothing happens.
+ #
+ # Returns an {Array} of the commented {Ranges}.
+ toggleLineCommentsInSelection: ->
+ @mutateSelectedText (selection) -> selection.toggleLineComments()
+
+ # Public: Indents selected lines based on grammar's suggested indent levels.
+ autoIndentSelectedRows: ->
+ @mutateSelectedText (selection) -> selection.autoIndentSelectedRows()
+
+ # Public: Converts all indents to the current {.getTabText} given a {Range}.
+ normalizeTabsInBufferRange: (bufferRange) ->
+ return unless @getSoftTabs()
+ @scanInBufferRange /\t/, bufferRange, ({replace}) => replace(@getTabText())
+
+ # Public: Copies and removes all characters from cursor to the end of the
+ # line.
+ cutToEndOfLine: ->
+ maintainPasteboard = false
+ @mutateSelectedText (selection) ->
+ selection.cutToEndOfLine(maintainPasteboard)
+ maintainPasteboard = true
+
+ # Public: Cuts the selected text.
+ cutSelectedText: ->
+ maintainPasteboard = false
+ @mutateSelectedText (selection) ->
+ selection.cut(maintainPasteboard)
+ maintainPasteboard = true
+
+ # Public: Copies the selected text.
+ copySelectedText: ->
+ maintainPasteboard = false
+ for selection in @getSelections()
+ selection.copy(maintainPasteboard)
+ maintainPasteboard = true
+
+ # Public: Pastes the text in the clipboard.
+ #
+ # * options:
+ # + A set of options equivalent to {Selection.insertText}.
+ pasteText: (options={}) ->
+ [text, metadata] = atom.pasteboard.read()
+
+ containsNewlines = text.indexOf('\n') isnt -1
+
+ if atom.config.get('editor.normalizeIndentOnPaste') and metadata
+ if !@getCursor().hasPrecedingCharactersOnLine() or containsNewlines
+ options.indentBasis ?= metadata.indentBasis
+
+ @insertText(text, options)
+
+ # Public: Undoes the last change.
+ undo: ->
+ @getCursor().needsAutoscroll = true
+ @buffer.undo(this)
+
+ # Pulic: Redoes the last change.
+ redo: ->
+ @getCursor().needsAutoscroll = true
+ @buffer.redo(this)
+
+ # Public: Folds all the rows.
+ foldAll: ->
+ @languageMode.foldAll()
+
+ # Public: Unfolds all the rows.
+ unfoldAll: ->
+ @languageMode.unfoldAll()
+
+ # Public: Creates a fold for each section at the given indent level.
+ foldAllAtIndentLevel: (indentLevel) ->
+ @languageMode.foldAllAtIndentLevel(indentLevel)
+
+ # Public: Folds the current row.
+ foldCurrentRow: ->
+ bufferRow = @bufferPositionForScreenPosition(@getCursorScreenPosition()).row
+ @foldBufferRow(bufferRow)
+
+ # Public: Folds a give buffer row.
+ foldBufferRow: (bufferRow) ->
+ @languageMode.foldBufferRow(bufferRow)
+
+ # Public: Unfolds the current row.
+ unfoldCurrentRow: ->
+ bufferRow = @bufferPositionForScreenPosition(@getCursorScreenPosition()).row
+ @unfoldBufferRow(bufferRow)
+
+ # Public: Unfolds a given a buffer row.
+ unfoldBufferRow: (bufferRow) ->
+ @languageMode.unfoldBufferRow(bufferRow)
+
+ # Public: Folds all selections.
+ foldSelection: ->
+ selection.fold() for selection in @getSelections()
+
+ # {Delegates to: DisplayBuffer.createFold}
+ createFold: (startRow, endRow) ->
+ @displayBuffer.createFold(startRow, endRow)
+
+ # {Delegates to: DisplayBuffer.destroyFoldWithId}
+ destroyFoldWithId: (id) ->
+ @displayBuffer.destroyFoldWithId(id)
+
+ # {Delegates to: DisplayBuffer.destroyFoldsContainingBufferRow}
+ destroyFoldsContainingBufferRow: (bufferRow) ->
+ @displayBuffer.destroyFoldsContainingBufferRow(bufferRow)
+
+ # Public: Removes any {Fold}s found that intersect the given buffer row.
+ destroyFoldsIntersectingBufferRange: (bufferRange) ->
+ for row in [bufferRange.start.row..bufferRange.end.row]
+ @destroyFoldsContainingBufferRow(row)
+
+ # Public: Returns whether the current row is folded.
+ isFoldedAtCursorRow: ->
+ @isFoldedAtScreenRow(@getCursorScreenRow())
+
+ # Public: Returns whether a given buffer row if folded
+ isFoldedAtBufferRow: (bufferRow) ->
+ @displayBuffer.isFoldedAtBufferRow(bufferRow)
+
+ # Public: Returns whether a given screen row if folded
+ isFoldedAtScreenRow: (screenRow) ->
+ @displayBuffer.isFoldedAtScreenRow(screenRow)
+
+ # {Delegates to: DisplayBuffer.largestFoldContainingBufferRow}
+ largestFoldContainingBufferRow: (bufferRow) ->
+ @displayBuffer.largestFoldContainingBufferRow(bufferRow)
+
+ # {Delegates to: DisplayBuffer.largestFoldStartingAtScreenRow}
+ largestFoldStartingAtScreenRow: (screenRow) ->
+ @displayBuffer.largestFoldStartingAtScreenRow(screenRow)
+
+ # Public: Suggests the indent for the given buffer row.
+ suggestedIndentForBufferRow: (bufferRow) ->
+ @languageMode.suggestedIndentForBufferRow(bufferRow)
+
+ # Public: Indents all the rows between two buffer rows.
+ #
+ # * startRow: The row {Number} to start at (inclusive)
+ # * endRow: The row {Number} to end at (inclusive)
+ autoIndentBufferRows: (startRow, endRow) ->
+ @languageMode.autoIndentBufferRows(startRow, endRow)
+
+ # Public: Indents the given buffer row to it's suggested level.
+ autoIndentBufferRow: (bufferRow) ->
+ @languageMode.autoIndentBufferRow(bufferRow)
+
+ # Public:
+ #
+ # FIXME: What does this do?
+ autoDecreaseIndentForBufferRow: (bufferRow) ->
+ @languageMode.autoDecreaseIndentForBufferRow(bufferRow)
+
+ # Public: Wraps the lines between two rows in comments.
+ #
+ # If the language doesn't have comments, nothing happens.
+ #
+ # startRow - The row {Number} to start at (inclusive)
+ # endRow - The row {Number} to end at (inclusive)
+ #
+ # Returns an {Array} of the commented {Ranges}.
+ toggleLineCommentsForBufferRows: (start, end) ->
+ @languageMode.toggleLineCommentsForBufferRows(start, end)
+
+ # Public: Moves the selected line up one row.
+ moveLineUp: ->
+ selection = @getSelectedBufferRange()
+ return if selection.start.row is 0
+ lastRow = @buffer.getLastRow()
+ return if selection.isEmpty() and selection.start.row is lastRow and @buffer.getLastLine() is ''
+
+ @transact =>
+ foldedRows = []
+ rows = [selection.start.row..selection.end.row]
+ if selection.start.row isnt selection.end.row and selection.end.column is 0
+ rows.pop() unless @isFoldedAtBufferRow(selection.end.row)
+ for row in rows
+ screenRow = @screenPositionForBufferPosition([row]).row
+ if @isFoldedAtScreenRow(screenRow)
+ bufferRange = @bufferRangeForScreenRange([[screenRow], [screenRow + 1]])
+ startRow = bufferRange.start.row
+ endRow = bufferRange.end.row - 1
+ foldedRows.push(endRow - 1)
else
- element.removeClass('fold-selected')
+ startRow = row
+ endRow = row
- saveScrollPositionForActiveEditSession: ->
- if @attached
- @activeEditSession.setScrollTop(@scrollTop())
- @activeEditSession.setScrollLeft(@scrollLeft())
+ endPosition = Point.min([endRow + 1], @buffer.getEofPosition())
+ lines = @buffer.getTextInRange([[startRow], endPosition])
+ if endPosition.row is lastRow and endPosition.column > 0 and not @buffer.lineEndingForRow(endPosition.row)
+ lines = "#{lines}\n"
+ @buffer.deleteRows(startRow, endRow)
+ @buffer.insert([startRow - 1], lines)
- # Toggle soft tabs on the edit session.
- toggleSoftTabs: ->
- @activeEditSession.setSoftTabs(not @activeEditSession.getSoftTabs())
+ @foldBufferRow(foldedRow) for foldedRow in foldedRows
- # Toggle soft wrap on the edit session.
- toggleSoftWrap: ->
- @setWidthInChars()
- @activeEditSession.setSoftWrap(not @activeEditSession.getSoftWrap())
+ @setSelectedBufferRange(selection.translate([-1]), preserveFolds: true)
- calculateWidthInChars: ->
- Math.floor(@scrollView.width() / @charWidth)
+ # Public: Moves the selected line down one row.
+ moveLineDown: ->
+ selection = @getSelectedBufferRange()
+ lastRow = @buffer.getLastRow()
+ return if selection.end.row is lastRow
+ return if selection.end.row is lastRow - 1 and @buffer.getLastLine() is ''
- calculateHeightInLines: ->
- Math.ceil($(window).height() / @lineHeight)
+ @transact =>
+ foldedRows = []
+ rows = [selection.end.row..selection.start.row]
+ if selection.start.row isnt selection.end.row and selection.end.column is 0
+ rows.shift() unless @isFoldedAtBufferRow(selection.end.row)
+ for row in rows
+ screenRow = @screenPositionForBufferPosition([row]).row
+ if @isFoldedAtScreenRow(screenRow)
+ bufferRange = @bufferRangeForScreenRange([[screenRow], [screenRow + 1]])
+ startRow = bufferRange.start.row
+ endRow = bufferRange.end.row - 1
+ foldedRows.push(endRow + 1)
+ else
+ startRow = row
+ endRow = row
- # Enables/disables soft wrap on the editor.
+ if endRow + 1 is lastRow
+ endPosition = [endRow, @buffer.lineLengthForRow(endRow)]
+ else
+ endPosition = [endRow + 1]
+ lines = @buffer.getTextInRange([[startRow], endPosition])
+ @buffer.deleteRows(startRow, endRow)
+ insertPosition = Point.min([startRow + 1], @buffer.getEofPosition())
+ if insertPosition.row is @buffer.getLastRow() and insertPosition.column > 0
+ lines = "\n#{lines}"
+ @buffer.insert(insertPosition, lines)
+
+ @foldBufferRow(foldedRow) for foldedRow in foldedRows
+
+ @setSelectedBufferRange(selection.translate([1]), preserveFolds: true)
+
+ # Public: Duplicates the current line.
#
- # softWrap - A {Boolean} which, if `true`, enables soft wrap
- setSoftWrap: (softWrap) ->
- if softWrap
- @addClass 'soft-wrap'
- @scrollLeft(0)
+ # If more than one cursor is present, only the most recently added one is
+ # duplicated.
+ duplicateLine: ->
+ return unless @getSelection().isEmpty()
+
+ @transact =>
+ cursorPosition = @getCursorBufferPosition()
+ cursorRowFolded = @isFoldedAtCursorRow()
+ if cursorRowFolded
+ screenRow = @screenPositionForBufferPosition(cursorPosition).row
+ bufferRange = @bufferRangeForScreenRange([[screenRow], [screenRow + 1]])
+ else
+ bufferRange = new Range([cursorPosition.row], [cursorPosition.row + 1])
+
+ insertPosition = new Point(bufferRange.end.row)
+ if insertPosition.row > @buffer.getLastRow()
+ @unfoldCurrentRow() if cursorRowFolded
+ @buffer.append("\n#{@getTextInBufferRange(bufferRange)}")
+ @foldCurrentRow() if cursorRowFolded
+ else
+ @buffer.insert(insertPosition, @getTextInBufferRange(bufferRange))
+
+ @setCursorScreenPosition(@getCursorScreenPosition().translate([1]))
+ @foldCurrentRow() if cursorRowFolded
+
+ # Private:
+ mutateSelectedText: (fn) ->
+ @transact => fn(selection) for selection in @getSelections()
+
+ # Private:
+ replaceSelectedText: (options={}, fn) ->
+ {selectWordIfEmpty} = options
+ @mutateSelectedText (selection) ->
+ range = selection.getBufferRange()
+ if selectWordIfEmpty and selection.isEmpty()
+ selection.selectWord()
+ text = selection.getText()
+ selection.deleteSelectedText()
+ selection.insertText(fn(text))
+ selection.setBufferRange(range)
+
+ # Public: Returns a valid {DisplayBufferMarker} object for the given id.
+ getMarker: (id) ->
+ @displayBuffer.getMarker(id)
+
+ # Public: Returns all {DisplayBufferMarker}s.
+ getMarkers: ->
+ @displayBuffer.getMarkers()
+
+ # Public: Returns all {DisplayBufferMarker}s that match all given attributes.
+ findMarkers: (attributes) ->
+ @displayBuffer.findMarkers(attributes)
+
+ # {Delegates to: DisplayBuffer.markScreenRange}
+ markScreenRange: (args...) ->
+ @displayBuffer.markScreenRange(args...)
+
+ # {Delegates to: DisplayBuffer.markBufferRange}
+ markBufferRange: (args...) ->
+ @displayBuffer.markBufferRange(args...)
+
+ # {Delegates to: DisplayBuffer.markScreenPosition}
+ markScreenPosition: (args...) ->
+ @displayBuffer.markScreenPosition(args...)
+
+ # {Delegates to: DisplayBuffer.markBufferPosition}
+ markBufferPosition: (args...) ->
+ @displayBuffer.markBufferPosition(args...)
+
+ # {Delegates to: DisplayBuffer.destroyMarker}
+ destroyMarker: (args...) ->
+ @displayBuffer.destroyMarker(args...)
+
+ # {Delegates to: DisplayBuffer.getMarkerCount}
+ getMarkerCount: ->
+ @buffer.getMarkerCount()
+
+ # Public: Determines if there are multiple cursors.
+ hasMultipleCursors: ->
+ @getCursors().length > 1
+
+ # Public: Returns an Array of all {Cursor}s, including cursors representing
+ # remote users.
+ getAllCursors: ->
+ @getCursors().concat(@getRemoteCursors())
+
+ # Public: Returns an Array of all local {Cursor}s.
+ getCursors: -> new Array(@cursors...)
+
+ # Public: Returns the most recently added {Cursor}.
+ getCursor: ->
+ _.last(@cursors)
+
+ # Public: Returns an Array of all remove {Cursor}s.
+ getRemoteCursors: -> new Array(@remoteCursors...)
+
+ # Public: Adds and returns a cursor at the given screen position.
+ addCursorAtScreenPosition: (screenPosition) ->
+ @markScreenPosition(screenPosition, @getSelectionMarkerAttributes())
+ @getLastSelection().cursor
+
+ # Public: Adds and returns a cursor at the given buffer position.
+ addCursorAtBufferPosition: (bufferPosition) ->
+ @markBufferPosition(bufferPosition, @getSelectionMarkerAttributes())
+ @getLastSelection().cursor
+
+ # Public: Adds and returns a cursor at the given {DisplayBufferMarker}
+ # position.
+ addCursor: (marker) ->
+ cursor = new Cursor(editor: this, marker: marker)
+ if marker.isLocal()
+ @cursors.push(cursor)
else
- @removeClass 'soft-wrap'
+ @remoteCursors.push(cursor)
+ @emit 'cursor-added', cursor
+ cursor
- # Sets the font size for the editor.
+ # Public: Removes and returns a cursor from the `Editor`.
+ removeCursor: (cursor) ->
+ _.remove(@cursors, cursor)
+
+ # Public: Creates a new selection at the given marker.
#
- # fontSize - A {Number} indicating the font size in pixels.
- setFontSize: (fontSize) ->
- @css('font-size', "#{fontSize}px}")
+ # * marker:
+ # The {DisplayBufferMarker} to highlight
+ # * options:
+ # + A hash of options that pertain to the {Selection} constructor.
+ #
+ # Returns the new {Selection}.
+ addSelection: (marker, options={}) ->
+ unless marker.getAttributes().preserveFolds
+ @destroyFoldsIntersectingBufferRange(marker.getBufferRange())
+ cursor = @addCursor(marker)
+ selection = new Selection(_.extend({editor: this, marker, cursor}, options))
- @clearCharacterWidthCache()
-
- if @isOnDom()
- @redraw()
+ if marker.isLocal()
+ @selections.push(selection)
else
- @redrawOnReattach = @attached
+ @remoteSelections.push(selection)
- # Retrieves the font size for the editor.
- #
- # Returns a {Number} indicating the font size in pixels.
- getFontSize: ->
- parseInt(@css("font-size"))
-
- # Sets the font family for the editor.
- #
- # fontFamily - A {String} identifying the CSS `font-family`,
- setFontFamily: (fontFamily='') ->
- @css('font-family', fontFamily)
-
- @clearCharacterWidthCache()
-
- @redraw()
-
- # Gets the font family for the editor.
- #
- # Returns a {String} identifying the CSS `font-family`,
- getFontFamily: -> @css("font-family")
-
- # Redraw the editor
- redraw: ->
- return unless @hasParent()
- return unless @attached
- @redrawOnReattach = false
- @calculateDimensions()
- @updatePaddingOfRenderedLines()
- @updateLayerDimensions()
- @requestDisplayUpdate()
-
- splitLeft: ->
- pane = @getPane()
- pane?.splitLeft(pane?.copyActiveItem()).activeView
-
- splitRight: ->
- pane = @getPane()
- pane?.splitRight(pane?.copyActiveItem()).activeView
-
- splitUp: ->
- pane = @getPane()
- pane?.splitUp(pane?.copyActiveItem()).activeView
-
- splitDown: ->
- pane = @getPane()
- pane?.splitDown(pane?.copyActiveItem()).activeView
-
- # Retrieve's the `Editor`'s pane.
- #
- # Returns a {Pane}.
- getPane: ->
- @parent('.item-views').parent('.pane').view()
-
- remove: (selector, keepData) ->
- return super if keepData or @removed
- super
- rootView?.focus()
-
- beforeRemove: ->
- @trigger 'editor:will-be-removed'
- @removed = true
- @activeEditSession?.destroy()
- $(window).off(".editor-#{@id}")
- $(document).off(".editor-#{@id}")
-
- getCursorView: (index) ->
- index ?= @cursorViews.length - 1
- @cursorViews[index]
-
- getCursorViews: ->
- new Array(@cursorViews...)
-
- addCursorView: (cursor, options) ->
- cursorView = new CursorView(cursor, this, options)
- @cursorViews.push(cursorView)
- @overlayer.append(cursorView)
- cursorView
-
- removeCursorView: (cursorView) ->
- _.remove(@cursorViews, cursorView)
-
- getSelectionView: (index) ->
- index ?= @selectionViews.length - 1
- @selectionViews[index]
-
- getSelectionViews: ->
- new Array(@selectionViews...)
-
- addSelectionView: (selection) ->
- selectionView = new SelectionView({editor: this, selection})
- @selectionViews.push(selectionView)
- @underlayer.append(selectionView)
- selectionView
-
- removeSelectionView: (selectionView) ->
- _.remove(@selectionViews, selectionView)
-
- removeAllCursorAndSelectionViews: ->
- cursorView.remove() for cursorView in @getCursorViews()
- selectionView.remove() for selectionView in @getSelectionViews()
-
- appendToLinesView: (view) ->
- @overlayer.append(view)
-
- ### Internal ###
-
- # Scrolls the editor vertically to a given position.
- scrollVertically: (pixelPosition, {center}={}) ->
- scrollViewHeight = @scrollView.height()
- scrollTop = @scrollTop()
- scrollBottom = scrollTop + scrollViewHeight
-
- if center
- unless scrollTop < pixelPosition.top < scrollBottom
- @scrollTop(pixelPosition.top - (scrollViewHeight / 2))
+ selectionBufferRange = selection.getBufferRange()
+ @mergeIntersectingSelections()
+ if selection.destroyed
+ for selection in @getSelections()
+ if selection.intersectsBufferRange(selectionBufferRange)
+ return selection
else
- linesInView = @scrollView.height() / @lineHeight
- maxScrollMargin = Math.floor((linesInView - 1) / 2)
- scrollMargin = Math.min(@vScrollMargin, maxScrollMargin)
- margin = scrollMargin * @lineHeight
- desiredTop = pixelPosition.top - margin
- desiredBottom = pixelPosition.top + @lineHeight + margin
- if desiredBottom > scrollBottom
- @scrollTop(desiredBottom - scrollViewHeight)
- else if desiredTop < scrollTop
- @scrollTop(desiredTop)
+ @emit 'selection-added', selection
+ selection
- # Scrolls the editor horizontally to a given position.
- scrollHorizontally: (pixelPosition) ->
- return if @activeEditSession.getSoftWrap()
+ # Public: Given a buffer range, this adds a new selection for it.
+ #
+ # * bufferRange:
+ # A {Range} in the buffer
+ # * options:
+ # + A hash of options for {.markBufferRange}
+ #
+ # Returns the new {Selection}.
+ addSelectionForBufferRange: (bufferRange, options={}) ->
+ @markBufferRange(bufferRange, _.defaults(@getSelectionMarkerAttributes(), options))
+ @getLastSelection()
- charsInView = @scrollView.width() / @charWidth
- maxScrollMargin = Math.floor((charsInView - 1) / 2)
- scrollMargin = Math.min(@hScrollMargin, maxScrollMargin)
- margin = scrollMargin * @charWidth
- desiredRight = pixelPosition.left + @charWidth + margin
- desiredLeft = pixelPosition.left - margin
+ # Public: Given a buffer range, this removes all previous selections and
+ # creates a new selection for it.
+ #
+ # * bufferRange:
+ # A {Range} in the buffer
+ # * options:
+ # + A hash of options for {.setSelectedBufferRanges}
+ setSelectedBufferRange: (bufferRange, options) ->
+ @setSelectedBufferRanges([bufferRange], options)
- if desiredRight > @scrollRight()
- @scrollRight(desiredRight)
- else if desiredLeft < @scrollLeft()
- @scrollLeft(desiredLeft)
- @saveScrollPositionForActiveEditSession()
+ # Public: Given an array of buffer ranges, this removes all previous
+ # selections and creates new selections for them.
+ #
+ # * bufferRange:
+ # A {Range} in the buffer
+ # * options:
+ # + A hash of options for {.setSelectedBufferRanges}
+ setSelectedBufferRanges: (bufferRanges, options={}) ->
+ throw new Error("Passed an empty array to setSelectedBufferRanges") unless bufferRanges.length
- calculateDimensions: ->
- fragment = $('x
')
- @renderedLines.append(fragment)
+ selections = @getSelections()
+ selection.destroy() for selection in selections[bufferRanges.length...]
- lineRect = fragment[0].getBoundingClientRect()
- charRect = fragment.find('span')[0].getBoundingClientRect()
- @lineHeight = lineRect.height
- @charWidth = charRect.width
- @charHeight = charRect.height
- fragment.remove()
- @setHeightInLines()
+ @mergeIntersectingSelections options, =>
+ for bufferRange, i in bufferRanges
+ bufferRange = Range.fromObject(bufferRange)
+ if selections[i]
+ selections[i].setBufferRange(bufferRange, options)
+ else
+ @addSelectionForBufferRange(bufferRange, options)
- updateLayerDimensions: ->
- height = @lineHeight * @getScreenLineCount()
- unless @layerHeight == height
- @layerHeight = height
- @underlayer.height(@layerHeight)
- @renderedLines.height(@layerHeight)
- @overlayer.height(@layerHeight)
- @verticalScrollbarContent.height(@layerHeight)
- @scrollBottom(height) if @scrollBottom() > height
+ # Public: Unselects a given selection.
+ #
+ # * selection - The {Selection} to remove.
+ removeSelection: (selection) ->
+ if selection.isLocal()
+ _.remove(@selections, selection)
+ else
+ _.remove(@remoteSelections, selection)
- minWidth = Math.max(@charWidth * @getMaxScreenLineLength() + 20, @scrollView.width())
- unless @layerMinWidth == minWidth
- @renderedLines.css('min-width', minWidth)
- @underlayer.css('min-width', minWidth)
- @overlayer.css('min-width', minWidth)
- @layerMinWidth = minWidth
- @trigger 'editor:min-width-changed'
+ # Public: Clears every selection.
+ #
+ # TODO: Is this still to be done?
+ clearSelections: ->
+ @consolidateSelections()
+ @getSelection().clear()
- # Override for speed. The base function checks computedStyle, unnecessary here.
- isHidden: ->
- style = this[0].style
- if style.display == 'none' or not @isOnDom()
+ # Public:
+ #
+ # FIXME: What does this do?
+ consolidateSelections: ->
+ selections = @getSelections()
+ if selections.length > 1
+ selection.destroy() for selection in selections[0...-1]
true
else
false
- clearRenderedLines: ->
- @renderedLines.empty()
- @firstRenderedScreenRow = null
- @lastRenderedScreenRow = null
+ # Public: Returns all selections, including remote selections.
+ getAllSelections: ->
+ @getSelections().concat(@getRemoteSelections())
- resetDisplay: ->
- return unless @attached
-
- @clearRenderedLines()
- @removeAllCursorAndSelectionViews()
- editSessionScrollTop = @activeEditSession.getScrollTop() ? 0
- editSessionScrollLeft = @activeEditSession.getScrollLeft() ? 0
- @updateLayerDimensions()
- @scrollTop(editSessionScrollTop)
- @scrollLeft(editSessionScrollLeft)
- @setSoftWrap(@activeEditSession.getSoftWrap())
- @newCursors = @activeEditSession.getAllCursors()
- @newSelections = @activeEditSession.getAllSelections()
- @updateDisplay(suppressAutoScroll: true)
-
- requestDisplayUpdate: ->
- return if @pendingDisplayUpdate
- return unless @isVisible()
- @pendingDisplayUpdate = true
- setImmediate =>
- @updateDisplay()
- @pendingDisplayUpdate = false
-
- updateDisplay: (options={}) ->
- return unless @attached and @activeEditSession
- return if @activeEditSession.destroyed
- unless @isOnDom() and @isVisible()
- @redrawOnReattach = true
- return
-
- @updateRenderedLines()
- @highlightCursorLine()
- @updateCursorViews()
- @updateSelectionViews()
- @autoscroll(options)
- @trigger 'editor:display-updated'
-
- updateCursorViews: ->
- if @newCursors.length > 0
- @addCursorView(cursor) for cursor in @newCursors when not cursor.destroyed
- @syncCursorAnimations()
- @newCursors = []
-
- for cursorView in @getCursorViews()
- if cursorView.needsRemoval
- cursorView.remove()
- else if @shouldUpdateCursor(cursorView)
- cursorView.updateDisplay()
-
- shouldUpdateCursor: (cursorView) ->
- return false unless cursorView.needsUpdate
-
- pos = cursorView.getScreenPosition()
- pos.row >= @firstRenderedScreenRow and pos.row <= @lastRenderedScreenRow
-
- updateSelectionViews: ->
- if @newSelections.length > 0
- @addSelectionView(selection) for selection in @newSelections when not selection.destroyed
- @newSelections = []
-
- for selectionView in @getSelectionViews()
- if selectionView.needsRemoval
- selectionView.remove()
- else if @shouldUpdateSelection(selectionView)
- selectionView.updateDisplay()
-
- shouldUpdateSelection: (selectionView) ->
- screenRange = selectionView.getScreenRange()
- startRow = screenRange.start.row
- endRow = screenRange.end.row
- (startRow >= @firstRenderedScreenRow and startRow <= @lastRenderedScreenRow) or # startRow in range
- (endRow >= @firstRenderedScreenRow and endRow <= @lastRenderedScreenRow) or # endRow in range
- (startRow <= @firstRenderedScreenRow and endRow >= @lastRenderedScreenRow) # selection surrounds the rendered items
-
- syncCursorAnimations: ->
- for cursorView in @getCursorViews()
- do (cursorView) -> cursorView.resetBlinking()
-
- autoscroll: (options={}) ->
- for cursorView in @getCursorViews()
- if !options.suppressAutoScroll and cursorView.needsAutoscroll()
- @scrollToPixelPosition(cursorView.getPixelPosition())
- cursorView.clearAutoscroll()
-
- for selectionView in @getSelectionViews()
- if !options.suppressAutoScroll and selectionView.needsAutoscroll()
- @scrollToPixelPosition(selectionView.getCenterPixelPosition(), center: true)
- selectionView.highlight()
- selectionView.clearAutoscroll()
-
- updateRenderedLines: ->
- firstVisibleScreenRow = @getFirstVisibleScreenRow()
- lastScreenRowToRender = firstVisibleScreenRow + @heightInLines - 1
- lastScreenRow = @getLastScreenRow()
-
- if @firstRenderedScreenRow? and firstVisibleScreenRow >= @firstRenderedScreenRow and lastScreenRowToRender <= @lastRenderedScreenRow
- renderFrom = Math.min(lastScreenRow, @firstRenderedScreenRow)
- renderTo = Math.min(lastScreenRow, @lastRenderedScreenRow)
- else
- renderFrom = Math.min(lastScreenRow, Math.max(0, firstVisibleScreenRow - @lineOverdraw))
- renderTo = Math.min(lastScreenRow, lastScreenRowToRender + @lineOverdraw)
-
- if @pendingChanges.length == 0 and @firstRenderedScreenRow and @firstRenderedScreenRow <= renderFrom and renderTo <= @lastRenderedScreenRow
- return
-
- changes = @pendingChanges
- intactRanges = @computeIntactRanges(renderFrom, renderTo)
-
- @gutter.updateLineNumbers(changes, renderFrom, renderTo)
-
- @clearDirtyRanges(intactRanges)
- @fillDirtyRanges(intactRanges, renderFrom, renderTo)
- @firstRenderedScreenRow = renderFrom
- @lastRenderedScreenRow = renderTo
- @updateLayerDimensions()
- @updatePaddingOfRenderedLines()
-
- computeSurroundingEmptyLineChanges: (change) ->
- emptyLineChanges = []
-
- if change.bufferDelta?
- afterStart = change.end + change.bufferDelta + 1
- if @lineForBufferRow(afterStart) is ''
- afterEnd = afterStart
- afterEnd++ while @lineForBufferRow(afterEnd + 1) is ''
- emptyLineChanges.push({start: afterStart, end: afterEnd, screenDelta: 0})
-
- beforeEnd = change.start - 1
- if @lineForBufferRow(beforeEnd) is ''
- beforeStart = beforeEnd
- beforeStart-- while @lineForBufferRow(beforeStart - 1) is ''
- emptyLineChanges.push({start: beforeStart, end: beforeEnd, screenDelta: 0})
-
- emptyLineChanges
-
- computeIntactRanges: (renderFrom, renderTo) ->
- return [] if !@firstRenderedScreenRow? and !@lastRenderedScreenRow?
-
- intactRanges = [{start: @firstRenderedScreenRow, end: @lastRenderedScreenRow, domStart: 0}]
-
- if not @mini and @showIndentGuide
- emptyLineChanges = []
- for change in @pendingChanges
- emptyLineChanges.push(@computeSurroundingEmptyLineChanges(change)...)
- @pendingChanges.push(emptyLineChanges...)
-
- for change in @pendingChanges
- newIntactRanges = []
- for range in intactRanges
- if change.end < range.start and change.screenDelta != 0
- newIntactRanges.push(
- start: range.start + change.screenDelta
- end: range.end + change.screenDelta
- domStart: range.domStart
- )
- else if change.end < range.start or change.start > range.end
- newIntactRanges.push(range)
- else
- if change.start > range.start
- newIntactRanges.push(
- start: range.start
- end: change.start - 1
- domStart: range.domStart)
- if change.end < range.end
- newIntactRanges.push(
- start: change.end + change.screenDelta + 1
- end: range.end + change.screenDelta
- domStart: range.domStart + change.end + 1 - range.start
- )
- intactRanges = newIntactRanges
-
- @truncateIntactRanges(intactRanges, renderFrom, renderTo)
-
- @pendingChanges = []
-
- intactRanges
-
- truncateIntactRanges: (intactRanges, renderFrom, renderTo) ->
- i = 0
- while i < intactRanges.length
- range = intactRanges[i]
- if range.start < renderFrom
- range.domStart += renderFrom - range.start
- range.start = renderFrom
- if range.end > renderTo
- range.end = renderTo
- if range.start >= range.end
- intactRanges.splice(i--, 1)
- i++
- intactRanges.sort (a, b) -> a.domStart - b.domStart
-
- clearDirtyRanges: (intactRanges) ->
- if intactRanges.length == 0
- @renderedLines[0].innerHTML = ''
- else if currentLine = @renderedLines[0].firstChild
- domPosition = 0
- for intactRange in intactRanges
- while intactRange.domStart > domPosition
- currentLine = @clearLine(currentLine)
- domPosition++
- for i in [intactRange.start..intactRange.end]
- currentLine = currentLine.nextSibling
- domPosition++
- while currentLine
- currentLine = @clearLine(currentLine)
-
- clearLine: (lineElement) ->
- next = lineElement.nextSibling
- @renderedLines[0].removeChild(lineElement)
- next
-
- fillDirtyRanges: (intactRanges, renderFrom, renderTo) ->
- i = 0
- nextIntact = intactRanges[i]
- currentLine = @renderedLines[0].firstChild
-
- row = renderFrom
- while row <= renderTo
- if row == nextIntact?.end + 1
- nextIntact = intactRanges[++i]
-
- if !nextIntact or row < nextIntact.start
- if nextIntact
- dirtyRangeEnd = nextIntact.start - 1
- else
- dirtyRangeEnd = renderTo
-
- for lineElement in @buildLineElementsForScreenRows(row, dirtyRangeEnd)
- @renderedLines[0].insertBefore(lineElement, currentLine)
- row++
- else
- currentLine = currentLine.nextSibling
- row++
-
- updatePaddingOfRenderedLines: ->
- paddingTop = @firstRenderedScreenRow * @lineHeight
- @renderedLines.css('padding-top', paddingTop)
- @gutter.lineNumbers.css('padding-top', paddingTop)
-
- paddingBottom = (@getLastScreenRow() - @lastRenderedScreenRow) * @lineHeight
- @renderedLines.css('padding-bottom', paddingBottom)
- @gutter.lineNumbers.css('padding-bottom', paddingBottom)
-
- ### Public ###
-
- # Retrieves the number of the row that is visible and currently at the top of the editor.
+ # Public: Gets all local selections.
#
- # Returns a {Number}.
- getFirstVisibleScreenRow: ->
- screenRow = Math.floor(@scrollTop() / @lineHeight)
- screenRow = 0 if isNaN(screenRow)
- screenRow
+ # Returns an {Array} of {Selection}s.
+ getSelections: -> new Array(@selections...)
- # Retrieves the number of the row that is visible and currently at the bottom of the editor.
- #
- # Returns a {Number}.
- getLastVisibleScreenRow: ->
- calculatedRow = Math.ceil((@scrollTop() + @scrollView.height()) / @lineHeight) - 1
- screenRow = Math.max(0, Math.min(@getScreenLineCount() - 1, calculatedRow))
- screenRow = 0 if isNaN(screenRow)
- screenRow
+ # Public: Returns the selection at the specified index.
+ getSelection: (index) ->
+ index ?= @selections.length - 1
+ @selections[index]
- # Given a row number, identifies if it is currently visible.
+ # Public: Returns the most recently added {Selection}
+ getLastSelection: ->
+ _.last(@selections)
+
+ # Public: Returns all remote selections.
+ getRemoteSelections: -> new Array(@remoteSelections...)
+
+ # Public: Gets all local selections, ordered by their position in the buffer.
#
- # row - A row {Number} to check
+ # Returns an {Array} of {Selection}s.
+ getSelectionsOrderedByBufferPosition: ->
+ @getSelections().sort (a, b) -> a.compare(b)
+
+ # Public: Gets all remote selections, ordered by their position in the buffer.
+ #
+ # Returns an {Array} of {Selection}s.
+ getRemoteSelectionsOrderedByBufferPosition: ->
+ @getRemoteSelections().sort (a, b) -> a.compare(b)
+
+ # Public: Gets the very last local selection in the buffer.
+ #
+ # Returns a {Selection}.
+ getLastSelectionInBuffer: ->
+ _.last(@getSelectionsOrderedByBufferPosition())
+
+ # Public: Determines if a given buffer range is included in a {Selection}.
+ #
+ # * bufferRange:
+ # The {Range} you're checking against
#
# Returns a {Boolean}.
- isScreenRowVisible: (row) ->
- @getFirstVisibleScreenRow() <= row <= @getLastVisibleScreenRow()
+ selectionIntersectsBufferRange: (bufferRange) ->
+ _.any @getSelections(), (selection) ->
+ selection.intersectsBufferRange(bufferRange)
- ### Internal ###
-
- handleScreenLinesChange: (change) ->
- @pendingChanges.push(change)
- @requestDisplayUpdate()
-
- buildLineElementForScreenRow: (screenRow) ->
- @buildLineElementsForScreenRows(screenRow, screenRow)[0]
-
- buildLineElementsForScreenRows: (startRow, endRow) ->
- div = document.createElement('div')
- div.innerHTML = @htmlForScreenRows(startRow, endRow)
- new Array(div.children...)
-
- htmlForScreenRows: (startRow, endRow) ->
- htmlLines = ''
- screenRow = startRow
- for line in @activeEditSession.linesForScreenRows(startRow, endRow)
- htmlLines += @htmlForScreenLine(line, screenRow++)
- htmlLines
-
- htmlForScreenLine: (screenLine, screenRow) ->
- { tokens, text, lineEnding, fold, isSoftWrapped } = screenLine
- if fold
- attributes = { class: 'fold line', 'fold-id': fold.id }
- else
- attributes = { class: 'line' }
-
- invisibles = @invisibles if @showInvisibles
- eolInvisibles = @getEndOfLineInvisibles(screenLine)
- htmlEolInvisibles = @buildHtmlEndOfLineInvisibles(screenLine)
-
- indentation = Editor.buildIndentation(screenRow, @activeEditSession)
-
- Editor.buildLineHtml({tokens, text, lineEnding, fold, isSoftWrapped, invisibles, eolInvisibles, htmlEolInvisibles, attributes, @showIndentGuide, indentation, @activeEditSession, @mini})
-
- @buildIndentation: (screenRow, activeEditSession) ->
- bufferRow = activeEditSession.bufferPositionForScreenPosition([screenRow]).row
- bufferLine = activeEditSession.lineForBufferRow(bufferRow)
- if bufferLine is ''
- indentation = 0
- nextRow = screenRow + 1
- while nextRow < activeEditSession.getBuffer().getLineCount()
- bufferRow = activeEditSession.bufferPositionForScreenPosition([nextRow]).row
- bufferLine = activeEditSession.lineForBufferRow(bufferRow)
- if bufferLine isnt ''
- indentation = Math.ceil(activeEditSession.indentLevelForLine(bufferLine))
- break
- nextRow++
-
- previousRow = screenRow - 1
- while previousRow >= 0
- bufferRow = activeEditSession.bufferPositionForScreenPosition([previousRow]).row
- bufferLine = activeEditSession.lineForBufferRow(bufferRow)
- if bufferLine isnt ''
- indentation = Math.max(indentation, Math.ceil(activeEditSession.indentLevelForLine(bufferLine)))
- break
- previousRow--
-
- indentation
- else
- Math.ceil(activeEditSession.indentLevelForLine(bufferLine))
-
- buildHtmlEndOfLineInvisibles: (screenLine) ->
- invisibles = []
- for invisible in @getEndOfLineInvisibles(screenLine)
- invisibles.push("#{invisible}")
- invisibles.join('')
-
- getEndOfLineInvisibles: (screenLine) ->
- return [] unless @showInvisibles and @invisibles
- return [] if @mini or screenLine.isSoftWrapped()
-
- invisibles = []
- invisibles.push(@invisibles.cr) if @invisibles.cr and screenLine.lineEnding is '\r\n'
- invisibles.push(@invisibles.eol) if @invisibles.eol
- invisibles
-
- lineElementForScreenRow: (screenRow) ->
- @renderedLines.children(":eq(#{screenRow - @firstRenderedScreenRow})")
-
- toggleLineCommentsInSelection: ->
- @activeEditSession.toggleLineCommentsInSelection()
-
- ### Public ###
-
- # Converts a buffer position to a pixel position.
+ # Public: Moves every local cursor to a given screen position.
#
- # position - An object that represents a buffer position. It can be either
- # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
+ # * position:
+ # An {Array} of two numbers: the screen row, and the screen column.
+ # * options:
+ # An object with properties based on {Cursor.setScreenPosition}
+ setCursorScreenPosition: (position, options) ->
+ @moveCursors (cursor) -> cursor.setScreenPosition(position, options)
+
+ # Public: Gets the current screen position of the most recently added
+ # local {Cursor}.
#
- # Returns an object with two values: `top` and `left`, representing the pixel positions.
- pixelPositionForBufferPosition: (position) ->
- @pixelPositionForScreenPosition(@screenPositionForBufferPosition(position))
+ # Returns an {Array} of two numbers: the screen row, and the screen column.
+ getCursorScreenPosition: ->
+ @getCursor().getScreenPosition()
- # Converts a screen position to a pixel position.
+ # Public: Gets the screen row of the most recently added local {Cursor}.
#
- # position - An object that represents a screen position. It can be either
- # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
+ # Returns the screen row {Number}.
+ getCursorScreenRow: ->
+ @getCursor().getScreenRow()
+
+ # Public: Moves every cursor to a given buffer position.
#
- # Returns an object with two values: `top` and `left`, representing the pixel positions.
- pixelPositionForScreenPosition: (position) ->
- return { top: 0, left: 0 } unless @isOnDom() and @isVisible()
- {row, column} = Point.fromObject(position)
- actualRow = Math.floor(row)
+ # * position:
+ # An {Array} of two numbers: the buffer row, and the buffer column.
+ # * options:
+ # + An object with properties based on {Cursor.setBufferPosition}
+ setCursorBufferPosition: (position, options) ->
+ @moveCursors (cursor) -> cursor.setBufferPosition(position, options)
- lineElement = existingLineElement = @lineElementForScreenRow(actualRow)[0]
- unless existingLineElement
- lineElement = @buildLineElementForScreenRow(actualRow)
- @renderedLines.append(lineElement)
- left = @positionLeftForLineAndColumn(lineElement, actualRow, column)
- unless existingLineElement
- @renderedLines[0].removeChild(lineElement)
- { top: row * @lineHeight, left }
+ # Public: Gets the current buffer position of the most recently added {Cursor}.
+ #
+ # Returns an {Array} of two numbers: the buffer row, and the buffer column.
+ getCursorBufferPosition: ->
+ @getCursor().getBufferPosition()
- positionLeftForLineAndColumn: (lineElement, screenRow, column) ->
- return 0 if column == 0
+ # Public: Returns the screen {Range} of the most recently added local
+ # {Selection}.
+ getSelectedScreenRange: ->
+ @getLastSelection().getScreenRange()
- bufferRow = @bufferRowsForScreenRows(screenRow, screenRow)[0] ? screenRow
- tokenizedLine = @activeEditSession.displayBuffer.tokenizedBuffer.tokenizedLines[bufferRow]
+ # Public: Returns the buffer {Range} of the most recently added local
+ # {Selection}.
+ getSelectedBufferRange: ->
+ @getLastSelection().getBufferRange()
- left = 0
- index = 0
- for token in tokenizedLine.tokens
- for char in token.value
- return left if index >= column
+ # Public: Gets an Array of buffer {Range}s of all the local {Selection}s.
+ #
+ # Sorted by their position in the file itself.
+ getSelectedBufferRanges: ->
+ selection.getBufferRange() for selection in @getSelectionsOrderedByBufferPosition()
- val = @getCharacterWidthCache(token.scopes, char)
- if val?
- left += val
- else
- return @measureToColumn(lineElement, tokenizedLine, column)
+ # Public: Gets an Array of buffer {Range}s of all the remote {Selection}s.
+ #
+ # Sorted by their position in the file itself.
+ getRemoteSelectedBufferRanges: ->
+ selection.getBufferRange() for selection in @getRemoteSelectionsOrderedByBufferPosition()
- index++
- left
+ # Public: Returns the selected text of the most recently added local {Selection}.
+ getSelectedText: ->
+ @getLastSelection().getText()
- scopesForColumn: (tokenizedLine, column) ->
- index = 0
- for token in tokenizedLine.tokens
- for char in token.value
- return token.scopes if index == column
- index++
- null
+ # Public: Returns the text within a given a buffer {Range}
+ getTextInBufferRange: (range) ->
+ @buffer.getTextInRange(range)
- measureToColumn: (lineElement, tokenizedLine, column) ->
- left = oldLeft = index = 0
- iterator = document.createNodeIterator(lineElement, NodeFilter.SHOW_TEXT, TextNodeFilter)
+ setTextInBufferRange: (range, text) -> @getBuffer().change(range, text)
- returnLeft = null
+ # Public: Returns the text of the most recent local cursor's surrounding
+ # paragraph.
+ getCurrentParagraphBufferRange: ->
+ @getCursor().getCurrentParagraphBufferRange()
- offsetLeft = @scrollView.offset().left
- paddingLeft = parseInt(@scrollView.css('padding-left'))
+ # Public: Returns the word under the most recently added local {Cursor}.
+ #
+ # * options:
+ # + An object with properties based on
+ # {Cursor.getBeginningOfCurrentWordBufferPosition}.
+ getWordUnderCursor: (options) ->
+ @getTextInBufferRange(@getCursor().getCurrentWordBufferRange(options))
- while textNode = iterator.nextNode()
- content = textNode.textContent
+ # Public: Moves every local cursor up one row.
+ moveCursorUp: (lineCount) ->
+ @moveCursors (cursor) -> cursor.moveUp(lineCount, moveToEndOfSelection: true)
- for char, i in content
- # Don't continue caching long lines :racehorse:
- break if index > LongLineLength and column < index
+ # Public: Moves every local cursor down one row.
+ moveCursorDown: (lineCount) ->
+ @moveCursors (cursor) -> cursor.moveDown(lineCount, moveToEndOfSelection: true)
- # Dont return right away, finish caching the whole line
- returnLeft = left if index == column
- oldLeft = left
+ # Public: Moves every local cursor left one column.
+ moveCursorLeft: ->
+ @moveCursors (cursor) -> cursor.moveLeft(moveToEndOfSelection: true)
- scopes = @scopesForColumn(tokenizedLine, index)
- cachedCharWidth = @getCharacterWidthCache(scopes, char)
+ # Public: Moves every local cursor right one column.
+ moveCursorRight: ->
+ @moveCursors (cursor) -> cursor.moveRight(moveToEndOfSelection: true)
- if cachedCharWidth?
- left = oldLeft + cachedCharWidth
- else
- # i + 1 to measure to the end of the current character
- MeasureRange.setEnd(textNode, i + 1)
- MeasureRange.collapse()
- rects = MeasureRange.getClientRects()
- return 0 if rects.length == 0
- left = rects[0].left - Math.floor(offsetLeft) + Math.floor(@scrollLeft()) - paddingLeft
+ # Public: Moves every local cursor to the top of the buffer.
+ moveCursorToTop: ->
+ @moveCursors (cursor) -> cursor.moveToTop()
- if scopes?
- cachedCharWidth = left - oldLeft
- @setCharacterWidthCache(scopes, char, cachedCharWidth)
+ # Public: Moves every local cursor to the bottom of the buffer.
+ moveCursorToBottom: ->
+ @moveCursors (cursor) -> cursor.moveToBottom()
- # Assume all the characters are the same width when dealing with long
- # lines :racehorse:
- return column * cachedCharWidth if index > LongLineLength
+ # Public: Moves every local cursor to the beginning of the line.
+ moveCursorToBeginningOfLine: ->
+ @moveCursors (cursor) -> cursor.moveToBeginningOfLine()
- index++
+ # Public: Moves every local cursor to the first non-whitespace character of the line.
+ moveCursorToFirstCharacterOfLine: ->
+ @moveCursors (cursor) -> cursor.moveToFirstCharacterOfLine()
- returnLeft ? left
+ # Public: Moves every local cursor to the end of the line.
+ moveCursorToEndOfLine: ->
+ @moveCursors (cursor) -> cursor.moveToEndOfLine()
- getCharacterWidthCache: (scopes, char) ->
- scopes ?= NoScope
- obj = Editor.characterWidthCache
- for scope in scopes
- obj = obj[scope]
- return null unless obj?
- obj[char]
+ # Public: Moves every local cursor to the beginning of the current word.
+ moveCursorToBeginningOfWord: ->
+ @moveCursors (cursor) -> cursor.moveToBeginningOfWord()
- setCharacterWidthCache: (scopes, char, val) ->
- scopes ?= NoScope
- obj = Editor.characterWidthCache
- for scope in scopes
- obj[scope] ?= {}
- obj = obj[scope]
- obj[char] = val
+ # Public: Moves every local cursor to the end of the current word.
+ moveCursorToEndOfWord: ->
+ @moveCursors (cursor) -> cursor.moveToEndOfWord()
- clearCharacterWidthCache: ->
- Editor.characterWidthCache = {}
+ # Public: Moves every local cursor to the beginning of the next word.
+ moveCursorToBeginningOfNextWord: ->
+ @moveCursors (cursor) -> cursor.moveToBeginningOfNextWord()
- pixelOffsetForScreenPosition: (position) ->
- {top, left} = @pixelPositionForScreenPosition(position)
- offset = @renderedLines.offset()
- {top: top + offset.top, left: left + offset.left}
+ # Public: Moves every local cursor to the previous word boundary.
+ moveCursorToPreviousWordBoundary: ->
+ @moveCursors (cursor) -> cursor.moveToPreviousWordBoundary()
- screenPositionFromMouseEvent: (e) ->
- { pageX, pageY } = e
- offset = @scrollView.offset()
+ # Public: Moves every local cursor to the next word boundary.
+ moveCursorToNextWordBoundary: ->
+ @moveCursors (cursor) -> cursor.moveToNextWordBoundary()
- editorRelativeTop = pageY - offset.top + @scrollTop()
- row = Math.floor(editorRelativeTop / @lineHeight)
- column = 0
+ # Internal: Executes given function on all local cursors.
+ moveCursors: (fn) ->
+ fn(cursor) for cursor in @getCursors()
+ @mergeCursors()
- if pageX > offset.left and lineElement = @lineElementForScreenRow(row)[0]
- range = document.createRange()
- iterator = document.createNodeIterator(lineElement, NodeFilter.SHOW_TEXT, acceptNode: -> NodeFilter.FILTER_ACCEPT)
- while node = iterator.nextNode()
- range.selectNodeContents(node)
- column += node.textContent.length
- {left, right} = range.getClientRects()[0]
- break if left <= pageX <= right
+ # 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) ->
+ lastSelection = @getLastSelection()
+ lastSelection.selectToScreenPosition(position)
+ @mergeIntersectingSelections(isReversed: lastSelection.isReversed())
- if node
- for characterPosition in [node.textContent.length...0]
- range.setStart(node, characterPosition - 1)
- range.setEnd(node, characterPosition)
- {left, right, width} = range.getClientRects()[0]
- break if left <= pageX - width / 2 <= right
- column--
+ # Public: Selects the text one position right of all local cursors.
+ selectRight: ->
+ @expandSelectionsForward (selection) => selection.selectRight()
- range.detach()
+ # Public: Selects the text one position left of all local cursors.
+ selectLeft: ->
+ @expandSelectionsBackward (selection) => selection.selectLeft()
- new Point(row, column)
+ # Public: Selects all the text one position above all local cursors.
+ selectUp: (rowCount) ->
+ @expandSelectionsBackward (selection) => selection.selectUp(rowCount)
- # Highlights the current line the cursor is on.
- highlightCursorLine: ->
- return if @mini
+ # Public: Selects all the text one position below all local cursors.
+ selectDown: (rowCount) ->
+ @expandSelectionsForward (selection) => selection.selectDown(rowCount)
- @highlightedLine?.removeClass('cursor-line')
- if @getSelection().isEmpty()
- @highlightedLine = @lineElementForScreenRow(@getCursorScreenRow())
- @highlightedLine.addClass('cursor-line')
- else
- @highlightedLine = null
+ # Public: Selects all the text from all local cursors to the top of the
+ # buffer.
+ selectToTop: ->
+ @expandSelectionsBackward (selection) => selection.selectToTop()
- # {Delegates to: EditSession.getGrammar}
+ # Public: Selects all the text in the buffer.
+ selectAll: ->
+ @expandSelectionsForward (selection) => selection.selectAll()
+
+ # Public: Selects all the text from all local cursors to the bottom of the
+ # buffer.
+ selectToBottom: ->
+ @expandSelectionsForward (selection) => selection.selectToBottom()
+
+ # Public: Selects all the text from all local cursors to the beginning of each
+ # of their lines.
+ selectToBeginningOfLine: ->
+ @expandSelectionsBackward (selection) => selection.selectToBeginningOfLine()
+
+ # Public: Selects to the first non-whitespace character of the line of all
+ # local cursors.
+ selectToFirstCharacterOfLine: ->
+ @expandSelectionsBackward (selection) => selection.selectToFirstCharacterOfLine()
+
+ # Public: Selects all the text from each local cursor to the end of their
+ # lines.
+ selectToEndOfLine: ->
+ @expandSelectionsForward (selection) => selection.selectToEndOfLine()
+
+ # Public: Selects all text from each local cursor to their previous word
+ # boundary.
+ selectToPreviousWordBoundary: ->
+ @expandSelectionsBackward (selection) => selection.selectToPreviousWordBoundary()
+
+ # Public: Selects all text from each local cursor to their next word
+ # boundary.
+ selectToNextWordBoundary: ->
+ @expandSelectionsForward (selection) => selection.selectToNextWordBoundary()
+
+ # Public: Selects the current line from each local cursor.
+ selectLine: ->
+ @expandSelectionsForward (selection) => selection.selectLine()
+
+ # Public: Moves each local selection down one row.
+ addSelectionBelow: ->
+ @expandSelectionsForward (selection) => selection.addSelectionBelow()
+
+ # Public: Moves each local selection up one row.
+ addSelectionAbove: ->
+ @expandSelectionsBackward (selection) => selection.addSelectionAbove()
+
+ # Public: Transposes the current text selections.
+ #
+ # FIXME: I have no idea what this function does.
+ #
+ # This only works if there is more than one selection. Each selection is transferred
+ # to the position of the selection after it. The last selection is transferred to the
+ # position of the first.
+ transpose: ->
+ @mutateSelectedText (selection) =>
+ if selection.isEmpty()
+ selection.selectRight()
+ text = selection.getText()
+ selection.delete()
+ selection.cursor.moveLeft()
+ selection.insertText text
+ else
+ selection.insertText selection.getText().split('').reverse().join('')
+
+ # Public: Uppercases all locally selected text.
+ upperCase: ->
+ @replaceSelectedText selectWordIfEmpty:true, (text) => text.toUpperCase()
+
+ # Public: Lowercases all locally selected text.
+ lowerCase: ->
+ @replaceSelectedText selectWordIfEmpty:true, (text) => text.toLowerCase()
+
+ # Public: Joins the current line with the one below it.
+ #
+ # FIXME: Needs more clarity.
+ #
+ # Multiple cursors are considered equally. If there's a selection in the editor,
+ # all the lines are joined together.
+ joinLine: ->
+ @mutateSelectedText (selection) -> selection.joinLine()
+
+ # {Delegates to: Selection.expandOverLine}
+ expandLastSelectionOverLine: ->
+ @getLastSelection().expandOverLine()
+
+ # Public: Selects all the text from all local cursors to the beginning of
+ # their current words.
+ selectToBeginningOfWord: ->
+ @expandSelectionsBackward (selection) => selection.selectToBeginningOfWord()
+
+ # Public: Selects all the text from all local cursors to the end of
+ # their current words.
+ selectToEndOfWord: ->
+ @expandSelectionsForward (selection) => selection.selectToEndOfWord()
+
+ # Public: Selects all the text from all local cursors to the beginning of
+ # the next word.
+ selectToBeginningOfNextWord: ->
+ @expandSelectionsForward (selection) => selection.selectToBeginningOfNextWord()
+
+ # Public: Selects the current word of each local cursor.
+ selectWord: ->
+ @expandSelectionsForward (selection) => selection.selectWord()
+
+ # {Delegates to: Selection.expandOverWord}
+ expandLastSelectionOverWord: ->
+ @getLastSelection().expandOverWord()
+
+ # Public: Selects the range associated with the given marker if it is valid.
+ #
+ # Returns the selected {Range} or a falsy value if the marker is invalid.
+ selectMarker: (marker) ->
+ if marker.isValid()
+ range = marker.getBufferRange()
+ @setSelectedBufferRange(range)
+ range
+
+ # Public:
+ #
+ # FIXME: Not sure how to describe what this does.
+ mergeCursors: ->
+ positions = []
+ for cursor in @getCursors()
+ position = cursor.getBufferPosition().toString()
+ if position in positions
+ cursor.destroy()
+ else
+ positions.push(position)
+
+ # Public:
+ #
+ # FIXME: Not sure how to describe what this does.
+ expandSelectionsForward: (fn) ->
+ @mergeIntersectingSelections =>
+ fn(selection) for selection in @getSelections()
+
+ # Public:
+ #
+ # FIXME: Not sure how to describe what this does.
+ expandSelectionsBackward: (fn) ->
+ @mergeIntersectingSelections isReversed: true, =>
+ fn(selection) for selection in @getSelections()
+
+ # Public:
+ #
+ # FIXME: No idea what this does.
+ finalizeSelections: ->
+ selection.finalize() for selection in @getSelections()
+
+ # Private: Merges intersecting selections. If passed a function, it executes
+ # the function with merging suppressed, then merges intersecting selections
+ # afterward.
+ mergeIntersectingSelections: (args...) ->
+ fn = args.pop() if _.isFunction(_.last(args))
+ options = args.pop() ? {}
+
+ return fn?() if @suppressSelectionMerging
+
+ if fn?
+ @suppressSelectionMerging = true
+ result = fn()
+ @suppressSelectionMerging = false
+
+ reducer = (disjointSelections, selection) ->
+ intersectingSelection = _.find(disjointSelections, (s) -> s.intersectsWith(selection))
+ if intersectingSelection?
+ intersectingSelection.merge(selection, options)
+ disjointSelections
+ else
+ disjointSelections.concat([selection])
+
+ _.reduce(@getSelections(), reducer, [])
+
+ # Private:
+ preserveCursorPositionOnBufferReload: ->
+ cursorPosition = null
+ @subscribe @buffer, "will-reload", =>
+ cursorPosition = @getCursorBufferPosition()
+ @subscribe @buffer, "reloaded", =>
+ @setCursorBufferPosition(cursorPosition) if cursorPosition
+ cursorPosition = null
+
+ # {Delegates to: DisplayBuffer.getGrammar}
getGrammar: ->
- @activeEditSession.getGrammar()
+ @displayBuffer.getGrammar()
- # {Delegates to: EditSession.setGrammar}
+ # {Delegates to: DisplayBuffer.setGrammar}
setGrammar: (grammar) ->
- throw new Error("Only mini-editors can explicity set their grammar") unless @mini
- @activeEditSession.setGrammar(grammar)
+ @displayBuffer.setGrammar(grammar)
- # {Delegates to: EditSession.reloadGrammar}
+ # {Delegates to: DisplayBuffer.reloadGrammar}
reloadGrammar: ->
- @activeEditSession.reloadGrammar()
+ @displayBuffer.reloadGrammar()
- # {Delegates to: EditSession.scopesForBufferPosition}
- scopesForBufferPosition: (bufferPosition) ->
- @activeEditSession.scopesForBufferPosition(bufferPosition)
+ # Private:
+ shouldAutoIndent: ->
+ atom.config.get("editor.autoIndent")
- # Copies the current file path to the native clipboard.
- copyPathToPasteboard: ->
- path = @getPath()
- atom.pasteboard.write(path) if path?
+ # Public: Performs all editor actions from the given function within a single
+ # undo step.
+ #
+ # Useful for implementing complex operations while still ensuring that the
+ # undo stack remains relevant.
+ transact: (fn) -> @buffer.transact(fn)
- ### Internal ###
+ # Private:
+ beginTransaction: -> @buffer.beginTransaction()
- @buildLineHtml: ({tokens, text, lineEnding, fold, isSoftWrapped, invisibles, eolInvisibles, htmlEolInvisibles, attributes, showIndentGuide, indentation, activeEditSession, mini}) ->
- scopeStack = []
- line = []
+ # Private:
+ commitTransaction: -> @buffer.commitTransaction()
- attributePairs = ''
- attributePairs += " #{attributeName}=\"#{value}\"" for attributeName, value of attributes
- line.push("")
+ # Private:
+ abortTransaction: -> @buffer.abortTransaction()
- if text == ''
- html = Editor.buildEmptyLineHtml(showIndentGuide, eolInvisibles, htmlEolInvisibles, indentation, activeEditSession, mini)
- line.push(html) if html
- else
- firstNonWhitespacePosition = text.search(/\S/)
- firstTrailingWhitespacePosition = text.search(/\s*$/)
- lineIsWhitespaceOnly = firstTrailingWhitespacePosition is 0
- position = 0
- for token in tokens
- @updateScopeStack(line, scopeStack, token.scopes)
- hasLeadingWhitespace = position < firstNonWhitespacePosition
- hasTrailingWhitespace = position + token.value.length > firstTrailingWhitespacePosition
- hasIndentGuide = not mini and showIndentGuide and (hasLeadingWhitespace or lineIsWhitespaceOnly)
- line.push(token.getValueAsHtml({invisibles, hasLeadingWhitespace, hasTrailingWhitespace, hasIndentGuide}))
- position += token.value.length
+ # Private:
+ inspect: ->
+ JSON.stringify @state.toObject()
- @popScope(line, scopeStack) while scopeStack.length > 0
- line.push(htmlEolInvisibles) unless text == ''
- line.push("") if fold
+ # Private:
+ logScreenLines: (start, end) -> @displayBuffer.logLines(start, end)
- line.push('
')
- line.join('')
+ # Private:
+ handleGrammarChange: ->
+ @unfoldAll()
+ @emit 'grammar-changed'
- @updateScopeStack: (line, scopeStack, desiredScopes) ->
- excessScopes = scopeStack.length - desiredScopes.length
- if excessScopes > 0
- @popScope(line, scopeStack) while excessScopes--
+ # Private:
+ handleMarkerCreated: (marker) =>
+ if marker.matchesAttributes(@getSelectionMarkerAttributes())
+ @addSelection(marker)
- # pop until common prefix
- for i in [scopeStack.length..0]
- break if _.isEqual(scopeStack[0...i], desiredScopes[0...i])
- @popScope(line, scopeStack)
-
- # push on top of common prefix until scopeStack == desiredScopes
- for j in [i...desiredScopes.length]
- @pushScope(line, scopeStack, desiredScopes[j])
-
- null
-
- @pushScope: (line, scopeStack, scope) ->
- scopeStack.push(scope)
- line.push("")
-
- @popScope: (line, scopeStack) ->
- scopeStack.pop()
- line.push("")
-
- @buildEmptyLineHtml: (showIndentGuide, eolInvisibles, htmlEolInvisibles, indentation, activeEditSession, mini) ->
- indentCharIndex = 0
- if not mini and showIndentGuide
- if indentation > 0
- tabLength = activeEditSession.getTabLength()
- indentGuideHtml = ''
- for level in [0...indentation]
- indentLevelHtml = ""
- for characterPosition in [0...tabLength]
- if invisible = eolInvisibles[indentCharIndex++]
- indentLevelHtml += "#{invisible}"
- else
- indentLevelHtml += ' '
- indentLevelHtml += ""
- indentGuideHtml += indentLevelHtml
-
- while indentCharIndex < eolInvisibles.length
- indentGuideHtml += "#{eolInvisibles[indentCharIndex++]}"
-
- return indentGuideHtml
-
- if htmlEolInvisibles.length > 0
- htmlEolInvisibles
- else
- ' '
-
- replaceSelectedText: (replaceFn) ->
- selection = @getSelection()
- return false if selection.isEmpty()
-
- text = replaceFn(@getTextInRange(selection.getBufferRange()))
- return false if text is null or text is undefined
-
- @insertText(text, select: true)
- true
-
- consolidateSelections: (e) -> e.abortKeyBinding() unless @activeEditSession.consolidateSelections()
-
- logCursorScope: ->
- console.log @activeEditSession.getCursorScopes()
-
- transact: (fn) -> @activeEditSession.transact(fn)
- beginTransaction: -> @activeEditSession.beginTransaction()
- commitTransaction: -> @activeEditSession.commitTransaction()
- abortTransaction: -> @activeEditSession.abortTransaction()
-
- saveDebugSnapshot: ->
- atom.showSaveDialog (path) =>
- fs.writeFileSync(path, @getDebugSnapshot()) if path
+ # Private:
+ getSelectionMarkerAttributes: ->
+ type: 'selection', editorId: @id, invalidate: 'never'
+ # Private:
getDebugSnapshot: ->
[
- "Debug Snapshot: #{@getPath()}"
- @getRenderedLinesDebugSnapshot()
- @activeEditSession.getDebugSnapshot()
- @getBuffer().getDebugSnapshot()
+ @displayBuffer.getDebugSnapshot()
+ @displayBuffer.tokenizedBuffer.getDebugSnapshot()
].join('\n\n')
-
- getRenderedLinesDebugSnapshot: ->
- lines = ['Rendered Lines:']
- firstRenderedScreenRow = @firstRenderedScreenRow
- @renderedLines.find('.line').each (n) ->
- lines.push "#{firstRenderedScreenRow + n}: #{$(this).text()}"
- lines.join('\n')
-
- logScreenLines: (start, end) ->
- @activeEditSession.logScreenLines(start, end)
-
- logRenderedLines: ->
- @renderedLines.find('.line').each (n) ->
- console.log n, $(this).text()
diff --git a/src/gutter.coffee b/src/gutter.coffee
index a776bf447..710200473 100644
--- a/src/gutter.coffee
+++ b/src/gutter.coffee
@@ -2,7 +2,7 @@
{Range} = require 'telepath'
_ = require 'underscore-plus'
-# Private: Represents the portion of the {Editor} containing row numbers.
+# Private: Represents the portion of the {EditorView} containing row numbers.
#
# The gutter also indicates if rows are folded.
module.exports =
@@ -25,37 +25,37 @@ class Gutter extends View
@attached = true
highlightLines = => @highlightLines()
- @getEditor().on 'cursor:moved', highlightLines
- @getEditor().on 'selection:changed', highlightLines
+ @getEditorView().on 'cursor:moved', highlightLines
+ @getEditorView().on 'selection:changed', highlightLines
@on 'mousedown', (e) => @handleMouseEvents(e)
beforeRemove: ->
- $(document).off(".gutter-#{@getEditor().id}")
+ $(document).off(".gutter-#{@getEditorView().id}")
handleMouseEvents: (e) ->
- editor = @getEditor()
- startRow = editor.screenPositionFromMouseEvent(e).row
+ editorView = @getEditorView()
+ startRow = editorView.screenPositionFromMouseEvent(e).row
if e.shiftKey
- editor.selectToScreenPosition([startRow + 1, 0])
+ editorView.selectToScreenPosition([startRow + 1, 0])
return
else
- editor.getSelection().setScreenRange([[startRow, 0], [startRow, 0]])
+ editorView.getSelection().setScreenRange([[startRow, 0], [startRow, 0]])
moveHandler = (e) =>
start = startRow
- end = editor.screenPositionFromMouseEvent(e).row
+ end = editorView.screenPositionFromMouseEvent(e).row
if end > start then end++ else start++
- editor.getSelection().setScreenRange([[start, 0], [end, 0]])
+ editorView.getSelection().setScreenRange([[start, 0], [end, 0]])
- $(document).on "mousemove.gutter-#{@getEditor().id}", moveHandler
- $(document).one "mouseup.gutter-#{@getEditor().id}", => $(document).off 'mousemove', moveHandler
+ $(document).on "mousemove.gutter-#{@getEditorView().id}", moveHandler
+ $(document).one "mouseup.gutter-#{@getEditorView().id}", => $(document).off 'mousemove', moveHandler
### Public ###
- # Retrieves the containing {Editor}.
+ # Retrieves the containing {EditorView}.
#
- # Returns an {Editor}.
- getEditor: ->
+ # Returns an {EditorView}.
+ getEditorView: ->
@parentView
# Defines whether to show the gutter or not.
@@ -192,9 +192,9 @@ class Gutter extends View
@elementBuilder.children
buildLineElementsHtml: (startScreenRow, endScreenRow) =>
- editor = @getEditor()
- maxDigits = editor.getLineCount().toString().length
- rows = editor.bufferRowsForScreenRows(startScreenRow, endScreenRow)
+ editorView = @getEditorView()
+ maxDigits = editorView.getLineCount().toString().length
+ rows = editorView.bufferRowsForScreenRows(startScreenRow, endScreenRow)
html = ''
for row in rows
@@ -204,7 +204,7 @@ class Gutter extends View
rowValue = (row + 1).toString()
classes = "line-number line-number-#{row}"
- classes += ' fold' if editor.isFoldedAtBufferRow(row)
+ classes += ' fold' if editorView.isFoldedAtBufferRow(row)
rowValuePadding = _.multiplyString(' ', maxDigits - rowValue.length)
@@ -230,8 +230,8 @@ class Gutter extends View
@highlightedLineNumbers.push(highlightedLineNumber)
highlightLines: ->
- if @getEditor().getSelection().isEmpty()
- row = @getEditor().getCursorScreenPosition().row
+ if @getEditorView().getSelection().isEmpty()
+ row = @getEditorView().getCursorScreenPosition().row
rowRange = new Range([row, 0], [row, 0])
return if @selectionEmpty and @highlightedRows?.isEqual(rowRange)
@@ -240,7 +240,7 @@ class Gutter extends View
@highlightedRows = rowRange
@selectionEmpty = true
else
- selectedRows = @getEditor().getSelection().getScreenRange()
+ selectedRows = @getEditorView().getSelection().getScreenRange()
endRow = selectedRows.end.row
endRow-- if selectedRows.end.column is 0
selectedRows = new Range([selectedRows.start.row, 0], [endRow, 0])
diff --git a/src/language-mode.coffee b/src/language-mode.coffee
index 1947de408..28ee1dc70 100644
--- a/src/language-mode.coffee
+++ b/src/language-mode.coffee
@@ -12,7 +12,7 @@ class LanguageMode
buffer: null
grammar: null
- editSession: null
+ editor: null
currentGrammarScore: null
### Internal ###
@@ -22,11 +22,11 @@ class LanguageMode
### Public ###
- # Sets up a `LanguageMode` for the given {EditSession}.
+ # Sets up a `LanguageMode` for the given {Editor}.
#
- # editSession - The {EditSession} to associate with
- constructor: (@editSession) ->
- @buffer = @editSession.buffer
+ # editor - The {Editor} to associate with
+ constructor: (@editor) ->
+ @buffer = @editor.buffer
# Wraps the lines between two rows in comments.
#
@@ -37,7 +37,7 @@ class LanguageMode
#
# Returns an {Array} of the commented {Ranges}.
toggleLineCommentsForBufferRows: (start, end) ->
- scopes = @editSession.scopesForBufferPosition([start, 0])
+ scopes = @editor.scopesForBufferPosition([start, 0])
properties = atom.syntax.propertiesForScope(scopes, "editor.commentStart")[0]
return unless properties
@@ -46,7 +46,7 @@ class LanguageMode
return unless commentStartString
- buffer = @editSession.buffer
+ buffer = @editor.buffer
commentStartRegexString = _.escapeRegExp(commentStartString).replace(/(\s+)$/, '($1)?')
commentStartRegex = new OnigRegExp("^(\\s*)(#{commentStartRegexString})")
shouldUncomment = commentStartRegex.test(buffer.lineForRow(start))
@@ -83,8 +83,8 @@ class LanguageMode
buffer.change([[row, columnStart], [row, columnEnd]], "")
else
indent = @minIndentLevelForRowRange(start, end)
- indentString = @editSession.buildIndentString(indent)
- tabLength = @editSession.getTabLength()
+ indentString = @editor.buildIndentString(indent)
+ tabLength = @editor.getTabLength()
indentRegex = new RegExp("(\t|[ ]{#{tabLength}}){#{Math.floor(indent)}}")
for row in [start..end]
line = buffer.lineForRow(row)
@@ -98,12 +98,12 @@ class LanguageMode
for currentRow in [0..@buffer.getLastRow()]
[startRow, endRow] = @rowRangeForFoldAtBufferRow(currentRow) ? []
continue unless startRow?
- @editSession.createFold(startRow, endRow)
+ @editor.createFold(startRow, endRow)
# Unfolds all the foldable lines in the buffer.
unfoldAll: ->
for row in [@buffer.getLastRow()..0]
- fold.destroy() for fold in @editSession.displayBuffer.foldsStartingAtBufferRow(row)
+ fold.destroy() for fold in @editor.displayBuffer.foldsStartingAtBufferRow(row)
# Fold all comment and code blocks at a given indentLevel
#
@@ -114,8 +114,8 @@ class LanguageMode
continue unless startRow?
# assumption: startRow will always be the min indent level for the entire range
- if @editSession.indentationForBufferRow(startRow) == indentLevel
- @editSession.createFold(startRow, endRow)
+ if @editor.indentationForBufferRow(startRow) == indentLevel
+ @editor.createFold(startRow, endRow)
# Given a buffer row, creates a fold at it.
#
@@ -126,14 +126,14 @@ class LanguageMode
for currentRow in [bufferRow..0]
[startRow, endRow] = @rowRangeForFoldAtBufferRow(currentRow) ? []
continue unless startRow? and startRow <= bufferRow <= endRow
- fold = @editSession.displayBuffer.largestFoldStartingAtBufferRow(startRow)
- return @editSession.createFold(startRow, endRow) unless fold
+ fold = @editor.displayBuffer.largestFoldStartingAtBufferRow(startRow)
+ return @editor.createFold(startRow, endRow) unless fold
# Given a buffer row, this unfolds it.
#
# bufferRow - A {Number} indicating the buffer row
unfoldBufferRow: (bufferRow) ->
- @editSession.displayBuffer.largestFoldContainingBufferRow(bufferRow)?.destroy()
+ @editor.displayBuffer.largestFoldContainingBufferRow(bufferRow)?.destroy()
# Find the row range for a fold at a given bufferRow. Will handle comments
# and code.
@@ -147,30 +147,30 @@ class LanguageMode
rowRange
rowRangeForCommentAtBufferRow: (bufferRow) ->
- return unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(bufferRow).isComment()
+ return unless @editor.displayBuffer.tokenizedBuffer.lineForScreenRow(bufferRow).isComment()
startRow = bufferRow
for currentRow in [bufferRow-1..0]
break if @buffer.isRowBlank(currentRow)
- break unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment()
+ break unless @editor.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment()
startRow = currentRow
endRow = bufferRow
for currentRow in [bufferRow+1..@buffer.getLastRow()]
break if @buffer.isRowBlank(currentRow)
- break unless @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment()
+ break unless @editor.displayBuffer.tokenizedBuffer.lineForScreenRow(currentRow).isComment()
endRow = currentRow
return [startRow, endRow] if startRow isnt endRow
rowRangeForCodeFoldAtBufferRow: (bufferRow) ->
return null unless @doesBufferRowStartFold(bufferRow)
- startIndentLevel = @editSession.indentationForBufferRow(bufferRow)
- scopes = @editSession.scopesForBufferPosition([bufferRow, 0])
- for row in [(bufferRow + 1)..@editSession.getLastBufferRow()]
- continue if @editSession.isBufferRowBlank(row)
- indentation = @editSession.indentationForBufferRow(row)
+ startIndentLevel = @editor.indentationForBufferRow(bufferRow)
+ scopes = @editor.scopesForBufferPosition([bufferRow, 0])
+ for row in [(bufferRow + 1)..@editor.getLastBufferRow()]
+ continue if @editor.isBufferRowBlank(row)
+ indentation = @editor.indentationForBufferRow(row)
if indentation <= startIndentLevel
- includeRowInFold = indentation == startIndentLevel and @foldEndRegexForScopes(scopes)?.search(@editSession.lineForBufferRow(row))
+ includeRowInFold = indentation == startIndentLevel and @foldEndRegexForScopes(scopes)?.search(@editor.lineForBufferRow(row))
foldEndRow = row if includeRowInFold
break
@@ -179,19 +179,19 @@ class LanguageMode
[bufferRow, foldEndRow]
doesBufferRowStartFold: (bufferRow) ->
- return false if @editSession.isBufferRowBlank(bufferRow)
- nextNonEmptyRow = @editSession.nextNonBlankBufferRow(bufferRow)
+ return false if @editor.isBufferRowBlank(bufferRow)
+ nextNonEmptyRow = @editor.nextNonBlankBufferRow(bufferRow)
return false unless nextNonEmptyRow?
- @editSession.indentationForBufferRow(nextNonEmptyRow) > @editSession.indentationForBufferRow(bufferRow)
+ @editor.indentationForBufferRow(nextNonEmptyRow) > @editor.indentationForBufferRow(bufferRow)
# Find a row range for a 'paragraph' around specified bufferRow.
# Right now, a paragraph is a block of text bounded by and empty line or a
# block of text that is not the same type (comments next to source code).
rowRangeForParagraphAtBufferRow: (bufferRow) ->
- return unless /\w/.test(@editSession.lineForBufferRow(bufferRow))
+ return unless /\w/.test(@editor.lineForBufferRow(bufferRow))
isRowComment = (row) =>
- @editSession.displayBuffer.tokenizedBuffer.lineForScreenRow(row).isComment()
+ @editor.displayBuffer.tokenizedBuffer.lineForScreenRow(row).isComment()
if isRowComment(bufferRow)
isOriginalRowComment = true
@@ -199,22 +199,22 @@ class LanguageMode
[firstRow, lastRow] = range or [bufferRow, bufferRow]
else
isOriginalRowComment = false
- [firstRow, lastRow] = [0, @editSession.getLastBufferRow()-1]
+ [firstRow, lastRow] = [0, @editor.getLastBufferRow()-1]
startRow = bufferRow
while startRow > firstRow
break if isRowComment(startRow - 1) != isOriginalRowComment
- break unless /\w/.test(@editSession.lineForBufferRow(startRow - 1))
+ break unless /\w/.test(@editor.lineForBufferRow(startRow - 1))
startRow--
endRow = bufferRow
- lastRow = @editSession.getLastBufferRow()
+ lastRow = @editor.getLastBufferRow()
while endRow < lastRow
break if isRowComment(endRow + 1) != isOriginalRowComment
- break unless /\w/.test(@editSession.lineForBufferRow(endRow + 1))
+ break unless /\w/.test(@editor.lineForBufferRow(endRow + 1))
endRow++
- new Range([startRow, 0], [endRow, @editSession.lineLengthForBufferRow(endRow)])
+ new Range([startRow, 0], [endRow, @editor.lineLengthForBufferRow(endRow)])
# Given a buffer row, this returns a suggested indentation level.
#
@@ -224,8 +224,8 @@ class LanguageMode
#
# Returns a {Number}.
suggestedIndentForBufferRow: (bufferRow) ->
- currentIndentLevel = @editSession.indentationForBufferRow(bufferRow)
- scopes = @editSession.scopesForBufferPosition([bufferRow, 0])
+ currentIndentLevel = @editor.indentationForBufferRow(bufferRow)
+ scopes = @editor.scopesForBufferPosition([bufferRow, 0])
return currentIndentLevel unless increaseIndentRegex = @increaseIndentRegexForScopes(scopes)
currentLine = @buffer.lineForRow(bufferRow)
@@ -233,8 +233,8 @@ class LanguageMode
return currentIndentLevel unless precedingRow?
precedingLine = @buffer.lineForRow(precedingRow)
- desiredIndentLevel = @editSession.indentationForBufferRow(precedingRow)
- desiredIndentLevel += 1 if increaseIndentRegex.test(precedingLine) and not @editSession.isBufferRowCommented(precedingRow)
+ desiredIndentLevel = @editor.indentationForBufferRow(precedingRow)
+ desiredIndentLevel += 1 if increaseIndentRegex.test(precedingLine) and not @editor.isBufferRowCommented(precedingRow)
return desiredIndentLevel unless decreaseIndentRegex = @decreaseIndentRegexForScopes(scopes)
desiredIndentLevel -= 1 if decreaseIndentRegex.test(currentLine)
@@ -248,7 +248,7 @@ class LanguageMode
#
# Returns a {Number} of the indent level of the block of lines.
minIndentLevelForRowRange: (startRow, endRow) ->
- indents = (@editSession.indentationForBufferRow(row) for row in [startRow..endRow] when not @editSession.isBufferRowBlank(row))
+ indents = (@editor.indentationForBufferRow(row) for row in [startRow..endRow] when not @editor.isBufferRowBlank(row))
indents = [0] unless indents.length
Math.min(indents...)
@@ -264,13 +264,13 @@ class LanguageMode
# bufferRow - The row {Number}
autoIndentBufferRow: (bufferRow) ->
indentLevel = @suggestedIndentForBufferRow(bufferRow)
- @editSession.setIndentationForBufferRow(bufferRow, indentLevel)
+ @editor.setIndentationForBufferRow(bufferRow, indentLevel)
# Given a buffer row, this decreases the indentation.
#
# bufferRow - The row {Number}
autoDecreaseIndentForBufferRow: (bufferRow) ->
- scopes = @editSession.scopesForBufferPosition([bufferRow, 0])
+ scopes = @editor.scopesForBufferPosition([bufferRow, 0])
increaseIndentRegex = @increaseIndentRegexForScopes(scopes)
decreaseIndentRegex = @decreaseIndentRegexForScopes(scopes)
return unless increaseIndentRegex and decreaseIndentRegex
@@ -278,16 +278,16 @@ class LanguageMode
line = @buffer.lineForRow(bufferRow)
return unless decreaseIndentRegex.test(line)
- currentIndentLevel = @editSession.indentationForBufferRow(bufferRow)
+ currentIndentLevel = @editor.indentationForBufferRow(bufferRow)
return if currentIndentLevel is 0
precedingRow = @buffer.previousNonBlankRow(bufferRow)
return unless precedingRow?
precedingLine = @buffer.lineForRow(precedingRow)
- desiredIndentLevel = @editSession.indentationForBufferRow(precedingRow)
+ desiredIndentLevel = @editor.indentationForBufferRow(precedingRow)
desiredIndentLevel -= 1 unless increaseIndentRegex.test(precedingLine)
if desiredIndentLevel >= 0 and desiredIndentLevel < currentIndentLevel
- @editSession.setIndentationForBufferRow(bufferRow, desiredIndentLevel)
+ @editor.setIndentationForBufferRow(bufferRow, desiredIndentLevel)
tokenizeLine: (line, stack, firstLine) ->
{tokens, stack} = @grammar.tokenizeLine(line, stack, firstLine)
diff --git a/src/pane.coffee b/src/pane.coffee
index 514e37e93..a33c7388b 100644
--- a/src/pane.coffee
+++ b/src/pane.coffee
@@ -7,7 +7,7 @@ PaneColumn = require './pane-column'
# Public: A container which can contains multiple items to be switched between.
#
-# Items can be almost anything however most commonly they're {Editor}s.
+# Items can be almost anything however most commonly they're {EditorView}s.
#
# Most packages won't need to use this class, unless you're interested in
# building a package that deals with switching between panes or tiems.
diff --git a/src/project.coffee b/src/project.coffee
index 4ad5065ae..9b4d477a5 100644
--- a/src/project.coffee
+++ b/src/project.coffee
@@ -7,7 +7,7 @@ Q = require 'q'
telepath = require 'telepath'
TextBuffer = require './text-buffer'
-EditSession = require './edit-session'
+Editor = require './editor'
{Emitter} = require 'emissary'
Directory = require './directory'
Task = require './task'
@@ -37,7 +37,7 @@ class Project extends telepath.Model
buffer.once 'destroyed', => @removeBuffer(buffer)
@openers = []
- @editSessions = []
+ @editors = []
@setPath(@path)
# Private: Called by telepath.
@@ -52,7 +52,7 @@ class Project extends telepath.Model
# Private:
destroy: ->
- editSession.destroy() for editSession in @getEditSessions()
+ editor.destroy() for editor in @getEditSessions()
buffer.release() for buffer in @getBuffers()
@destroyRepo()
@@ -133,14 +133,14 @@ class Project extends telepath.Model
@rootDirectory?.contains(pathToCheck) ? false
# Public: Given a path to a file, this constructs and associates a new
- # {EditSession}, showing the file.
+ # {Editor}, showing the file.
#
# * filePath:
# The {String} path of the file to associate with
- # * editSessionOptions:
- # Options that you can pass to the {EditSession} constructor
+ # * options:
+ # Options that you can pass to the {Editor} constructor
#
- # Returns a promise that resolves to an {EditSession}.
+ # Returns a promise that resolves to an {Editor}.
open: (filePath, options={}) ->
filePath = @resolve(filePath)
resource = null
@@ -160,20 +160,20 @@ class Project extends telepath.Model
@buildEditSessionForBuffer(@bufferForPathSync(filePath), options)
- # Public: Retrieves all {EditSession}s for all open files.
+ # Public: Retrieves all {Editor}s for all open files.
#
- # Returns an {Array} of {EditSession}s.
+ # Returns an {Array} of {Editor}s.
getEditSessions: ->
- new Array(@editSessions...)
+ new Array(@editors...)
- # Public: Add the given {EditSession}.
- addEditSession: (editSession) ->
- @editSessions.push editSession
- @emit 'edit-session-created', editSession
+ # Public: Add the given {Editor}.
+ addEditSession: (editor) ->
+ @editors.push editor
+ @emit 'editor-created', editor
- # Public: Return and removes the given {EditSession}.
- removeEditSession: (editSession) ->
- _.remove(@editSessions, editSession)
+ # Public: Return and removes the given {Editor}.
+ removeEditSession: (editor) ->
+ _.remove(@editors, editor)
# Private: Retrieves all the {TextBuffer}s in the project; that is, the
# buffers for all open files.
@@ -331,15 +331,15 @@ class Project extends telepath.Model
deferred.promise
# Private:
- buildEditSessionForBuffer: (buffer, editSessionOptions) ->
- editSession = new EditSession(_.extend({buffer}, editSessionOptions))
- @addEditSession(editSession)
- editSession
+ buildEditSessionForBuffer: (buffer, editorOptions) ->
+ editor = new Editor(_.extend({buffer}, editorOptions))
+ @addEditSession(editor)
+ editor
# Private:
eachEditSession: (callback) ->
- callback(editSession) for editSession in @getEditSessions()
- @on 'edit-session-created', (editSession) -> callback(editSession)
+ callback(editor) for editor in @getEditSessions()
+ @on 'editor-created', (editor) -> callback(editor)
# Private:
eachBuffer: (args...) ->
diff --git a/src/root-view.coffee b/src/root-view.coffee
index d1d071272..fd8e02417 100644
--- a/src/root-view.coffee
+++ b/src/root-view.coffee
@@ -5,12 +5,12 @@ Q = require 'q'
_ = require 'underscore-plus'
fs = require 'fs-plus'
telepath = require 'telepath'
-Editor = require './editor'
+EditorView = require './editor-view'
Pane = require './pane'
PaneColumn = require './pane-column'
PaneRow = require './pane-row'
PaneContainer = require './pane-container'
-EditSession = require './edit-session'
+Editor = require './editor'
# Public: The container for the entire Atom application.
#
@@ -38,7 +38,7 @@ EditSession = require './edit-session'
#
module.exports =
class RootView extends View
- registerDeserializers(this, Pane, PaneRow, PaneColumn, Editor)
+ registerDeserializers(this, Pane, PaneRow, PaneColumn, EditorView)
@version: 1
@@ -169,26 +169,26 @@ class RootView extends View
# * options
# + initialLine: The buffer line number to open to.
#
- # Returns a promise that resolves to the {EditSession} for the file URI.
+ # Returns a promise that resolves to the {Editor} for the file URI.
open: (filePath, options={}) ->
changeFocus = options.changeFocus ? true
filePath = project.resolve(filePath)
initialLine = options.initialLine
activePane = @getActivePane()
- editSession = activePane.itemForUri(project.relativize(filePath)) if activePane and filePath
- promise = project.open(filePath, {initialLine}) if not editSession
+ editor = activePane.itemForUri(project.relativize(filePath)) if activePane and filePath
+ promise = project.open(filePath, {initialLine}) if not editor
- Q(editSession ? promise)
- .then (editSession) =>
+ Q(editor ? promise)
+ .then (editor) =>
if not activePane
- activePane = new Pane(editSession)
+ activePane = new Pane(editor)
@panes.setRoot(activePane)
- activePane.showItem(editSession)
+ activePane.showItem(editor)
activePane.focus() if changeFocus
@trigger "uri-opened"
- editSession
+ editor
.catch (error) ->
console.error(error.stack ? error)
@@ -249,7 +249,7 @@ class RootView extends View
setTitle: (title) ->
document.title = title
- # Private: Returns an Array of all of the application's {Editor}s.
+ # Private: Returns an Array of all of the application's {EditorView}s.
getEditors: ->
@panes.find('.pane > .item-views > .editor').map(-> $(this).view()).toArray()
@@ -259,7 +259,7 @@ class RootView extends View
getModifiedBuffers: ->
modifiedBuffers = []
for pane in @getPanes()
- for item in pane.getItems() when item instanceof EditSession
+ for item in pane.getItems() when item instanceof Editor
modifiedBuffers.push item.buffer if item.buffer.isModified()
modifiedBuffers
@@ -267,7 +267,7 @@ class RootView extends View
#
# Returns an {Array} of {String}s.
getOpenBufferPaths: ->
- _.uniq(_.flatten(@getEditors().map (editor) -> editor.getOpenBufferPaths()))
+ _.uniq(_.flatten(@getEditors().map (editorView) -> editorView.getOpenBufferPaths()))
# Public: Returns the currently focused {Pane}.
getActivePane: ->
@@ -308,14 +308,14 @@ class RootView extends View
indexOfPane: (pane) ->
@panes.indexOfPane(pane)
- # Private: Fires a callback on each open {Editor}.
+ # Private: Fires a callback on each open {EditorView}.
eachEditor: (callback) ->
callback(editor) for editor in @getEditors()
attachedCallback = (e, editor) -> callback(editor)
@on('editor:attached', attachedCallback)
off: => @off('editor:attached', attachedCallback)
- # Public: Fires a callback on each open {EditSession}.
+ # Public: Fires a callback on each open {Editor}.
eachEditSession: (callback) ->
project.eachEditSession(callback)
@@ -325,6 +325,6 @@ class RootView extends View
# Private: Destroys everything.
remove: ->
- editor.remove() for editor in @getEditors()
+ editorView.remove() for editorView in @getEditors()
project?.destroy()
super
diff --git a/src/select-list.coffee b/src/select-list.coffee
index 78a305945..3c858758d 100644
--- a/src/select-list.coffee
+++ b/src/select-list.coffee
@@ -1,5 +1,5 @@
{$, View} = require './space-pen-extensions'
-Editor = require './editor'
+EditorView = require './editor-view'
fuzzyFilter = require('fuzzaldrin').filter
# Public: Provides a widget for users to make a selection from a list of
@@ -10,7 +10,7 @@ class SelectList extends View
# Private:
@content: ->
@div class: @viewClass(), =>
- @subview 'miniEditor', new Editor(mini: true)
+ @subview 'miniEditor', new EditorView(mini: true)
@div class: 'error-message', outlet: 'error'
@div class: 'loading', outlet: 'loadingArea', =>
@span class: 'loading-message', outlet: 'loading'
diff --git a/src/selection-view.coffee b/src/selection-view.coffee
index e01ea384d..6dc301bab 100644
--- a/src/selection-view.coffee
+++ b/src/selection-view.coffee
@@ -11,12 +11,12 @@ class SelectionView extends View
regions: null
needsRemoval: false
- initialize: ({@editor, @selection} = {}) ->
+ initialize: ({@editorView, @selection} = {}) ->
@regions = []
- @selection.on 'screen-range-changed', => @editor.requestDisplayUpdate()
+ @selection.on 'screen-range-changed', => @editorView.requestDisplayUpdate()
@selection.on 'destroyed', =>
@needsRemoval = true
- @editor.requestDisplayUpdate()
+ @editorView.requestDisplayUpdate()
if @selection.marker.isRemote()
@addClass("site-#{@selection.marker.getOriginSiteId()}")
@@ -26,7 +26,7 @@ class SelectionView extends View
range = @getScreenRange()
@trigger 'selection:changed'
- @editor.highlightFoldsContainingBufferRange(@getBufferRange())
+ @editorView.highlightFoldsContainingBufferRange(@getBufferRange())
return if range.isEmpty()
rowSpan = range.end.row - range.start.row
@@ -40,11 +40,11 @@ class SelectionView extends View
@appendRegion(1, { row: range.end.row, column: 0 }, range.end)
appendRegion: (rows, start, end) ->
- { lineHeight, charWidth } = @editor
- css = @editor.pixelPositionForScreenPosition(start)
+ { lineHeight, charWidth } = @editorView
+ css = @editorView.pixelPositionForScreenPosition(start)
css.height = lineHeight * rows
if end
- css.width = @editor.pixelPositionForScreenPosition(end).left - css.left
+ css.width = @editorView.pixelPositionForScreenPosition(end).left - css.left
else
css.right = 0
@@ -57,7 +57,7 @@ class SelectionView extends View
startRow = start.row
endRow = end.row
endRow-- if end.column == 0
- @editor.pixelPositionForScreenPosition([((startRow + endRow + 1) / 2), start.column])
+ @editorView.pixelPositionForScreenPosition([((startRow + endRow + 1) / 2), start.column])
clearRegions: ->
region.remove() for region in @regions
@@ -85,5 +85,5 @@ class SelectionView extends View
@removeClass('highlighted')
remove: ->
- @editor.removeSelectionView(this)
+ @editorView.removeSelectionView(this)
super
diff --git a/src/selection.coffee b/src/selection.coffee
index f0a0dc623..99c790994 100644
--- a/src/selection.coffee
+++ b/src/selection.coffee
@@ -2,27 +2,27 @@
{Emitter} = require 'emissary'
{pick} = require 'underscore-plus'
-# Public: Represents a selection in the {EditSession}.
+# Public: Represents a selection in the {Editor}.
module.exports =
class Selection
Emitter.includeInto(this)
cursor: null
marker: null
- editSession: null
+ editor: null
initialScreenRange: null
wordwise: false
needsAutoscroll: null
# Private:
- constructor: ({@cursor, @marker, @editSession}) ->
+ constructor: ({@cursor, @marker, @editor}) ->
@cursor.selection = this
@marker.on 'changed', => @screenRangeChanged()
@marker.on 'destroyed', =>
@destroyed = true
- @editSession.removeSelection(this)
- @emit 'destroyed' unless @editSession.destroyed
+ @editor.removeSelection(this)
+ @emit 'destroyed' unless @editor.destroyed
# Private:
destroy: ->
@@ -65,7 +65,7 @@ class Selection
# * options:
# + A hash of options matching those found in {.setBufferRange}
setScreenRange: (screenRange, options) ->
- @setBufferRange(@editSession.bufferRangeForScreenRange(screenRange), options)
+ @setBufferRange(@editor.bufferRangeForScreenRange(screenRange), options)
# Public: Returns the buffer {Range} for the selection.
getBufferRange: ->
@@ -79,12 +79,12 @@ class Selection
# + preserveFolds:
# if `true`, the fold settings are preserved after the selection moves
# + autoscroll:
- # if `true`, the {EditSession} scrolls to the new selection
+ # if `true`, the {Editor} scrolls to the new selection
setBufferRange: (bufferRange, options={}) ->
bufferRange = Range.fromObject(bufferRange)
@needsAutoscroll = options.autoscroll
options.isReversed ?= @isReversed()
- @editSession.destroyFoldsIntersectingBufferRange(bufferRange) unless options.preserveFolds
+ @editor.destroyFoldsIntersectingBufferRange(bufferRange) unless options.preserveFolds
@modifySelection =>
@cursor.needsAutoscroll = false if options.autoscroll?
@marker.setBufferRange(bufferRange, options)
@@ -102,7 +102,7 @@ class Selection
# Public: Returns the text in the selection.
getText: ->
- @editSession.buffer.getTextInRange(@getBufferRange())
+ @editor.buffer.getTextInRange(@getBufferRange())
# Public: Clears the selection, moving the marker to the head.
clear: ->
@@ -132,7 +132,7 @@ class Selection
# * row:
# The line Number to select (default: the row of the cursor)
selectLine: (row=@cursor.getBufferPosition().row) ->
- range = @editSession.bufferRangeForBufferRow(row, includeNewline: true)
+ range = @editor.bufferRangeForBufferRow(row, includeNewline: true)
@setBufferRange(range)
@linewise = true
@wordwise = false
@@ -202,7 +202,7 @@ class Selection
# Public: Selects all the text in the buffer.
selectAll: ->
- @setBufferRange(@editSession.buffer.getRange(), autoscroll: false)
+ @setBufferRange(@editor.buffer.getRange(), autoscroll: false)
# Public: Selects all the text from the current cursor position to the
# beginning of the line.
@@ -247,17 +247,17 @@ class Selection
range = (@getGoalBufferRange() ? @getBufferRange()).copy()
nextRow = range.end.row + 1
- for row in [nextRow..@editSession.getLastBufferRow()]
+ for row in [nextRow..@editor.getLastBufferRow()]
range.start.row = row
range.end.row = row
- clippedRange = @editSession.clipBufferRange(range)
+ clippedRange = @editor.clipBufferRange(range)
if range.isEmpty()
continue if range.end.column > 0 and clippedRange.end.column is 0
else
continue if clippedRange.isEmpty()
- @editSession.addSelectionForBufferRange(range, goalBufferRange: range)
+ @editor.addSelectionForBufferRange(range, goalBufferRange: range)
break
# Public:
@@ -274,14 +274,14 @@ class Selection
for row in [previousRow..0]
range.start.row = row
range.end.row = row
- clippedRange = @editSession.clipBufferRange(range)
+ clippedRange = @editor.clipBufferRange(range)
if range.isEmpty()
continue if range.end.column > 0 and clippedRange.end.column is 0
else
continue if clippedRange.isEmpty()
- @editSession.addSelectionForBufferRange(range, goalBufferRange: range)
+ @editor.addSelectionForBufferRange(range, goalBufferRange: range)
break
# Public: Replaces text at the current selection.
@@ -302,7 +302,7 @@ class Selection
# if `skip`, skips the undo stack for this operation.
insertText: (text, options={}) ->
oldBufferRange = @getBufferRange()
- @editSession.destroyFoldsContainingBufferRow(oldBufferRange.end.row)
+ @editor.destroyFoldsContainingBufferRow(oldBufferRange.end.row)
wasReversed = @isReversed()
@clear()
@cursor.needsAutoscroll = @cursor.isLastCursor()
@@ -310,18 +310,18 @@ class Selection
if options.indentBasis? and not options.autoIndent
text = @normalizeIndents(text, options.indentBasis)
- newBufferRange = @editSession.buffer.change(oldBufferRange, text, pick(options, 'undo'))
+ newBufferRange = @editor.buffer.change(oldBufferRange, text, pick(options, 'undo'))
if options.select
@setBufferRange(newBufferRange, isReversed: wasReversed)
else
@cursor.setBufferPosition(newBufferRange.end, skipAtomicTokens: true) if wasReversed
if options.autoIndent
- @editSession.autoIndentBufferRow(row) for row in newBufferRange.getRows()
+ @editor.autoIndentBufferRow(row) for row in newBufferRange.getRows()
else if options.autoIndentNewline and text == '\n'
- @editSession.autoIndentBufferRow(newBufferRange.end.row)
+ @editor.autoIndentBufferRow(newBufferRange.end.row)
else if options.autoDecreaseIndent and /\S/.test text
- @editSession.autoDecreaseIndentForBufferRow(newBufferRange.start.row)
+ @editor.autoDecreaseIndentForBufferRow(newBufferRange.start.row)
newBufferRange
@@ -336,9 +336,9 @@ class Selection
isCursorInsideExistingLine = /\S/.test(textPrecedingCursor)
lines = text.split('\n')
- firstLineIndentLevel = @editSession.indentLevelForLine(lines[0])
+ firstLineIndentLevel = @editor.indentLevelForLine(lines[0])
if isCursorInsideExistingLine
- minimumIndentLevel = @editSession.indentationForBufferRow(@cursor.getBufferRow())
+ minimumIndentLevel = @editor.indentationForBufferRow(@cursor.getBufferRow())
else
minimumIndentLevel = @cursor.getIndentLevel()
@@ -349,7 +349,7 @@ class Selection
else if line == '' # remove all indentation from empty lines
indentLevel = 0
else
- lineIndentLevel = @editSession.indentLevelForLine(lines[i])
+ lineIndentLevel = @editor.indentLevelForLine(lines[i])
indentLevel = minimumIndentLevel + (lineIndentLevel - indentBasis)
normalizedLines.push(@setIndentationForLine(line, indentLevel))
@@ -361,19 +361,19 @@ class Selection
# * options - A hash with one key,
# + autoIndent:
# If `true`, the indentation is performed appropriately. Otherwise,
- # {EditSession.getTabText} is used
+ # {Editor.getTabText} is used
indent: ({ autoIndent }={})->
{ row, column } = @cursor.getBufferPosition()
if @isEmpty()
@cursor.skipLeadingWhitespace()
- desiredIndent = @editSession.suggestedIndentForBufferRow(row)
+ desiredIndent = @editor.suggestedIndentForBufferRow(row)
delta = desiredIndent - @cursor.getIndentLevel()
if autoIndent and delta > 0
- @insertText(@editSession.buildIndentString(delta))
+ @insertText(@editor.buildIndentString(delta))
else
- @insertText(@editSession.getTabText())
+ @insertText(@editor.getTabText())
else
@indentSelectedRows()
@@ -381,18 +381,18 @@ class Selection
indentSelectedRows: ->
[start, end] = @getBufferRowRange()
for row in [start..end]
- @editSession.buffer.insert([row, 0], @editSession.getTabText()) unless @editSession.buffer.lineLengthForRow(row) == 0
+ @editor.buffer.insert([row, 0], @editor.getTabText()) unless @editor.buffer.lineLengthForRow(row) == 0
# Public: ?
setIndentationForLine: (line, indentLevel) ->
desiredIndentLevel = Math.max(0, indentLevel)
- desiredIndentString = @editSession.buildIndentString(desiredIndentLevel)
+ desiredIndentString = @editor.buildIndentString(desiredIndentLevel)
line.replace(/^[\t ]*/, desiredIndentString)
# Public: Removes the first character before the selection if the selection
# is empty otherwise it deletes the selection.
backspace: ->
- @selectLeft() if @isEmpty() and not @editSession.isFoldedAtScreenRow(@cursor.getScreenRow())
+ @selectLeft() if @isEmpty() and not @editor.isFoldedAtScreenRow(@cursor.getScreenRow())
@deleteSelectedText()
# Public: Removes from the start of the selection to the beginning of the
@@ -414,7 +414,7 @@ class Selection
# selection if the selection is empty.
delete: ->
if @isEmpty()
- if @cursor.isAtEndOfLine() and fold = @editSession.largestFoldStartingAtScreenRow(@cursor.getScreenRow() + 1)
+ if @cursor.isAtEndOfLine() and fold = @editor.largestFoldStartingAtScreenRow(@cursor.getScreenRow() + 1)
@selectToBufferPosition(fold.getBufferRange().end)
else
@selectRight()
@@ -429,9 +429,9 @@ class Selection
# Public: Removes only the selected text.
deleteSelectedText: ->
bufferRange = @getBufferRange()
- if bufferRange.isEmpty() and fold = @editSession.largestFoldContainingBufferRow(bufferRange.start.row)
+ if bufferRange.isEmpty() and fold = @editor.largestFoldContainingBufferRow(bufferRange.start.row)
bufferRange = bufferRange.union(fold.getBufferRange(includeNewline: true))
- @editSession.buffer.delete(bufferRange) unless bufferRange.isEmpty()
+ @editor.buffer.delete(bufferRange) unless bufferRange.isEmpty()
@cursor?.setBufferPosition(bufferRange.start)
# Public: Removes the line at the beginning of the selection if the selection
@@ -440,18 +440,18 @@ class Selection
deleteLine: ->
if @isEmpty()
start = @cursor.getScreenRow()
- range = @editSession.bufferRowsForScreenRows(start, start + 1)
+ range = @editor.bufferRowsForScreenRows(start, start + 1)
if range[1] > range[0]
- @editSession.buffer.deleteRows(range[0], range[1] - 1)
+ @editor.buffer.deleteRows(range[0], range[1] - 1)
else
- @editSession.buffer.deleteRow(range[0])
+ @editor.buffer.deleteRow(range[0])
else
range = @getBufferRange()
start = range.start.row
end = range.end.row
- if end isnt @editSession.buffer.getLastRow() and range.end.column is 0
+ if end isnt @editor.buffer.getLastRow() and range.end.column is 0
end--
- @editSession.buffer.deleteRows(start, end)
+ @editor.buffer.deleteRows(start, end)
# Public: Joins the current line with the one below it.
#
@@ -459,16 +459,16 @@ class Selection
joinLine: ->
selectedRange = @getBufferRange()
if selectedRange.isEmpty()
- return if selectedRange.start.row is @editSession.buffer.getLastRow()
+ return if selectedRange.start.row is @editor.buffer.getLastRow()
else
- joinMarker = @editSession.markBufferRange(selectedRange, invalidationStrategy: 'never')
+ joinMarker = @editor.markBufferRange(selectedRange, invalidationStrategy: 'never')
rowCount = Math.max(1, selectedRange.getRowCount() - 1)
for row in [0...rowCount]
@cursor.setBufferPosition([selectedRange.start.row])
@cursor.moveToEndOfLine()
nextRow = selectedRange.start.row + 1
- if nextRow <= @editSession.buffer.getLastRow() and @editSession.buffer.lineLengthForRow(nextRow) > 0
+ if nextRow <= @editor.buffer.getLastRow() and @editor.buffer.lineLengthForRow(nextRow) > 0
@insertText(' ')
@cursor.moveToEndOfLine()
@modifySelection =>
@@ -484,8 +484,8 @@ class Selection
# Public: Removes one level of indent from the currently selected rows.
outdentSelectedRows: ->
[start, end] = @getBufferRowRange()
- buffer = @editSession.buffer
- leadingTabRegex = new RegExp("^ {1,#{@editSession.getTabLength()}}|\t")
+ buffer = @editor.buffer
+ leadingTabRegex = new RegExp("^ {1,#{@editor.getTabLength()}}|\t")
for row in [start..end]
if matchLength = buffer.lineForRow(row).match(leadingTabRegex)?[0].length
buffer.delete [[row, 0], [row, matchLength]]
@@ -494,7 +494,7 @@ class Selection
# by the relevant grammars.
autoIndentSelectedRows: ->
[start, end] = @getBufferRowRange()
- @editSession.autoIndentBufferRows(start, end)
+ @editor.autoIndentBufferRows(start, end)
# Public: Wraps the selected lines in comments if they aren't currently part
# of a comment.
@@ -503,7 +503,7 @@ class Selection
#
# Returns an Array of the commented {Range}s.
toggleLineComments: ->
- @editSession.toggleLineCommentsForBufferRows(@getBufferRowRange()...)
+ @editor.toggleLineCommentsForBufferRows(@getBufferRowRange()...)
# Public: Cuts the selection until the end of the line.
#
@@ -527,19 +527,19 @@ class Selection
# ?
copy: (maintainPasteboard=false) ->
return if @isEmpty()
- text = @editSession.buffer.getTextInRange(@getBufferRange())
+ text = @editor.buffer.getTextInRange(@getBufferRange())
if maintainPasteboard
[currentText, metadata] = atom.pasteboard.read()
text = currentText + '\n' + text
else
- metadata = { indentBasis: @editSession.indentationForBufferRow(@getBufferRange().start.row) }
+ metadata = { indentBasis: @editor.indentationForBufferRow(@getBufferRange().start.row) }
atom.pasteboard.write(text, metadata)
# Public: Creates a fold containing the current selection.
fold: ->
range = @getBufferRange()
- @editSession.createFold(range.start.row, range.end.row)
+ @editor.createFold(range.start.row, range.end.row)
@cursor.setBufferPosition([range.end.row + 1, 0])
# Public: ?
diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee
index 52d494fb0..e90c836fb 100644
--- a/src/text-buffer.coffee
+++ b/src/text-buffer.coffee
@@ -126,12 +126,12 @@ class TextBuffer extends telepath.Model
# Identifies if the buffer belongs to multiple editors.
#
- # For example, if the {Editor} was split.
+ # For example, if the {EditorView} was split.
#
# Returns a {Boolean}.
hasMultipleEditors: -> @refcount > 1
- # Reloads a file in the {EditSession}.
+ # Reloads a file in the {Editor}.
#
# Sets the buffer's content to the cached disk contents
reload: ->
diff --git a/src/window.coffee b/src/window.coffee
index 8b5e001f0..1bd367c69 100644
--- a/src/window.coffee
+++ b/src/window.coffee
@@ -49,7 +49,7 @@ window.startEditorWindow = ->
atom.restoreDimensions()
atom.config.load()
atom.config.setDefaults('core', require('./root-view').configDefaults)
- atom.config.setDefaults('editor', require('./editor').configDefaults)
+ atom.config.setDefaults('editor', require('./editor-view').configDefaults)
atom.keymap.loadBundledKeymaps()
atom.themes.loadBaseStylesheets()
atom.packages.loadPackages()