Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement better inverse search #2219

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion autoload/health/vimtex.vim
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ function! s:check_view() abort " {{{1

if executable('xdotool') && !executable('pstree')
call health#report_warn('pstree is not available',
\ 'vimtex#view#reverse_goto is better if pstree is available.')
\ 'vimtex#view#inverse_search is better if pstree is available.')
endif
endfunction

Expand Down
2 changes: 1 addition & 1 deletion autoload/vimtex.vim
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ function! s:init_default_mappings() abort " {{{1

if has_key(b:vimtex, 'viewer')
call s:map(0, 'n', '<localleader>lv', '<plug>(vimtex-view)')
if has_key(b:vimtex.viewer, 'reverse_search')
if maparg('<plug>(vimtex-reverse-search)', 'n')
call s:map(0, 'n', '<localleader>lr', '<plug>(vimtex-reverse-search)')
endif
endif
Expand Down
4 changes: 0 additions & 4 deletions autoload/vimtex/options.vim
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ function! vimtex#options#init() abort " {{{1
call s:init_option('vimtex_compiler_enabled', 1)
call s:init_option('vimtex_compiler_silent', 0)
call s:init_option('vimtex_compiler_method', 'latexmk')
call s:init_option('vimtex_compiler_progname',
\ has('nvim') && executable('nvr')
\ ? 'nvr'
\ : get(v:, 'progpath', get(v:, 'progname', '')))
call s:init_option('vimtex_compiler_latexmk_engines', {})
call s:init_option('vimtex_compiler_latexrun_engines', {})

Expand Down
16 changes: 16 additions & 0 deletions autoload/vimtex/paths.vim
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ endfunction

" }}}1

function! vimtex#paths#join(root, tail) abort " {{{1
return vimtex#paths#s(a:root . '/' . a:tail)
endfunction

" }}}1

function! vimtex#paths#s(path) abort " {{{1
" Handle shellescape issues and simplify path
let l:path = exists('+shellslash') && !&shellslash
\ ? tr(a:path, '/', '\')
\ : a:path

return simplify(l:path)
endfunction

" }}}1
function! vimtex#paths#is_abs(path) abort " {{{1
return a:path =~# s:re_abs
endfunction
Expand Down
110 changes: 91 additions & 19 deletions autoload/vimtex/view.vim
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,15 @@
function! vimtex#view#init_buffer() abort " {{{1
if !g:vimtex_view_enabled | return | endif

" Store neovim servername for inheritance to inverse search
if has('nvim') && empty($NVIM_LISTEN_ADDRESS_VIMTEX)
let $NVIM_LISTEN_ADDRESS_VIMTEX = v:servername
endif

command! -buffer -nargs=? -complete=file VimtexView
\ call vimtex#view#view(<q-args>)
if has_key(b:vimtex.viewer, 'reverse_search')
command! -buffer -nargs=* VimtexViewRSearch
\ call vimtex#view#reverse_search()
endif

nnoremap <buffer> <plug>(vimtex-view) :VimtexView<cr>
if has_key(b:vimtex.viewer, 'reverse_search')
nnoremap <buffer> <plug>(vimtex-reverse-search) :VimtexViewRSearch<cr>
endif
endfunction

" }}}1
Expand Down Expand Up @@ -49,13 +47,6 @@ function! vimtex#view#view(...) abort " {{{1
endif
endfunction

" }}}1
function! vimtex#view#reverse_search() abort " {{{1
if exists('*b:vimtex.viewer.reverse_search')
call b:vimtex.viewer.reverse_search()
endif
endfunction

" }}}1
function! vimtex#view#not_readable(output) abort " {{{1
if filereadable(a:output) | return 0 | endif
Expand All @@ -66,10 +57,20 @@ endfunction

" }}}1

function! vimtex#view#reverse_goto(line, filename) abort " {{{1
if mode() ==# 'i' | stopinsert | endif
function! vimtex#view#inverse_search(line, filename) abort " {{{1
" Only activate in VimTeX buffers
if !exists('b:vimtex') | return -1 | endif

" Only activate in relevant VimTeX projects
let l:file = resolve(a:filename)
let l:sources = copy(b:vimtex.sources)
if vimtex#paths#is_abs(l:file)
call map(l:sources, {_, x -> vimtex#paths#join(b:vimtex.root, x)})
endif
if index(l:sources, l:file) < 0 | return -2 | endif


if mode() ==# 'i' | stopinsert | endif

" Open file if necessary
if !bufloaded(l:file)
Expand All @@ -81,13 +82,13 @@ function! vimtex#view#reverse_goto(line, filename) abort " {{{1
\ 'Reverse goto failed!',
\ printf('Command error: %s %s',
\ g:vimtex_view_reverse_search_edit_cmd, l:file)])
return
return -3
endtry
else
call vimtex#log#warning([
\ 'Reverse goto failed!',
\ printf('File not readable: "%s"', l:file)])
return
return -4
endif
endif

Expand All @@ -104,14 +105,85 @@ function! vimtex#view#reverse_goto(line, filename) abort " {{{1
endtry

execute 'normal!' a:line . 'G'
redraw
call s:focus_vim()
redraw

if exists('#User#VimtexEventViewReverse')
doautocmd <nomodeline> User VimtexEventViewReverse
endif
endfunction

