Using fzf to quick access my notes from the cli
I wanted to create a simple script to quickly access my notes from the
command line.
fzf is a great and flexible tool which
can be used to fuzzy search in the given input, like the file names in my
notes directory. I already use it to search in the
command line history
and in vim to open files with fzf.vim.
In this post I will walk you through how I built my note
script using fzf.
Building the script
Executing the command fzf
in the cli without any options will list all the
files for the current and every sub directory. The first thing I do in the script
is to change the directory where I store my notes and execute fzf
.
#!/bin/bash
notes_dir="$HOME/notes"
cd $notes_dir
I will need the output of fzf and the exit code later so I save them too.
fzf_output=$(fzf)
exit_code=$?
fzf options
fzf has many customization options how to show the results.
One of the most important one for this script is the
--print-query
option which prints the query what we typed in
so it can be used to create a new file if there is no match.
The value of the query is printed before the match in a new line in the
fzf output.
Additionally to the --print-query
option I use some styling
options like: --border
and the --preview
to show the first
20 lines from a note.
My final version with all the parameters of the executed fzf
command
looks like this:
fzf_output=$(fzf --reverse --prompt=$notes_dir/ --border --print-query --preview="head -n 20 {+}" --preview-window=down:50% --inline-info)
The full list of options can be listed with the fzf --help
command and
by viewing the man page for fzf (man fzf
).
Process the output from fzf
To work with output of the fzf command I will split the output into an array in the bash script, where the query we typed in will be the first line and if there is a match it will be printed in the second line.
# split the output into an array
readarray -t y <<<"$fzf_output"
query=${y[0]} # query is the firts line
match=${y[1]} # match is the second line if there is any
Open or create a note
fzf has multiple exit codes which is very great if we want to build additional tooling around it.
0 Normal exit
1 No match
2 Error
130 Interrupted with CTRL-C or ESC
Based on the exit code the script will decide what to do.
Open an existing note or to create a new. Using the $EDITOR
environment variable will make it more flexible. No change
is needed if some other editor is set in the environment.
if [[ 0 -eq $exit_code ]]; then
# open the matched file with an editor
$EDITOR $notes_dir/$match
elif [[ 1 -eq $exit_code ]]; then
# create a new md file where the file name will be the query
$EDITOR $notes_dir/$query.md
fi
The whole script
After going through on each part this is the whole script.
#!/bin/bash
notes_dir="$HOME/notes"
cd $notes_dir
fzf_output=$(fzf --reverse --prompt=$notes_dir/ --border --print-query --preview="head -n 20 {+}" --preview-window=down:50% --inline-info)
exitcode=$?
# --print-query prints the query which can be used
# to create a new file if there is no match
# in this case the query is printed before a match in a new line
# split the output into an array
readarray -t y <<<"$fzf_output"
query=${y[0]} # query is the firts line
match=${y[1]} # match is the second line if there is any
# Exit codes
#0 Normal exit
#1 No match
#2 Error
#130 Interrupted with CTRL-C or ESC
if [[ 0 -eq $exitcode ]]; then
# open the matched file with an editor
$EDITOR $notes_dir/$match
elif [[ 1 -eq $exitcode ]]; then
# create a new md file where the file name will be the query
$EDITOR $notes_dir/$query.md
fi
Conclusion
As you can see it is very easy to create additional scripts around fzf to improve your cli environment. There are many great fzf examples worth checking out (docker, git …) if you want to improve your cli tools.