52

Inspired by the comments to this answer I am curious how to actually setup and use forward/reverse (inverse) search with vim, pdflatex and an open-source PDF-viewer under Linux.

Btw, to give more details:

Forward search means that when you at some location in your text editor you issue some command and auto-magically the PDF-viewer jumps to the corresponding location in the typeset PDF. Perhaps even marks it somehow.

Reverse search means that issuing a command in your PDF-Viewer (e.g. clicking somewhere in the document), instructs the PDF-viewer to send a command to your editor that then jumps to the corresponding source location.

Edit: Currently I am not using any latex plugin in vim. And usually the LaTeX documents I edit with vim make use of \include or \input a lot.

  • Just saw your edit. I might be able to give some advice about overcoming the \input or \include problem, but it'll mean knowing something about whether you put anything in your included documents to mark what the master document is for a given subdocument, or whether you use any other conventions. (E.g., is the main document always called main.tex or something? Or do you put % mainfile=whatever.tex on one of the first lines of the file, or ...? – frabjous Sep 9 '10 at 19:25
  • @frabjous: No, currently I am just using \include (for parts, chapters, sections - depending on the documentclass and size of the divisions) and \input (for e.g. complicated tables/figures) without any marking. The main file is not always of the same name. – maxschlepzig Sep 10 '10 at 8:11
  • Are you willing to mark it somehow? Consider that it's possible to use the same subdocument in multiple master documents, and then it'll be impossible for vim to know which pdf to forwardsearch in. You need a way to tell vim which one you want. Anyway, the important thing that won't work in my instructions below is "%:p:r.pdf", which is vim-ese for "the current document name with full path, with the extension removed, and .pdf" stuck on. That won't work if the .pdf name doesn't match the name of the file you're editing. You'll need to change that part of the function when working with subdocs. – frabjous Sep 10 '10 at 22:01
  • 1
    I realize that this topic is kind of dead by now. Still I would like to see vim+synctex+(nice pdf reader) work sometime. Concerning the mainfile. As long as you don't edit 2 LaTeX documents at the same time, this mainfile is uniquely determined by the intersection of all open *.tex files, and all open *.pdf files. Might this work, to make multiple master documents possible? I guess with a little bit of more fu, it is possible to ask the system which candidate of the multiple master documents was active as last. What do you think? – jmc Jun 28 '12 at 17:47
30

It would help to know which, if any, LaTeX plugin you're using for vim. (E.g., the latex-suite, vim-auctex, latex-box, etc.)

Next, as far as viewer choice, the only widely used open source PDF viewer for Linux which currently supports SyncTeX well out of the box is Okular. That's probably your best choice.

There are instructions fo setting up SyncTeX with Okular with the vim-latex plugin here, and some related observations here. I had mixed results following those directions. Here's what seems to be important.

  1. Be sure that your LaTeX compilation method (which will depend on your plugin) calls pdflatex (or xelatex or whatever) with the -synctex=1 flag.

  2. I think something like this should suffice for Forward Searches with Okular, though it might be better to try to rewrite or modify the forward search function for your plugin (there's some info on that in one of the links above). Put this in your .vimrc (and change the mapping to whatever you like).

    function! SyncTexForward()
         let execstr = "silent !okular --unique %:p:r.pdf\\#src:".line(".")."%:p &"
         exec execstr
    endfunction
    nmap <Leader>f :call SyncTexForward()<CR>
    
  3. For reverse searches, set the editor line in Okular to gvim --servername GVIM --remote +%l %f. It might also work to use gvim --servername GVIM --remote-send "<Esc>%lgg" if you only use it with the file already open. Change the servername to whatever you use. (Not sure if it's different with regular vim, but this doesn't make much sense out of a graphical environment.)

I do not have Okular installed right now, however, so I could not test any of that. (And the links I gave earlier have slightly different advice which is worth trying.) I really hope someone with both Okular and gvim installed can test this advice, and correct where I went wrong.

And all of that advice isn't going to work well if you're using subdocuments called through \input{...} or \include{...}, where the PDF name doesn't match the name of the document you're editing. There are ways around that, but it would require knowing more about what LaTeX plugins and methods you're already using, if any.

However, other choices are kinda/sorta already available. The next version of evince will support SyncTeX through D-Bus, and apparently someone is already working on a plugin for vim to make use of it. Details here. However, it's very unlikely that this version of evince is already available for your Linux distribution, and there may be some problems with it.

There's an old fork of an old version evince that provides synctex support; there are instructions that come with that detail how to set this up with gvim. It works fine. It's easy to set up if you're using Arch Linux, since this is in the AUR. If you're not, I don't know how hard it would be to compile. (I used to use Ubuntu before Arch, and couldn't get it working there, but that may have been my ignorance.)