" }}}1
function! vimtex#view#inverse_search_cmd(line, filename) abort " {{{1
" One may call this function manually, but the main usage is to through the
" command "VimtexInverseSearch". See ":help vimtex-synctex-inverse-search"
" for more info.

if a:line > 0 && !empty(a:filename)
try
if has('nvim')
call s:inverse_search_cmd_nvim(a:line, a:filename)
else
call s:inverse_search_cmd_vim(a:line, a:filename)
endif
catch
endtry
endif

quitall!
endfunction

" }}}1

function! s:inverse_search_cmd_nvim(line, filename) abort " {{{1
" WARNING: The following code is somewhat messy, as it mixes Python with
" Vimscript. Read with care!
if empty($NVIM_LISTEN_ADDRESS_VIMTEX)
if vimtex#util#is_win()
py3 << EOF
import psutil

sockets = [
p.environ()["NVIM_LISTEN_ADDRESS_VIMTEX"]
for p in psutil.process_iter(attrs=["name"])
if ("nvim" in p.info["name"]
and "NVIM_LISTEN_ADDRESS_VIMTEX" in p.environ())
]
EOF
else
py3 << EOF
import psutil

sockets = []
for proc in (p for p in psutil.process_iter(attrs=['name'])
if p.info['name'] in ('nvim', 'nvim.exe', 'nvim-qt.exe')):
sockets += [c.laddr for c in proc.connections('unix') if c.laddr]
EOF
endif
let l:socket_ids = filter(py3eval('sockets'), 'v:val != v:servername')
unsilent echo l:socket_ids
else
let l:socket_ids = [$NVIM_LISTEN_ADDRESS_VIMTEX]
endif

for l:socket_id in l:socket_ids
let l:socket = sockconnect('pipe', l:socket_id, {'rpc': 1})
call rpcnotify(l:socket,
\ 'nvim_call_function',
\ 'vimtex#view#inverse_search',
\ [a:line, a:filename])
call chanclose(l:socket)
endfor
endfunction

" }}}1
function! s:inverse_search_cmd_vim(line, filename) abort " {{{1
for l:server in split(serverlist(), "\n")
call remote_expr(l:server,
\ printf("vimtex#view#inverse_search(%d, '%s')", a:line, a:filename))
endfor
endfunction

" }}}1

function! s:focus_vim() abort " {{{1
Expand Down
4 changes: 4 additions & 0 deletions autoload/vimtex/view/mupdf.vim
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ function! vimtex#view#mupdf#new() abort " {{{1
return {}
endif

" Add reverse search mapping
nnoremap <buffer> <plug>(vimtex-reverse-search)
\ :<c-u>call b:vimtex.viewer.reverse_search()<cr>

return vimtex#view#_template_xwin#apply(deepcopy(s:mupdf))
endfunction

Expand Down
29 changes: 17 additions & 12 deletions autoload/vimtex/view/zathura.vim
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,8 @@ let s:zathura = {
function! s:zathura.start(outfile) dict abort " {{{1
let l:cmd = 'zathura'
if self.has_synctex
let l:cmd .= ' -x "' . g:vimtex_compiler_progname
\ . ' --servername ' . v:servername
\ . ' --remote-expr '
\ . '\"vimtex#view#reverse_goto(%{line}, ''%{input}'')\""'
let l:cmd .= ' -x "' . s:inverse_search_cmd
\ . ' -c \"VimtexInverseSearch %{line} ''%{input}''\""'
if g:vimtex_view_forward_search_on_start
let l:cmd .= ' --synctex-forward '
\ . line('.')
Expand Down Expand Up @@ -77,20 +75,22 @@ endfunction
" }}}1
function! s:zathura.latexmk_append_argument() dict abort " {{{1
if g:vimtex_view_use_temp_files
let cmd = ' -view=none'
let l:cmd = ' -view=none'
else
let zathura = 'zathura ' . g:vimtex_view_zathura_options
let l:zathura = 'zathura ' . g:vimtex_view_zathura_options
if self.has_synctex
let zathura .= ' -x \"' . g:vimtex_compiler_progname
\ . ' --servername ' . v:servername
\ . ' --remote-expr \"\\\"\"vimtex#view#reverse_goto(\%{line}, ''"''"''\%{input}''"''"'')\"\\\"\"\" \%S'
" The inverse search command requires insane amount of quote escapes,
" because the command is parsed through several layers of interpreting,
" e.g. perl -> shell, perhaps more.
let l:zathura .= ' -x \"' . s:inverse_search_cmd
\ . ' -c \"\\\"\"VimtexInverseSearch \%{line} ''"''"''\%{input}''"''"''\"\\\"\"\" \%S'
endif

let cmd = vimtex#compiler#latexmk#wrap_option('new_viewer_always', '0')
let cmd .= vimtex#compiler#latexmk#wrap_option('pdf_previewer', zathura)
let l:cmd = vimtex#compiler#latexmk#wrap_option('new_viewer_always', '0')
let l:cmd .= vimtex#compiler#latexmk#wrap_option('pdf_previewer', l:zathura)
endif

return cmd
return l:cmd
endfunction

" }}}1
Expand All @@ -109,3 +109,8 @@ function! s:zathura.get_pid() dict abort " {{{1
endfunction

" }}}1

let s:inverse_search_cmd = get(v:, 'progpath', get(v:, 'progname', ''))
\ . (has('nvim')
\ ? ' --headless'
\ : ' -T dumb --not-a-term -n')
Loading