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.
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 dateweekly
: new entry date to start of weekmonthly
: new entry date to start of monthyearly
: 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.
Search
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 help in Vim at :help vimwiki-tables