1 {Range} = require 'atom'
4 {mergeRanges} = require './utils'
7 constructor: (@editor, @state) ->
10 isRecordable: -> false
12 execute: -> @select.apply(this, arguments)
14 class SelectInsideWord extends TextObject
16 for selection in @editor.getSelections()
17 selection.expandOverWord()
20 class SelectInsideWholeWord extends TextObject
22 for selection in @editor.getSelections()
23 range = selection.cursor.getCurrentWordBufferRange({wordRegex: WholeWordRegex})
24 selection.setBufferRange(mergeRanges(selection.getBufferRange(), range))
27 # SelectInsideQuotes and the next class defined (SelectInsideBrackets) are
28 # almost-but-not-quite-repeated code. They are different because of the depth
29 # checks in the bracket matcher.
31 class SelectInsideQuotes extends TextObject
32 constructor: (@editor, @char, @includeQuotes) ->
34 findOpeningQuote: (pos) ->
38 line = @editor.lineTextForBufferRow(pos.row)
39 pos.column = line.length - 1 if pos.column is -1
41 if line[pos.column] is @char
42 if pos.column is 0 or line[pos.column - 1] isnt '\\'
46 return @lookForwardOnLine(start)
50 @lookForwardOnLine(start)
52 isStartQuote: (end) ->
53 line = @editor.lineTextForBufferRow(end.row)
54 numQuotes = line.substring(0, end.column + 1).replace( "'#{@char}", '').split(@char).length - 1
57 lookForwardOnLine: (pos) ->
58 line = @editor.lineTextForBufferRow(pos.row)
60 index = line.substring(pos.column).indexOf(@char)
66 findClosingQuote: (start) ->
70 while end.row < @editor.getLineCount()
71 endLine = @editor.lineTextForBufferRow(end.row)
72 while end.column < endLine.length
73 if endLine[end.column] is '\\'
75 else if endLine[end.column] is @char
76 -- start.column if @includeQuotes
77 ++ end.column if @includeQuotes
85 for selection in @editor.getSelections()
86 start = @findOpeningQuote(selection.cursor.getBufferPosition())
88 ++ start.column # skip the opening quote
89 end = @findClosingQuote(start)
91 selection.setBufferRange(mergeRanges(selection.getBufferRange(), [start, end]))
92 not selection.isEmpty()
94 # SelectInsideBrackets and the previous class defined (SelectInsideQuotes) are
95 # almost-but-not-quite-repeated code. They are different because of the depth
96 # checks in the bracket matcher.
98 class SelectInsideBrackets extends TextObject
99 constructor: (@editor, @beginChar, @endChar, @includeBrackets) ->
101 findOpeningBracket: (pos) ->
105 line = @editor.lineTextForBufferRow(pos.row)
106 pos.column = line.length - 1 if pos.column is -1
107 while pos.column >= 0
108 switch line[pos.column]
109 when @endChar then ++ depth
111 return pos if -- depth < 0
116 findClosingBracket: (start) ->
119 while end.row < @editor.getLineCount()
120 endLine = @editor.lineTextForBufferRow(end.row)
121 while end.column < endLine.length
122 switch endLine[end.column]
123 when @beginChar then ++ depth
126 -- start.column if @includeBrackets
127 ++ end.column if @includeBrackets
135 for selection in @editor.getSelections()
136 start = @findOpeningBracket(selection.cursor.getBufferPosition())
138 ++ start.column # skip the opening quote
139 end = @findClosingBracket(start)
141 selection.setBufferRange(mergeRanges(selection.getBufferRange(), [start, end]))
142 not selection.isEmpty()
144 class SelectAWord extends TextObject
146 for selection in @editor.getSelections()
147 selection.expandOverWord()
149 endPoint = selection.getBufferRange().end
150 char = @editor.getTextInRange(Range.fromPointWithDelta(endPoint, 0, 1))
151 break unless AllWhitespace.test(char)
152 selection.selectRight()
155 class SelectAWholeWord extends TextObject
157 for selection in @editor.getSelections()
158 range = selection.cursor.getCurrentWordBufferRange({wordRegex: WholeWordRegex})
159 selection.setBufferRange(mergeRanges(selection.getBufferRange(), range))
161 endPoint = selection.getBufferRange().end
162 char = @editor.getTextInRange(Range.fromPointWithDelta(endPoint, 0, 1))
163 break unless AllWhitespace.test(char)
164 selection.selectRight()
167 class Paragraph extends TextObject
170 for selection in @editor.getSelections()
171 @selectParagraph(selection)
173 # Return a range delimted by the start or the end of a paragraph
174 paragraphDelimitedRange: (startPoint) ->
175 inParagraph = @isParagraphLine(@editor.lineTextForBufferRow(startPoint.row))
176 upperRow = @searchLines(startPoint.row, -1, inParagraph)
177 lowerRow = @searchLines(startPoint.row, @editor.getLineCount(), inParagraph)
178 new Range([upperRow + 1, 0], [lowerRow, 0])
180 searchLines: (startRow, rowLimit, startedInParagraph) ->
181 for currentRow in [startRow..rowLimit]
182 line = @editor.lineTextForBufferRow(currentRow)
183 if startedInParagraph isnt @isParagraphLine(line)
187 isParagraphLine: (line) -> (/\S/.test(line))
189 class SelectInsideParagraph extends Paragraph
190 selectParagraph: (selection) ->
191 oldRange = selection.getBufferRange()
192 startPoint = selection.cursor.getBufferPosition()
193 newRange = @paragraphDelimitedRange(startPoint)
194 selection.setBufferRange(mergeRanges(oldRange, newRange))
197 class SelectAParagraph extends Paragraph
198 selectParagraph: (selection) ->
199 oldRange = selection.getBufferRange()
200 startPoint = selection.cursor.getBufferPosition()
201 newRange = @paragraphDelimitedRange(startPoint)
202 nextRange = @paragraphDelimitedRange(newRange.end)
203 selection.setBufferRange(mergeRanges(oldRange, [newRange.start, nextRange.end]))
206 module.exports = {TextObject, SelectInsideWord, SelectInsideWholeWord, SelectInsideQuotes,
207 SelectInsideBrackets, SelectAWord, SelectAWholeWord, SelectInsideParagraph, SelectAParagraph}