2021-01-17

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 -

  1. Create notes
  2. Search and open notes
  3. 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.