aboutsummaryrefslogtreecommitdiff
path: root/autoload/hints.vim
blob: 7ab8797be277692e96fbf0660948fc335dfec956 (plain) (blame)
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
" Display qutebrowser-like hints.

" Max number of tags is 105, which is LCM(21, 5)
let s:cons = "bcdfghjklmnpqrstvwxyz" " 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 plugin = hints#plugins#getPluginForFiletype(&ft)
  call plugin.Before(expand("%"))

  let ci = 0
  let vi = 0

  let line = line('w0')
  let endline = line('w$')

  let hints = {}

  while line <= endline
    if plugin.TagLine(line, getline(line))
      let tag=printf("%s%s",
            \ s:cons[ci % len(s:cons)], s:vowel[vi % len(s:vowel)])
      let hints[tag] = line

      " Advance _both_ the consonants and vowels. We want the tags to generally
      " have as little in common as possible.
      let ci += 1
      let vi += 1
    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! 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

  let c2 = getchar()

  call s:cleanup_hints()

  let line = get(hints, nr2char(c1) . nr2char(c2), -1)

  if line >= 0
    if a:visual == 'o'
      norm! V
    endif
    norm m'
    call cursor(line, 1)
    norm ^
  endif
endfunction