summaryrefslogtreecommitdiffstats
path: root/autoload/vimtex/fzf.vim
diff options
context:
space:
mode:
Diffstat (limited to 'autoload/vimtex/fzf.vim')
-rw-r--r--autoload/vimtex/fzf.vim114
1 files changed, 114 insertions, 0 deletions
diff --git a/autoload/vimtex/fzf.vim b/autoload/vimtex/fzf.vim
new file mode 100644
index 00000000..c7f62c99
--- /dev/null
+++ b/autoload/vimtex/fzf.vim
@@ -0,0 +1,114 @@
+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#fzf#run(...) abort " {{{1
+ " Arguments: Two optional arguments
+ "
+ " First argument: ToC filter (default: 'ctli')
+ " This may be used to select certain entry types according to the different
+ " "layers" of vimtex-toc:
+ " c: content: This is the main part and the "real" ToC
+ " t: todo: This shows TODOs from comments and `\todo{...}` commands
+ " l: label: This shows `\label{...}` commands
+ " i: include: This shows included files
+ "
+ " Second argument: Custom options for fzf
+ " It should be an object containing the parameters passed to fzf#run().
+
+ " Note: The '--with-nth 3..' option hides the first two words from the fzf
+ " window. These words are the file name and line number and are used by
+ " the sink.
+ let l:opts = extend({
+ \ 'source': <sid>parse_toc(a:0 == 0 ? 'ctli' : a:1),
+ \ 'sink': function('vimtex#fzf#open_selection'),
+ \ 'options': '--ansi --with-nth 3..',
+ \}, a:0 > 1 ? a:2 : {})
+
+ call fzf#run(l:opts)
+endfunction
+
+" }}}1
+function! vimtex#fzf#open_selection(sel) abort " {{{1
+ let line = split(a:sel)[0]
+ let file = split(a:sel)[1]
+ let curr_file = expand('%:p')
+
+ if curr_file == file
+ execute 'normal! ' . line . 'gg'
+ else
+ execute printf('edit +%s %s', line, file)
+ endif
+endfunction
+
+" }}}1
+
+
+function! s:parse_toc(filter) abort " {{{1
+ " Parsing is mostly adapted from the Denite source
+ " (see rplugin/python3/denite/source/vimtex.py)
+ python3 << EOF
+import vim
+import json
+
+def format_number(n):
+ if not n or not type(n) is dict or not 'chapter' in n:
+ return ''
+
+ num = [str(n[k]) for k in [
+ 'chapter',
+ 'section',
+ 'subsection',
+ 'subsubsection',
+ 'subsubsubsection'] if n[k] != '0']
+
+ if n['appendix'] != '0':
+ num[0] = chr(int(num[0]) + 64)
+
+ return '.'.join(num)
+
+def colorize(e):
+ try:
+ from colorama import Fore, Style
+ color = {'content' : Fore.WHITE,
+ 'include' : Fore.BLUE,
+ 'label' : Fore.GREEN,
+ 'todo' : Fore.RED}[e['type']]
+ return f"{color}{e['title']:65}{Style.RESET_ALL}"
+ except ModuleNotFoundError:
+ import os
+ if os.name == 'nt':
+ # Colour support on Windows requires Colorama
+ return f"{e['title']:65}"
+ else:
+ color = {'content' : "\u001b[37m",
+ 'include' : "\u001b[34m",
+ 'label' : "\u001b[32m",
+ 'todo' : "\u001b[31m"}[e['type']]
+ return f"{color}{e['title']:65}\u001b[0m"
+
+def create_candidate(e, depth):
+ number = format_number(dict(e['number']))
+ return f"{e.get('line', 0)} {e['file']} {colorize(e)} {number}"
+
+entries = vim.eval('vimtex#parser#toc()')
+depth = max([int(e['level']) for e in entries])
+filter = vim.eval("a:filter")
+candidates = [create_candidate(e, depth)
+ for e in entries if e['type'][0] in filter]
+
+# json.dumps will convert single quotes to double quotes
+# so that vim understands the ansi escape sequences
+vim.command(f"let candidates = {json.dumps(candidates)}")
+EOF
+
+ return candidates
+endfunction
+
+" }}}1
+
+endif