aboutsummaryrefslogtreecommitdiff
path: root/atom/packages/vim-mode/lib/text-objects.coffee
diff options
context:
space:
mode:
authorBen Beltran <ben@nsovocal.com>2015-07-10 11:12:25 -0500
committerBen Beltran <ben@nsovocal.com>2015-07-10 11:12:25 -0500
commit24c7594d62d8d7fbbcdb64b11ce4adc5d8e6991a (patch)
treeded312222bb108923da1820ba40b04d710d20e5b /atom/packages/vim-mode/lib/text-objects.coffee
parenteb786e82d170e2abc351a432ade616d6ecdeeb6b (diff)
Adds atom
Diffstat (limited to 'atom/packages/vim-mode/lib/text-objects.coffee')
-rw-r--r--atom/packages/vim-mode/lib/text-objects.coffee164
1 files changed, 164 insertions, 0 deletions
diff --git a/atom/packages/vim-mode/lib/text-objects.coffee b/atom/packages/vim-mode/lib/text-objects.coffee
new file mode 100644
index 0000000..6d9741b
--- /dev/null
+++ b/atom/packages/vim-mode/lib/text-objects.coffee
@@ -0,0 +1,164 @@
+{Range} = require 'atom'
+AllWhitespace = /^\s$/
+
+class TextObject
+ constructor: (@editor, @state) ->
+
+ isComplete: -> true
+ isRecordable: -> false
+
+class SelectInsideWord extends TextObject
+ select: ->
+ @editor.selectWordsContainingCursors()
+ [true]
+
+# SelectInsideQuotes and the next class defined (SelectInsideBrackets) are
+# almost-but-not-quite-repeated code. They are different because of the depth
+# checks in the bracket matcher.
+
+class SelectInsideQuotes extends TextObject
+ constructor: (@editor, @char, @includeQuotes) ->
+
+ findOpeningQuote: (pos) ->
+ start = pos.copy()
+ pos = pos.copy()
+ while pos.row >= 0
+ line = @editor.lineTextForBufferRow(pos.row)
+ pos.column = line.length - 1 if pos.column is -1
+ while pos.column >= 0
+ if line[pos.column] is @char
+ if pos.column is 0 or line[pos.column - 1] isnt '\\'
+ if @isStartQuote(pos)
+ return pos
+ else
+ return @lookForwardOnLine(start)
+ -- pos.column
+ pos.column = -1
+ -- pos.row
+ @lookForwardOnLine(start)
+
+ isStartQuote: (end) ->
+ line = @editor.lineTextForBufferRow(end.row)
+ numQuotes = line.substring(0, end.column + 1).replace( "'#{@char}", '').split(@char).length - 1
+ numQuotes % 2
+
+ lookForwardOnLine: (pos) ->
+ line = @editor.lineTextForBufferRow(pos.row)
+
+ index = line.substring(pos.column).indexOf(@char)
+ if index >= 0
+ pos.column += index
+ return pos
+ null
+
+ findClosingQuote: (start) ->
+ end = start.copy()
+ escaping = false
+
+ while end.row < @editor.getLineCount()
+ endLine = @editor.lineTextForBufferRow(end.row)
+ while end.column < endLine.length
+ if endLine[end.column] is '\\'
+ ++ end.column
+ else if endLine[end.column] is @char
+ -- start.column if @includeQuotes
+ ++ end.column if @includeQuotes
+ return end
+ ++ end.column
+ end.column = 0
+ ++ end.row
+ return
+
+ select: ->
+ for selection in @editor.getSelections()
+ start = @findOpeningQuote(selection.cursor.getBufferPosition())
+ if start?
+ ++ start.column # skip the opening quote
+ end = @findClosingQuote(start)
+ if end?
+ selection.setBufferRange([start, end])
+ not selection.isEmpty()
+
+# SelectInsideBrackets and the previous class defined (SelectInsideQuotes) are
+# almost-but-not-quite-repeated code. They are different because of the depth
+# checks in the bracket matcher.
+
+class SelectInsideBrackets extends TextObject
+ constructor: (@editor, @beginChar, @endChar, @includeBrackets) ->
+
+ findOpeningBracket: (pos) ->
+ pos = pos.copy()
+ depth = 0
+ while pos.row >= 0
+ line = @editor.lineTextForBufferRow(pos.row)
+ pos.column = line.length - 1 if pos.column is -1
+ while pos.column >= 0
+ switch line[pos.column]
+ when @endChar then ++ depth
+ when @beginChar
+ return pos if -- depth < 0
+ -- pos.column
+ pos.column = -1
+ -- pos.row
+
+ findClosingBracket: (start) ->
+ end = start.copy()
+ depth = 0
+ while end.row < @editor.getLineCount()
+ endLine = @editor.lineTextForBufferRow(end.row)
+ while end.column < endLine.length
+ switch endLine[end.column]
+ when @beginChar then ++ depth
+ when @endChar
+ if -- depth < 0
+ -- start.column if @includeBrackets
+ ++ end.column if @includeBrackets
+ return end
+ ++ end.column
+ end.column = 0
+ ++ end.row
+ return
+
+ select: ->
+ for selection in @editor.getSelections()
+ start = @findOpeningBracket(selection.cursor.getBufferPosition())
+ if start?
+ ++ start.column # skip the opening quote
+ end = @findClosingBracket(start)
+ if end?
+ selection.setBufferRange([start, end])
+ not selection.isEmpty()
+
+class SelectAWord extends TextObject
+ select: ->
+ for selection in @editor.getSelections()
+ selection.selectWord()
+ loop
+ endPoint = selection.getBufferRange().end
+ char = @editor.getTextInRange(Range.fromPointWithDelta(endPoint, 0, 1))
+ break unless AllWhitespace.test(char)
+ selection.selectRight()
+ true
+
+class SelectInsideParagraph extends TextObject
+ constructor: (@editor, @inclusive) ->
+ select: ->
+ for selection in @editor.getSelections()
+ range = selection.cursor.getCurrentParagraphBufferRange()
+ if range?
+ selection.setBufferRange(range)
+ selection.selectToBeginningOfNextParagraph()
+ true
+
+class SelectAParagraph extends TextObject
+ constructor: (@editor, @inclusive) ->
+ select: ->
+ for selection in @editor.getSelections()
+ range = selection.cursor.getCurrentParagraphBufferRange()
+ if range?
+ selection.setBufferRange(range)
+ selection.selectToBeginningOfNextParagraph()
+ selection.selectDown()
+ true
+
+module.exports = {TextObject, SelectInsideWord, SelectInsideQuotes, SelectInsideBrackets, SelectAWord, SelectInsideParagraph, SelectAParagraph}