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
|
" 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.
"
" Note: Using '#####' as delimiter allows spaces in the file path, while
" keeping the visuals in fzf window unaffected.
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.. --delimiter "#####"',
\}, a:0 > 1 ? a:2 : {})
call fzf#run(l:opts)
endfunction
" }}}1
" {{{1 function! vimtex#fzf#open_selection(sel) abort
if !exists('*vimtex#fzf#open_selection')
function! vimtex#fzf#open_selection(sel) abort
let [l:line, l:file; _] = split(a:sel, '#####')
if expand('%:p') == l:file
execute 'normal! ' . l:line . 'gg'
else
execute printf('edit +%s %s', l:line, l:file)
endif
endfunction
endif
" }}}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
|