Next, I wrote some scripts that provide very limited, very poor, but still better than nothing, synctex support between gvim and the open-source vim-like PDF viewer Zathura, which uses vim-like keybindings. You'll find them mentioned and detailed in this thread in the Arch forums here. (post #370)

Finally, I think this kind of stuff will work its way into the major LaTeX plugins for vim soon, and then you don't have to resort to so much trial and error.

| improve this answer | |
  • 6
    It should be noted that instead of passing -synctex=1 to the pdflatex or xelatex processor, you can also put \synctex=1 in the preamble of your document. – Konrad Rudolph Sep 11 '10 at 8:09
  • 2
    In okular you must shift-click to activate the editor. The vim-latex documentation says double-click and debugging this caused me much frustration. – Dan Stahlke Oct 12 '12 at 22:32
  • Sometimes okular won't come to the foreground with this command: I'm forcing it with wmctrl: :execute "silent !make && okular --caption OkularVIM --unique %:p:r.pdf\\#src:" . line(".") . "%:p && wmctrl -a OkularVIM &"<cr> – Ciro Santilli 郝海东冠状病六四事件法轮功 Aug 23 '14 at 9:25
  • 1
    I was struggling for some time to figure out why shift-click had stopped working in my case. The tool has to be set to "Browse" in Okular. If you have any other tool selected, it won't open the editor. – fabikw Dec 8 '14 at 20:39
14

This is a solution for evince, thanks to José Aliste who wrote gedit-synctex-plugin:

Preamble

  1. Download these files
  2. deflate them to ~/bin (or something within $PATH)

Backward Search (Evince → Editor)

  1. Adopt the first line of »~/bin/evince« (EDITORCMD) to your needs. (run »evince_backward_search« to get help for possible entries)
  2. Compile your .tex File with synctex (»pdflatex -synctex=1 myfile.tex«)
  3. Run »evince myfile.pdf« (The script should run evince_backward_search and evince)
  4. click on some text in evince with »Ctrl+leftclick«
  5. the editor should jump to the corresponding line

Forward Search (Editor → Evince)

  1. you have to tell your editor, to run »evince_forward_search $PDFFILE $LINE $TEXFILE« when pressing some key.
  2. go to some line in your editor and press the key
  3. evince should mark the corresponding line

Using vim-latexsuite, write in ~/.vim/ftplugin/tex.vim:

function! Tex_ForwardSearchLaTeX()
  let cmd = 'evince_forward_search ' . fnamemodify(Tex_GetMainFileName(), ":p:r") .  '.pdf ' . line(".") . ' ' . expand("%:p")
  let output = system(cmd)
endfunction

Afterwards you can do forward search in vim with \ls

| improve this answer | |
5

Following frabjous's answer and with some inputs from this blogpost I got this working with GVim + Zathura. Important things to do are:

  • Configure ~/.config/zathura/zathurarc to setup inverse search

as:

set dbus-service true
set synctex true
set synctex-editor-command "gvim --servername GVIM --remote +%{line} %{input}"
  • Configure ~/.vimrc to setup forward search

as:

function! SyncTexForward()
    let execstr = "silent !zathura --synctex-forward ".line(".").":".col(".").":%:p %:p:r.pdf &"
    exec execstr
endfunction
au FileType tex nmap <Leader>f :call SyncTexForward()<CR>
  • Complile the tex file like pdflatex -synctex=1 paper.tex

  • Open the pdf file in Zathura.

  • (optional) Open GVim gvim paper.tex --servername GVIM

Simply Ctrl+Click somewhere on the PDF opened with Zathura - to open the GVim instance, if not open - and perform inverse search. For forward search from GVim Leaderf.

| improve this answer | |
  • It's a personal preference, but I find it cumbersome to use %:p which uses the full absolute filepath (then it's too long to manually enter the zathura --synctex-forward command when opening the pdf for the first time. I do have an alias, but still). So my version only uses the relative file path, like this: let execstr = "silent !zathura --synctex-forward ".line(".").":".col(".").":".@%." ".fnamemodify(@%, ":r") . ".pdf &" – PlasmaBinturong Feb 9 '18 at 14:47
