Vim and Note-taking/Writing
A while ago I posted about research tools I've built and a few parts focused on enhancements to vim (taking screenshots, opening media and links, automatically formatting text from pdfs), which is still my preferred program for writing and note-taking. Here are a few other enhancements that make it a more pleasant experience.
I have all of the following snippets enabled for markdown only (in ~/.vim/ftplugin/markdown.vim
).
Spelling correction
I still make a lot of typos and don't notice until a bit later. This snippet lets you hit <ctrl-f>
while in insert or normal mode to automatically fix the closest speling error. This is an example.
setlocal spell
" quickly fix the closest previous spelling error.
imap <c-f> <c-g>u<Esc>[s1z=`]a<c-g>u
nmap <c-f> [s1z=``
The only shortcoming is that the default vim dictionary is really lacking, so a lot of common words come up as spelling errors. You can easily add words to the dictionary by moving over them and hitting zg
by default.
Preview markdown as HTML
Sometimes it's easier to read through a markdown file as HTML. This lets you use <leader>v
to compile the file and open it in a browser using nom
.
" compile and open in browser
nnoremap <leader>v :r !nom view "%:p"<cr>
Create footnote from text
I try my best to keep my citations organized in anything public-facing, but if you have a lot of footnotes it can be troublesome to manage them all in markdown. This lets me highlight a citation, hit <ctrl-f>
, and then fills my clipboard with a markdown-formatted citation to paste in.
" make footnote from selected text
vnoremap <C-f> y:! cite "<C-r>0" \| xsel -b<cr>
Writing mode
One challenge with writing in vim is that the text width can be too wide. There's a popular plugin called goyo
that helps with this by artificially constraining the current vim window to a smaller number of columns, but I always had issues with it. Fortunately I found a much simpler implementation that I adapted below.
" writing mode
" <https://stackoverflow.com/a/59955784>
function! ToggleWriteMode()
let l:name = '_writeroom_'
if bufwinnr(l:name) > 0
colorscheme dark
:bwipeout _writeroom_
else
colorscheme light
" hide vertical split
hi VertSplit ctermfg=bg ctermbg=NONE cterm=NONE
" auto-close writeroom buffers when the text buffer closes
autocmd QuitPre <buffer> :bwipeout _writeroom_
" target column width
let l:target = 90
let l:width = (&columns - l:target) / 2
silent! execute 'topleft' l:width . 'vsplit +setlocal\ nobuflisted' l:name | wincmd p
silent! execute 'botright' l:width . 'vsplit +setlocal\ nobuflisted' l:name | wincmd p
endif
endfunction
nnoremap <silent> <leader>w :call ToggleWriteMode()<cr>
Table of contents navigation
In vim it's harder to get a sense of the high-level document structure and navigate through sections. There's a plugin called VOoM
that basically adds a table of contents pane for markdown documents. It's nice but a bit cumbersome to jump to it and make your section selection there.
Instead I've set up a way to pull up section headings and quickly jump to them using the fzf.vim
plugin (which I'll describe in more detail in the next section) and ripgrep
.
" Table of Contents (for markdown files)
" Jump to line match from ripgrep
" Expects that the line is delimited with ':'
" and the first field is the line number.
function! s:line_handler(line)
let keys = split(a:line, ':')
execute "normal! " . keys[0] . "gg"
endfunction
" Args
" - Source: user ripgrep to search for one or more '#' at the start of a line
" in the current file
" - Sink: use the line hanlder function above to jump to the selected line
" - Options:
" - reverse output
" - split on ':' and take all fields from the 2nd on
" (i.e. skip the line number)
command! -bang -complete=dir -nargs=? TOC
\ call fzf#run(fzf#wrap('toc', {
\'source': 'rg -Tcsv --line-number --no-heading "^#+" '.expand('%:p'),
\'sink': function('s:line_handler'),
\'options': '--reverse --delimiter=: --with-nth=2..'
\}, <bang>0))
nnoremap <leader>e :TOC<cr>
fzf.vim
I put very little effort into keeping my notes organized these days because of fzf.vim
. It makes it very easy to quickly search through files by filename or contents from within vim (using ripgrep
).
You can get a pseudo-wiki functionality with the following, which searches files for the word under the cursor:
" Search for word under cursor
nnoremap <silent> <Leader>g :Rg <C-R><C-W><CR>
Honorable mention: Opening files
This isn't anything I've added to vim, but is really useful. If your cursor is over a file path, you can hit gf
to open that file in vim. It gives you a wiki-like functionality (though more cumbersome) or a way of making indices for research topics.