I use Neovim in a Linux (Arch Linux) environment. I have written a function to help me preview my markdown documents in PDF format without using a whole plugin. I've also added a simple command named "Prev" to call this function.

Here's the relevant part of my vimrc file :

function! s:pdf_preview()
    ! pandoc % -s -f markdown -t odt -o ~/.cache/%:t:r.odt > ~/.cache/%:t:r_Prev_log.txt 2>&1
    ! soffice --headless --convert-to pdf --outdir ~/.cache ~/.cache/%:t:r.odt >> ~/.cache/%:t:r_Prev_log.txt 2>&1
    ! zathura ~/.cache/%:t:r.pdf >> ~/.cache/%:t:r_Prev_log.txt 2>&1
command Prev call s:pdf_preview()

Note : I'm using soffice to convert from odt to pdf to avoid installing a LaTeX processor (which I think would be required by pandoc for a direct conversion from markdown to pdf).

I'd like to improve this function in two ways :

  1. save the current file in the .cache folder before the "! pandoc" command, so that I can use this temporary file for the preview instead of having to save my document each time ;
  2. delete the temporary files (the odt and the pdf files) once the preview with zathura is closed.

Thanx for any help !

1 Answer 1


You can use :write {filename} to save your file in a different location without changing the active buffer.

Regarding your second question, you could look at :help job-control which describes how to start asynchronous process in Neovim. The on_exit callback may be what you need. For example the following snippet prints a message after then seconds

function! Echo(job_id, data, event)
    echo "CLOSED!"

call jobstart (
    \ [
    \ 'bash',
    \ '-c',
    \ 'for i in {1..10}; do echo hello $i!; sleep 1; done'],
    \ {'on_exit': 'Echo'})

So, jobstart takes two arguments, the first is a list with the command to execute, and the second is a dictionary that maps events to functions. You only care about exiting Zathura, that's why the example only includes the on_exit event. You could try to write a function mapped to the on_exit event that deletes the file when called, and a script executed by jobstart that launches Zathura and returns the control to Neovim when it is closed

  • Unfortunately, adding ! write ~/.cache/%:t:r.md before the pandoc function does nothing : the file is not saved, and the message write : /home/me/file.md is not connected is returned.
    – Dupond
    Apr 12, 2020 at 6:29
  • That's because :write is a Neovim command, not an external command, so you should not prepend it with !
    – Tae
    Apr 12, 2020 at 7:42
  • OK, it works without ! but asks for a confirmation to overwrite the file if it already exists. Is there a way to avoid this ? By the way, I've read the "Concepts" and "Usage" pages of :h job-control, but haven't understood theme well. An example is given, but I don't see how to apply it to my use case.
    – Dupond
    Apr 12, 2020 at 8:01
  • You can use :write! <filename> to overwrite it. (BTW, the : at the beginning is optional in script files.) I’ll update the answer with an example for job control
    – Tae
    Apr 12, 2020 at 8:06
  • Thank you very much for the example. I've tried to adapt it, but the function mapped to on_exit is not executed, thus the files are not deleted : function! Echo(job_id, data, event) ! rm ~/.cache/%:t:r.md endfunction call jobstart ( \ ['zathura ~/.cache/%:t:r.pdf'], \ {'on_exit': 'Echo'}) (the formatting is bad, there are several lines obviously)
    – Dupond
    Apr 12, 2020 at 9:29

Your Answer

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

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