summaryrefslogtreecommitdiffstats
path: root/autoload/vimtex/util.vim
diff options
context:
space:
mode:
Diffstat (limited to 'autoload/vimtex/util.vim')
-rw-r--r--autoload/vimtex/util.vim273
1 files changed, 273 insertions, 0 deletions
diff --git a/autoload/vimtex/util.vim b/autoload/vimtex/util.vim
new file mode 100644
index 00000000..eccf466e
--- /dev/null
+++ b/autoload/vimtex/util.vim
@@ -0,0 +1,273 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
+
+" vimtex - LaTeX plugin for Vim
+"
+" Maintainer: Karl Yngve Lervåg
+" Email: karl.yngve@gmail.com
+"
+
+function! vimtex#util#command(cmd) abort " {{{1
+ let l:a = @a
+ try
+ silent! redir @a
+ silent! execute a:cmd
+ redir END
+ finally
+ let l:res = @a
+ let @a = l:a
+ return split(l:res, "\n")
+ endtry
+endfunction
+
+" }}}1
+function! vimtex#util#flatten(list) abort " {{{1
+ let l:result = []
+
+ for l:element in a:list
+ if type(l:element) == type([])
+ call extend(l:result, vimtex#util#flatten(l:element))
+ else
+ call add(l:result, l:element)
+ endif
+ unlet l:element
+ endfor
+
+ return l:result
+endfunction
+
+" }}}1
+function! vimtex#util#get_os() abort " {{{1
+ if has('win32') || has('win32unix')
+ return 'win'
+ elseif has('unix')
+ if has('mac') || system('uname') =~# 'Darwin'
+ return 'mac'
+ else
+ return 'linux'
+ endif
+ endif
+endfunction
+
+" }}}1
+function! vimtex#util#in_comment(...) abort " {{{1
+ return call('vimtex#util#in_syntax', ['texComment'] + a:000)
+endfunction
+
+" }}}1
+function! vimtex#util#in_mathzone(...) abort " {{{1
+ return call('vimtex#util#in_syntax', ['texMathZone'] + a:000)
+endfunction
+
+" }}}1
+function! vimtex#util#in_syntax(name, ...) abort " {{{1
+
+ " Usage: vimtex#util#in_syntax(name, [line, col])
+
+ " Get position and correct it if necessary
+ let l:pos = a:0 > 0 ? [a:1, a:2] : [line('.'), col('.')]
+ if mode() ==# 'i'
+ let l:pos[1] -= 1
+ endif
+ call map(l:pos, 'max([v:val, 1])')
+
+ " Check syntax at position
+ return match(map(synstack(l:pos[0], l:pos[1]),
+ \ "synIDattr(v:val, 'name')"),
+ \ '^' . a:name) >= 0
+endfunction
+
+" }}}1
+function! vimtex#util#extend_recursive(dict1, dict2, ...) abort " {{{1
+ let l:option = a:0 > 0 ? a:1 : 'force'
+ if index(['force', 'keep', 'error'], l:option) < 0
+ throw 'E475: Invalid argument: ' . l:option
+ endif
+
+ for [l:key, l:value] in items(a:dict2)
+ if !has_key(a:dict1, l:key)
+ let a:dict1[l:key] = l:value
+ elseif type(l:value) == type({})
+ call vimtex#util#extend_recursive(a:dict1[l:key], l:value, l:option)
+ elseif l:option ==# 'error'
+ throw 'E737: Key already exists: ' . l:key
+ elseif l:option ==# 'force'
+ let a:dict1[l:key] = l:value
+ endif
+ unlet l:value
+ endfor
+
+ return a:dict1
+endfunction
+
+" }}}1
+function! vimtex#util#shellescape(cmd) abort " {{{1
+ "
+ " Path used in "cmd" only needs to be enclosed by double quotes.
+ " shellescape() on Windows with "shellslash" set will produce a path
+ " enclosed by single quotes, which "cmd" does not recognize and reports an
+ " error.
+ "
+ if has('win32')
+ let l:shellslash = &shellslash
+ set noshellslash
+ let l:cmd = escape(shellescape(a:cmd), '\')
+ let &shellslash = l:shellslash
+ return l:cmd
+ else
+ return escape(shellescape(a:cmd), '\')
+ endif
+endfunction
+
+" }}}1
+function! vimtex#util#tex2unicode(line) abort " {{{1
+ " Convert compositions to unicode
+ let l:line = a:line
+ for [l:pat, l:symbol] in s:tex2unicode_list
+ let l:line = substitute(l:line, l:pat, l:symbol, 'g')
+ endfor
+
+ " Remove the \IeC macro
+ let l:line = substitute(l:line, '\\IeC\s*{\s*\([^}]\{-}\)\s*}', '\1', 'g')
+
+ return l:line
+endfunction
+
+"
+" Define list for converting compositions like \"u to unicode ű
+let s:tex2unicode_list = [
+ \ ['\\''A', 'Á'],
+ \ ['\\`A', 'À'],
+ \ ['\\^A', 'À'],
+ \ ['\\¨A', 'Ä'],
+ \ ['\\"A', 'Ä'],
+ \ ['\\''a', 'á'],
+ \ ['\\`a', 'à'],
+ \ ['\\^a', 'à'],
+ \ ['\\¨a', 'ä'],
+ \ ['\\"a', 'ä'],
+ \ ['\\\~a', 'ã'],
+ \ ['\\''E', 'É'],
+ \ ['\\`E', 'È'],
+ \ ['\\^E', 'Ê'],
+ \ ['\\¨E', 'Ë'],
+ \ ['\\"E', 'Ë'],
+ \ ['\\''e', 'é'],
+ \ ['\\`e', 'è'],
+ \ ['\\^e', 'ê'],
+ \ ['\\¨e', 'ë'],
+ \ ['\\"e', 'ë'],
+ \ ['\\''I', 'Í'],
+ \ ['\\`I', 'Î'],
+ \ ['\\^I', 'Ì'],
+ \ ['\\¨I', 'Ï'],
+ \ ['\\"I', 'Ï'],
+ \ ['\\''i', 'í'],
+ \ ['\\`i', 'î'],
+ \ ['\\^i', 'ì'],
+ \ ['\\¨i', 'ï'],
+ \ ['\\"i', 'ï'],
+ \ ['\\''i', 'í'],
+ \ ['\\''O', 'Ó'],
+ \ ['\\`O', 'Ò'],
+ \ ['\\^O', 'Ô'],
+ \ ['\\¨O', 'Ö'],
+ \ ['\\"O', 'Ö'],
+ \ ['\\''o', 'ó'],
+ \ ['\\`o', 'ò'],
+ \ ['\\^o', 'ô'],
+ \ ['\\¨o', 'ö'],
+ \ ['\\"o', 'ö'],
+ \ ['\\o', 'ø'],
+ \ ['\\''U', 'Ú'],
+ \ ['\\`U', 'Ù'],
+ \ ['\\^U', 'Û'],
+ \ ['\\¨U', 'Ü'],
+ \ ['\\"U', 'Ü'],
+ \ ['\\''u', 'ú'],
+ \ ['\\`u', 'ù'],
+ \ ['\\^u', 'û'],
+ \ ['\\¨u', 'ü'],
+ \ ['\\"u', 'ü'],
+ \ ['\\`N', 'Ǹ'],
+ \ ['\\\~N', 'Ñ'],
+ \ ['\\''n', 'ń'],
+ \ ['\\`n', 'ǹ'],
+ \ ['\\\~n', 'ñ'],
+ \]
+
+" }}}1
+function! vimtex#util#tex2tree(str) abort " {{{1
+ let tree = []
+ let i1 = 0
+ let i2 = -1
+ let depth = 0
+ while i2 < len(a:str)
+ let i2 = match(a:str, '[{}]', i2 + 1)
+ if i2 < 0
+ let i2 = len(a:str)
+ endif
+ if i2 >= len(a:str) || a:str[i2] ==# '{'
+ if depth == 0
+ let item = substitute(strpart(a:str, i1, i2 - i1),
+ \ '^\s*\|\s*$', '', 'g')
+ if !empty(item)
+ call add(tree, item)
+ endif
+ let i1 = i2 + 1
+ endif
+ let depth += 1
+ else
+ let depth -= 1
+ if depth == 0
+ call add(tree, vimtex#util#tex2tree(strpart(a:str, i1, i2 - i1)))
+ let i1 = i2 + 1
+ endif
+ endif
+ endwhile
+ return tree
+endfunction
+
+" }}}1
+function! vimtex#util#trim(str) abort " {{{1
+ if exists('*trim') | return trim(a:str) | endif
+
+ let l:str = substitute(a:str, '^\s*', '', '')
+ let l:str = substitute(l:str, '\s*$', '', '')
+
+ return l:str
+endfunction
+
+" }}}1
+function! vimtex#util#uniq(list) abort " {{{1
+ if exists('*uniq') | return uniq(a:list) | endif
+ if len(a:list) <= 1 | return a:list | endif
+
+ let l:uniq = [a:list[0]]
+ for l:next in a:list[1:]
+ if l:uniq[-1] != l:next
+ call add(l:uniq, l:next)
+ endif
+ endfor
+ return l:uniq
+endfunction
+
+" }}}1
+function! vimtex#util#uniq_unsorted(list) abort " {{{1
+ if len(a:list) <= 1 | return a:list | endif
+
+ let l:visited = {}
+ let l:result = []
+ for l:x in a:list
+ let l:key = string(l:x)
+ if !has_key(l:visited, l:key)
+ let l:visited[l:key] = 1
+ call add(l:result, l:x)
+ endif
+ endfor
+
+ return l:result
+endfunction
+
+" }}}1
+
+endif