6

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?

  • 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 '16 at 13:39
  • @statox edited question – PhoenixPerson Apr 1 '16 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 '16 at 13:53
  • 1
    (I.e. you could start from something like latexmk -pdf -pvc file.tex) – VanLaser Apr 1 '16 at 14:55
  • @VanLaser may god bless you – PhoenixPerson Apr 1 '16 at 15:46
6

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!

3

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

$ ls foo.tex | entr <your command here>
  • 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 '16 at 14:03
  • Because I prefer to use specialized tools. – romainl Apr 1 '16 at 14:31
3

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

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.

2

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 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.

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.