1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
" Display qutebrowser-like hints.
" Max number of tags is 105, which is LCM(21, 5)
let s:cons = "tnshrdlcumwfgypkbvjxqz" " 21
let s:vowel = "aeiou" " 5
let s:signs_to_unplace = []
let s:signs_to_undefine = []
let s:sign_index = 5555
if !exists('g:hints_ns')
let g:hints_ns = nvim_create_namespace("")
endif
" Generate hints on the current file. This may use specific plugins for each
" filetype.
function! s:generate_hints() abort
let marklist = getmarklist(bufnr())
let plugin = hints#plugins#getPluginForFiletype(&ft)
call plugin.Before(expand("%"))
let line = line('w0')
let endline = line('w$')
let hints = {}
for i in marklist
let hints[i.mark] = i.pos[1]
endfor
while line <= endline
if plugin.TagLine(line, getline(line))
let tag=printf("%s%s",
\ s:cons[line % len(s:cons)], s:vowel[line % len(s:vowel)])
let hints[tag] = line
endif
let line += 1
endwhile
return hints
endfunction
function! s:display_hints(hints) abort
let s = s:sign_index
for [tag, line] in items(a:hints)
call add(s:signs_to_undefine, "tag_" . tag)
call add(s:signs_to_unplace, s)
"call nvim_buf_set_virtual_text(
" \ 0, g:hints_ns, line - 1, [[tag, "Number"]], {})
exec printf("sign define tag_%s text=%s texthl=Number", tag, tag)
exec printf("sign place %d line=%d name=tag_%s file=%s", s, line, tag, expand('%:p'))
let s += 1
endfor
endfunction
function! s:cleanup_hints() abort
call nvim_buf_clear_namespace(0, g:hints_ns, 0, -1)
for s in s:signs_to_unplace
try
exec printf("sign unplace %d", s)
catch
endtry
endfor
for s in s:signs_to_undefine
try
exec printf("sign undefine %s", s)
catch
endtry
endfor
endfunction
function! s:get(hint_dict, str) abort
if has_key(a:hint_dict, a:str)
return a:hint_dict[a:str]
endif
if len(a:str) == 1 || a:str[0] == a:str[1]
return s:get(a:hint_dict, "'" . a:str[0])
endif
return -1
endfunction
function! hints#runHints(visual) abort
let hints = s:generate_hints()
call s:display_hints(hints)
redraw
let c1 = getchar()
if c1 == 0x1b " Escape
call s:cleanup_hints()
return
endif
if stridx(s:cons, nr2char(c1)) >= 0 || nr2char(c1) == "'"
let c2 = getchar()
else
let c2 = ""
endif
call s:cleanup_hints()
let line = s:get(hints, nr2char(c1) . nr2char(c2))
if line >= 0
if a:visual == 'o'
norm! V
endif
norm m'
call cursor(line, 1)
norm ^
endif
endfunction
|