My note-taking system
Vim
Vim's built in markdown highlighting does pretty much everything I need, or maybe
it's vim-polyglot? I also have goyo.vim installed but I rarely ever use it.
I found a nice spellchecker for coc which comes in pretty handy.
notes script
Fish scripting is a real pain, especially if you've never done it before. This article and the tutorial helped a lot. I didn't read either in their entirety, just searched for what I needed and copy-pasted. Here's the function I ended up with -
function notes
if test (count $argv) -lt 1
if test (pwd) != $HOME"/notes"
pushd ~/notes
end
else if test $argv[1] = "-t"
if test (pwd) != $HOME"/notes"
pushd ~/notes
end
set note_file (date +%Y-%m-%d)".md"
nvim $note_file
set -e note_file
else if test $argv[1] = "-s"
if test (pwd) != $HOME"/notes"
pushd ~/notes
end
if test (count $argv) -gt 1
set raw (fzf --print-query -1 -q $argv[2])
if test (count $raw) -gt 1
nvim $raw[2]
else
set note_file (date +%Y-%m-%d)" "$raw[1]".md"
nvim $note_file
set -e note_file
end
set -e raw
else
set raw (fzf --print-query)
if test (count $raw) -gt 1
nvim $raw[2]
else
set note_file (date +%Y-%m-%d)" "$raw[1]".md"
nvim $note_file
set -e note_file
end
set -e raw
end
else
if test (pwd) != $HOME"/notes"
pushd ~/notes
end
set note_file (date +%Y-%m-%d)" "$argv[1..(count $argv)]".md"
nvim $note_file
set -e note_file
end
end
I tried using Python/Ruby to write this but I couldn't get the directory change
to show up in the shell. I couldn't figure out how to compare stuff - but then I
read the manpage for the test command.
I wanted this script/function to serve 3 purposes -
- Create notes
- Search and open notes
- Create "today" files
I'd like to merge 1 and 2 someday, like having an fzf prompt create a file if
it doesn't exist, but for now keeping them separate shouldn't be a huge problem.
The process
I started by figuring out a way to name the files. I use the YYYY-MM-DD title.md
format for all my notes and I quickly found a way to generate these with
command substitution
and the date command.
function notes
set note_file (date +%Y-%m-%d)" "$argv[1]".md"
echo $note_file
set -e note_file
end
I ran into an error when I ran the command without $argv[1] which was easily
fixed with an if-statement.
function notes
if test (count $argv) -lt 1
echo "Note title missing"
else
if test (pwd) != $HOME"/notes"
pushd ~/notes
end
set note_file (date +%Y-%m-%d)" "$argv[1]".md"
nvim $note_file
set -e note_file
end
end
I added another if-statement which pushds to my notes directory if I'm not already
there. This way I can popd back to whatever I was working on after I'm done
with my note-taking. That's goal 1 finished, onward!
I knew I wanted to use fzf to search the files I just didn't know how. I started
by adding an else-if in the control flow which checks if $argv[1] is -s. Then
I tried to search and open the file with a command substitution.
...
else if test $argv[1] = "-s"
if test (pwd) != $HOME"/notes"
pushd ~/notes
end
nvim (fzf)
...
This worked well enough, but if I didn't find what I was looking for and Ctrl-C'ed
out of fzf, it opened neovim with an empty buffer. I wanted to go back to the shell
if this happened so I could create a new note. I tried to figure out how to open
a file from stdin, which led me to this
very helpful comment on an issue, thanks @tarruda!
I piped the output from fzf into nvim.
...
fzf | xargs nvim
...
Since my filenames had spaces, nvim considered them a list of files and opened them in separate buffers ("2021-01-17", "notes.md" would be different buffers instead of one). Some google-foo led me to this stackexchange post and I modified my code accordingly.
...
fzf | xargs -I {} nvim {}
...
This worked as I intended. Onto number 3.
3 was easy enough, I check if $argv[1] is -t, pushd into my notes directory
with the same if snippet, set the name of the file and then open it in neovim.
...
else if test $argv[1] = "-t"
pushd ~/notes
set note_file (date +%Y-%m-%d)".md"
nvim $note_file
set -e note_file
...
Update: I've aliased notes and notes -s to n and ns respectively.
alias n=notes
alias ns=notes -s
While going through the fzf man page I found the -1 option and added it to
the -s else-if branch where I'm passing $argv[2] to fzf. It automatically
opens the note if it's the only match, which gives it a very z-like feel.
Using the --print-query option for fzf and some clever list work, I was able
to get the combination of 1 and 2 I wanted. Now the script creates a new note
from the fzf query if there are no results.
Expansion
When I get the time, I'll write a Python script which pulls events from my Google
Calendar and tasks from Notion into my today file. I'll run it if the file doesn't
exist from the -t else-if branch. Maybe I can check if the file exists in the
Python script itself and keep the fish function clean?
I'd also like to map notes -s to a keystroke (ctrl-n is a good candidate).
Also see Expanding my notetaking system.
Syncing
Using rclone to access Google Drive on Linux
Reading
I'm probably going to build a nextjs app which authenticates via Google, reads these from Google Drive and renders them nicely so I can read them from anywhere.