NVim and Pandoc settings
Table of content
For quite some time now, I only used markdown for either note-taking or making revealjs
(Fr) presentations. And this blog of course…
Anyway, while looking for my next employer, I recently had to produce a document and I wanted to use my usual tools: nvim
to write markdown
and compile it using pandoc
. The thing is, my nvim
configuration was kind of hard-coded for revealjs
.
It was time for me to address this issue and have it work for every type of pandoc
use case.
The issue
Say, you open a markdown
file with the .md
extension with nvim
. The filetype is automatically detected to markdown
and you’re happy.
But, how to instruct nvim
on what to do with it? How to tell whether it’s a regular markdown
file containing notes, a blog post, or a pandoc
and maybe revealjs
oriented redaction?
And of course, what to do with this information?
The solution
The approach I’ve taken here is two-fold:
- Set some information about the file’s content using the
modeline
feature, - Define a custom
makeprg
based on this information.
Modeline
Setting the correct filetype is as easy as using a modeline
.
A modeline
is a commented piece of instruction for nvim
at the start or end of a file. When the file is (re)loaded in a buffer, the editor executes those commands.
There are some restrictions such as it cannot run code that may break your machine. For example, it’s impossible to set a custom makeprg
which would have been of great use here. But this blog post is all about finding a way to overcome this limitation.
As said before, a modeline
is one or more commented lines. There are no comments in markdown
… But pandoc
documents have this yaml
header which may contain comments. So there is no issue here: a regular markdown
will be detected as such and any pandoc
source will be able to set its own filetype.
I picked two filetypes for the occasion: pandoc
and revealjs
. I use the former to generate basic HTML
files automatically and the latter to generate a presentation manually.
# vim: set filetype=pandoc:
# vim: set filetype=revealjs:
Makeprg
While nvim
forbid the redefinition of makeprg
through the modeline
for security reasons, it allows us to define filetype-based behavior.
It’s as easy as writing a small bit of lua
in the ~/.config/nvim/after/ftplugin/pandoc.lua
and ~/.config/nvim/after/ftplugin/revealjs.lua
files.
Pandoc.lua
1 vim.opt_local.makeprg = "pandoc % --output %:r.html --standalone"
2
3 local pandoc = vim.api.nvim_create_augroup("pandoc", { clear = true })
4
5 vim.api.nvim_create_autocmd({ "BufWritePost" }, {
6 group = pandoc,
7 command = [[ silent make ]]
8 })
The first line defines the makeprg
. Using pandoc
to generate an (almost) self-contained HTML
file.
And the seventh line calls this makeprg
every time I save the buffer to disc. It’s a really fast process so I allow this often.
Revealjs.lua
vim.opt_local.makeprg = "pandoc % \
--output %:r.html \
--from markdown+emoji \
--to revealjs \
--slide-level 4 \
--standalone \
--variable revealjs-url=https://unpkg.com/reveal.js@latest/ \
--variable slideNumber=true \
--variable theme=solarized
This time, the makeprg
is more complex and there is no automatic call on BufWritePost
. Generating a revealjs
presentation takes more time so I manually call :make<CR>
every now and then when I want to see the output.
Conclusion
NVim
does not allow for file defined makeprg
. But it does allow for filetype defined one.
What we get here is a fine-grained configuration while remaining safe: there is no way for someone to send us an ill-intentioned file that’ll arm our system when opened with nvim
.
Bonus
When I’m ready to share the final output, whether it’s a simple HTML
or a revealjs
presentation, I add the --embed-resources
flag to pandoc
. It’ll output the file while embedding every asset in it, making it fully self-contained so no external resources (images, revealjs
library) will be loaded on opening.
:make --embed-resources<CR>
👌