 
   # Public: Returns the visibility of the cursor.
   isVisible: -> @visible
+
+  ###
+  Section: Comparing to another cursor
+  ###
+
+  # Public: Compare this cursor's buffer position to another cursor's buffer position.
+  #
+  # See {Point::compare} for more details.
+  #
+  # * `otherCursor`{Cursor} to compare against
+  compare: (otherCursor) ->
+    @getBufferPosition().compare(otherCursor.getBufferPosition())
+
+  ###
+  Section: Utilities
+  ###
+
+  # Public: Prevents this cursor from causing scrolling.
+  clearAutoscroll: ->
+    @needsAutoscroll = null
+
+  # Public: Deselects the current selection.
+  clearSelection: ->
+    @selection?.clear()
 
   # Public: Get the RegExp used by the cursor to determine what a "word" is.
   #

      segments.push("[#{_.escapeRegExp(nonWordCharacters)}]+")
    new RegExp(segments.join("|"), "g")

  # Public: Identifies if this cursor is the last in the {Editor}.
  #
  # "Last" is defined as the most recently added cursor.
  #
  # Returns a {Boolean}.
  isLastCursor: ->
    this == @editor.getLastCursor()

  # Public: Identifies if the cursor is surrounded by whitespace.
  #
  # "Surrounded" here means that the character directly before and after the
  # cursor are both whitespace.
  #
  # Returns a {Boolean}.
  isSurroundedByWhitespace: ->
    {row, column} = @getBufferPosition()
    range = [[row, column - 1], [row, column + 1]]
    /^\s+$/.test @editor.getTextInBufferRange(range)

  # Public: Returns whether the cursor is currently between a word and non-word
  # character. The non-word characters are defined by the
  # `editor.nonWordCharacters` config value.
  #
  # This method returns false if the character before or after the cursor is
  # whitespace.
  #
  # Returns a Boolean.
  isBetweenWordAndNonWord: ->
    return false if @isAtBeginningOfLine() or @isAtEndOfLine()

    {row, column} = @getBufferPosition()
    range = [[row, column - 1], [row, column + 1]]
    [before, after] = @editor.getTextInBufferRange(range)
    return false if /\s/.test(before) or /\s/.test(after)

    nonWordCharacters = atom.config.get('editor.nonWordCharacters').split('')
    _.contains(nonWordCharacters, before) isnt _.contains(nonWordCharacters, after)

  # Public: Returns whether this cursor is between a word's start and end.
  isInsideWord: ->
    {row, column} = @getBufferPosition()
    range = [[row, column], [row, Infinity]]
    @editor.getTextInBufferRange(range).search(@wordRegExp()) == 0

  # Public: Prevents this cursor from causing scrolling.
  clearAutoscroll: ->
    @needsAutoscroll = null

  # Public: Deselects the current selection.
  clearSelection: ->
    @selection?.clear()

  # Public: Returns the cursor's current screen row.
  getScreenRow: ->
    @getScreenPosition().row

  # Public: Returns the cursor's current screen column.
  getScreenColumn: ->
    @getScreenPosition().column

  # Public: Retrieves the cursor's current buffer row.
  getBufferRow: ->
    @getBufferPosition().row

  # Public: Returns the cursor's current buffer column.
  getBufferColumn: ->
    @getBufferPosition().column

  # Public: Returns the cursor's current buffer row of text excluding its line
  # ending.
  getCurrentBufferLine: ->
    @editor.lineTextForBufferRow(@getBufferRow())

  # Public: Moves the cursor up one screen row.
  #
  # * `rowCount` (optional) {Number} number of rows to move (default: 1)
  # * `options` (optional) {Object} with the following keys:
  #   * `moveToEndOfSelection` if true, move to the left of the selection if a
  #     selection exists.
  moveUp: (rowCount=1, {moveToEndOfSelection}={}) ->
    range = @marker.getScreenRange()
    if moveToEndOfSelection and not range.isEmpty()
      { row, column } = range.start
    else
      { row, column } = @getScreenPosition()

    column = @goalColumn if @goalColumn?
    @setScreenPosition({row: row - rowCount, column: column})
    @goalColumn = column

  # Public: Moves the cursor down one screen row.
  #
  # * `rowCount` (optional) {Number} number of rows to move (default: 1)
  # * `options` (optional) {Object} with the following keys:
  #   * `moveToEndOfSelection` if true, move to the left of the selection if a
  #     selection exists.
  moveDown: (rowCount=1, {moveToEndOfSelection}={}) ->
    range = @marker.getScreenRange()
    if moveToEndOfSelection and not range.isEmpty()
      { row, column } = range.end
    else
      { row, column } = @getScreenPosition()

    column = @goalColumn if @goalColumn?
    @setScreenPosition({row: row + rowCount, column: column})
    @goalColumn = column

  # Public: Moves the cursor left one screen column.
  #
  # * `columnCount` (optional) {Number} number of columns to move (default: 1)
  # * `options` (optional) {Object} with the following keys:
  #   * `moveToEndOfSelection` if true, move to the left of the selection if a
  #     selection exists.
  moveLeft: (columnCount=1, {moveToEndOfSelection}={}) ->
    range = @marker.getScreenRange()
    if moveToEndOfSelection and not range.isEmpty()
      @setScreenPosition(range.start)
    else
      {row, column} = @getScreenPosition()

      while columnCount > column and row > 0
        columnCount -= column
        column = @editor.lineTextForScreenRow(--row).length
        columnCount-- # subtract 1 for the row move

      column = column - columnCount
      @setScreenPosition({row, column})

  # Public: Moves the cursor right one screen column.
  #
  # * `columnCount` (optional) {Number} number of columns to move (default: 1)
  # * `options` (optional) {Object} with the following keys:
  #   * `moveToEndOfSelection` if true, move to the right of the selection if a
  #     selection exists.
  moveRight: (columnCount=1, {moveToEndOfSelection}={}) ->
    range = @marker.getScreenRange()
    if moveToEndOfSelection and not range.isEmpty()
      @setScreenPosition(range.end)
    else
      { row, column } = @getScreenPosition()
      maxLines = @editor.getScreenLineCount()
      rowLength = @editor.lineTextForScreenRow(row).length
      columnsRemainingInLine = rowLength - column

      while columnCount > columnsRemainingInLine and row < maxLines - 1
        columnCount -= columnsRemainingInLine
        columnCount-- # subtract 1 for the row move

        column = 0
        rowLength = @editor.lineTextForScreenRow(++row).length
        columnsRemainingInLine = rowLength

      column = column + columnCount
      @setScreenPosition({row, column}, skipAtomicTokens: true, wrapBeyondNewlines: true, wrapAtSoftNewlines: true)

  # Public: Moves the cursor to the top of the buffer.
  moveToTop: ->
    @setBufferPosition([0,0])

  # Public: Moves the cursor to the bottom of the buffer.
  moveToBottom: ->
    @setBufferPosition(@editor.getEofBufferPosition())

  # Public: Moves the cursor to the beginning of the line.
  moveToBeginningOfScreenLine: ->
    @setScreenPosition([@getScreenRow(), 0])

  # Public: Moves the cursor to the beginning of the buffer line.
  moveToBeginningOfLine: ->
    @setBufferPosition([@getBufferRow(), 0])

  # Public: Moves the cursor to the beginning of the first character in the
  # line.
  moveToFirstCharacterOfLine: ->
    screenRow = @getScreenRow()
    lineBufferRange = @editor.bufferRangeForScreenRange([[screenRow, 0], [screenRow, Infinity]])

    firstCharacterColumn = null
    @editor.scanInBufferRange /\S/, lineBufferRange, ({range, stop}) ->
      firstCharacterColumn = range.start.column
      stop()

    if firstCharacterColumn? and firstCharacterColumn isnt @getBufferColumn()
      targetBufferColumn = firstCharacterColumn
    else
      targetBufferColumn = lineBufferRange.start.column

    @setBufferPosition([lineBufferRange.start.row, targetBufferColumn])

  # Public: Moves the cursor to the end of the line.
  moveToEndOfScreenLine: ->
    @setScreenPosition([@getScreenRow(), Infinity])

  # Public: Moves the cursor to the end of the buffer line.
  moveToEndOfLine: ->
    @setBufferPosition([@getBufferRow(), Infinity])

  # Public: Moves the cursor to the beginning of the word.
  moveToBeginningOfWord: ->
    @setBufferPosition(@getBeginningOfCurrentWordBufferPosition())

  # Public: Moves the cursor to the end of the word.
  moveToEndOfWord: ->
    if position = @getEndOfCurrentWordBufferPosition()
      @setBufferPosition(position)

  # Public: Moves the cursor to the beginning of the next word.
  moveToBeginningOfNextWord: ->
    if position = @getBeginningOfNextWordBufferPosition()
      @setBufferPosition(position)

  # Public: Moves the cursor to the previous word boundary.
  moveToPreviousWordBoundary: ->
    if position = @getPreviousWordBoundaryBufferPosition()
      @setBufferPosition(position)

  # Public: Moves the cursor to the next word boundary.
  moveToNextWordBoundary: ->
    if position = @getMoveNextWordBoundaryBufferPosition()
      @setBufferPosition(position)

  # Public: Moves the cursor to the beginning of the buffer line, skipping all
  # whitespace.
  skipLeadingWhitespace: ->
    position = @getBufferPosition()
    scanRange = @getCurrentLineBufferRange()
    endOfLeadingWhitespace = null
    @editor.scanInBufferRange /^[ \t]*/, scanRange, ({range}) ->
      endOfLeadingWhitespace = range.end

    @setBufferPosition(endOfLeadingWhitespace) if endOfLeadingWhitespace.isGreaterThan(position)

  # Public: Retrieves the buffer position of where the current word starts.
  #
  # * `options` (optional) An {Object} with the following keys:
  #   * `wordRegex` A {RegExp} indicating what constitutes a "word"
  #     (default: {::wordRegExp}).
  #   * `includeNonWordCharacters` A {Boolean} indicating whether to include
  #     non-word characters in the default word regex.
  #     Has no effect if wordRegex is set.
  #   * `allowPrevious` A {Boolean} indicating whether the beginning of the
  #     previous word can be returned.
  #
  # Returns a {Range}.
  getBeginningOfCurrentWordBufferPosition: (options = {}) ->
    allowPrevious = options.allowPrevious ? true
    currentBufferPosition = @getBufferPosition()
    previousNonBlankRow = @editor.buffer.previousNonBlankRow(currentBufferPosition.row) ? 0
    scanRange = [[previousNonBlankRow, 0], currentBufferPosition]

    beginningOfWordPosition = null
    @editor.backwardsScanInBufferRange (options.wordRegex ? @wordRegExp(options)), scanRange, ({range, stop}) ->
      if range.end.isGreaterThanOrEqual(currentBufferPosition) or allowPrevious
        beginningOfWordPosition = range.start
      if not beginningOfWordPosition?.isEqual(currentBufferPosition)
        stop()

    if beginningOfWordPosition?
      beginningOfWordPosition
    else if allowPrevious
      new Point(0, 0)
    else
      currentBufferPosition

  # Public: Retrieves buffer position of previous word boundary. It might be on
  # the current word, or the previous word.
  getPreviousWordBoundaryBufferPosition: (options = {}) ->
    currentBufferPosition = @getBufferPosition()
    previousNonBlankRow = @editor.buffer.previousNonBlankRow(currentBufferPosition.row)
    scanRange = [[previousNonBlankRow, 0], currentBufferPosition]

    beginningOfWordPosition = null
    @editor.backwardsScanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) ->
      if range.start.row < currentBufferPosition.row and currentBufferPosition.column > 0
        # force it to stop at the beginning of each line
        beginningOfWordPosition = new Point(currentBufferPosition.row, 0)
      else if range.end.isLessThan(currentBufferPosition)
        beginningOfWordPosition = range.end
      else
        beginningOfWordPosition = range.start

      if not beginningOfWordPosition?.isEqual(currentBufferPosition)
        stop()

    beginningOfWordPosition or currentBufferPosition

  # Public: Retrieves buffer position of the next word boundary. It might be on
  # the current word, or the previous word.
  getMoveNextWordBoundaryBufferPosition: (options = {}) ->
    currentBufferPosition = @getBufferPosition()
    scanRange = [currentBufferPosition, @editor.getEofBufferPosition()]

    endOfWordPosition = null
    @editor.scanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) ->
      if range.start.row > currentBufferPosition.row
        # force it to stop at the beginning of each line
        endOfWordPosition = new Point(range.start.row, 0)
      else if range.start.isGreaterThan(currentBufferPosition)
        endOfWordPosition = range.start
      else
        endOfWordPosition = range.end

      if not endOfWordPosition?.isEqual(currentBufferPosition)
        stop()

    endOfWordPosition or currentBufferPosition

  # Public: Retrieves the buffer position of where the current word ends.
  #
  # * `options` (optional) {Object} with the following keys:
  #   * `wordRegex` A {RegExp} indicating what constitutes a "word"
  #      (default: {::wordRegExp})
  #   * `includeNonWordCharacters` A Boolean indicating whether to include
  #     non-word characters in the default word regex. Has no effect if
  #     wordRegex is set.
  #
  # Returns a {Range}.
  getEndOfCurrentWordBufferPosition: (options = {}) ->
    allowNext = options.allowNext ? true
    currentBufferPosition = @getBufferPosition()
    scanRange = [currentBufferPosition, @editor.getEofBufferPosition()]

    endOfWordPosition = null
    @editor.scanInBufferRange (options.wordRegex ? @wordRegExp(options)), scanRange, ({range, stop}) ->
      if range.start.isLessThanOrEqual(currentBufferPosition) or allowNext
        endOfWordPosition = range.end
      if not endOfWordPosition?.isEqual(currentBufferPosition)
        stop()

    endOfWordPosition ? currentBufferPosition

  # Public: Retrieves the buffer position of where the next word starts.
  #
  # * `options` (optional) {Object}
  #   * `wordRegex` A {RegExp} indicating what constitutes a "word"
  #     (default: {::wordRegExp}).
  #
  # Returns a {Range}
  getBeginningOfNextWordBufferPosition: (options = {}) ->
    currentBufferPosition = @getBufferPosition()
    start = if @isInsideWord() then @getEndOfCurrentWordBufferPosition() else currentBufferPosition
    scanRange = [start, @editor.getEofBufferPosition()]

    beginningOfNextWordPosition = null
    @editor.scanInBufferRange (options.wordRegex ? @wordRegExp()), scanRange, ({range, stop}) ->
      beginningOfNextWordPosition = range.start
      stop()

    beginningOfNextWordPosition or currentBufferPosition

  # Public: Returns the buffer Range occupied by the word located under the cursor.
  #
  # * `options` (optional) {Object}
  #   * `wordRegex` A {RegExp} indicating what constitutes a "word"
  #     (default: {::wordRegExp}).
  getCurrentWordBufferRange: (options={}) ->
    startOptions = _.extend(_.clone(options), allowPrevious: false)
    endOptions = _.extend(_.clone(options), allowNext: false)
    new Range(@getBeginningOfCurrentWordBufferPosition(startOptions), @getEndOfCurrentWordBufferPosition(endOptions))

  # Public: Returns the buffer Range for the current line.
  #
  # * `options` (optional) {Object}
  #   * `includeNewline` A {Boolean} which controls whether the Range should
  #     include the newline.
  getCurrentLineBufferRange: (options) ->
    @editor.bufferRangeForBufferRow(@getBufferRow(), options)

  # Public: Moves the cursor to the beginning of the next paragraph
  moveToBeginningOfNextParagraph: ->
    if position = @getBeginningOfNextParagraphBufferPosition()
      @setBufferPosition(position)

  # Public: Moves the cursor to the beginning of the previous paragraph
  moveToBeginningOfPreviousParagraph: ->
    if position = @getBeginningOfPreviousParagraphBufferPosition()
      @setBufferPosition(position)

  getBeginningOfNextParagraphBufferPosition: (editor) ->
    start = @getBufferPosition()

  onDidDestroy: (callback) ->
    @emitter.on 'did-destroy', callback

  # Public: Calls your `callback` when the cursor's visibility has changed
  #
  # * `callback` {Function}
  #   * `visibility` {Boolean}
