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

synctex preview of labels for navigation/completion #2939

Open
bellecp opened this issue Apr 23, 2024 · 1 comment
Open

synctex preview of labels for navigation/completion #2939

bellecp opened this issue Apr 23, 2024 · 1 comment

Comments

@bellecp
Copy link

bellecp commented Apr 23, 2024

After some testing, it appears possible, with the following few lines in .vimrc, to navigate to labels (or any element from vimtex's TOC) with fzf while previewing the corresponding label/TOC element inside the PDF previewer.
As a different entry is focused inside vim's fzf window, the corresponding equation or section title is instantly highlighted in the PDF. The key is in the --bind ''focus:execute-silent(...) part of fzf's options.

The video describes what it looks like:

  • FZF inside vim for fuzzy selection of labels on the left,
  • zathura on the right where the equations/theorems are previewed as different FZF entries get the focus.
recording.mp4

For label/TOC navigation:

nnoremap <c-x><c-l> :call vimtex#fzf#run('ctli', {
            \ 'up': '90%',
            \ 'sink':  function('vimtex#fzf#open_selection'),
            \ 'options': '-d "#####" --with-nth=3..  --ansi --bind ''focus:execute-silent(zathura --synctex-forward {1}:1:{2} "$(sed "s/tex$/pdf/" <<< {2})" )''  '
            \ })<CR>

For completion: (e.g., type \Cref{thm<C-L> in insert mode)

inoremap <expr> <c-l> fzf#vim#complete({
            \ 'source': map(filter(vimtex#parser#toc(), {_, d -> d['type'] == 'label'}), {_,d -> join([d['line'], d['file'], d['title']], '#####')}),
            \ 'up': '90%',
            \ 'reducer': {lines -> trim(split(split(lines[0], ' (')[0],'#####')[-1])},
            \ 'options': '--with-nth 3.. --delimiter "#####" --ansi --bind ''focus:execute-silent(zathura --synctex-forward {1}:1:{2} "$(sed "s/tex$/pdf/" <<< {2})" )''  '
            \})

Is your feature request related to a problem? Please describe it.
The above is sufficient for my use case, so I am not asking to implement it more deeply into vimtex itself. I wanted to point out this nice possibility on top of some API already provided by vimtex (vimtex#parser#toc(), 'vimtex#fzf#open_selection' and fzf. With my limited testing, it provides a very pleasant workflow for navigation and label completion.

Describe the solution you'd like
If you are interested in pushing this further, some remarks:

  • one issue is to implement the above for any PDF previewer Zathura is hardcoded above, and I am not sure it would be even possible to.
  • the above code assumes that the PDF filename can always be obtained by replacing .tex$ by .pdf from the .tex file given by vimtex#parser#toc(). The above code will break if the latex manuscript is scattered in many .tex file using \input.
  • One difficulty is that the inside of focus:execute-silent(..) is executed by FZF in a shell: none of vimtex's vimscript functions are available at that point.

Some caveat:

  1. Vimtex's continuous compilation should be started beforehand, and zathura's window already opened. Otherwise the behavior is undetermined.

  2. With the above code, forward search is performed on the first character of the line where the label is located. Sometimes this forward search fails and the PDF previewer shows some unrelated portion of the PDF close to the label. It happens for instance with

\begin{equation}
    \label{mylab}
    x^2+y^2=z^2
\end{equation}

for which synctex forward search on the line of the label focuses on the right page but fails to highlight the equation.
The problem is resolved by writing instead

\begin{equation}
    x^2+y^2=z^2 
    \label{mylab}
\end{equation}

I haven't found a robust way to fix this. Forward search with the line of the label plus one could give better results on average, but this does not sound ideal.

@lervag
Copy link
Owner

lervag commented Apr 23, 2024

After some testing, it appears possible, with the following few lines in .vimrc, to navigate to labels (or any element from vimtex's TOC) with fzf while previewing the corresponding label/TOC element inside the PDF previewer. As a different entry is focused inside vim's fzf window, the corresponding equation or section title is instantly highlighted in the PDF. The key is in the --bind ''focus:execute-silent(...) part of fzf's options.

The video describes what it looks like: …

That's an interesting idea, for sure!

The above is sufficient for my use case, so I am not asking to implement it more deeply into vimtex itself. I wanted to point out this nice possibility on top of some API already provided by vimtex (vimtex#parser#toc(), 'vimtex#fzf#open_selection' and fzf. With my limited testing, it provides a very pleasant workflow for navigation and label completion.

First, I'm glad you are not proposing that this should be implemented directly into VimTeX. It may be a good idea, but I see a lot of complicated issues with it. So, at least for now, let's discuss the concept from the user config side.

one issue is to implement the above for any PDF previewer Zathura is hardcoded above, and I am not sure it would be even possible to.

I believe it should be possible for viewers that have a similar forward search on the command line, which I think are really most viewers.

  • the above code assumes that the PDF filename can always be obtained by replacing .tex$ by .pdf from the .tex file given by vimtex#parser#toc(). The above code will break if the latex manuscript is scattered in many .tex file using \input.

  • One difficulty is that the inside of focus:execute-silent(..) is executed by FZF in a shell: none of vimtex's vimscript functions are available at that point.

Yes, but at the same time, you are free to do some preprocessing here. I'm thinking something like this, where b:vimtex.tex and b:vimtex.compiler.get_file('pdf') are interpolated when you call the mapping.

function! OpenSync() abort
  let l:bind = printf(
        \ "--bind 'focus:execute-silent(zathura --synctex-forward {1}:1:\"%s\" \"%s\")'",
        \ b:vimtex.tex,
        \ b:vimtex.compiler.get_file('pdf')
        \)
  call vimtex#fzf#run('ctli', {
        \ 'up': '90%',
        \ 'sink':  function('vimtex#fzf#open_selection'),
        \ 'options': '-d "#####" --with-nth=3.. --ansi ' . l:bind
        \})
endfunction

nnoremap <c-x><c-l> :call OpenSync()<cr>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants