mkaz.blog

Working with Vim

VimWiki

VimWiki is a powerful plugin that enables Vim to manage your own personal wiki or knowledge base. It is a great tool to keep track of notes, lists, or just about anything.

😎

Yes, Vim is a text editor and obviously you can type notes or lists in any text editor. VimWiki provides shortcuts, and a defined spaces for daily notes, and a scratch area always ready to write.

Install and Configuration

Install the plugin using vim-plug

Plug 'vimwiki/vimwiki'

I configure VimWiki to a specific directory that I sync across devices using Syncthing. VimWiki stores everything in plain text file with default markup in it's own wiki format. I recommend switching to use markdown it is a standard choice now.

To set default directory, and default format to markdown:

" Vim .vimrc
let g:vimwiki_list = [{'path': '~/wiki/', 'syntax': 'markdown'}]

Or if you are using Neovim, and a Lua config:

-- Neovim init.lua
vim.g.vimwiki_list = {{
	path = '~/wiki',
	syntax = 'markdown',
	ext = 'md'
}}

Usage

Type <Leader>ww to open the index file, one will be created if it does not already exist. Using the config above, the index file is ~/wiki/index.md.

This works regardless of Vim's current directory, for example if working in another project. Use <Leader>ww and it opens directly to the configured wiki. Nice for an instant scratch pad to take whatever notes.

Create additional files by inserting links and navigating to them.

Insert a link by surrounding text with double-brackets, for example [[LinkText]]. Navigate by moving your cursor over the link in normal mode and press enter. This will open the linked page, creating the file if needed.

Create pages for any list, tasks, info, notes, or for whatever you want.

Shortcuts

  • <Leader>ww – Open the default wiki index file
  • <Enter> – Follow/Create wiki link
  • <Backspace> – Go back to previous page
  • <Tab> – Go to next wiki link
  • <Shift-Tab> – Go to previous wiki link

Todo Lists

VimWiki has a few built-in types and features. One is a todo list that enables using the standard markdown checkboxes and creates shortcuts to mark complete, or cycle through partial completion.

-   [ ] Write Vim Lessons
-   [ ] Edit Vim Lessons
-   [ ] Publish

To toggle an item complete use ctrl-<Space> with your cursor on the line you want to toggle. Todo lists also work for nested items, simply indent the item. Vim folding works with nested lists. Toggling will also mark all sub-items.

For an item that might be partially complete, use gln to toggle forward completion levels, and use glp to toggle backwards completion levels. Levels progress through '.oOX' sequence which you consider equating to:

[ ] -- 0% complete
[.] -- 1-33% complete
[o] -- 34-66% complete
[O] -- 67-99% complete
[X] -- 100% complete

The sequence of characters to mark completion status can be changed using g:vimwiki_listsyms for example

let g:vimwiki_listsyms: '✗○◐●✓'

Vimwiki todo help section in Vim at :help vimwiki-todo

Diary

The Vimwiki diary is the most useful feature, I use it similar as the daily notes in Obsidian.

Daily Notes

VimWiki diary makes it easy to create a daily entry. Type <Leader>w<Leader>w to create a new entry based on today's date. A diary subdirectory is created containing the wiki files, to configure the subdirectory use diary_rel_path in the vimwiki_list_ config.

For example, to use Notes/ subdirectory relative to wiki path:

vim.g.vimwiki_list = {{
	path = '~/wiki',
	syntax = 'markdown',
	ext = 'md',
    diary_rel_path = 'Notes'
}}

Use <Ctrl-Up> and <Ctrl-Down> to navigate to previous and next notes. This will only navigate to notes that already exist, it will not create new notes. This is extremely helpful, my typical process is start on today's note and then check what was left over from yesterday.

Calendar

This Calendar plugin works with the diary feature, allowing you to browse and create entries using a calendar interface. I map the F3 key to open the calendar using :Calendar command.

A less useful alternate to the calendar is the diary index page. Use <Leader>wi to open the diary index page, this will be at diary/diary.md. In the diary index page use the :VimwikiDiaryGenerateLinks command to fill the page with links to all the pages created. I find this less useful and requiring additional steps.

The calendar allows browsing in an easier format, but no reason you can't use both methods.

Vimwiki Calendar Screenshot

Diary Frequency

The diary can be configured at different frequencies than daily.

Set diary_frequency option in vimwiki_list to one of the following:

  • daily : new entry dated with today's date
  • weekly : new entry date to start of week
  • monthly : new entry date to start of month
  • yearly : new entry date to start of yearly

For example, a monthly note will be dated to the start of the month so the note would be 2024-04-01.md and not 2024-04.md

For weekly frequency, change the start day of the week using diary_start_week_day setting to a day, default is monday.

Diary Template

Use the vimwiki_auto_header setting to automatically insert a header based on the filename. For the diary entries this would be a date like # 2024-04-25 at the top of the file.

vim.g.vimwiki_auto_header = 1

However, I wanted a fancier date format and some stubbed out sections, so I use a vim auto command to call a script and insert the header.

vim.api.nvim_create_autocmd({'BufNewFile'}, {
    pattern = { "*diary/*.md" },
    command = "0r! ~/bin/vimwiki-diary-tpl.py '%'",
})

The script could be in whatever programming language, and used just for a dynamic date, if I just wanted a static template I could use read without the ! to pull in. The autocmd calls the script and passes in filename, in case it is not today's page.

Here's the content of the script, mine is in Python because it's the best programming langauge:

#!/usr/bin/env python3
 
from datetime import datetime
from pathlib import Path
 
template = """# {date}
 
## Todo
 
- [ ] 
 
## Notes"""
 
# default
dt = datetime.now()
 
if len(sys.argv) > 1:
    fp = Path(sys.argv[1])
    dt = datetime.strptime(fp.stem, "%Y-%m-%d")
 
print(template.format(date=dt.strftime("%b %d, %Y")))

🎩 Hat tip to Jakub Kadlcik for this solution.

Vimwiki does have a search tool built-in, but I don't tend to use it. I use ripgrep search as I would any other directory. See my vim search page for additional.

The search tool is useful when working in different directory, and bounce over to the wiki to add notes. The ripgrep search is based off the working directory, where Vimwiki search is always the wiki.

Use :VWS /term/ from a wiki page to search. It will search the entire wiki, but requires to be in the wiki context first.

After searching, use :lopen to see all results

Tables

Use :VimwikiTable 4 2 to create a table with 4 columns and 2 rows

| sdfas |     |     |     |     |
| ----- | --- | --- | --- | --- |
|       |     |     |     |     |
|       |     |     |     |     |

Press tab to advance to the next column, it auto formats as you go. Press enter or tab on the last row to create another row. Here's a quick example showing how quick it is to create a markdown table in Vimwiki:

Vimwiki table example

Vimwiki table help in Vim at :help vimwiki-tables