Skip to content

Instantly share code, notes, and snippets.

@joereynolds
Created December 17, 2025 13:13
Show Gist options
  • Select an option

  • Save joereynolds/b04c8826121b228cbdbd20f1f3c37d55 to your computer and use it in GitHub Desktop.

Select an option

Save joereynolds/b04c8826121b228cbdbd20f1f3c37d55 to your computer and use it in GitHub Desktop.
CLI note manager
# Rewriting this in Nim so here's the bash version...
#!/usr/bin/env bash
version=0.1
yellow="\x1b[33m"
red="\x1b[31m"
green="\x1b[32m"
blue="\x1b[34m"
magenta="\x1b[35m"
cyan="\x1b[36m"
reset="\x1b[0m"
find_provider_fd_list_books() {
fd . $(get_notes_location) --type directory --max-depth 1
}
find_provider_fd_list_root() {
fd . $(get_notes_location) --type file --max-depth 1
}
find_provider_fd_list_notes() {
fd . $1 --type file
}
find_provider_fd_most_recent() {
fd . --changed-within "2 weeks" $(get_notes_location)
}
get_config_dir() {
echo $XDG_CONFIG_HOME
}
get_editor() {
echo $EDITOR
}
get_fuzzy_provider() {
"${jn_fuzzy_provider:-'fzf'}"
}
get_notes_location() {
# TODO - In here, first listen to config, then XDG_DOCUMENTS_DIR and then ~/Documents/
echo $jn_notes_location
}
jn__config() {
$(get_editor) $(get_config_dir)/jn/config.sh
}
jn__book() {
jn__book__ls $1
}
jn__book__ls() {
book=$(echo "$1" | tr -d '@')
list_notes "$(get_notes_location)/$book"
}
jn__books() {
jn__books__ls
}
jn__books__ls() {
list_books
}
jn__help() {
usage="
jn - a file-based command line notebook
Usage:
jn [command]
Available Commands:
book Show all books
@<book> Show all notes for a book
[Tab] Fuzzy search all notes
config, -c, --config Edit the jn config file
help, -h, --help Display this help
version, -v, --version Print jn's version
Examples:
Show all notes for a book called "docker"
jn @docker
"
echo "$usage"
}
create_note() {
nice_name=$(echo "$1" | tr ' ' '-')
if [ $# -eq 2 ]; then
nice_name=$(echo $2)
fi
file_path=$jn_notes_location/$jn_notes_prefix-$nice_name$jn_notes_suffix
echo "$1" > $file_path
_post_creation_notice "$file_path"
}
jn__cat() {
notes=$(find_provider_fd_list_notes $(get_notes_location))
cat $(echo -e "$notes" | get_fuzzy_provider)
}
edit_note() {
notes=$(find_provider_fd_list_notes $(get_notes_location))
$(get_editor) $(echo -e "$notes" | get_fuzzy_provider)
}
star_note() {
starred="$(get_notes_location)/starred"
if [ ! -d "$starred" ]; then
mkdir $starred
fi
notes=$(find_provider_fd_list_notes $(get_notes_location))
selected_note=$(echo -e "$notes" | get_fuzzy_provider)
ln -sf "$selected_note" "$starred"
echo -e "${green}Starred $selected_note in $starred${reset}"
}
list_notes() {
while IFS= read -r file_path; do
line_count=$(wc -l < "$file_path")
directory=$(dirname "$file_path")
last_dir=$(basename "$directory")
file_name=$(basename "$file_path")
echo -e "$file_name ${yellow}($line_count lines)${reset}"
done < <(find_provider_fd_list_notes $1)
}
list_books() {
note_count=$(find_provider_fd_list_root | wc -l)
echo -e ". ${yellow}($note_count notes)${reset}"
while IFS= read -r book; do
note_count=$(ls $book | wc -l)
nice_name=$(basename $book)
echo -e "$nice_name ${yellow}($note_count notes)${reset}"
done < <(find_provider_fd_list_books)
}
_post_creation_notice() {
echo -e "${green}Created $1${reset}"
}
jn() {
if [ "$1" = "config" ] || [ "$1" = "-c" ] || [ "$1" = "--config" ]; then
jn__config
elif [[ "$1" = "book" ]]; then
jn__books $@
elif [[ "$1" = "cat" ]]; then
jn__cat $@
elif [[ "$1" = "help" || "$1" = "-h" || "$1" = "--help" ]]; then
jn__help
elif [[ "$1" = "version" || "$1" = "-v" || "$1" = "--version" ]]; then
echo $version
elif [[ "$1" == @* ]]; then
jn__book $@
elif [[ "$1" == "/" ]]; then
edit_note
elif [[ "$1" == "star" ]]; then
star_note
elif [ $# -eq 0 ]; then
list_books
elif [ $# -gt 0 ]; then
create_note "$@"
fi
}
source $(get_config_dir)/jn/config.sh
_complete_jn() {
local cur="${COMP_WORDS[COMP_CWORD]}"
if [[ "$cur" == @* ]]; then
local books
local dir_list
books=$(find_provider_fd_list_books)
dir_list=$(echo "$books" | xargs -n1 basename)
COMPREPLY=( $(compgen -W "$dir_list" -- "${cur#@}") )
COMPREPLY=( "${COMPREPLY[@]/#/@}" )
return
fi
}
complete -F _complete_jn jn
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment