Taking Notes with Vim

6 minute read

I’ve been using Joplin for about 3 months, I love it, than any other note taking apps. Everything works fine until this Tuesday afternoon (around 3:20 PM to be more accurate), Joplin deleted all my notes under Work without any promption, the only thing I do at that time is renamed all the sub-notebooks under it (from abbreviation of months to numbers), I feel disappointed, because I love it so much and count on it, I exported all my notes from evernote and imported to Joplin.

At first googled to find how to recover the notes, all I found is how to recover deleted notes, and it is not well documented, I think it is not suit for my case, there are 367 issues regarding deleted notes in github repository at the time of this writing.

The good thing is I have synchronized all the notes to my MacBook via Joplin server this morning before I get to work, so I only have one day’s notes missing, I decide to move on, seeking more better way to do note taking, first thing come to my mind is I have to full control of my notes, it’ll better sync with github repo and saved to plain text file like markdown, Joplin can also export notes to markdown files, but it is acctually saved in sqlite3 database, it is not a issue before, but totally different right now.

I found these two are git based, but seems not fit for my situation:

  • GitNote is based on git, but it seems to be closed sourced
  • GitJournal can also sync with git, it only have mobile client, and need to buy it.

I decided to make my own note-taking system after I read this post witten by scottshipp on dev.to.

I have exported all the notes and commited to github repository, all I need is to find an editor that support markdown format. I make some diagrams with mermaid and js-sequence-diagrams, that would be great if the editor have support for them.

The one scottshipp used is TextMate, I need an app that support both macOS and Ubuntu, so this is not an option for me.

Visual Studio Code is the most popular IDE for developers, I heard it from peoples at work, I totally get lost after I luanched it, it’s too heavy for note taking purpose:

$ brew install --cask visual-studio-code

Foam is fabulous, but it needs to work with Visual Studio Code: Foam Show Graph

Mark Text is markdown editor, it is simple and support two OSs that I use, and it supports rending mermaid and js-sequence-diagrams, the only down side is it keeps deleting empty lines, this issue is still open for discussion, install it with brew:

$ brew install --cask mark-text

Atom is clean just like MarkText, it supports markdown preview in its core package, you have to press ctrl-shift-m to enable it, when scroll up and down, the preview tab does not move accordingly, install and try it with:

$ brew install --cask atom

There are online markdown editors out there, such as StackEdit, takenote, none of them fit my needs.

After trying those apps, I still cannot find one to fulfill my requirements.

I’ve been using vim for more than ten years, and get used to it, mostly for coding and writing blog posts, it has plenty of plugins to make it a powerful IDE, why not just using it as an note-taking frontend and save notes to github, the features I need is the following:

  • open source
  • sync with github
  • saved as plain text
  • markdown preview
  • mermaid
  • js-sequence-diagrams
  • show hierarchy of the notes
  • clean design

VIM can do markdown preview with Markdown Preview for (Neo)vim plugin, it supports both mermaid and js-sequence-diagrams, besides, it also supports:

So vim seems a perfect one for me to take notes, another options is Neovim which is much similar.

The plugin I used as follows:

Use the following snippets to do a quick setup:

git clone --depth=1 https://github.com/amix/vimrc.git ~/.vim_runtime
sh ~/.vim_runtime/install_awesome_vimrc.sh
git clone https://github.com/iamcco/markdown-preview.nvim.git ~/.vim_runtime/my_plugins/markdown-preview.nvim

cd ~/.vim_runtime/my_plugins/markdown-preview.nvim
yarn install && yarn upgrade

cat << EOF >> ~/.vim_runtime/my_configs.vim
set number
silent! unmap <space>

" Quik close and save
map <leader>q :q<cr>
map <leader>a :qa<cr>
map <leader>w :w<cr>

map <leader>tn :tabnew

" Open NERDTree at left side
let g:NERDTreeWinPos = "left"

" Markdown Preview"
nmap <C-p> <Plug>MarkdownPreviewToggle
imap <C-p> <Plug>MarkdownPreviewToggle

