Linking Zettelkasten Notes

For several years I have been keeping a journal and notes in Vimwiki. While Vimwiki is a great plugin, I wanted more control over how things were done, so I decided to develop my own system while still using Vim. The system is a work in progress. There are two things I have committed to. The first being the format will be plain text using markdown syntax. The second being the notes part of the system will be using the idea of zettelkasten for the actual taking of notes.

At this point I should tell you what zettelkasten is but I am not. That is for another post. Today I am going to talk about how to link notes together.

One of the sites I find very helpful about using Vim with zettelkasten is Edwin Wenick's Blog. His article titled Creating and Linking Zettelkasten Notes in Vim has been very helpful. This article would be not possible without it.

Edwin created some vim script that uses CtrlP to link the current note you are editing to a previous note. A reader, Fernando, created script that did the same thing except it used fzf and he posted it in the comments. I mentioned I wanted to build on that idea and add Silver Searcher to the linking script so it would be easier to find the previous note by searching on the text of all the notes rather than just file names. Well, before I could get around to it another reader, hbenevides, created a script that uses Ripgrep to search on the text of all the notes to create a link to a particular note and posted it. His script can be found also in the comments of the above article.

Rather than create something new for silver searcher, I built off hbenvides script.

Here is the modified script:

" make_note_link: List -> Str
" returned string: [Title](YYYYMMDDHH.md)
function! s:make_note_link(l)
        " fzf#vim#complete returns a list with all info in index 0
        let line = split(a:l[0], ':')
        let ztk_id = l:line[0]
    try
        let ztk_title = substitute(l:line[2], '\#\+\s\+', '', 'g')
catch

        let ztk_title = substitute(l:line[1], '\#\+\s\+', '', 'g')
endtry
        let mdlink = "[" . ztk_title ."](". ztk_id .")"
        return mdlink
endfunction

" mnemonic link zettel
inoremap <expr> <c-l>z fzf#vim#complete({
  \ 'source':  'rg --no-heading --smart-case  .',
  \ 'reducer': function('<sid>make_note_link'),
  \ 'options': '--multi --reverse --margin 15%,0',
  \ 'up':    5})
" mnemonic link ag
inoremap <expr> <c-l>a fzf#vim#complete(fzf#vim#with_preview({
  \ 'source':  'ag --smart-case  .',
  \ 'reducer': function('<sid>make_note_link'),
  \ 'options': '--multi --reverse --margin 15%,0',

What does this script do? This script has two different hot keys, one for Ripgrep and another for Silver Searcher. If you have both search tools installed you can use both and decide which one you like best. I left hbenevides original Ripgrep search alone except for one change. The script was originally designed to only search headers. I changed the search to also include all text. If you only want to search only headers you can start your search with the hashtag or modify the script back to the original search.

The script for Silver Search behaves much the same way but presents at the bottom of the page, which can be changed. The Silver Searcher script includes the fzf-vim preview window. If you use RipGrep and want the preview window that could certainly be added to the script for Ripgrep.

To use the RipGrep search in insert mode the key mapping is z and to use the Silver Searcher in insert mode the mapping is a

Hopefully someone besides me finds it helpful.

I am new to Vim Script so use at your own risk.

You may notice this article has a Zettelkasten ID. This is not a zettelkasten note but I am expanding the ID idea to many of my other text documents.

Zettelkasten ID linkingzettelkasten-2020-05-11-0735