5

Automatic LaTeX Plugin for Vim supports forward and backward search for many viewers (Xpdf, Okular, Evince, or Skim on MacOs).

Note: Link replaced by archive link. The software doesn't seem to exist anymore.

| improve this answer | |
  • 6
    If this is a product of yours, please disclose it, see the faq. – doncherry Nov 24 '12 at 16:55
3

sure, I'm a little late. I'm using vim without any tex plugins + ConteXt + synctex (but this should work for LaTeX too), but here is my current method (save as file into ftplugin directory):

if exists("b:did_context_synctex_plugin")
    finish
endif
let b:did_context_synctex_plugin = 1

function! SynctexShow()
    let synctex = glob("*.synctex.gz")
    if strlen(synctex) == 0
        echo "no synctex file found"
    else
        let pdffile = substitute(synctex,"synctex.gz","pdf","")
        let execline = printf(":!okular --unique '%s#src:%d %s'", shellescape(pdffile), line("."),shellescape(bufname("%")))
        exec execline
    end
endfunction

map <buffer> <localleader>f :call SynctexShow()<Enter><Enter>

When creating the document with synctex support a file "*.synctex.gz" is generated, so this script will just look for a file ending with "synctex.gz", find the current buffer and syncs the view with the pdf viewer. Due to the use of the synctex file for naming the pdf (which must have the same base name) one can split up the TeX document and use synctex, too.

| improve this answer | |
  • Does this work if you have more than one *.synctex.gz file in the current directory? In that case syntex and pdffile will be strings of multiple lines, and the execline command not be correct. – Aditya Feb 6 '11 at 3:35
  • this script is just very simple serving more or less my needs at least ... if you want support for more synctex-files in a directory there are some possible options to improve the script. Use for example <synctex_files = split(glob("*.synctex.gz"),"\n"))> to retrieve a list of all synctex files. Using that list one can either ask the user or unzip the files and test if the current file is referenced in any of them (hopefully just one, or open all). Alternatively add a global variable with the correct synctex file, which can be changed by the user at any time. or maybe combine all of these... – urso Feb 6 '11 at 7:19
2

Nowadays, Evince supports SyncTeX. And starting with Vim 8, there is DBus supports, so developing a nice solution for vim+Evince has been done: https://github.com/peder2tm/sved

| improve this answer | |
  • Thanks for pointing to SVED. It's simple to install and configure and really works like a charm! – rindPHI Jul 25 '19 at 14:06
1

I am not able to comment so just post a fix to @Ben 's answer [Evince <-> Editor] here. For genome-3, there are some additional changes to make forward/backward search work, which has been discussed here.

In evince_synctex/evince_backward_search, change

...
def on_sync_source(self, input_file, source_link):
...
self.source_handler(input_file, source_link)

to

...
def on_sync_source(self, input_file, source_link, time):
...
self.source_handler(input_file, source_link, time)

In file evince_forward_search, change

window.SyncView(tex_file, (line_number,1), dbus_interface="org.gnome.evince.Window")

to

window.SyncView(tex_file, (line_number,1), 0, dbus_interface="org.gnome.evince.Window")
| improve this answer | |
0

Evince also has an overview page for that which uses the dbus script from the gedit latex plugin.

https://help.gnome.org/users/evince/stable/synctex-editors.html

| improve this answer | |
0

Steps for Vim & Okular

The accepted answer got me most of the way to making this work with Okular, but I had a couple of issues. So I'd like to provide an elaborate description with some more explanatory information. Note that these steps do NOT require any third party files, extra plugins, or gVim.

1. compile the tex file with SyncTeX support

First, make sure you compile your Latex document with SyncTeX. This will generate a .synctex file (in addition to the .pdf file) which provides the mapping between the tex file(s) and pdf file. You can compile a .tex file with Synctex support using either the pdflatex or latexmk shell commands:

$ pdflatex -synctex=-1 file.tex

or

$ latexmk -pdf -pdflatex="pdflatex -synctex=-1" -cd /path/to/file.tex

Note that you can also generate a zipped .synctex.gz file by replacing the -1 in the commands above with a 1. This may be helpful to reduce file size. As an alternative to using the -synctex flag, you can tell the compiler to use Synctex by putting the line \synctex=1 in the preamble of your Latex file. As far as I know, you can't generate an uncompressed .synctex file this way though.

