diff --git a/utils/.local/bin/notes b/utils/.local/bin/notes new file mode 100755 index 0000000..05f9fc9 --- /dev/null +++ b/utils/.local/bin/notes @@ -0,0 +1,171 @@ +#!/bin/bash +#shellcheck disable=SC2155,SC2207 +set -eo pipefail + +NOTES_DIR="$HOME/notes" +EDITOR="${EDITOR:-nano}" +mkdir -p "$NOTES_DIR" + +show_usage() { + cat < [options] + +Commands: + add Create a new note + edit Open a note in editor + rm Remove a note + list List all notes + +Options for 'add': + -n, --name Custom note name (default: -untitled-note.md) + -t, --title Custom note title (default: "Untitled note") + --no-time Don't add creation timestamp + --no-edit Don't open editor + +Options for 'edit': + <name> Note filename to edit + +Options for 'rm': + <name> Note filename to remove + +Options for 'list': + (none) + +EOF +} + +cmd_add() { + local name="untitled-note" + local title="Untitled note" + local add_time=true + local new_edit=true + + while [[ $# -gt 0 ]]; do + case "$1" in + -n|--name) name="$2"; shift 2 ;; + -t|--title) title="$2"; shift 2 ;; + --no-time) add_time=false; shift ;; + --no-edit) new_edit=false; shift ;; + *) + echo "Unknown option: $1" + show_usage + exit 1 + ;; + esac + done + + local filename="$(date +%s)-${name}.md" + local filepath="$NOTES_DIR/$filename" + + { + echo "# $title" + echo + if [[ "$add_time" == true ]]; then + echo + echo "Created at $(date '+%Y-%m-%d %H:%M:%S')" + echo + fi + echo "---" + echo + } > "$filepath" + + echo "Created note: $filepath" + + if [[ "$new_edit" == true ]]; then + $EDITOR "$filepath" + fi +} + +cmd_edit() { + if [[ $# -lt 1 ]]; then + echo "Error: Note name required" + show_usage + exit 1 + fi + + local filename="$1" + local filepath="$NOTES_DIR/$filename" + + if [[ ! -f "$filepath" ]]; then + echo "Error: Note not found: $filename" + exit 1 + fi + + $EDITOR "$filepath" +} + +cmd_rm() { + if [[ $# -lt 1 ]]; then + echo "Error: Note name required" + show_usage + exit 1 + fi + + local filename="$1" + local filepath="$NOTES_DIR/$filename" + + if [[ ! -f "$filepath" ]]; then + echo "Error: Note not found: $filename" + exit 1 + fi + + rm -v "$filepath" +} + +cmd_list() { + local count=0 + printf "%-40s %s\n" "Filename" "Title" + printf "%-40s %s\n" "--------" "-----" + + # Use nullglob to handle empty directory case + local shopt_save + shopt_save=$(shopt -p nullglob) + shopt -s nullglob + + local files=("$NOTES_DIR"/*.md) + + # Restore original nullglob setting + eval "$shopt_save" + + for file in "${files[@]}"; do + if [[ -f "$file" ]]; then + local filename=$(basename "$file") + local title=$(sed -n 's/^# \([^#].*\)/\1/p' "$file" | head -n1) + + if [[ -z "$title" ]]; then + title="Untitled note" + fi + + printf "%-40s # %s\n" "$filename" "$title" + ((count++)) + fi + done + + if [[ $count -eq 0 ]]; then + echo "No notes found" + else + echo "" + echo "Total: $count note(s)" + fi +} + +if [[ $# -lt 1 ]]; then + cmd_list "$@" + exit 0 +fi + +command="$1" +shift + +case "$command" in + add) cmd_add "$@" ;; + edit) cmd_edit "$@" ;; + rm) cmd_rm "$@" ;; + list) cmd_list "$@" ;; + -h|--help|help) show_usage ;; + *) + echo "Unknown command: $command" + show_usage + exit 1 + ;; +esac diff --git a/utils/.local/bin/notes-completion b/utils/.local/bin/notes-completion new file mode 100644 index 0000000..c713dad --- /dev/null +++ b/utils/.local/bin/notes-completion @@ -0,0 +1,62 @@ +#!/bin/bash +#shellcheck disable=SC2155,SC2207,SC2309,SC2034,SC2154,SC1087 +set -eo pipefail + +_notes_completion() { + local cur="${COMP_WORDS[COMP_CWORD]}" + local command="${COMP_WORDS[1]}" + + if [[ COMP_CWORD -eq 1 ]]; then + COMPREPLY=($(compgen -W "add edit rm list" -- "$cur")) + return + fi + + if [[ "$command" == "edit" || "$command" == "rm" ]]; then + local notes_dir="$HOME/notes" + local notes=() + if [[ -d "$notes_dir" ]]; then + for file in "$notes_dir"/*.md; do + if [[ -f "$file" ]]; then + notes+=("$(basename "$file")") + fi + done + fi + local IFS=$'\n' + COMPREPLY=($(compgen -W "$(printf '%s\n' "${notes[@]}")" -- "$cur")) + compopt -o filenames + return + fi +} + +_notes() { + local -a commands=( + 'add:Create a new note' + 'edit:Open a note in editor' + 'rm:Remove a note' + 'list:List all notes' + ) + + if (( CURRENT == 2 )); then + _describe 'command' commands + elif (( CURRENT >= 3 )); then + case $words[2] in + edit|rm) + local notes_dir="$HOME/notes" + if [[ -d "$notes_dir" ]]; then + _files -W "$notes_dir" -g '*.md' + fi + ;; + *) + _message 'no more arguments' + ;; + esac + fi +} + +if [[ -n "$BASH_VERSION" ]]; then + complete -F _notes_completion notes ./notes +fi + +if [[ -n "$ZSH_VERSION" ]]; then + compdef _notes notes ./notes +fi