>> 2022-02-15 - Note taking with Vim

I seem to always be on the hunt for a good notetaking app. I've tried a LOT of
different apps but none of them really fit my needs and end up getting overly
complex. I tend to stick with tools I build myself so I thought why not write a
note-taking tool. 

# Overview
My needs were fairly simple: 
- Support for cross-linked notes 
- Must sync between machines 
- Command line support 
- Something flexible

I already enjoy using vim, so that seemed like a natural choice. 

## Cross-linked Notes
Cross-linked notes are a killer feature for me. I like being able to
cross-reference notes. I used to use "Tomboy" a long time ago and it is what
turned me on to this functionality. I was able to accomplish this directly in
vim with the help of a little vimscript. To create a cross-linked note I just
enclose a word in curly braces: {some_other_note}. Then I simply move the cursor
over that word and press '\l' and vim opens a new buffer named after the word
the cursor was over in the previous buffer. If a file already exists it opens
it, otherwise it creates a new file with a basic header (file name, created
date, updated date, last referenced date).

Here is the function and mapping from my vimrc:
-------------------------------------------------------------------------------
"##### stuff for Notes #####

"This sets syntax highlighting for cross-note links
au BufRead,BufNewFile *.note hi nlink
        \ guifg=black guibg=green
        \ ctermfg=black ctermbg=green
au BufRead,BufNewFile *.note syn match nlink "{[a-z].*}"

"This function opens a link in a new buffer
noremap <leader>l :<c-u>call OpenNoteLink()<cr>

function! OpenNoteLink()
    let word = expand("<cword>")

    execute "below split " . word . ".note"
    let bufsize = wordcount()['chars']
    
    if bufsize == 0
        let currdate = strftime("%Y-%m-%d")
        call append(0,"      file: " . word . ".note")
        call append(1,"   created: " . currdate)
        call append(2,"   updated: " . currdate)
        call append(3,"referenced: " . currdate)
        call append(4,repeat('=',80))
    else
	    call setpos('.', [0, 6, 0, 0])
    endif
endfunction
-------------------------------------------------------------------------------

## Sync
Sync was pretty simple as I just used something that already existed: git. using
git allows me to not only sync between computers but also gives me a nice way to
track all the changes made to my notes and lists. 

## Misc
'todo.note' - This is a special file where you can put a list of things to get
done. Each line begins with a dash '-'. When the item is completed you replcae
the dash with a plus sign and it gets moved to a 'completed.note' file. Moving
items from 'todo' to 'completed' is handled by a simple shell scritp named
'complete.sh'.

Code for 'complete.sh':
-------------------------------------------------------------------------------
#! /bin/bash
todos='todo.note'
completed='completed.note'
curr_date="$(date +'%Y-%m-%d')"

# Find completed tasks and add them to completed
printf "\e[36mArchiving task(s)...\e[0m\n"
grep '^+ ' "${todos}" | sed 's/+ //' | \
xargs -I{} echo "${curr_date}: {}" >> "${completed}"

# Remove the completed items
sed -i 's/^+ .*//g' "${todos}"
-------------------------------------------------------------------------------

Syntax highlighting - I chose to use the '.note' file extension so I could add
special syntax highlight rules for links to other notes. Whenever a note is
opened in vim, links to other notes are highlighted in bright green.

# Conclusion
Overall this system has been a lot of fun to write and has met my needs. I am
thinking about adding a feature that would integrate with my shell prompt and
let me know if I have any todos that have gotten old, but I'm not sure if it
would be useful.

If anyone finds this setup useful, I'd love to know! 

- Mark
  me@markw.dev