command-t-standalone 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +20 -0
- data/command-t-standalone.gemspec +22 -0
- data/lib/command-t-standalone.rb +5 -0
- data/lib/command-t-standalone/depend +24 -0
- data/lib/command-t-standalone/ext.c +65 -0
- data/lib/command-t-standalone/ext.h +36 -0
- data/lib/command-t-standalone/extconf.rb +34 -0
- data/lib/command-t-standalone/finder.rb +54 -0
- data/lib/command-t-standalone/finder/file_finder.rb +39 -0
- data/lib/command-t-standalone/match.c +189 -0
- data/lib/command-t-standalone/match.h +29 -0
- data/lib/command-t-standalone/match_window.rb +445 -0
- data/lib/command-t-standalone/matcher.c +164 -0
- data/lib/command-t-standalone/matcher.h +30 -0
- data/lib/command-t-standalone/ruby_compat.h +49 -0
- data/lib/command-t-standalone/scanner.rb +28 -0
- data/lib/command-t-standalone/scanner/file_scanner.rb +110 -0
- data/lib/command-t-standalone/version.rb +3 -0
- metadata +68 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
// Copyright 2010 Wincent Colaiuta. All rights reserved.
|
2
|
+
//
|
3
|
+
// Redistribution and use in source and binary forms, with or without
|
4
|
+
// modification, are permitted provided that the following conditions are met:
|
5
|
+
//
|
6
|
+
// 1. Redistributions of source code must retain the above copyright notice,
|
7
|
+
// this list of conditions and the following disclaimer.
|
8
|
+
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
9
|
+
// this list of conditions and the following disclaimer in the documentation
|
10
|
+
// and/or other materials provided with the distribution.
|
11
|
+
//
|
12
|
+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
13
|
+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
14
|
+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
15
|
+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
|
16
|
+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
17
|
+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
18
|
+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
19
|
+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
20
|
+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
21
|
+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
22
|
+
// POSSIBILITY OF SUCH DAMAGE.
|
23
|
+
|
24
|
+
#include <ruby.h>
|
25
|
+
|
26
|
+
extern VALUE CommandTMatch_initialize(int argc, VALUE *argv, VALUE self);
|
27
|
+
extern VALUE CommandTMatch_matches(VALUE self);
|
28
|
+
extern VALUE CommandTMatch_score(VALUE self);
|
29
|
+
extern VALUE CommandTMatch_to_s(VALUE self);
|
@@ -0,0 +1,445 @@
|
|
1
|
+
# Copyright 2010-2012 Wincent Colaiuta. All rights reserved.
|
2
|
+
#
|
3
|
+
# Redistribution and use in source and binary forms, with or without
|
4
|
+
# modification, are permitted provided that the following conditions are met:
|
5
|
+
#
|
6
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
7
|
+
# this list of conditions and the following disclaimer.
|
8
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer in the documentation
|
10
|
+
# and/or other materials provided with the distribution.
|
11
|
+
#
|
12
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
13
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
14
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
15
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
|
16
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
17
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
18
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
19
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
20
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
21
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
22
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
23
|
+
|
24
|
+
require 'ostruct'
|
25
|
+
require 'command-t/settings'
|
26
|
+
|
27
|
+
module CommandT
|
28
|
+
class MatchWindow
|
29
|
+
SELECTION_MARKER = '> '
|
30
|
+
MARKER_LENGTH = SELECTION_MARKER.length
|
31
|
+
UNSELECTED_MARKER = ' ' * MARKER_LENGTH
|
32
|
+
MH_START = '<commandt>'
|
33
|
+
MH_END = '</commandt>'
|
34
|
+
@@buffer = nil
|
35
|
+
|
36
|
+
def initialize options = {}
|
37
|
+
@prompt = options[:prompt]
|
38
|
+
@reverse_list = options[:match_window_reverse]
|
39
|
+
@min_height = options[:min_height]
|
40
|
+
|
41
|
+
# save existing window dimensions so we can restore them later
|
42
|
+
@windows = []
|
43
|
+
(0..(::VIM::Window.count - 1)).each do |i|
|
44
|
+
@windows << OpenStruct.new(:index => i,
|
45
|
+
:height => ::VIM::Window[i].height,
|
46
|
+
:width => ::VIM::Window[i].width)
|
47
|
+
end
|
48
|
+
|
49
|
+
# global settings (must manually save and restore)
|
50
|
+
@settings = Settings.new
|
51
|
+
::VIM::set_option 'timeout' # ensure mappings timeout
|
52
|
+
::VIM::set_option 'timeoutlen=0' # respond immediately to mappings
|
53
|
+
::VIM::set_option 'nohlsearch' # don't highlight search strings
|
54
|
+
::VIM::set_option 'noinsertmode' # don't make Insert mode the default
|
55
|
+
::VIM::set_option 'noshowcmd' # don't show command info on last line
|
56
|
+
::VIM::set_option 'report=9999' # don't show "X lines changed" reports
|
57
|
+
::VIM::set_option 'sidescroll=0' # don't sidescroll in jumps
|
58
|
+
::VIM::set_option 'sidescrolloff=0' # don't sidescroll automatically
|
59
|
+
::VIM::set_option 'noequalalways' # don't auto-balance window sizes
|
60
|
+
|
61
|
+
# show match window
|
62
|
+
split_location = options[:match_window_at_top] ? 'topleft' : 'botright'
|
63
|
+
if @@buffer # still have buffer from last time
|
64
|
+
::VIM::command "silent! #{split_location} #{@@buffer.number}sbuffer"
|
65
|
+
raise "Can't re-open GoToFile buffer" unless $curbuf.number == @@buffer.number
|
66
|
+
$curwin.height = 1
|
67
|
+
else # creating match window for first time and set it up
|
68
|
+
split_command = "silent! #{split_location} 1split GoToFile"
|
69
|
+
[
|
70
|
+
split_command,
|
71
|
+
'setlocal bufhidden=unload', # unload buf when no longer displayed
|
72
|
+
'setlocal buftype=nofile', # buffer is not related to any file
|
73
|
+
'setlocal nomodifiable', # prevent manual edits
|
74
|
+
'setlocal noswapfile', # don't create a swapfile
|
75
|
+
'setlocal nowrap', # don't soft-wrap
|
76
|
+
'setlocal nonumber', # don't show line numbers
|
77
|
+
'setlocal nolist', # don't use List mode (visible tabs etc)
|
78
|
+
'setlocal foldcolumn=0', # don't show a fold column at side
|
79
|
+
'setlocal foldlevel=99', # don't fold anything
|
80
|
+
'setlocal nocursorline', # don't highlight line cursor is on
|
81
|
+
'setlocal nospell', # spell-checking off
|
82
|
+
'setlocal nobuflisted', # don't show up in the buffer list
|
83
|
+
'setlocal textwidth=0' # don't hard-wrap (break long lines)
|
84
|
+
].each { |command| ::VIM::command command }
|
85
|
+
|
86
|
+
# don't show the color column
|
87
|
+
::VIM::command 'setlocal colorcolumn=0' if VIM::exists?('+colorcolumn')
|
88
|
+
|
89
|
+
# don't show relative line numbers
|
90
|
+
::VIM::command 'setlocal norelativenumber' if VIM::exists?('+relativenumber')
|
91
|
+
|
92
|
+
# sanity check: make sure the buffer really was created
|
93
|
+
raise "Can't find GoToFile buffer" unless $curbuf.name.match /GoToFile\z/
|
94
|
+
@@buffer = $curbuf
|
95
|
+
end
|
96
|
+
|
97
|
+
# syntax coloring
|
98
|
+
if VIM::has_syntax?
|
99
|
+
::VIM::command "syntax match CommandTSelection \"^#{SELECTION_MARKER}.\\+$\""
|
100
|
+
::VIM::command 'syntax match CommandTNoEntries "^-- NO MATCHES --$"'
|
101
|
+
::VIM::command 'syntax match CommandTNoEntries "^-- NO SUCH FILE OR DIRECTORY --$"'
|
102
|
+
::VIM::command 'setlocal synmaxcol=9999'
|
103
|
+
|
104
|
+
if VIM::has_conceal?
|
105
|
+
::VIM::command 'setlocal conceallevel=2'
|
106
|
+
::VIM::command 'setlocal concealcursor=nvic'
|
107
|
+
::VIM::command 'syntax region CommandTCharMatched ' \
|
108
|
+
"matchgroup=CommandTCharMatched start=+#{MH_START}+ " \
|
109
|
+
"matchgroup=CommandTCharMatchedEnd end=+#{MH_END}+ concealends"
|
110
|
+
::VIM::command 'highlight def CommandTCharMatched ' \
|
111
|
+
'term=bold,underline cterm=bold,underline ' \
|
112
|
+
'gui=bold,underline'
|
113
|
+
end
|
114
|
+
|
115
|
+
::VIM::command 'highlight link CommandTSelection Visual'
|
116
|
+
::VIM::command 'highlight link CommandTNoEntries Error'
|
117
|
+
::VIM::evaluate 'clearmatches()'
|
118
|
+
|
119
|
+
# hide cursor
|
120
|
+
@cursor_highlight = get_cursor_highlight
|
121
|
+
hide_cursor
|
122
|
+
end
|
123
|
+
|
124
|
+
# perform cleanup using an autocmd to ensure we don't get caught out
|
125
|
+
# by some unexpected means of dismissing or leaving the Command-T window
|
126
|
+
# (eg. <C-W q>, <C-W k> etc)
|
127
|
+
::VIM::command 'autocmd! * <buffer>'
|
128
|
+
::VIM::command 'autocmd BufLeave <buffer> silent! ruby $command_t.leave'
|
129
|
+
::VIM::command 'autocmd BufUnload <buffer> silent! ruby $command_t.unload'
|
130
|
+
|
131
|
+
@has_focus = false
|
132
|
+
@selection = nil
|
133
|
+
@abbrev = ''
|
134
|
+
@window = $curwin
|
135
|
+
end
|
136
|
+
|
137
|
+
def close
|
138
|
+
# Unlisted buffers like those provided by Netrw, NERDTree and Vim's help
|
139
|
+
# don't actually appear in the buffer list; if they are the only such
|
140
|
+
# buffers present when Command-T is invoked (for example, when invoked
|
141
|
+
# immediately after starting Vim with a directory argument, like `vim .`)
|
142
|
+
# then performing the normal clean-up will yield an "E90: Cannot unload
|
143
|
+
# last buffer" error. We can work around that by doing a :quit first.
|
144
|
+
if ::VIM::Buffer.count == 0
|
145
|
+
::VIM::command 'silent quit'
|
146
|
+
end
|
147
|
+
|
148
|
+
# Workaround for upstream bug in Vim 7.3 on some platforms
|
149
|
+
#
|
150
|
+
# On some platforms, $curbuf.number always returns 0. One workaround is
|
151
|
+
# to build Vim with --disable-largefile, but as this is producing lots of
|
152
|
+
# support requests, implement the following fallback to the buffer name
|
153
|
+
# instead, at least until upstream gets fixed.
|
154
|
+
#
|
155
|
+
# For more details, see: https://wincent.com/issues/1617
|
156
|
+
if $curbuf.number == 0
|
157
|
+
# use bwipeout as bunload fails if passed the name of a hidden buffer
|
158
|
+
::VIM::command 'silent! bwipeout! GoToFile'
|
159
|
+
@@buffer = nil
|
160
|
+
else
|
161
|
+
::VIM::command "silent! bunload! #{@@buffer.number}"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def leave
|
166
|
+
close
|
167
|
+
unload
|
168
|
+
end
|
169
|
+
|
170
|
+
def unload
|
171
|
+
restore_window_dimensions
|
172
|
+
@settings.restore
|
173
|
+
@prompt.dispose
|
174
|
+
show_cursor
|
175
|
+
end
|
176
|
+
|
177
|
+
def add! char
|
178
|
+
@abbrev += char
|
179
|
+
end
|
180
|
+
|
181
|
+
def backspace!
|
182
|
+
@abbrev.chop!
|
183
|
+
end
|
184
|
+
|
185
|
+
def select_next
|
186
|
+
if @selection < @matches.length - 1
|
187
|
+
@selection += 1
|
188
|
+
print_match(@selection - 1) # redraw old selection (removes marker)
|
189
|
+
print_match(@selection) # redraw new selection (adds marker)
|
190
|
+
move_cursor_to_selected_line
|
191
|
+
else
|
192
|
+
# (possibly) loop or scroll
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def select_prev
|
197
|
+
if @selection > 0
|
198
|
+
@selection -= 1
|
199
|
+
print_match(@selection + 1) # redraw old selection (removes marker)
|
200
|
+
print_match(@selection) # redraw new selection (adds marker)
|
201
|
+
move_cursor_to_selected_line
|
202
|
+
else
|
203
|
+
# (possibly) loop or scroll
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def matches= matches
|
208
|
+
matches = matches.reverse if @reverse_list
|
209
|
+
if matches != @matches
|
210
|
+
@matches = matches
|
211
|
+
@selection = @reverse_list ? @matches.length - 1 : 0
|
212
|
+
print_matches
|
213
|
+
move_cursor_to_selected_line
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def focus
|
218
|
+
unless @has_focus
|
219
|
+
@has_focus = true
|
220
|
+
if VIM::has_syntax?
|
221
|
+
::VIM::command 'highlight link CommandTSelection Search'
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def unfocus
|
227
|
+
if @has_focus
|
228
|
+
@has_focus = false
|
229
|
+
if VIM::has_syntax?
|
230
|
+
::VIM::command 'highlight link CommandTSelection Visual'
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def find char
|
236
|
+
# is this a new search or the continuation of a previous one?
|
237
|
+
now = Time.now
|
238
|
+
if @last_key_time.nil? or @last_key_time < (now - 0.5)
|
239
|
+
@find_string = char
|
240
|
+
else
|
241
|
+
@find_string += char
|
242
|
+
end
|
243
|
+
@last_key_time = now
|
244
|
+
|
245
|
+
# see if there's anything up ahead that matches
|
246
|
+
@matches.each_with_index do |match, idx|
|
247
|
+
if match[0, @find_string.length].casecmp(@find_string) == 0
|
248
|
+
old_selection = @selection
|
249
|
+
@selection = idx
|
250
|
+
print_match(old_selection) # redraw old selection (removes marker)
|
251
|
+
print_match(@selection) # redraw new selection (adds marker)
|
252
|
+
break
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
# Returns the currently selected item as a String.
|
258
|
+
def selection
|
259
|
+
@matches[@selection]
|
260
|
+
end
|
261
|
+
|
262
|
+
def print_no_such_file_or_directory
|
263
|
+
print_error 'NO SUCH FILE OR DIRECTORY'
|
264
|
+
end
|
265
|
+
|
266
|
+
private
|
267
|
+
|
268
|
+
def move_cursor_to_selected_line
|
269
|
+
# on some non-GUI terminals, the cursor doesn't hide properly
|
270
|
+
# so we move the cursor to prevent it from blinking away in the
|
271
|
+
# upper-left corner in a distracting fashion
|
272
|
+
@window.cursor = [@selection + 1, 0]
|
273
|
+
end
|
274
|
+
|
275
|
+
def print_error msg
|
276
|
+
return unless VIM::Window.select(@window)
|
277
|
+
unlock
|
278
|
+
clear
|
279
|
+
@window.height = @min_height > 0 ? @min_height : 1
|
280
|
+
@@buffer[1] = "-- #{msg} --"
|
281
|
+
lock
|
282
|
+
end
|
283
|
+
|
284
|
+
def restore_window_dimensions
|
285
|
+
# sort from tallest to shortest, tie-breaking on window width
|
286
|
+
@windows.sort! do |a, b|
|
287
|
+
order = b.height <=> a.height
|
288
|
+
if order.zero?
|
289
|
+
b.width <=> a.width
|
290
|
+
else
|
291
|
+
order
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
# starting with the tallest ensures that there are no constraints
|
296
|
+
# preventing windows on the side of vertical splits from regaining
|
297
|
+
# their original full size
|
298
|
+
@windows.each do |w|
|
299
|
+
# beware: window may be nil
|
300
|
+
if window = ::VIM::Window[w.index]
|
301
|
+
window.height = w.height
|
302
|
+
window.width = w.width
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
def match_text_for_idx idx
|
308
|
+
match = truncated_match @matches[idx].to_s
|
309
|
+
if idx == @selection
|
310
|
+
prefix = SELECTION_MARKER
|
311
|
+
suffix = padding_for_selected_match match
|
312
|
+
else
|
313
|
+
if VIM::has_syntax? && VIM::has_conceal?
|
314
|
+
match = match_with_syntax_highlight match
|
315
|
+
end
|
316
|
+
prefix = UNSELECTED_MARKER
|
317
|
+
suffix = ''
|
318
|
+
end
|
319
|
+
prefix + match + suffix
|
320
|
+
end
|
321
|
+
|
322
|
+
# Highlight matching characters within the matched string.
|
323
|
+
#
|
324
|
+
# Note that this is only approximate; it will highlight the first matching
|
325
|
+
# instances within the string, which may not actually be the instances that
|
326
|
+
# were used by the matching/scoring algorithm to determine the best score
|
327
|
+
# for the match.
|
328
|
+
#
|
329
|
+
def match_with_syntax_highlight match
|
330
|
+
highlight_chars = @prompt.abbrev.downcase.chars.to_a
|
331
|
+
match.chars.inject([]) do |output, char|
|
332
|
+
if char.downcase == highlight_chars.first
|
333
|
+
highlight_chars.shift
|
334
|
+
output.concat [MH_START, char, MH_END]
|
335
|
+
else
|
336
|
+
output << char
|
337
|
+
end
|
338
|
+
end.join
|
339
|
+
end
|
340
|
+
|
341
|
+
# Print just the specified match.
|
342
|
+
def print_match idx
|
343
|
+
return unless VIM::Window.select(@window)
|
344
|
+
unlock
|
345
|
+
@@buffer[idx + 1] = match_text_for_idx idx
|
346
|
+
lock
|
347
|
+
end
|
348
|
+
|
349
|
+
# Print all matches.
|
350
|
+
def print_matches
|
351
|
+
match_count = @matches.length
|
352
|
+
if match_count == 0
|
353
|
+
print_error 'NO MATCHES'
|
354
|
+
else
|
355
|
+
return unless VIM::Window.select(@window)
|
356
|
+
unlock
|
357
|
+
clear
|
358
|
+
actual_lines = 1
|
359
|
+
@window_width = @window.width # update cached value
|
360
|
+
max_lines = VIM::Screen.lines - 5
|
361
|
+
max_lines = 1 if max_lines < 0
|
362
|
+
actual_lines = match_count < @min_height ? @min_height : match_count
|
363
|
+
actual_lines = max_lines if actual_lines > max_lines
|
364
|
+
@window.height = actual_lines
|
365
|
+
(1..actual_lines).each do |line|
|
366
|
+
idx = line - 1
|
367
|
+
if @@buffer.count >= line
|
368
|
+
@@buffer[line] = match_text_for_idx idx
|
369
|
+
else
|
370
|
+
@@buffer.append line - 1, match_text_for_idx(idx)
|
371
|
+
end
|
372
|
+
end
|
373
|
+
lock
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
# Prepare padding for match text (trailing spaces) so that selection
|
378
|
+
# highlighting extends all the way to the right edge of the window.
|
379
|
+
def padding_for_selected_match str
|
380
|
+
len = str.length
|
381
|
+
if len >= @window_width - MARKER_LENGTH
|
382
|
+
''
|
383
|
+
else
|
384
|
+
' ' * (@window_width - MARKER_LENGTH - len)
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
# Convert "really/long/path" into "really...path" based on available
|
389
|
+
# window width.
|
390
|
+
def truncated_match str
|
391
|
+
len = str.length
|
392
|
+
available_width = @window_width - MARKER_LENGTH
|
393
|
+
return str if len <= available_width
|
394
|
+
left = (available_width / 2) - 1
|
395
|
+
right = (available_width / 2) - 2 + (available_width % 2)
|
396
|
+
str[0, left] + '...' + str[-right, right]
|
397
|
+
end
|
398
|
+
|
399
|
+
def clear
|
400
|
+
# range = % (whole buffer)
|
401
|
+
# action = d (delete)
|
402
|
+
# register = _ (black hole register, don't record deleted text)
|
403
|
+
::VIM::command 'silent %d _'
|
404
|
+
end
|
405
|
+
|
406
|
+
def get_cursor_highlight
|
407
|
+
# there are 3 possible formats to check for, each needing to be
|
408
|
+
# transformed in a certain way in order to reapply the highlight:
|
409
|
+
# Cursor xxx guifg=bg guibg=fg -> :hi! Cursor guifg=bg guibg=fg
|
410
|
+
# Cursor xxx links to SomethingElse -> :hi! link Cursor SomethingElse
|
411
|
+
# Cursor xxx cleared -> :hi! clear Cursor
|
412
|
+
highlight = VIM::capture 'silent! 0verbose highlight Cursor'
|
413
|
+
|
414
|
+
if highlight =~ /^Cursor\s+xxx\s+links to (\w+)/
|
415
|
+
"link Cursor #{$~[1]}"
|
416
|
+
elsif highlight =~ /^Cursor\s+xxx\s+cleared/
|
417
|
+
'clear Cursor'
|
418
|
+
elsif highlight =~ /Cursor\s+xxx\s+(.+)/
|
419
|
+
"Cursor #{$~[1]}"
|
420
|
+
else # likely cause E411 Cursor highlight group not found
|
421
|
+
nil
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
def hide_cursor
|
426
|
+
if @cursor_highlight
|
427
|
+
::VIM::command 'highlight Cursor NONE'
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
def show_cursor
|
432
|
+
if @cursor_highlight
|
433
|
+
::VIM::command "highlight #{@cursor_highlight}"
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
def lock
|
438
|
+
::VIM::command 'setlocal nomodifiable'
|
439
|
+
end
|
440
|
+
|
441
|
+
def unlock
|
442
|
+
::VIM::command 'setlocal modifiable'
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|