notes utils
This commit is contained in:
171
utils/.local/bin/notes
Executable file
171
utils/.local/bin/notes
Executable file
@@ -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 <<EOF
|
||||
Usage: $(basename "$0") <command> [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 <name> Custom note name (default: <unixtime>-untitled-note.md)
|
||||
-t, --title <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
|
||||
62
utils/.local/bin/notes-completion
Normal file
62
utils/.local/bin/notes-completion
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user