16

My writing routine is like this:

  1. I edit a .tex file using vim
  2. I go to the command line and I compile it using pdflatex. I find myself always saving the file with :w and immediately having to switch terminals to execute pdflatex (I use Ubuntu) to compile it.

This annoys me. I would like to make this more efficient so that I can manage to do both steps with a single shot. Is there a way to configure vim so that every time I save a .tex file with :w, the command pdflatex is executed automatically?

5
  • 2
    Your question is too broad right now. Do you already have a command to compile your latex files or are you looking for the :Latekmk command of latex-box plugin? Or are you looking for an autocommand to execute something on a file writing... Please clarify your question by indicating what you have searched and found so far.
    – statox
    Apr 1, 2016 at 13:39
  • @statox edited question Apr 1, 2016 at 13:53
  • 3
    There are latex commands that auto-(re)compile your file(s) each time they change, outside & independent of Vim. Study that ;)
    – VanLaser
    Apr 1, 2016 at 13:53
  • 2
    (I.e. you could start from something like latexmk -pdf -pvc file.tex)
    – VanLaser
    Apr 1, 2016 at 14:55
  • 1
    @VanLaser may god bless you Apr 1, 2016 at 15:46

6 Answers 6

16

Don't be so inefficient! Your time is valuable. Use the vimtex plugin offered by @lervag: see here. You can control all of the plugins you install by using Vundle or any similar plugin manager (vim-plug is getting pretty popular).

Why waste your time installing vimtex? Great question!

Features

  1. Continuous compilation using latexmk (please and thank you!)
  2. Automatic warning/error notification using the vim quickfix window.
  3. Forward and inverse search.
  4. Support for a variety of PDF viewers.
  5. Support for multi-file projects (I love this one) in conjunction with gf and <ctrl-w>gf.
  6. commands that make things perform operations like latexmk -C.
  7. It's under active development!
  8. So much more!

Note, feature number 1 is the one which addresses your question. Each time you execute :w your document will be saved and automatically recompiled by latexmk. latexmk watches your LaTeX file for changes, automatically recompiling when changes are detected.

This post is not sponsored by or promoted by any developer or affiliate of the vimtex team (I'm just a lover).

Go be efficient!

2
  • 2
    I've installed vimtex, how do I use continuous compilation? If it should "just work" ... it's not doing much.
    – CtrlAltF2
    May 19, 2020 at 16:29
  • 1
    @CtrlAltF2 this stumped me as well. you need to use the command :VimtexCompile to start the continuous compilation.
    – user27221
    Dec 13, 2021 at 9:08
7

Adding this to my .vimrc works:

autocmd BufWritePost *.tex silent! execute "!pdflatex % >/dev/null 2>&1" | redraw!

On all .tex files it will execute pdflatex <filename> upon :w without outputting anything in vim.

This is minimal and uses no plugins or extra programs.

Note: on compilation errors vim appears to hang, but pressing return solves this.

1
  • How can I see what the status is? I would want to see the live log being written into the stream by pdflatex
    – codepoet
    Jan 20, 2021 at 3:10
4

If you use tpope's Dispatch plugin: https://github.com/tpope/vim-dispatch you can run commands in the background.

I use this snippet to run xelatex on every save:

augroup latex
    autocmd!
    autocmd BufEnter *.tex let b:dispatch='xelatex --output-directory=output %'
    autocmd BufWrite * Dispatch!
augroup end
3

I wouldn't configure Vim for that. Instead, I would use something like entr:

$ ls foo.tex | entr <your command here>
2
  • The entr tool seems pretty interesting but in this case why would you recommend it more than an autocommand like autocmd FileWritePost *.tex Latexmk?
    – statox
    Apr 1, 2016 at 14:03
  • Because I prefer to use specialized tools.
    – romainl
    Apr 1, 2016 at 14:31
3

Since compiling a .tex file make take a few seconds, I prefer to do it in the background. There are two ways I've done this in the past: by running an asynchronous command using job_start(), and by using tmux to send the compilation command to another terminal.

1. using job_start()

Add the following to your .vimrc:

function! RedrawScreen(channel)
    redraw!
endfunction

function! RunLatexmk()
    let tex_file = expand('%:p')    " current file
    let tex_cmd = 'latexmk -pdf -interaction=nonstopmode -cd ' . tex_file
    let s:job = job_start(['/bin/sh', '-c', tex_cmd],
        \ {'close_cb': 'RedrawScreen'})
endfunction

autocmd BufWrite *.tex :call RunLatexmk()

I have defined the RedrawScreen() callback function because my screen often gets messed up when the job_start() job completes. Note that this uses latexmk -pdf which calls pdflatex. If instead you want to use pdflatex directly, you will have to first cd into the directory of the .tex file before you can call pdflatex.

2. using tmux to send the latexmk command to another terminal

Add the following to your .vimrc:

function! TmuxSend()
    let tex_file = expand('%:p')    " current file
    let tex_cmd = 'latexmk -pdf -interaction=nonstopmode -cd ' . tex_file
    let tmux_cmd = 'tmux send-keys -t vim_output.0 "' . tex_cmd . '" ENTER'
    let output = system(tmux_cmd)   
endfunction

autocmd BufWrite *.tex :call TmuxSend()

Now, open another terminal and create a tmux session named "vim_output": tmux new-session -s vim_output. Now, when you save your file in Vim, the latexmk command will be run in the terminal you just created.

2

You can easily do exactly what you want:

Assuming you are using linux (I do not know the Windows command)

To save and send to 'pdflatex':

:w | !pdflatex %

The '%' means 'the current file'
Notice that vertical bar |, it is necessary so that vim chains both commands one after another.

You can make a nice shortcut for this using 'cabbrev'.
In your 'vimrc' file, put:

cabbrev W w | !pdflatex %

This will make it so when you type ":W " (and make a space after), it will autocorrect to

:w | !pdflatex %

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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