]>
Commit | Line | Data |
---|---|---|
24c7594d BB |
1 | {Range} = require 'atom' |
2 | AllWhitespace = /^\s$/ | |
3 | ||
4 | class TextObject | |
5 | constructor: (@editor, @state) -> | |
6 | ||
7 | isComplete: -> true | |
8 | isRecordable: -> false | |
9 | ||
10 | class SelectInsideWord extends TextObject | |
11 | select: -> | |
12 | @editor.selectWordsContainingCursors() | |
13 | [true] | |
14 | ||
15 | # SelectInsideQuotes and the next class defined (SelectInsideBrackets) are | |
16 | # almost-but-not-quite-repeated code. They are different because of the depth | |
17 | # checks in the bracket matcher. | |
18 | ||
19 | class SelectInsideQuotes extends TextObject | |
20 | constructor: (@editor, @char, @includeQuotes) -> | |
21 | ||
22 | findOpeningQuote: (pos) -> | |
23 | start = pos.copy() | |
24 | pos = pos.copy() | |
25 | while pos.row >= 0 | |
26 | line = @editor.lineTextForBufferRow(pos.row) | |
27 | pos.column = line.length - 1 if pos.column is -1 | |
28 | while pos.column >= 0 | |
29 | if line[pos.column] is @char | |
30 | if pos.column is 0 or line[pos.column - 1] isnt '\\' | |
31 | if @isStartQuote(pos) | |
32 | return pos | |
33 | else | |
34 | return @lookForwardOnLine(start) | |
35 | -- pos.column | |
36 | pos.column = -1 | |
37 | -- pos.row | |
38 | @lookForwardOnLine(start) | |
39 | ||
40 | isStartQuote: (end) -> | |
41 | line = @editor.lineTextForBufferRow(end.row) | |
42 | numQuotes = line.substring(0, end.column + 1).replace( "'#{@char}", '').split(@char).length - 1 | |
43 | numQuotes % 2 | |
44 | ||
45 | lookForwardOnLine: (pos) -> | |
46 | line = @editor.lineTextForBufferRow(pos.row) | |
47 | ||
48 | index = line.substring(pos.column).indexOf(@char) | |
49 | if index >= 0 | |
50 | pos.column += index | |
51 | return pos | |
52 | null | |
53 | ||
54 | findClosingQuote: (start) -> | |
55 | end = start.copy() | |
56 | escaping = false | |
57 | ||
58 | while end.row < @editor.getLineCount() | |
59 | endLine = @editor.lineTextForBufferRow(end.row) | |
60 | while end.column < endLine.length | |
61 | if endLine[end.column] is '\\' | |
62 | ++ end.column | |
63 | else if endLine[end.column] is @char | |
64 | -- start.column if @includeQuotes | |
65 | ++ end.column if @includeQuotes | |
66 | return end | |
67 | ++ end.column | |
68 | end.column = 0 | |
69 | ++ end.row | |
70 | return | |
71 | ||
72 | select: -> | |
73 | for selection in @editor.getSelections() | |
74 | start = @findOpeningQuote(selection.cursor.getBufferPosition()) | |
75 | if start? | |
76 | ++ start.column # skip the opening quote | |
77 | end = @findClosingQuote(start) | |
78 | if end? | |
79 | selection.setBufferRange([start, end]) | |
80 | not selection.isEmpty() | |
81 | ||
82 | # SelectInsideBrackets and the previous class defined (SelectInsideQuotes) are | |
83 | # almost-but-not-quite-repeated code. They are different because of the depth | |
84 | # checks in the bracket matcher. | |
85 | ||
86 | class SelectInsideBrackets extends TextObject | |
87 | constructor: (@editor, @beginChar, @endChar, @includeBrackets) -> | |
88 | ||
89 | findOpeningBracket: (pos) -> | |
90 | pos = pos.copy() | |
91 | depth = 0 | |
92 | while pos.row >= 0 | |
93 | line = @editor.lineTextForBufferRow(pos.row) | |
94 | pos.column = line.length - 1 if pos.column is -1 | |
95 | while pos.column >= 0 | |
96 | switch line[pos.column] | |
97 | when @endChar then ++ depth | |
98 | when @beginChar | |
99 | return pos if -- depth < 0 | |
100 | -- pos.column | |
101 | pos.column = -1 | |
102 | -- pos.row | |
103 | ||
104 | findClosingBracket: (start) -> | |
105 | end = start.copy() | |
106 | depth = 0 | |
107 | while end.row < @editor.getLineCount() | |
108 | endLine = @editor.lineTextForBufferRow(end.row) | |
109 | while end.column < endLine.length | |
110 | switch endLine[end.column] | |
111 | when @beginChar then ++ depth | |
112 | when @endChar | |
113 | if -- depth < 0 | |
114 | -- start.column if @includeBrackets | |
115 | ++ end.column if @includeBrackets | |
116 | return end | |
117 | ++ end.column | |
118 | end.column = 0 | |
119 | ++ end.row | |
120 | return | |
121 | ||
122 | select: -> | |
123 | for selection in @editor.getSelections() | |
124 | start = @findOpeningBracket(selection.cursor.getBufferPosition()) | |
125 | if start? | |
126 | ++ start.column # skip the opening quote | |
127 | end = @findClosingBracket(start) | |
128 | if end? | |
129 | selection.setBufferRange([start, end]) | |
130 | not selection.isEmpty() | |
131 | ||
132 | class SelectAWord extends TextObject | |
133 | select: -> | |
134 | for selection in @editor.getSelections() | |
135 | selection.selectWord() | |
136 | loop | |
137 | endPoint = selection.getBufferRange().end | |
138 | char = @editor.getTextInRange(Range.fromPointWithDelta(endPoint, 0, 1)) | |
139 | break unless AllWhitespace.test(char) | |
140 | selection.selectRight() | |
141 | true | |
142 | ||
143 | class SelectInsideParagraph extends TextObject | |
144 | constructor: (@editor, @inclusive) -> | |
145 | select: -> | |
146 | for selection in @editor.getSelections() | |
147 | range = selection.cursor.getCurrentParagraphBufferRange() | |
148 | if range? | |
149 | selection.setBufferRange(range) | |
150 | selection.selectToBeginningOfNextParagraph() | |
151 | true | |
152 | ||
153 | class SelectAParagraph extends TextObject | |
154 | constructor: (@editor, @inclusive) -> | |
155 | select: -> | |
156 | for selection in @editor.getSelections() | |
157 | range = selection.cursor.getCurrentParagraphBufferRange() | |
158 | if range? | |
159 | selection.setBufferRange(range) | |
160 | selection.selectToBeginningOfNextParagraph() | |
161 | selection.selectDown() | |
162 | true | |
163 | ||
164 | module.exports = {TextObject, SelectInsideWord, SelectInsideQuotes, SelectInsideBrackets, SelectAWord, SelectInsideParagraph, SelectAParagraph} |