File: ui.vim

package info (click to toggle)
vim-vimtex 2.17-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 8,844 kB
  • sloc: makefile: 360; python: 103
file content (213 lines) | stat: -rw-r--r-- 5,530 bytes parent folder | download
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
" VimTeX - LaTeX plugin for Vim
"
" Maintainer: Karl Yngve LervÄg
" Email:      karl.yngve@gmail.com
"

function! vimtex#ui#echo(input, ...) abort
  if empty(a:input) | return | endif
  let l:opts = extend({'indent': 0}, a:0 > 0 ? a:1 : {})

  if type(a:input) == v:t_string
    call s:echo_string(a:input, l:opts)
  elseif type(a:input) == v:t_list
    call s:echo_formatted(a:input, l:opts)
  elseif type(a:input) == v:t_dict
    call s:echo_dict(a:input, l:opts)
  else
    call vimtex#log#warn('Argument not supported: ' . type(a:input))
  endif
endfunction

function! vimtex#ui#confirm(prompt) abort
  return vimtex#ui#{g:vimtex_ui_method.confirm}#confirm(a:prompt)
endfunction

function! vimtex#ui#input(options) abort
  let l:options = extend({
        \ 'prompt': '> ',
        \ 'text': '',
        \ 'info': '',
        \}, a:options)

  return vimtex#ui#{g:vimtex_ui_method.input}#input(l:options)
endfunction

function! vimtex#ui#menu(actions) abort
  " Argument: The 'actions' argument is a dictionary/object which contains
  "   a list of menu items and corresponding actions (dict functions).
  "   Something like this:
  "
  "   let a:actions = {
  "         \ 'prompt': 'Prompt string for menu',
  "         \ 'menu': [
  "         \   {'name': 'My first action',
  "         \    'func': 'action1'},
  "         \   {'name': 'My second action',
  "         \    'func': 'action2'},
  "         \   ...
  "         \ ],
  "         \ 'action1': Func,
  "         \ 'action2': Func,
  "         \ ...
  "         \}
  if empty(a:actions) | return | endif

  let l:choice = vimtex#ui#select(a:actions.menu, {
        \ 'prompt': a:actions.prompt,
        \})
  if empty(l:choice) | return | endif

  try
    call a:actions[l:choice.func]()
  catch
    " error here
  endtry
endfunction

function! vimtex#ui#select(container, ...) abort
  let l:options = extend(
        \ {
        \   'prompt': 'Please choose item:',
        \   'return': 'value',
        \   'force_choice': v:false,
        \   'auto_select': v:true,
        \ },
        \ a:0 > 0 ? a:1 : {})

  let l:list = type(a:container) == v:t_dict
        \ ? values(a:container)
        \ : a:container
  let [l:index, l:value] = empty(l:list)
        \ ? [-1, '']
        \ : (len(l:list) == 1 && l:options.auto_select
        \   ? [0, l:list[0]]
        \   : vimtex#ui#{g:vimtex_ui_method.select}#select(l:options, l:list))

  if l:options.return ==# 'value'
    return l:value
  endif

  if type(a:container) == v:t_dict
    return l:index >= 0 ? keys(a:container)[l:index] : ''
  endif

  return l:index
endfunction

function! vimtex#ui#get_number(max, digits, force_choice, do_echo) abort
  let l:choice = ''

  if a:do_echo
    echo '> '
  endif

  while len(l:choice) < a:digits
    if len(l:choice) > 0 && (l:choice . '0') > a:max
      return l:choice - 1
    endif

    let l:input = nr2char(getchar())

    if !a:force_choice && index(["\<C-c>", "\<Esc>", 'x'], l:input) >= 0
      if a:do_echo
        echon 'aborted!'
      endif
      return -2
    endif

    if len(l:choice) > 0 && l:input ==# "\<cr>"
      return l:choice - 1
    endif

    if l:input !~# '\d' | continue | endif

    if (l:choice . l:input) > 0
      let l:choice .= l:input
      if a:do_echo
        echon l:input
      endif
    endif
  endwhile

  return l:choice - 1
endfunction

function! vimtex#ui#get_winwidth() abort
  let l:numwidth = (&number || &relativenumber)
        \ ? max([&numberwidth, strlen(line('$')) + 1])
        \ : 0
  let l:foldwidth = str2nr(matchstr(&foldcolumn, '\d\+$'))

  " Get width of signcolumn
  " Note: A signcolumn is 2-char wide, so in some cases we multiply by 2
  if &signcolumn ==# 'yes'
    let l:signwidth = 2
  elseif &signcolumn =~# 'yes'
    let l:signwidth = 2*split(&signcolumn, ':')[1]
  elseif &signcolumn ==# 'auto'
    let l:signlist = split(execute(
          \ printf('sign place %s buffer=%d',
          \   has('nvim-0.4.2') || has('patch-8.1.614') ? 'group=*' : '',
          \   bufnr())), "\n")
    let l:signwidth = len(l:signlist) > 2 ? 2 : 0
  elseif &signcolumn =~# 'auto'
    " Get number of signs on each line that has a sign
    let l:sign_lenths = map(
          \ sign_getplaced(bufnr(), {'group': '*'})[0].signs,
          \ { _, x -> len(
          \   sign_getplaced(bufnr(),
          \                  {'group': '*', 'lnum': x.lnum})[0].signs)})
    let l:signwidth = 2*max(l:sign_lenths)
  else
    let l:signwidth = 0
  endif

  return winwidth(0) - l:numwidth - l:foldwidth - l:signwidth
endfunction

function! vimtex#ui#blink() abort
  call sign_define('vimtexblink', #{ linehl: 'VimtexBlink' })

  for i in range(1, 4)
    call sign_place(1, 'vimtex', 'vimtexblink', '', #{ lnum: '.' })
    redraw
    sleep 150m
    call sign_unplace('vimtex')
    redraw
    sleep 150m
  endfor

  call sign_undefine("vimtexblink")
endfunction


function! s:echo_string(msg, opts) abort
  echohl VimtexMsg
  echo repeat(' ', a:opts.indent) . a:msg
  echohl None
endfunction

function! s:echo_formatted(parts, opts) abort
  echo repeat(' ', a:opts.indent)
  try
    for l:part in a:parts
      if type(l:part) == v:t_string
        echohl VimtexMsg
        echon l:part
      else
        execute 'echohl' l:part[0]
        echon l:part[1]
      endif
      unlet l:part
    endfor
  finally
    echohl None
  endtry
endfunction

function! s:echo_dict(dict, opts) abort
  for [l:key, l:val] in items(a:dict)
    call s:echo_formatted([['Label', l:key . ': '], l:val], a:opts)
  endfor
endfunction