" 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