Setting up VimWiki in Neovim

To Logseq or not to Logseq

In recent years I’ve been trying many different solutions for my note taking needs. The app that I’ve been using the most has been Logseq, which I still use and like, but has some kinks and pain points that are not being actively addressed by the developing team recently:

Translating the Vimscript commands into Lua

This will:


vim.g.vimwiki_list = {
  {
    path = "~/Notes/VimWiki",
    syntax = "markdown",
    ext = ".md",
    links_space_char = "_",
    auto_tags = 1
  }
}

To activate the syntax highlighting for code blocks instead, I use this:


vim.g.vimwiki_syntax_plugins = {
	codeblock = {
		["```lua"] = { parser = "lua" },
		["```python"] = { parser = "python" },
		["```javascript"] = { parser = "javascript" },
		["```bash"] = { parser = "bash" },
		["```html"] = { parser = "html" },
		["```css"] = { parser = "css" },
		["```c"] = { parser = "c" },
	},
}

To make so that the settings are loaded properly by Neovim, at the start of the plugin, we can make use of the init option in lazy.nvim. Here’s my vimwiki.lua:

return {
	"vimwiki/vimwiki",
	init = function()
		-- Default directory, syntax and file type,
		-- symbols for spaces, auto re-index tags db
		vim.g.vimwiki_list = {
			{
				path = "~/Notes/VimWiki",
				syntax = "markdown",
				ext = ".md",
				links_space_char = "_",
				auto_tags = 1,
			},
		}

		-- Disable header levels keybindings so oil.nvim will work
		vim.g.vimwiki_key_mappings = {
			headers = 0,
		}

		-- Syntax highlighting for code blocks
		vim.g.vimwiki_syntax_plugins = {
			codeblock = {
				["```lua"] = { parser = "lua" },
				["```python"] = { parser = "python" },
				["```javascript"] = { parser = "javascript" },
				["```bash"] = { parser = "bash" },
				["```html"] = { parser = "html" },
				["```css"] = { parser = "css" },
				["```c"] = { parser = "c" },
			},
		}
	end,
}

After figuring out the init section of lazy.nvim the previous workaround is meaningless.

A pesky code snippet

Most important of all, I had to find where exactly to put this code in my Neovim config, because for some VimWiki quirks already not completely clear to me, it won’t work at all if I put them in my settings.lua file, as I’d like to.
As of now, my modular Neovim configuration works like this:

init.lua----
|   |   |   |
|   |   |   keymaps.lua
|   |   |
|   |   settings.lua
|   |
|   autocmds.lua
|
plugins.lua
    |
    init.lua   <--- PUT IT HERE!
    |
    LSP/
    UI/
    coding/
    navigation/
    treesitter/
    utilities/

~~I had to put the VimWiki config files right after calling LazyVim to load my plugins, in the `init.lua` file that loads all the plugins modules, otherwise Neovim won't read it at all.~~

Markdown it all

I started playing around with VimWiki while keeping its original file format and syntax, but honestly it feels quite wasteful to learn and use yet another syntax that I will only ever use for VimWiki and nothing else. Writing notes in markdown is much better, it’s kind of a standard nowadays, I already use it everywhere, and also it will come in handy in case I want to translate some notes into HTML, since with markdown the browser can do it for me. No need for any extra steps, post-processing or plugins whatsoever.

MDwiki

Speaking of which, I found this little “program” (it’s literally just an HTML file) called MDwiki, that can open all my VimWiki notes and structures in the browser, and render it clearly. All I have to do is put the file MDwiki.html in the root directory of VimWiki and launch a local server (for example I’m using alive-server), and the wiki will show up (locally) in my browser. Obviously, all the notes must be in markdown for this to work. Pretty neat!

Convert from .wiki to .md

Since I had already used VimWiki for a couple of days and I didn’t want to redo all my structure (I use PARA by the way) and manually convert the few notes I wrote, I needed some kind of script for the conversion from .wiki to .md. It took me some trial and error but I’m happy to say that we have a winner here:


#!/bin/bash

set -euo pipefail

# files to change extension from to md format
readarray -d '' mv_files < <( \
  find . \( -iwholename '*diary/*.wiki' \
    -or -iwholename '*unorganized_things/*.wiki' \
    -or -iwholename '*design_docs/*.wiki' \
    -and -not -iname 'diary.wiki' \
    -and -not -iname 'index.wiki' \) \
    -print0
)

for file in "${mv_files[@]}"; do
  md_file="${file%%.wiki}.md"
  mv "$file" "$md_file"
done

readarray -d '' files < <(find . -name "*.wiki" -print0)
for file in "${files[@]}"; do
  md_file="${file%%.wiki}.md"
  sed -r -e 's/\{\{\{$/\{\{\{bash/g' -e 's/%%/TODO: comment/g' "$file" | pandoc --from vimwiki --to commonmark_x -o "$md_file"
  sed -r -i -e 's/(\[.*\])\(([^#]*)((.*) "wikilink")\)/\1\(\2.md\4\)/g' \
    -e "s/\\\'/\'/g" \
    -e "s/\[\]\{\.done[0-3]\}/\[ \] /g" \
    -e "s/\[\]\{\.done4\}/\[X\] /g" \
    "$md_file"
  rm "$file"
done

The only things I had to fix were a table and some backslashes around some files, but the rest worked flawlessly. Maybe I can tweak the script in the future. I didn’t wrote the script, I found it on this blog article.

Tags system and Telescope

I use tags in my other systems quite extensively and I like to have a tag “system” in VimWiki as well. Too bad it’s quite limited for now. Tags are added by surrounding a word with semicolons :work:, and can be chained together, if multiple: :work:programming:python:. The major issue though is the search system: it’s just bad, and slow.

What I ended up doing is using Telescope, which I have already installed in Neovim, with fzf and ripgrep for some sweet extra speed.
And then I found this plugin for Telescope on GitHub, which makes for an even better integration, so I can use specific keybindings to search directly only inside my VimWiki notes, either just for notes’ titles or live grep all the notes’ content, no matter the CWD. Alas, it looks like the development of the plugin is not active anymore but I wish they’d implement tags as well!

Shortcuts and commands

Here’s a table of shortcuts for VimWiki commands and a few more to deal with the Neovim speller (which is nice to have):

CommandDescription
<leader> wwOpen VimWiki
<leader> wiOpen VimWikiDiary
<leader> w <leader> iGenerate day’s links in the Diary index page
<leader> w <leader> wOpen Today
<leader> w <leader> yOpen Yesterday
<leader> w <leader> mOpen Tomorrow
<leader> fvTelescope: search VimWiki’s notes titles
<leader> fwTelescope: live grep inside VimWiki directory
------------------------------------------------------------
“n”, zgAdd words to the spell checker
”n”, ]s - [sJump to the next misspelled word
”n”, z=Gives suggestions for correct words
”i”, <c-x> sGives a list with suggestions

That's all folks!