@@ -20,6 +20,21 @@ let s:TRUE = !0
20
20
let s: FALSE = 0
21
21
let s: DIRECTION = {' forward' : 0 , ' backward' : 1 }
22
22
23
+ " Check Vim version
24
+ function ! s: has_patch (major, minor, patch) abort
25
+ let l: version = (a: major * 100 + a: minor )
26
+ return has (' patch-' . a: major . ' .' . a: minor . ' .' . a: patch ) ||
27
+ \ (v: version > l: version ) ||
28
+ \ (v: version == l: version && ' patch' . a: patch )
29
+ endfunction
30
+
31
+ " matchadd('Conceal', {pattern}, {priority}, -1, {'conceal': {char}}}) can
32
+ " highlight pattern and conceal target correctly even if the target is keyword
33
+ " characters.
34
+ " - http://ftp.vim.org/vim/patches/7.4/7.4.792
35
+ " - https://groups.google.com/forum/#!searchin/vim_dev/matchadd$20conceal/vim_dev/8bKa98GhHdk/VOzIBhd1m8YJ
36
+ let s: can_preserve_syntax = s: has_patch (7 , 4 , 792 )
37
+
23
38
" s:move() moves cursor over/accross window with Hit-A-Hint feature like
24
39
" vim-easymotion
25
40
" @param {dict} config
@@ -251,14 +266,22 @@ let s:Hinter = {
251
266
function ! s: Hinter .new (hint_dict, config) abort
252
267
let s = deepcopy (self )
253
268
let s .config = a: config
254
- let win2pos2hint = s: create_win2pos2hint (a: hint_dict )
255
- let s .winnrs = sort (map (keys (win2pos2hint), ' str2nr(v:val)' ))
256
- let s .win2pos2hint = win2pos2hint
257
- let s .w2l2c2h = s: win2pos2hint_to_w2l2c2h (win2pos2hint)
258
- call s ._save_lines ()
269
+ call s .init (a: hint_dict )
259
270
return s
260
271
endfunction
261
272
273
+ function ! s: Hinter .init (hint_dict) abort
274
+ let win2pos2hint = s: create_win2pos2hint (a: hint_dict )
275
+ let self .winnrs = sort (map (keys (win2pos2hint), ' str2nr(v:val)' ))
276
+ let self .win2pos2hint = win2pos2hint
277
+ let self .w2l2c2h = s: win2pos2hint_to_w2l2c2h (win2pos2hint)
278
+ let self .hl_target_ids = {}
279
+ for winnr in self .winnrs
280
+ let self .hl_target_ids[winnr ] = []
281
+ endfor
282
+ call self ._save_lines ()
283
+ endfunction
284
+
262
285
function ! s: Hinter .before () abort
263
286
let self .highlight_id_cursor = matchadd (' Cursor' , ' \%#' , 101 )
264
287
call self .save_options ()
@@ -322,28 +345,32 @@ function! s:Hinter.modify_env_for_win(winnr) abort
322
345
setlocal modifiable
323
346
setlocal noreadonly
324
347
325
- ownsyntax overwin
348
+ if ! s: can_preserve_syntax
349
+ ownsyntax overwin
350
+ endif
351
+
326
352
setlocal conceallevel= 2
327
353
setlocal concealcursor= ncv
328
354
329
355
let self .highlight_ids[a: winnr ] = get (self .highlight_ids, a: winnr , [])
330
356
if self .config.do_shade
331
- syntax clear
357
+ if ! s: can_preserve_syntax
358
+ syntax clear
359
+ endif
332
360
let self .highlight_ids[a: winnr ] += [matchadd (self .config.highlight .shade, ' \_.*' , 100 )]
333
361
endif
334
362
endfunction
335
363
336
364
function ! s: Hinter .restore_env () abort
337
- syntax clear HitAHintTarget
338
365
call s: PHighlight .set (' Conceal' , self .save_conceal)
339
366
let nr = winnr ()
340
367
try
341
368
for winnr in self .winnrs
342
369
call s: move_to_win (winnr )
343
370
call self .restore_lines_for_win (winnr )
344
- " Clear syntax defined by Hit-A-Hint motion before restoring syntax.
345
- syntax clear HitAHintTarget
346
- if self .config.do_shade
371
+ call self . remove_hints ( winnr )
372
+
373
+ if ! s: can_preserve_syntax && self .config.do_shade
347
374
let &syntax = self .save_syntax[winnr ]
348
375
endif
349
376
@@ -470,7 +497,7 @@ function! s:Hinter._show_hint_for_win(winnr) abort
470
497
endif
471
498
execute ' highlight! link Conceal' self .config.highlight .target
472
499
for [lnum, cnum, char] in hints
473
- call s: show_hint_pos (lnum, cnum, char)
500
+ call self . show_hint_pos (lnum, cnum, char, a: winnr )
474
501
endfor
475
502
endfunction
476
503
@@ -520,11 +547,12 @@ endfunction
520
547
function ! s: Hinter ._replace_line_for_hint (lnum, col_num, line , hint) abort
521
548
let line = a: line
522
549
let col_num = a: col_num
550
+ let do_replace_target = ! (self .config.do_shade || s: can_preserve_syntax )
523
551
let target = matchstr (line , ' \%' . col_num .' c.' )
524
552
" Append one space for empty line or match at end of line
525
553
if target is # ' '
526
554
let hintwidth = strdisplaywidth (join (a: hint [:1 ], ' ' ))
527
- let char = self .config.do_shade ? ' ' : ' .'
555
+ let char = do_replace_target ? ' ' : ' .'
528
556
let line .= repeat (char, hintwidth)
529
557
return [line , hintwidth, 0 ]
530
558
endif
@@ -536,7 +564,7 @@ function! s:Hinter._replace_line_for_hint(lnum, col_num, line, hint) abort
536
564
let line = self ._replace_text_to_space (line , a: lnum , col_num, strdisplaywidth (target))
537
565
let offset = strdisplaywidth (target) - len (target)
538
566
else
539
- if ! self .config.do_shade
567
+ if do_replace_target
540
568
" The priority of :syn-cchar is always under the priority of keywords.
541
569
" So, Hit-A-Hint replaces targets character with '.'.
542
570
let space = ' .'
@@ -566,6 +594,26 @@ function! s:Hinter._replace_text_to_space(line, lnum, col_num, len) abort
566
594
return line
567
595
endfunction
568
596
597
+ function ! s: Hinter .show_hint_pos (lnum, cnum, char, winnr ) abort
598
+ let p = ' \%' . a: lnum . ' l\%' . a: cnum . ' c.'
599
+ if s: can_preserve_syntax
600
+ let self .hl_target_ids[a: winnr ] += [matchadd (' Conceal' , p , 101 , -1 , {' conceal' : a: char })]
601
+ else
602
+ exec " syntax match HitAHintTarget '" . p . " ' contains=NONE containedin=.* conceal cchar=" . a: char
603
+ endif
604
+ endfunction
605
+
606
+ function ! s: Hinter .remove_hints (winnr ) abort
607
+ if s: can_preserve_syntax
608
+ for id in self .hl_target_ids[a: winnr ]
609
+ call matchdelete (id)
610
+ endfor
611
+ else
612
+ " Clear syntax defined by Hit-A-Hint motion before restoring syntax.
613
+ syntax clear HitAHintTarget
614
+ endif
615
+ endfunction
616
+
569
617
" @param {number} col_num col_num is 1 origin like col()
570
618
function ! s: tab2spacelen (line , col_num) abort
571
619
let before_line = a: col_num > 2 ? a: line [: a: col_num - 2 ]
@@ -705,11 +753,6 @@ function! s:wincall(func, arglist, ...) abort
705
753
return r
706
754
endfunction
707
755
708
- function ! s: show_hint_pos (lnum, cnum, char) abort
709
- let p = ' \%' . a: lnum . ' l\%' . a: cnum . ' c.'
710
- exec " syntax match HitAHintTarget '" . p . " ' contains=NONE containedin=.* conceal cchar=" . a: char
711
- endfunction
712
-
713
756
" deepextend (nest: 1)
714
757
function ! s: deepextend (expr1, expr2) abort
715
758
let expr2 = copy (a: expr2 )
0 commit comments