Skip to content

Instantly share code, notes, and snippets.

@vext01
Last active February 14, 2024 03:36
Show Gist options
  • Star 59 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save vext01/16df5bd48019d451e078 to your computer and use it in GitHub Desktop.
Save vext01/16df5bd48019d451e078 to your computer and use it in GitHub Desktop.
Vim+Zathura+Synctex

Vim+Zathura+Synctex

  • In a script called 'vimura':
#!/bin/sh
echo $1
zathura -s -x "gvim --servername $1 -c \"let g:syncpdf='$1'\" --remote +%{line} %{input}" $*

For zathura >= 0.3.2 remove -s.

  • In your vimrc:
function! Synctex()
        " remove 'silent' for debugging
        execute "silent !zathura --synctex-forward " . line('.') . ":" . col('.') . ":" . bufname('%') . " " . g:syncpdf
endfunction
map <C-enter> :call Synctex()<cr>
  • Build your latex doc with synctex enabled
pdflatex -synctex=1 ...
  • Open PDF with vimura script.

  • CTRL+Click in Zathura jumps to source in vim.

  • CTRL+Enter in vim jumps to corresponding position in PDF.

@natema
Copy link

natema commented Sep 17, 2016

Thank you so much, I tried to make synctex work with evince but eventually gave up. Now I can finally fully enjoy the power of vim without any regret. Only one question: is there any way to make this work by starting gvim first and then opening zathura with \ll?

@scemama
Copy link

scemama commented Feb 10, 2017

Thanks! Very useful!

@fmeynadier
Copy link

To make it work without starting a new vim instance, allowing to link to an already open file, I think you just have to use a fixed servername, i.e.

vimura:

#!/bin/sh
echo $1
zathura -s -x "vim --servername vim -c \"let g:syncpdf='$1'\" --remote +%{line} %{input}" $*

and put this alias in .bashrc (or equivalent)
alias vim='/usr/bin/vim --servername vim'
At least it works for my basic usage of vim, I don’t know if there are side effects with gvim and/or more advanced usage of vim.

You could also keep the "vimura" script as it is and launch vim with the corresponding servername (i.e. the .tex filename).

@fmeynadier
Copy link

fmeynadier commented Sep 6, 2017

Also, if you prefer not to use the g:syncpdf variable defined in the vimura script, leaving you free to display it independently and still get forward search :

function! Synctex()
  " remove 'silent' for debugging
  execute "silent !zathura --synctex-forward " . line('.') . ":" . col('.') . ":" . bufname('%') . " " . bufname('%')[:-5]. ".pdf"
  redraw!
endfunction
map <C-enter> :call Synctex()<cr>

This assumes of course corresponding root names between the tex file and the pdf file.
Also, with vim I have to redraw terminal after that, hence the "redraw!" that might not be needed with gvim.

I realize this may be going away from the initial intent, and may be less robust, but I thought it could be useful to others...

@hringriin
Copy link

With gVim it seems to work fine, but I'd really like to use normal vim, but when I execute the function Synctex() from within normal vim, I get the terminal messed up. Is there any way to debug that in order to use normal vim?

screenshot_2018-12-07_23-53-51

Regards
hringriin

@perelo
Copy link

perelo commented Jul 8, 2019

An update for this great gist in order to use it with NeoVim

NeoVim don't have --servername syntax natively, but you can use neovim-remote :

pip3 install neovim-remote
alias nvim="NVIM_LISTEN_ADDRESS=/tmp/nvimsocket nvim"

then the vimura script :

#!/bin/bash
if [ $1 == "neovim" ]; then
    synctex_command="nvr --remote +%{line} %{input}"
else
    synctex_command="vim --servername vimd --remote +%{line} %{input}" 
fi
zathura -x "$synctex_command" ${@:2}

Also, in order to execute background jobs from neovim, we must use jobstart() instead of terminating the command by &. Thus, in .vimrc:

function! Synctex()
    let vimura_param = " --synctex-forward " . line('.') . ":" . col('.') . ":" . expand('%:p') . " " . substitute(expand('%:p'),"tex$","pdf", "")
    if has('nvim')
        call jobstart("vimura neovim" . vimura_param)
    else
        exe "silent !vimura vim" . vimura_param . "&"
    endif
    redraw!
endfunction

Note that I added redraw! at the end, and I use full path with %:p so I can deal with multiple pdf in multiple directories.

