I write my todo lists like this:
- DONE! morning exercise
- DONE! buy milk
- pet the cat
- get your shit done
- read some book
..or like this:
- ✅ morning exercise
- ✅ buy milk
- pet the cat
- get your shit done
- read some book
Typing “DONE!” a bunch of times each day gets old pretty quick, as does searching for the emoji character so I wanted a way to make it faster to mark things as done. Also, it’d be nice to have a way of making items I’ve done stand out more. Here are some of the approaches I use:
This remap allows you to type ‘,done’ when in normal mode to insert ‘DONE!’ at the start of the todo item. It will then move the cursor down to the next line.
noremap ,done 02liDONE! <Esc>j
Prefer using the checkbox emoji? No probs…
noremap ,done 02li✅ <Esc>j
This approach would be ideal if you could hit ‘.’ to check off a load of items one after the other but there is a limitation of Vim that prevents this: The movements are not repeated. This means that the ‘0’ (move to start of the line), ‘2l’ (move 2 characters to the right), and ‘j’ (move to next line) won’t work so you’ll have to type ‘,done’ each time. Very frustrating.
This is the simplest way to mark a completed todo item as done, and it works with the “.” repeat. The downsides is that you’ll have to position the cursor yourself each time you use it.
iabbrev ,done DONE!
Or for checkboxes:
iabbrev ,done ✅
Because the action of marking something as done involves putting a checkbox or string in a specific place, it’s probably best to use the abbreviation approach as a generic emoji inserting tool.
To make ‘DONE!’ items stand out we can make a highlight rule which sets the foreground and background color of the string.
" Highlight the string DONE! with green background and black text
highlight HighlightDone guifg=black guibg=green
highlight HighlightDone ctermfg=16 ctermbg=28
call matchadd('HighlightDone', 'DONE\!')
Note how we’re using matchadd
here, this allows us to add additional matches
later on. If you only have a single match then match HighlightDone /DONE\!/
will work also.
The following highlight rule will make all lines starting with “- ✅” have green text making them stand out as done.
" Items starting with the checkbox emjoi have green text
highlight HighlightCheckbox ctermfg=46
call matchadd('HighlightCheckbox', '^\s*-\s✅.*$')
It’d be nice to have a strike through effect here too but alas, that is not available.
Add a checkbox to the current line with the following function. After defining the function we map it to a normal mode keystroke. To use it enter normal mode then type ‘,done’, the function will add a check box then move down to the below line.
" Insert checkbox emoji
function! InsertCheckEmoji()
" Get the current line
let l:line = getline('.')
" If it starts with '- ', insert the check emoji
if l:line =~ '^-\s'
let l:line = substitute(l:line, '^\(- \)', '\1✅ ', '')
call setline('.', l:line)
normal! j
else
echo "Line doesn't start with '- '"
endif
endfunction
noremap ,done :call InsertCheckEmoji()<CR>
Why bother will all these lines when a simple normal mode remap will do? Well I’d hoped that this approach would let me use ‘.’ to repeat but nope, it suffers the same limitation as before. That said, having the logic available does make this approach more powerful should you need it.
When defining highlights there is a distinction between ctermfg
and guifg
(or their background counterparts): gui will effect GUI based vim editors
while cterm will affect terminal based vim editors.
Colors for highlights sometimes work when using the name of colors (eg ctermfg=red) but I’ve found it more reliable to use the the Xterm number instead so find a list of 256 colors and use those. I guess that the theme you are using can override the color names which explains why it is unreliable?