nnoremap <F3> "=strftime("%a %Y-%m-%d %H:%M:%S")<CR>P
inoremap <F3> <C-R>=strftime("%a %Y-%m-%d %H:%M:%S")<CR>
EOF

How to use:

  • <leader> nn to show NERDTree
  • Press t in NERDTree to open file in new tab
  • F3 to insert date and time
  • Ctrl-P to enable/disable mardown preview

For using nvim for macOS and Linux, install it with brew:

$ brew install neovim

Until now, there is only one piece missing compared to Joplin or Evernote, that is yaml front matter, when writing note with Joplin, it will create the following header for you:

---
title: 'My Note Title'
updated: 2021-11-29 09:43:04Z
created: 2021-11-27 01:07:23Z
latitude: 34.77320000
longitude: 113.72200000
altitude: 0.0000
---

I miss this feature so much, this can be easily done in shell script:

  1. title can be passed by parameter.
  2. updated and created date and time can be generated with date.
  3. geolocation can be retrieved from ip address with the help of available API.
  4. I also want to add the weather infomation, like this one.

To create yaml format front matter like Jolin did, save below script to note.sh:

#!/bin/bash

notebook=$HOME/workdir/Joplin-notes
title=$1
items=($title)
item1=${items[0]}
item2=${items[1]}
item3=${items[2]}
notename=$(date "+%F")-$(echo $title | tr ' ' '-').md
updated=$(date "+%F %H:%M:%S%z")
created=$(date "+%F %H:%M:%S%z")
dir="Work/$(date +%Y)/$(date +%m)"
ipaddr=$(curl -s ifconfig.me)
city=$(curl -s http://ipinfo.io/${ipaddr} | jq -r '.city')
loc=$(curl -s http://ipinfo.io/${ipaddr} | jq -r '.loc')
latitude="${loc%,*}"
longitude="${loc#*,}"
weather=$(curl -s wttr.in/${city}?format=3)

[[ -z $1 ]] && echo "You need to tell me what this note is about!"

[ ! -d "$notebook" ] && git clone https://github.com/fudongbai/Joplin-notes
cd "$notebook"

cat << EOF >> $dir/$notename
---
title: $title
updated: $updated
created: $created
weather: $weather
latitude: $latitude
longitude: $longitude
---

# Plan
- [ ] $item1
- [ ] $item2
- [ ] $item3

# Breakdown

## $item1

## $item2

## $item3

EOF

vim $dir/$notename

Don’t forget to install `jq:

$ brew install jq

Execute below command:

./note.sh "First note"

Will create a note named 2021-12-02-First-note.md with following contents:

---
title: First note
updated: 2021-12-02 06:33:23+0800
created: 2021-12-02 06:33:23+0800
weather: Qingdao: ☀️ +5°C
latitude: 36.0649
longitude: 120.3804
---

# Plan
- [ ] item 1
- [ ] item 2
- [ ] item 3

# Breakdown

## item 1

## item 2

## item 3

I commit the notes to git and push the commit at the end of the day, so I can continue my work at home with just git pull, what if I forget (which is very likely) to push the commit, syncthing can save my ass, this is the docker-compose.yml that I used for syncing:

version: "3"
services:
  syncthing:
    image: syncthing/syncthing
    container_name: syncthing
    hostname: my-syncthing
    environment:
      - PUID=1000
      - PGID=1000
    volumes:
      - ./notebook/:/var/syncthing/notebook
    ports:
      - 8384:8384
      - 22000:22000/tcp
      - 22000:22000/udp
    restart: unless-stopped

For a detailed configuration of syncthing is beyond the scope of this post, see sync things with syncthing ofr more detail.

After use this setup for couple of days, I am pretty satisified with it, as being said, start small and evolve, this system will be extended to meet my needs, for now, this is the end of note-taking app searching journey.

At the end, I attached this full list of editors and plugins I’ve tried to find my own solution finally:

https://github.com/skanehira/preview-markdown.vim [obsidian]: https://obsidian.md