@bruno-caldas
Copy link

In order to work fine with normal vim, you can reload the file, i.e add at the end of the line of your .vimrc which you call Synctex() with the
:e <CR>

With gVim it seems to work fine, but I'd really like to use normal vim, but when I execute the function Synctex() from within normal vim, I get the terminal messed up. Is there any way to debug that in order to use normal vim?

screenshot_2018-12-07_23-53-51

Regards
hringriin

@vext01
Copy link
Author

vext01 commented Oct 11, 2019

Hi,

I wonder if we should make a git repo for this. Perhaps if I import what I started with, people can raise PRs to have stuff merged in?

@de-arl
Copy link

de-arl commented Mar 29, 2020

Hello there
Support for synctex with vim or gvim and zathura is included in glartex now, a command-line utility to start a latex session.
www.github.com/de-arl/glartex

@lumbric
Copy link

lumbric commented Feb 25, 2021

Thanks for the instructions! Is there away to avoid loosing the focus in the VIM terminal when executing the sync to viewer command?

@mazunki
Copy link

mazunki commented Oct 14, 2021

The answer by @perelo led me to the following latex.vim snippet for my nvim configuration:

function! OpenZathura()
    let position = line('.') . ":" . col('.') . ":" . expand('%:p') . " "
    call jobstart("zathura -x 'nvr --remote +%{line} %{input}' --synctex-forward " . position . " " . substitute(expand('%:p'),"tex$","pdf", ""))
endfunction
map <leader><Enter> :call OpenZathura()<cr>

I would love to hook in any motion to automatically call the function (which by some miracle doesn't reopen a new process, unless it's not open yet), but only if I already opened Zathura manually. Any ideas on how to do this? Having one function to only open Zathura (which I thought I had), and one to re-sync the position sounds like the ideal solution.

As a note, I had misconfigured texlab (getting cmd ["texlab"] is not executable errors), causing me to have to press enter after pressing Ctrl+Click in Zathura. I disabled the LSP server for texlab, and synctex works without any problem. I still need to clean up the LSP. Regardless, is there some way of "ignoring" this error message, or appending a <cr> keypress through nvr?

@charlie39
Copy link

charlie39 commented Jul 1, 2022

I would love to hook in any motion to automatically call the function (which by some miracle doesn't reopen a new process, unless it's not open yet), but only if I already opened Zathura manually. Any ideas on how to do this? Having one function to only open Zathura (which I thought I had), and one to re-sync the position sounds like the ideal solution.

You can have it trigger on CursorMoveI events on *.tex file patterns.

autocmd CursorMoveI *.tex call OpenZathura()

With this whenever you enter insert and move around your cursor, zathura would do the same.
But this also implies that you have to compile (if it's not compiled ) before entering insert mode.

I have another command to compile any *.tex file on BufReadPost and BufWritePost so i don't have to always remember about compiling it first.
In my case it's not necessary to have zathura opened already. If the pdf file already exist , it (that function ) would open up without any problem

@mazunki
Copy link

mazunki commented Jul 1, 2022

I would love to hook in any motion to automatically call the function (which by some miracle doesn't reopen a new process, unless it's not open yet), but only if I already opened Zathura manually. Any ideas on how to do this? Having one function to only open Zathura (which I thought I had), and one to re-sync the position sounds like the ideal solution.

You can have it trigger on CursorMoveI events on *.tex file patterns.

autocmd CursorMoveI *.tex call OpenZathura()

With this whenever you enter insert and move around your cursor, zathura would do the same. But this also implies that you have to compile (if it's not compiled ) before entering insert mode.

I have another command to compile any *.tex file on BufReadPost and BufWritePost so i don't have to always remember about compiling it first. In my case it's not necessary to have zathura opened already. If the pdf file already exist , it (that function ) would open up without any problem

Nice! Didn't know about CursorMoveI, I'll add this myself when I get to it :)

@charlie39
Copy link

charlie39 commented Jul 2, 2022

@mazunki
This is my tex autocmd group

  augroup latex
    autocmd! CursorMovedI *.tex call OpenZathura()
    autocmd! BufWritePost,BufReadPre *.tex silent !compiler %
  augroup end

Also a tiny detail:

Also imp to have the compiler (whaterver compiling script or command you have) mapped to a certain key binding without silent, for for debugging.

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