mirror of
https://github.com/atom/atom.git
synced 2026-02-08 05:35:04 -05:00
165 lines
5.3 KiB
CoffeeScript
165 lines
5.3 KiB
CoffeeScript
Point = require 'point'
|
|
Range = require 'range'
|
|
Anchor = require 'anchor'
|
|
EventEmitter = require 'event-emitter'
|
|
_ = require 'underscore'
|
|
|
|
module.exports =
|
|
class Cursor
|
|
screenPosition: null
|
|
bufferPosition: null
|
|
goalColumn: null
|
|
wordRegex: /(\w+)|([^\w\s]+)/g
|
|
|
|
constructor: ({@editSession, screenPosition, bufferPosition}) ->
|
|
@anchor = new Anchor(@editSession)
|
|
@setScreenPosition(screenPosition) if screenPosition
|
|
@setBufferPosition(bufferPosition) if bufferPosition
|
|
|
|
destroy: ->
|
|
@editSession.removeCursor(this)
|
|
@trigger 'destroy'
|
|
|
|
setScreenPosition: (screenPosition, options) ->
|
|
@anchor.setScreenPosition(screenPosition, options)
|
|
@goalColumn = null
|
|
@clearSelection()
|
|
@trigger 'change-screen-position', @getScreenPosition(), bufferChange: false
|
|
|
|
getScreenPosition: ->
|
|
@anchor.getScreenPosition()
|
|
|
|
setBufferPosition: (bufferPosition, options) ->
|
|
@anchor.setBufferPosition(bufferPosition, options)
|
|
@goalColumn = null
|
|
@clearSelection()
|
|
@trigger 'change-screen-position', @getScreenPosition(), bufferChange: false
|
|
|
|
getBufferPosition: ->
|
|
@anchor.getBufferPosition()
|
|
|
|
clearSelection: ->
|
|
if @selection
|
|
@selection.clear() unless @selection.retainSelection
|
|
|
|
getScreenRow: ->
|
|
@getScreenPosition().row
|
|
|
|
getBufferRow: ->
|
|
@getBufferPosition().row
|
|
|
|
getCurrentBufferLine: ->
|
|
@editSession.lineForBufferRow(@getBufferRow())
|
|
|
|
refreshScreenPosition: ->
|
|
@anchor.refreshScreenPosition()
|
|
@trigger 'change-screen-position', @getScreenPosition(), bufferChange: false
|
|
|
|
handleBufferChange: (e) ->
|
|
@anchor.handleBufferChange(e)
|
|
@trigger 'change-screen-position', @getScreenPosition(), bufferChange: true
|
|
|
|
moveUp: ->
|
|
{ row, column } = @getScreenPosition()
|
|
column = @goalColumn if @goalColumn?
|
|
@setScreenPosition({row: row - 1, column: column})
|
|
@goalColumn = column
|
|
|
|
moveDown: ->
|
|
{ row, column } = @getScreenPosition()
|
|
column = @goalColumn if @goalColumn?
|
|
@setScreenPosition({row: row + 1, column: column})
|
|
@goalColumn = column
|
|
|
|
moveLeft: ->
|
|
{ row, column } = @getScreenPosition()
|
|
[row, column] = if column > 0 then [row, column - 1] else [row - 1, Infinity]
|
|
@setScreenPosition({row, column})
|
|
|
|
moveRight: ->
|
|
{ row, column } = @getScreenPosition()
|
|
@setScreenPosition([row, column + 1], skipAtomicTokens: true, wrapBeyondNewlines: true, wrapAtSoftNewlines: true)
|
|
|
|
moveToTop: ->
|
|
@setBufferPosition([0,0])
|
|
|
|
moveToBottom: ->
|
|
@setBufferPosition(@editSession.getEofBufferPosition())
|
|
|
|
moveToBeginningOfLine: ->
|
|
@setBufferPosition([@getBufferRow(), 0])
|
|
|
|
moveToFirstCharacterOfLine: ->
|
|
position = @getBufferPosition()
|
|
range = @editSession.bufferRangeForBufferRow(position.row)
|
|
newPosition = null
|
|
@editSession.scanInRange /^\s*/, range, (match, matchRange) =>
|
|
newPosition = matchRange.end
|
|
return unless newPosition
|
|
newPosition = [position.row, 0] if newPosition.isEqual(position)
|
|
@setBufferPosition(newPosition)
|
|
|
|
moveToEndOfLine: ->
|
|
@setBufferPosition([@getBufferRow(), Infinity])
|
|
|
|
moveToBeginningOfWord: ->
|
|
@setBufferPosition(@getBeginningOfCurrentWordBufferPosition())
|
|
|
|
moveToEndOfWord: ->
|
|
@setBufferPosition(@getEndOfCurrentWordBufferPosition())
|
|
|
|
moveToNextWord: ->
|
|
@setBufferPosition(@getBeginningOfNextWordBufferPosition())
|
|
|
|
getBeginningOfCurrentWordBufferPosition: (options = {}) ->
|
|
allowPrevious = options.allowPrevious ? true
|
|
currentBufferPosition = @getBufferPosition()
|
|
previousRow = Math.max(0, currentBufferPosition.row - 1)
|
|
previousLinesRange = [[previousRow, 0], currentBufferPosition]
|
|
|
|
beginningOfWordPosition = currentBufferPosition
|
|
@editSession.backwardsScanInRange @wordRegex, previousLinesRange, (match, matchRange, { stop }) =>
|
|
if matchRange.end.isGreaterThanOrEqual(currentBufferPosition) or allowPrevious
|
|
beginningOfWordPosition = matchRange.start
|
|
stop()
|
|
beginningOfWordPosition
|
|
|
|
getEndOfCurrentWordBufferPosition: (options = {}) ->
|
|
allowNext = options.allowNext ? true
|
|
currentBufferPosition = @getBufferPosition()
|
|
range = [currentBufferPosition, @editSession.getEofBufferPosition()]
|
|
|
|
endOfWordPosition = null
|
|
@editSession.scanInRange @wordRegex, range, (match, matchRange, { stop }) =>
|
|
endOfWordPosition = matchRange.end
|
|
if not allowNext and matchRange.start.isGreaterThan(currentBufferPosition)
|
|
endOfWordPosition = currentBufferPosition
|
|
stop()
|
|
endOfWordPosition
|
|
|
|
getBeginningOfNextWordBufferPosition: ->
|
|
currentBufferPosition = @getBufferPosition()
|
|
eofBufferPosition = @editSession.getEofBufferPosition()
|
|
range = [currentBufferPosition, eofBufferPosition]
|
|
|
|
nextWordPosition = eofBufferPosition
|
|
@editSession.scanInRange @wordRegex, range, (match, matchRange, { stop }) =>
|
|
if matchRange.start.isGreaterThan(currentBufferPosition)
|
|
nextWordPosition = matchRange.start
|
|
stop()
|
|
nextWordPosition
|
|
|
|
getCurrentWordBufferRange: ->
|
|
new Range(@getBeginningOfCurrentWordBufferPosition(allowPrevious: false), @getEndOfCurrentWordBufferPosition(allowNext: false))
|
|
|
|
getCurrentLineBufferRange: ->
|
|
@editSession.bufferRangeForBufferRow(@getBufferRow())
|
|
|
|
isAtBeginningOfLine: ->
|
|
@getBufferPosition().column == 0
|
|
|
|
isAtEndOfLine: ->
|
|
@getBufferPosition().isEqual(@getCurrentLineBufferRange().end)
|
|
|
|
_.extend Cursor.prototype, EventEmitter
|