diakonos 0.8.11 → 0.9.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG +439 -0
- data/LICENCE.md +675 -0
- data/bin/diakonos +6 -0
- data/diakonos-256-colour.conf +220 -0
- data/diakonos.conf +1802 -0
- data/help/about-help.dhf +31 -0
- data/help/clipboard.dhf +45 -0
- data/help/close-file.dhf +6 -0
- data/help/code-block-navigation.dhf +16 -0
- data/help/column-markers.dhf +15 -0
- data/help/config.dhf +69 -0
- data/help/cursor-stack.dhf +19 -0
- data/help/delete.dhf +41 -0
- data/help/extensions.dhf +125 -0
- data/help/file-type.dhf +24 -0
- data/help/key-mapping.dhf +127 -0
- data/help/line-numbers.dhf +22 -0
- data/help/macros.dhf +27 -0
- data/help/new-file.dhf +6 -0
- data/help/open-file.dhf +21 -0
- data/help/quit.dhf +7 -0
- data/help/resizing.dhf +19 -0
- data/help/ruby.dhf +17 -0
- data/help/save-file.dhf +10 -0
- data/help/scripting.dhf +92 -0
- data/help/search.dhf +103 -0
- data/help/shell.dhf +60 -0
- data/help/speed.dhf +23 -0
- data/help/support.dhf +15 -0
- data/help/switch-buffers.dhf +15 -0
- data/help/tabs.dhf +36 -0
- data/help/undo.dhf +9 -0
- data/help/uninstall.dhf +18 -0
- data/help/welcome.dhf +32 -0
- data/help/word-wrap.dhf +17 -0
- data/lib/diakonos/about.rb +70 -0
- data/lib/diakonos/bookmark.rb +46 -0
- data/lib/diakonos/buffer/bookmarking.rb +47 -0
- data/lib/diakonos/buffer/cursor.rb +335 -0
- data/lib/diakonos/buffer/delete.rb +170 -0
- data/lib/diakonos/buffer/display.rb +362 -0
- data/lib/diakonos/buffer/file.rb +157 -0
- data/lib/diakonos/buffer/indentation.rb +175 -0
- data/lib/diakonos/buffer/searching.rb +552 -0
- data/lib/diakonos/buffer/selection.rb +360 -0
- data/lib/diakonos/buffer/undo.rb +73 -0
- data/lib/diakonos/buffer-hash.rb +60 -0
- data/lib/diakonos/buffer-management.rb +59 -0
- data/lib/diakonos/buffer.rb +698 -0
- data/lib/diakonos/clipboard-klipper-dbus.rb +62 -0
- data/lib/diakonos/clipboard-klipper.rb +62 -0
- data/lib/diakonos/clipboard-osx.rb +59 -0
- data/lib/diakonos/clipboard-xclip.rb +60 -0
- data/lib/diakonos/clipboard.rb +47 -0
- data/lib/diakonos/config-file.rb +67 -0
- data/lib/diakonos/config.rb +382 -0
- data/lib/diakonos/core-ext/enumerable.rb +15 -0
- data/lib/diakonos/core-ext/hash.rb +60 -0
- data/lib/diakonos/core-ext/object.rb +6 -0
- data/lib/diakonos/core-ext/regexp.rb +6 -0
- data/lib/diakonos/core-ext/string.rb +122 -0
- data/lib/diakonos/ctag.rb +28 -0
- data/lib/diakonos/cursor.rb +27 -0
- data/lib/diakonos/display/format.rb +75 -0
- data/lib/diakonos/display.rb +336 -0
- data/lib/diakonos/extension-set.rb +49 -0
- data/lib/diakonos/extension.rb +34 -0
- data/lib/diakonos/finding.rb +40 -0
- data/lib/diakonos/functions/basics.rb +34 -0
- data/lib/diakonos/functions/bookmarking.rb +61 -0
- data/lib/diakonos/functions/buffers.rb +491 -0
- data/lib/diakonos/functions/clipboard.rb +70 -0
- data/lib/diakonos/functions/cursor.rb +264 -0
- data/lib/diakonos/functions/grepping.rb +83 -0
- data/lib/diakonos/functions/indentation.rb +71 -0
- data/lib/diakonos/functions/readline.rb +93 -0
- data/lib/diakonos/functions/search.rb +179 -0
- data/lib/diakonos/functions/selection.rb +98 -0
- data/lib/diakonos/functions/sessions.rb +78 -0
- data/lib/diakonos/functions/shell.rb +250 -0
- data/lib/diakonos/functions/tags.rb +65 -0
- data/lib/diakonos/functions/text-manipulation.rb +196 -0
- data/lib/diakonos/functions-deprecated.rb +77 -0
- data/lib/diakonos/functions.rb +292 -0
- data/lib/diakonos/grep.rb +98 -0
- data/lib/diakonos/help.rb +47 -0
- data/lib/diakonos/hooks.rb +13 -0
- data/lib/diakonos/installation.rb +19 -0
- data/lib/diakonos/interaction-handler.rb +216 -0
- data/lib/diakonos/interaction.rb +52 -0
- data/lib/diakonos/key-map.rb +62 -0
- data/lib/diakonos/keying.rb +442 -0
- data/lib/diakonos/line-mover.rb +42 -0
- data/lib/diakonos/list.rb +59 -0
- data/lib/diakonos/logging.rb +27 -0
- data/lib/diakonos/mode.rb +17 -0
- data/lib/diakonos/mouse.rb +18 -0
- data/lib/diakonos/number-fitter.rb +11 -0
- data/lib/diakonos/range.rb +31 -0
- data/lib/diakonos/readline/functions.rb +82 -0
- data/lib/diakonos/readline.rb +223 -0
- data/lib/diakonos/search.rb +58 -0
- data/lib/diakonos/sessions.rb +257 -0
- data/lib/diakonos/sized-array.rb +48 -0
- data/lib/diakonos/text-mark.rb +19 -0
- data/lib/diakonos/vendor/fuzzy_file_finder.rb +386 -0
- data/lib/diakonos/version.rb +25 -0
- data/lib/diakonos/window.rb +43 -0
- data/lib/diakonos.rb +592 -0
- metadata +160 -68
@@ -0,0 +1,552 @@
|
|
1
|
+
module Diakonos
|
2
|
+
|
3
|
+
class Buffer
|
4
|
+
|
5
|
+
attr_reader :num_matches_found, :last_search_regexps
|
6
|
+
|
7
|
+
CHARACTER_PAIRS = {
|
8
|
+
'(' => { partner: ')', direction: :forward },
|
9
|
+
'<' => { partner: '>', direction: :forward },
|
10
|
+
'{' => { partner: '}', direction: :forward },
|
11
|
+
'[' => { partner: ']', direction: :forward },
|
12
|
+
')' => { partner: '(', direction: :backward },
|
13
|
+
'>' => { partner: '<', direction: :backward },
|
14
|
+
'}' => { partner: '{', direction: :backward },
|
15
|
+
']' => { partner: '[', direction: :backward },
|
16
|
+
}
|
17
|
+
|
18
|
+
OPPOSITE_DIRECTION = {
|
19
|
+
up: :down,
|
20
|
+
down: :up,
|
21
|
+
}
|
22
|
+
|
23
|
+
def search_area?
|
24
|
+
@search_area
|
25
|
+
end
|
26
|
+
|
27
|
+
def clear_search_area
|
28
|
+
@search_area = nil
|
29
|
+
@text_marks.delete :search_area_pre
|
30
|
+
@text_marks.delete :search_area_post
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_search_area(mark)
|
34
|
+
if mark.nil?
|
35
|
+
raise 'Call Diakonos::Buffer#clear_search_area instead'
|
36
|
+
return
|
37
|
+
end
|
38
|
+
|
39
|
+
@search_area = mark
|
40
|
+
@text_marks[ :search_area_pre ] = TextMark.new(
|
41
|
+
::Diakonos::Range.new(0, 0, mark.start_row, mark.start_col),
|
42
|
+
@settings[ 'view.non_search_area.format' ]
|
43
|
+
)
|
44
|
+
@text_marks[ :search_area_post ] = TextMark.new(
|
45
|
+
::Diakonos::Range.new(mark.end_row, mark.end_col, @lines.length - 1, @lines[ -1 ].length),
|
46
|
+
@settings[ 'view.non_search_area.format' ]
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
def confirm_finding( regexps, search_area, from_row, from_col, match )
|
51
|
+
found_text = match[0]
|
52
|
+
range = ::Diakonos::Range.new(from_row, from_col, from_row, from_col + found_text.length)
|
53
|
+
Finding.confirm(range, regexps, @lines, search_area, match)
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [Array<String>]
|
57
|
+
def search_area_lines
|
58
|
+
return [] if @search_area.nil?
|
59
|
+
|
60
|
+
lines = @lines[@search_area.start_row..@search_area.end_row]
|
61
|
+
lines[0] = lines[0][@search_area.start_col..-1]
|
62
|
+
lines[-1] = lines[-1][0..@search_area.end_col]
|
63
|
+
|
64
|
+
lines
|
65
|
+
end
|
66
|
+
|
67
|
+
def _find_down(regexps, regexp, from_row, from_col, search_area)
|
68
|
+
# Check the current row first.
|
69
|
+
|
70
|
+
index = @lines[ from_row ].index(
|
71
|
+
regexp,
|
72
|
+
( @last_finding ? @last_finding.start_col : from_col ) + 1
|
73
|
+
)
|
74
|
+
if index
|
75
|
+
finding = confirm_finding( regexps, search_area, from_row, index, Regexp.last_match )
|
76
|
+
return finding if finding
|
77
|
+
end
|
78
|
+
|
79
|
+
# Check below the cursor.
|
80
|
+
|
81
|
+
( (from_row + 1)..search_area.end_row ).each do |i|
|
82
|
+
line = @lines[ i ]
|
83
|
+
if i == search_area.end_row
|
84
|
+
line = line[ 0...search_area.end_col ]
|
85
|
+
end
|
86
|
+
index = line.index( regexp )
|
87
|
+
if index
|
88
|
+
finding = confirm_finding( regexps, search_area, i, index, Regexp.last_match )
|
89
|
+
return finding if finding
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
if index
|
94
|
+
finding = confirm_finding( regexps, search_area, search_area.end_row, index, Regexp.last_match )
|
95
|
+
return finding if finding
|
96
|
+
end
|
97
|
+
|
98
|
+
# Wrap around.
|
99
|
+
|
100
|
+
@wrapped = true
|
101
|
+
|
102
|
+
index = @lines[ search_area.start_row ].index( regexp, search_area.start_col )
|
103
|
+
if index
|
104
|
+
finding = confirm_finding( regexps, search_area, search_area.start_row, index, Regexp.last_match )
|
105
|
+
return finding if finding
|
106
|
+
end
|
107
|
+
|
108
|
+
( search_area.start_row+1...from_row ).each do |i|
|
109
|
+
index = @lines[ i ].index( regexp )
|
110
|
+
if index
|
111
|
+
finding = confirm_finding( regexps, search_area, i, index, Regexp.last_match )
|
112
|
+
return finding if finding
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# And finally, the other side of the current row.
|
117
|
+
|
118
|
+
if from_row == search_area.start_row
|
119
|
+
index_col = search_area.start_col
|
120
|
+
else
|
121
|
+
index_col = 0
|
122
|
+
end
|
123
|
+
if index = @lines[ from_row ].index( regexp, index_col )
|
124
|
+
if index <= ( @last_finding ? @last_finding.start_col : from_col )
|
125
|
+
finding = confirm_finding( regexps, search_area, from_row, index, Regexp.last_match )
|
126
|
+
return finding if finding
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def _find_up(regexps, regexp, search_area, from_row, from_col)
|
132
|
+
# Check the current row first.
|
133
|
+
|
134
|
+
col_to_check = ( @last_finding ? @last_finding.end_col : from_col ) - 1
|
135
|
+
if ( col_to_check >= 0 ) && ( index = @lines[ from_row ][ 0...col_to_check ].rindex( regexp ) )
|
136
|
+
finding = confirm_finding( regexps, search_area, from_row, index, Regexp.last_match )
|
137
|
+
return finding if finding
|
138
|
+
end
|
139
|
+
|
140
|
+
# Check above the cursor.
|
141
|
+
|
142
|
+
(from_row - 1).downto( 0 ) do |i|
|
143
|
+
if index = @lines[ i ].rindex( regexp )
|
144
|
+
finding = confirm_finding( regexps, search_area, i, index, Regexp.last_match )
|
145
|
+
return finding if finding
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Wrap around.
|
150
|
+
|
151
|
+
@wrapped = true
|
152
|
+
|
153
|
+
(@lines.length - 1).downto(from_row + 1) do |i|
|
154
|
+
if index = @lines[ i ].rindex( regexp )
|
155
|
+
finding = confirm_finding( regexps, search_area, i, index, Regexp.last_match )
|
156
|
+
return finding if finding
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# And finally, the other side of the current row.
|
161
|
+
|
162
|
+
search_col = ( @last_finding ? @last_finding.start_col : from_col ) + 1
|
163
|
+
if index = @lines[ from_row ].rindex( regexp )
|
164
|
+
if index > search_col
|
165
|
+
finding = confirm_finding( regexps, search_area, from_row, index, Regexp.last_match )
|
166
|
+
return finding if finding
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# @param regexps [Array] Regexps which represent a user-provided regexp,
|
172
|
+
# split across newline characters. Once the first element is found,
|
173
|
+
# each successive element must match against lines following the first
|
174
|
+
# element.
|
175
|
+
# @return [Integer] the number of replacements made
|
176
|
+
def find( regexps, options = {} )
|
177
|
+
return if regexps.nil?
|
178
|
+
regexp = regexps[ 0 ]
|
179
|
+
return if regexp.nil? || regexp == //
|
180
|
+
|
181
|
+
direction = options[ :direction ]
|
182
|
+
replacement = options[ :replacement ]
|
183
|
+
auto_choice = options[ :auto_choice ]
|
184
|
+
from_row = options[ :starting_row ] || @last_row
|
185
|
+
from_col = options[ :starting_col ] || @last_col
|
186
|
+
show_context_after = options[ :show_context_after ]
|
187
|
+
|
188
|
+
if options[:starting]
|
189
|
+
@num_matches_found = nil
|
190
|
+
end
|
191
|
+
|
192
|
+
num_replacements = 0
|
193
|
+
|
194
|
+
# TODO: Just use Range here instead of TextMark?
|
195
|
+
search_area = @search_area || TextMark.new( ::Diakonos::Range.new(0, 0, @lines.size - 1, @lines[ -1 ].size), nil )
|
196
|
+
if ! search_area.contains?( from_row, from_col )
|
197
|
+
from_row, from_col = search_area.start_row, search_area.start_col
|
198
|
+
end
|
199
|
+
|
200
|
+
if direction == :opposite
|
201
|
+
direction = OPPOSITE_DIRECTION[@last_search_direction]
|
202
|
+
end
|
203
|
+
@last_search_regexps = regexps
|
204
|
+
@last_search_direction = direction
|
205
|
+
|
206
|
+
@wrapped = false
|
207
|
+
|
208
|
+
if direction == :down
|
209
|
+
finding = _find_down(regexps, regexp, from_row, from_col, search_area)
|
210
|
+
elsif direction == :up
|
211
|
+
finding = _find_up(regexps, regexp, search_area, from_row, from_col)
|
212
|
+
end
|
213
|
+
|
214
|
+
if ! finding
|
215
|
+
remove_selection DONT_DISPLAY
|
216
|
+
clear_matches DO_DISPLAY
|
217
|
+
if ! options[ :quiet ] && ( replacement.nil? || num_replacements == 0 )
|
218
|
+
$diakonos.set_iline "/#{regexp.source}/ not found."
|
219
|
+
end
|
220
|
+
else
|
221
|
+
if @wrapped && ! options[ :quiet ]
|
222
|
+
if @search_area
|
223
|
+
$diakonos.set_iline( "(search wrapped around to start of search area)" )
|
224
|
+
else
|
225
|
+
$diakonos.set_iline( "(search wrapped around BOF/EOF)" )
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
remove_selection( DONT_DISPLAY )
|
230
|
+
@last_finding = finding
|
231
|
+
if @settings[ "found_cursor_start" ]
|
232
|
+
anchor_selection( finding.end_row, finding.end_col, DONT_DISPLAY )
|
233
|
+
cursor_to( finding.start_row, finding.start_col )
|
234
|
+
else
|
235
|
+
anchor_selection( finding.start_row, finding.start_col, DONT_DISPLAY )
|
236
|
+
cursor_to( finding.end_row, finding.end_col )
|
237
|
+
end
|
238
|
+
if show_context_after
|
239
|
+
watermark = Curses::lines / 6
|
240
|
+
if @last_row - @top_line > watermark
|
241
|
+
pitch_view( @last_row - @top_line - watermark )
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
@changing_selection = false
|
246
|
+
|
247
|
+
if regexps.length == 1
|
248
|
+
@highlight_regexp = regexp
|
249
|
+
highlight_matches
|
250
|
+
else
|
251
|
+
clear_matches
|
252
|
+
end
|
253
|
+
display
|
254
|
+
|
255
|
+
if replacement
|
256
|
+
# Substitute placeholders (e.g. \1) in str for the group matches of the last match.
|
257
|
+
actual_replacement = replacement.dup
|
258
|
+
actual_replacement.gsub!( /\\(\\|\d+)/ ) { |m|
|
259
|
+
ref = $1
|
260
|
+
if ref == "\\"
|
261
|
+
"\\"
|
262
|
+
else
|
263
|
+
finding.captured_group(ref.to_i)
|
264
|
+
end
|
265
|
+
}
|
266
|
+
|
267
|
+
choices = [ CHOICE_YES, CHOICE_NO, CHOICE_ALL, CHOICE_CANCEL, CHOICE_YES_AND_STOP, ]
|
268
|
+
if @search_area
|
269
|
+
choices << CHOICE_WITHIN_SELECTION
|
270
|
+
end
|
271
|
+
choice = auto_choice || $diakonos.get_choice(
|
272
|
+
"#{@num_matches_found} match#{ @num_matches_found != 1 ? 'es' : '' } - Replace this one?",
|
273
|
+
choices,
|
274
|
+
CHOICE_YES
|
275
|
+
)
|
276
|
+
case choice
|
277
|
+
when CHOICE_YES
|
278
|
+
paste [ actual_replacement ]
|
279
|
+
num_replacements += 1 + find( regexps, direction: direction, replacement: replacement )
|
280
|
+
when CHOICE_ALL
|
281
|
+
num_replacements += replace_all(regexp, replacement)
|
282
|
+
when CHOICE_WITHIN_SELECTION
|
283
|
+
num_replacements += replace_all(regexp, replacement, :within_search_area)
|
284
|
+
when CHOICE_NO
|
285
|
+
num_replacements += find( regexps, direction: direction, replacement: replacement )
|
286
|
+
when CHOICE_CANCEL
|
287
|
+
# Do nothing further.
|
288
|
+
when CHOICE_YES_AND_STOP
|
289
|
+
paste [ actual_replacement ]
|
290
|
+
num_replacements += 1
|
291
|
+
# Do nothing further.
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
num_replacements
|
297
|
+
end
|
298
|
+
|
299
|
+
# @return [Integer] the number of replacements made
|
300
|
+
def replace_all( regexp, replacement, within_search_area = false )
|
301
|
+
return if( regexp.nil? || replacement.nil? )
|
302
|
+
|
303
|
+
num_replacements = 0
|
304
|
+
|
305
|
+
take_snapshot
|
306
|
+
|
307
|
+
if within_search_area && @search_area
|
308
|
+
lines = self.search_area_lines
|
309
|
+
else
|
310
|
+
lines = @lines
|
311
|
+
end
|
312
|
+
|
313
|
+
lines_modified = lines.collect { |line|
|
314
|
+
num_replacements += line.scan(regexp).size
|
315
|
+
line.gsub( regexp, replacement )
|
316
|
+
}
|
317
|
+
|
318
|
+
if within_search_area && @search_area
|
319
|
+
@lines[@search_area.start_row][@search_area.start_col..-1] = lines_modified[0]
|
320
|
+
if @search_area.end_row - @search_area.start_row > 1
|
321
|
+
@lines[@search_area.start_row+1..@search_area.end_row-1] = lines_modified[1..-2]
|
322
|
+
end
|
323
|
+
@lines[@search_area.end_row][0..@search_area.end_col] = lines_modified[-1]
|
324
|
+
else
|
325
|
+
@lines = lines_modified
|
326
|
+
end
|
327
|
+
|
328
|
+
set_modified
|
329
|
+
clear_matches
|
330
|
+
display
|
331
|
+
num_replacements
|
332
|
+
end
|
333
|
+
|
334
|
+
def highlight_matches( regexp = @highlight_regexp )
|
335
|
+
@highlight_regexp = regexp
|
336
|
+
return if @highlight_regexp.nil?
|
337
|
+
|
338
|
+
if @search_area
|
339
|
+
lines = self.search_area_lines
|
340
|
+
line_index_offset = @search_area.start_row
|
341
|
+
col_offset = @search_area.start_col
|
342
|
+
else
|
343
|
+
lines = @lines
|
344
|
+
line_index_offset = 0
|
345
|
+
col_offset = 0
|
346
|
+
end
|
347
|
+
|
348
|
+
grepped_lines = lines.grep_indices( @highlight_regexp )
|
349
|
+
n = grepped_lines.count
|
350
|
+
found_marks = grepped_lines.collect do |line_index, start_col, end_col|
|
351
|
+
TextMark.new(
|
352
|
+
::Diakonos::Range.new(
|
353
|
+
line_index + line_index_offset,
|
354
|
+
start_col + ( line_index == 0 ? col_offset : 0 ),
|
355
|
+
line_index + line_index_offset,
|
356
|
+
end_col,
|
357
|
+
),
|
358
|
+
@settings["lang.#{@language}.format.found"]
|
359
|
+
)
|
360
|
+
end
|
361
|
+
@text_marks[:found] = found_marks
|
362
|
+
@num_matches_found ||= found_marks.size
|
363
|
+
end
|
364
|
+
|
365
|
+
def clear_matches( do_display = DONT_DISPLAY )
|
366
|
+
@text_marks[ :found ] = []
|
367
|
+
@highlight_regexp = nil
|
368
|
+
display if do_display
|
369
|
+
end
|
370
|
+
|
371
|
+
def pos_of_next( regexp, start_row, start_col )
|
372
|
+
row, col = start_row, start_col
|
373
|
+
col = @lines[ row ].index( regexp, col )
|
374
|
+
while col.nil? && row < @lines.length - 1
|
375
|
+
row += 1
|
376
|
+
col = @lines[ row ].index( regexp )
|
377
|
+
end
|
378
|
+
if col
|
379
|
+
[ row, col, Regexp.last_match( 0 ) ]
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
def pos_of_prev( regexp, start_row, start_col )
|
384
|
+
row, col = start_row, start_col
|
385
|
+
if col < 0
|
386
|
+
row -= 1
|
387
|
+
col = -1
|
388
|
+
end
|
389
|
+
return if row < 0
|
390
|
+
|
391
|
+
col = @lines[ row ].rindex( regexp, col )
|
392
|
+
while col.nil? && row > 0
|
393
|
+
row -= 1
|
394
|
+
col = @lines[ row ].rindex( regexp )
|
395
|
+
end
|
396
|
+
if col
|
397
|
+
[ row, col, Regexp.last_match( 0 ) ]
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
def pos_of_pair_match( row = @last_row, col = @last_col )
|
402
|
+
c = @lines[ row ][ col ]
|
403
|
+
data = CHARACTER_PAIRS[ c ]
|
404
|
+
return if data.nil?
|
405
|
+
d = data[ :partner ]
|
406
|
+
c_ = Regexp.escape c
|
407
|
+
d_ = Regexp.escape d
|
408
|
+
target = /(?:#{c_}|#{d_})/
|
409
|
+
|
410
|
+
case data[ :direction ]
|
411
|
+
when :forward
|
412
|
+
row, col, char = pos_of_next( target, row, col + 1 )
|
413
|
+
while char == c # Take care of nested pairs
|
414
|
+
row, col = pos_of_pair_match( row, col )
|
415
|
+
break if col.nil?
|
416
|
+
row, col, char = pos_of_next( target, row, col + 1 )
|
417
|
+
end
|
418
|
+
when :backward
|
419
|
+
row, col, char = pos_of_prev( target, row, col - 1 )
|
420
|
+
while char == c # Take care of nested pairs
|
421
|
+
row, col = pos_of_pair_match( row, col )
|
422
|
+
break if col.nil?
|
423
|
+
row, col, char = pos_of_prev( target, row, col - 1 )
|
424
|
+
end
|
425
|
+
end
|
426
|
+
[ row, col ]
|
427
|
+
end
|
428
|
+
|
429
|
+
def go_to_pair_match
|
430
|
+
row, col = pos_of_pair_match
|
431
|
+
if row && col
|
432
|
+
if cursor_to( row, col )
|
433
|
+
highlight_pair
|
434
|
+
display
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
def highlight_pair
|
440
|
+
match_row, match_col = pos_of_pair_match( @last_row, @last_col )
|
441
|
+
if match_col.nil?
|
442
|
+
@text_marks[ :pair ] = nil
|
443
|
+
else
|
444
|
+
@text_marks[ :pair ] = TextMark.new(
|
445
|
+
::Diakonos::Range.new(match_row, match_col, match_row, match_col + 1),
|
446
|
+
@settings[ "lang.#{@language}.format.pair" ] || @settings[ "lang.shared.format.pair" ]
|
447
|
+
)
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
def clear_pair_highlight
|
452
|
+
@text_marks[ :pair ] = nil
|
453
|
+
end
|
454
|
+
|
455
|
+
def find_again( last_search_regexps, direction = @last_search_direction )
|
456
|
+
if @last_search_regexps.nil? || @last_search_regexps.empty?
|
457
|
+
@last_search_regexps = last_search_regexps
|
458
|
+
end
|
459
|
+
if @last_search_regexps
|
460
|
+
find @last_search_regexps, direction: direction
|
461
|
+
end
|
462
|
+
end
|
463
|
+
|
464
|
+
def seek( regexp, direction = :down )
|
465
|
+
return if regexp.nil? || regexp == //
|
466
|
+
|
467
|
+
found_row = nil
|
468
|
+
found_col = nil
|
469
|
+
found_text = nil
|
470
|
+
|
471
|
+
catch :found do
|
472
|
+
if direction == :down
|
473
|
+
# Check the current row first.
|
474
|
+
|
475
|
+
index, match_text = @lines[ @last_row ].group_index( regexp, @last_col + 1 )
|
476
|
+
if index
|
477
|
+
found_row = @last_row
|
478
|
+
found_col = index
|
479
|
+
found_text = match_text
|
480
|
+
throw :found
|
481
|
+
end
|
482
|
+
|
483
|
+
# Check below the cursor.
|
484
|
+
|
485
|
+
( (@last_row + 1)...@lines.length ).each do |i|
|
486
|
+
index, match_text = @lines[ i ].group_index( regexp )
|
487
|
+
if index
|
488
|
+
found_row = i
|
489
|
+
found_col = index
|
490
|
+
found_text = match_text
|
491
|
+
throw :found
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
else
|
496
|
+
# Check the current row first.
|
497
|
+
|
498
|
+
col_to_check = @last_col - 1
|
499
|
+
if col_to_check >= 0
|
500
|
+
index, match_text = @lines[ @last_row ].group_rindex( regexp, col_to_check )
|
501
|
+
if index
|
502
|
+
found_row = @last_row
|
503
|
+
found_col = index
|
504
|
+
found_text = match_text
|
505
|
+
throw :found
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
# Check above the cursor.
|
510
|
+
|
511
|
+
(@last_row - 1).downto( 0 ) do |i|
|
512
|
+
index, match_text = @lines[ i ].group_rindex( regexp )
|
513
|
+
if index
|
514
|
+
found_row = i
|
515
|
+
found_col = index
|
516
|
+
found_text = match_text
|
517
|
+
throw :found
|
518
|
+
end
|
519
|
+
end
|
520
|
+
end
|
521
|
+
end
|
522
|
+
|
523
|
+
if found_text
|
524
|
+
cursor_to( found_row, found_col )
|
525
|
+
display
|
526
|
+
true
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
# Returns an Array of results, where each result is a String usually
|
531
|
+
# containing \n's due to context
|
532
|
+
def grep( regexp_source )
|
533
|
+
if @name
|
534
|
+
filename = File.basename( @name )
|
535
|
+
filepath = @name
|
536
|
+
else
|
537
|
+
filename = "(unnamed buffer)"
|
538
|
+
filepath = "(unnamed buffer #{object_id})"
|
539
|
+
end
|
540
|
+
|
541
|
+
::Diakonos.grep_array(
|
542
|
+
Regexp.new( regexp_source ),
|
543
|
+
@lines,
|
544
|
+
$diakonos.settings[ 'grep.context' ],
|
545
|
+
"#{filename}:",
|
546
|
+
filepath
|
547
|
+
)
|
548
|
+
end
|
549
|
+
|
550
|
+
end
|
551
|
+
|
552
|
+
end
|