You can run the pdflatex and latexmk compilation commands from a terminal. Alternatively, you can run these commands from Vim itself. A quick way to do so would be to enter the following command in Vim's colon command line :!latexmk -pdf -pdflatex="pdflatex -synctex=-1" -cd % (note % represents the path to the current file). But this method may not be ideal if you often edit and compile tex files. Other ways to compile a tex file from Vim are described in the answers to this question.

2. tex-to-pdf search (Vim to Okular)

If you compiled the tex file as in step 1, you should have a Synctex (.synctex or .synctex.gz) file along with the corresponding tex and pdf files. You can then issue the following shell command to use Okular to open the pdf to the location which corresponds to line_number in the tex file:

 $ okular --noraise --unique "/path/to/file.pdf#src:line_number /path/to/file.tex" 

Note the quotation marks are necessary. Also note that the --unique option will ensure only one Okular window is opened, and the --noraise option will prevent the Okular window from being focused and raised. This will be helpful in the next step so that Vim isn't exited every time a search is done1.

The next step is to run the okular shell command from Vim, using the line number the cursor is on. As an example of how to do this, you can add the following to your .vimrc file:

function! OkularFind()
    let this_tex_file = expand('%:p')
    let master_tex_file = this_tex_file
    let pdf_file = fnamemodify(master_tex_file, ':p:r') . '.pdf'
    let line_number = line('.')
    let okular_cmd = 'okular --noraise --unique "' . pdf_file . '#src:' . line_number . ' ' . this_tex_file . '"'
    let s:okular_job = job_start(['/bin/bash', '-c', okular_cmd])
endfunction
nnoremap <leader>f :call OkularFind()<cr>

The last line just defines a keymap to apply the function (note: the <leader> key is \ by default).

Also, this code assumes that your project only involves one tex file. If your project involves a master tex file and other tex files referenced by the master, you will have to change the master_tex_file variable.

3. pdf-to-tex search (Okular to Vim)

The way I know how to do Okular-to-Vim search is by using a server in Vim. Note that I figured out some of the following information from the documentation and issues of vimtex.

To use a server in Vim, your Vim installation must be compiled with the +clientserver option2. Note that you can check to see if this option is installed by using Vim's :version command. To start a server named "VIM" in Vim, you can run Vim as

$ vim --servername VIM

If Vim is already running, you can start a server from within Vim with

:call remote_startserver('VIM')

With Vim running as a server, you can jump to line_number of a tex file with the shell command

 $ vim --remote +line_number /path/to/file.tex 

The next step is to run that vim --remote command from Okular. When viewing a pdf that is part of a tex project, Okular's Editor feature has the native ability to map locations in the pdf to lines in the corresponding tex file, by means of the Synctex file. Upon a Shift + Left Mouse Button (when using the Browse tool) the Editor will run a shell command, which is intended to open a text editor to view the tex file. As part of this shell command, Okular provides the symbols %l and %f to be used as placeholders for the line number and filename (see The Okular Handbook for more info). So, search from Okular to Vim can be accomplished with the following steps:

  • go to Settings 🡢 Configure Okular 🡢 Editor and select Custom Text Editor, and in Command type3

    vim --remote +%l %f
    
  • make sure you're using the Browse Tool (Tools 🡢 Browse)

  • put the cursor over the part of the pdf you want to search for, and do Shift + Left Mouse Button

The last step should take you to the corresponding line in your tex file4.


notes:

1 The --noraise option will prevent the Okular window from being focused and raised. You can leave this option off if you want to focus the Okular window. Additionally, if you want to raise, but not focus the Okular window, you can combine the okular command with a shell command that can interact with windows, for example xdotool or wmctrl. As an example, you could augment the okular shell command above like this:

this_WID=$(xdotool getactivewindow) && \
okular --unique "/path/to/file.pdf#src:line_number /path/to/file.tex" && \ 
xdotool windowactivate $this_WID 

This will focus the Okular window the first time it is opened, but not subsequent times.

2 In Arch Linux, the default vim package is not compiled with the +clientserver option, so you must install the gvim package, which will install gVim, as well as a more fully-featured version of Vim which is compiled with the +clientserver option.

3 You should also be able to leave off the %f because Okular should add it to the end of the command automatically.

4 Depending on your system configuration, this may or may not focus the Vim window. See the answers to this question and this question for workarounds.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.