>> 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 l :call OpenNoteLink() function! OpenNoteLink() let word = expand("") 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