Vim: Simple note taking
One thing I find immensely useful, is to be able to quickly summon a scratchpad and write some notes. There are already many note taking plugins for vim, so this may feel redundant, however, I have a simpler notion of note taking than most, and felt a quick note (heh) on this is still worth its salt.
First of all, I don’t always have the chance to plug into a plugin ecosystem. Sometimes all I can do is sftp over my .vim files, because the target machine I’ve to work on may be blocked from outside connections. Second, I treat notes as something transient. Some information I need for a specific task to be kept in mind, or a quick idea for something to do in the near future. If something is important enough to graduate from transient to permanent, it should probably live in a git repository anyway.
With that out of the way, let’s dive in.
The Problem Statement
This is actually a smaller thing to create than it looks on the surface, because vim comes with a built-in file explorer called Netrw
. It can be invoked with :Explore any time, and this means we do not need to create any customizations for removing, renaming, listing or reopening notes that have already been created.
The only functionality we do actively need to think about is creating a new note.
The first decision to be made is to choose a directory, and ensure it exists. There is actually no need to shell out from vimscript for this, because it includes its own equivalent to bash’s [ ! -d ] and also mkdir:
let l:dir = expand('~/Documents/notes/')
if !isdirectory(l:dir)
call mkdir(l:dir, 'p')
endif
This is much like saying:
DIR="$HOME/Documents/notes/"
if [ ! -d $DIR ]; then
mkdir -p $DIR
fi
Now, the next problem is naming the notes. We might want to give more than a single word as the title for a note, and that means our function needs to be able to accept an undetermined number of arguments as an input.
Fortunately vimscript makes this rather easy. Simply by passing ... as the argument into a function, we can tell it to expect a variable number of inputs.
The array of inputs passed in is then represented by a:000, and any single element can also be referenced like a:000[0]. a:000[1], a:000[2] etc.
This means multiple words can be passed in, and all of them can be referenced. I do not like to have spaces in filenames, so this is also a great opportunity to replace them with something else:
let l:title = len(a:000) > 0 ? '_' . join(a:000, '_') : ''
My naming convention is to stick the date in front of the note, just comes in handy for me to have some sort of chronology in the notes dir:
let l:fname = l:dir . strftime('%Y%m%d%H%M') . l:title . '.md'
And that is pretty much it for creating the files, call execute edit on l:fname and vim will open it right up for editing.
Assembling the function
function! QuickNote(...)
let l:dir = expand('~/Documents/notes/')
if !isdirectory(l:dir)
call mkdir(l:dir, 'p')
endif
let l:title = len(a:000) > 0 ? '_' . join(a:000, '_') : ''
let l:fname = l:dir . strftime('%Y%m%d%H%M') . l:title . '.md'
execute 'new'
execute 'edit ' . fnameescape(l:fname)
endfunction
command! -nargs=* Note call QuickNote(<f-args>)
Assign it to a command, and it’s good to go.
The only unresolved problem now is opening, and (re)moving files. This actually gets surprisingly simple from here, because vim comes with its own built in file explorer called Netrw.
Vim’s Netrw to the rescue
Basically, for revisiting the existing notes, we only need a simple one liner below the function:
command! Notes edit ~/Documents/notes/
Basically :edit normally means “edit this file”, but when the target is a directory, vim will open up the directory using Netrw as if we had just instructed an :Explore instead (the “standard” way to invoke Netrw).
A sidenote on using Netrw
This section is just a short guide on navigating and managing files with Netrw.
Navigation
->
Enter: Opens a directory or a file.->
-: Go up to the parent directory.->
u: Go back to the previous directory in the history.->
gb: Jump to the most recent directory saved on the “Bookmarks”. To create a bookmark we use mb.
File Management
->
p: Opens a preview window.->
Closes the preview window.z ->
gh: Toggles hidden files on/off.->
%: (Almost) creates a file. You will need to name it for it to be created, use:writeafter entering the name->
R: Renames a file->
mt: Assign the “target directory” used by the move and copy commands.->
mf: Marks a file or directory. Any action that can be performed on multiple files depend on these marks. So if you want to copy, move or delete files, you need to mark them.->
mc: Copy the marked files in the target directory.->
mm: Move the marked files to the target directory.->
mx: Runs an external command on the marked files.->
D: Deletes a file or an empty directory. Does not work with non-empty directories. If you really want to delete directories through vim, mark them, then usemxand have it runrm -rf…->
d: Creates a directory.
Conclusion
I hope these simple tricks help you stay more organized as much as it has helped me. A clean $HOME goes for a long way.