Update zet

Signed-off-by: Oliver Davies <oliver@oliverdavies.uk>
This commit is contained in:
Oliver Davies 2025-09-17 23:41:24 +01:00
parent 5e2f716c88
commit 4e70ae51df

333
zet
View file

@ -1,204 +1,241 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -o pipefail
EDITOR="${EDITOR:-nvim}" IFS= read -rd '' USAGE <<EOF
ZET_DIR="${ZET_DIR:-$HOME/Documents/zet}"
ZET_TMP_FILE="$HOME/.local/state/zets"
if [[ ! -d "$ZET_DIR" ]]; then Zettel helper script.
mkdir -p "$ZET_DIR"
(cd "$ZET_DIR" && git init)
git -C "$ZET_DIR" add .
git -C "$ZET_DIR" commit -m 'Initial commit'
fi
commit_changes() { Usage:
filename="$1"
commit_message="$2"
git -C "$ZET_DIR" diff --quiet "$filename" || { zet create|c TITLE... : Create a new zettel
read -rp "Commit? " commit_choice zet edit|e QUERY... : Search for a zettel and edit it
zet help|h : Show this help screen
zet id QUERY... : Search for a zettel and display its ID
zet print|p QUERY... : Search for a zettel and print it
zet push : Push changes
zet search|s QUERY... : Print IDs and titles of zettels matching QUERY
zet view|v QUERY... : Search for a zettel and view it
if [[ "$commit_choice" =~ ^[Yy]$ ]]; then EOF
git -C "$ZET_DIR" add "$filename"
commit_message="${commit_message//$ZET_DIR\//}" set -o errexit
commit_message="${commit_message//\/index.adoc/}"
git -C "$ZET_DIR" commit -m "$commit_message" COMMAND="${1:-}"
shift 1
echo "Changes committed." SELECTED_ZET=''
else ZET_DIR=${ZET_DIR:-.}
echo "Changes not committed." ZET_LIST=()
fi
} cmd_create() {
create_zettel "${1^}"
} }
delete_zet() { cmd_edit() {
query="$1" parse_zet_list < <(search_zettel "$@")
select_zet
edit_zet "$SELECTED_ZET"
}
if [[ "$1" == "last" ]]; then cmd_id() {
file="$(find "$ZET_DIR" -type f -name "index.adoc" | sort | tail -1)" parse_zet_list < <(search_zettel "$@")
else select_zet
file="$(get_filepath_for_zet "$query")"
echo "$SELECTED_ZET"
}
cmd_links() {
QUERY="$1"
generate_links "$(cmd_search "$QUERY")"
}
cmd_push() {
git push
}
cmd_search() {
parse_zet_list < <(search_zettel "$@")
printf "%s\n" "${ZET_LIST[@]}"
}
cmd_view() {
parse_zet_list < <(search_zettel "$@")
select_zet
view_zettel "$SELECTED_ZET"
}
commit_zettel() {
ZID="$1"
MESSAGE="$2"
if [[ -z "$MESSAGE" ]]; then
get_title "$ZID"
fi fi
if [[ -f "$file" ]]; then git add "$ZID"
run_git_command rm -rf "$file" git commit -m "$MESSAGE"
}
commit_message="Delete $file" create_zettel() {
commit_message="${commit_message//$ZET_DIR\//}" TITLE="$1"
commit_message="${commit_message//\/index.adoc/}" ZID=$(new_zid)
git -C "$ZET_DIR" commit -m "$commit_message" mkdir -p "$ZID"
echo "= $TITLE" > "$ZID/index.adoc"
edit_file "$ZID/index.adoc"
on_save "$ZID"
}
update_zet_list delete_zettel() {
else [[ -d "$ZID" ]] && rm -fr "$ZID"
result="$(search_zets "$query")" commit_zettel "$ZID"
result_count="$(echo "$result" | grep -c '^')" }
if [[ "$result_count" -eq 0 ]]; then
echo "No results found for query: $query" >&2
exit 1
elif [[ "$result_count" -eq 1 ]]; then
id="$(echo "$result" | awk '{print $1}')"
else
selected="$(echo "$result" | sort | fzf)" || exit 0
id="$(echo "$selected" | awk '{print $1}')"
fi
delete_zet "$id"
fi
edit_file() {
"$EDITOR" "$1"
} }
edit_zet() { edit_zet() {
query="$1" edit_file "$1/index.adoc"
on_save "$1"
if [[ "$1" == "last" ]]; then
file="$(get_last_zet)"
else
file="$(get_filepath_for_zet "$query")"
fi
if [[ -f "$file" ]]; then
"$EDITOR" "$file"
commit_changes "$file" "Edit $file"
update_zet_list
else
result="$(search_zets "$query")"
result_count="$(echo "$result" | grep -c '^')"
if [[ "$result_count" -eq 0 ]]; then
echo "No results found for query: $query" >&2
exit 1
elif [[ "$result_count" -eq 1 ]]; then
id="$(echo "$result" | awk '{print $1}')"
else
selected="$(echo "$result" | sort | fzf)" || exit 0
id="$(echo "$selected" | awk '{print $1}')"
fi
edit_zet "$id"
fi
} }
generate_links() { generate_links() {
query="$1" echo "$1" | while IFS= read -r line; do
related="$(search_zets "$query")"
echo "$related" | while IFS= read -r line; do
id="${line%% *}" id="${line%% *}"
title="${line#* }" title="${line#* }"
echo "* link:../${id}/index.adoc[${title}]" echo "* link:../${id}/index.adoc[${title}]"
done | sort done
} }
get_filepath_for_zet() { get_latest_zettel() {
echo "${ZET_DIR}/$1/index.adoc" find . -maxdepth 1 -type d -name '[0-9]*' -printf '%f\n' | sort -r | head -n 1
} }
get_last_zet() { get_title() {
find "$ZET_DIR" -type f -name "index.adoc" | sort | tail -1 get_title_from_file "$1/index.adoc"
} }
get_zet_id_from_filepath() { get_title_from_file() {
basename "$(dirname "$file")" head -n 1 "$1" | sed -e 's/^[#=] //'
} }
main() { main() {
[[ $# -eq 0 ]] && show_titles && exit if [[ -z "$COMMAND" ]]; then
show_usage
exit 1
fi
case "${1:-}" in case "$COMMAND" in
delete) delete_zet "$2" ;; create | c)
edit) edit_zet "$2" ;; cmd_create "$@"
find|search) shift 1; search_zets "$@" ;; ;;
git) shift 1; run_git_command "$@" ;;
links) generate_links "$2" ;; edit | e)
new|create) shift 1; new_zet "$@" ;; cmd_edit "$@"
source) show_zet "$2" ;; ;;
titles) show_titles ;;
*) search_zets "$1"; help | h)
show_usage
;;
id)
cmd_id "$@"
;;
links | l)
cmd_links "$@"
;;
push)
cmd_push
;;
search | s)
cmd_search "$@"
;;
view | v)
cmd_view "$@"
;;
*)
echo "ERROR: $COMMAND"
show_usage
exit 1
;;
esac esac
} }
new_zet() { new_zid() {
id="$(date "+%Y%m%d%H%M%S")" date '+%Y%m%d%H%M%S'
filename="$(get_filepath_for_zet "$id")"
mkdir -p "$(dirname "$filename")"
title="$*"
echo "= $title" > "$filename"
echo "$id $title" >> "$ZET_TMP_FILE"
"$EDITOR" "$filename"
run_git_command add --intent-to-add "$filename"
commit_changes "$filename" "Add $filename"
} }
run_git_command() { on_save() {
git -C "$ZET_DIR" "$@" ZID="$1"
if [[ -s "$ZID/index.adoc" ]]; then
TITLE=$(get_title "$ZID")
commit_zettel "$ZID" "$TITLE"
else
echo "Deleting empty zettel: $ZID"
delete_zettel "$ZID"
fi
} }
search_zets() { parse_zet_list() {
find "$ZET_DIR" -type f -name "index.adoc" -exec grep --files-with-matches --ignore-case "$*" {} + | while read -r file; do ZET_LIST=()
id="$(get_zet_id_from_filepath "$file")"
title=$(head -1 "$file" | sed 's/^= //' | sed 's/# //')
echo "$id $title" while IFS= read -r ZID; do
done | sort TITLE=$(get_title "$ZID")
ZET_LIST+=("$ZID $TITLE")
done
} }
show_titles() { search_zettel() {
cat "$ZET_TMP_FILE" if [[ "$*" == "latest" ]] || [[ "$*" == "l" ]]; then
} get_latest_zettel
return
show_zet() {
id="$1"
file="$(get_filepath_for_zet "$id")"
if [[ -f "$file" ]]; then
cat "$file" && exit 0
fi fi
echo "Note not found: $id" >&2 QUERY="$*"
git grep -i --name-only -E "$QUERY" | grep -o -E '[0-9]{14}' | sort | uniq
}
select_zet() {
if [[ "${#ZET_LIST[@]}" == 0 ]]; then
echo "No zettels to select"
exit 1 exit 1
fi
if [[ "${#ZET_LIST[@]}" == 1 ]]; then
SELECTED_ZET=$(awk '{ print $1 }' <<<"${ZET_LIST[0]}")
return
fi
selector
if [[ -z "$SELECTED_ZET" ]]; then
echo "No zet selected"
exit 1
fi
} }
update_zet_list() { selector() {
find "$ZET_DIR" -type f -name 'index.adoc' | while read -r file; do ITEM=$(printf "%s\n" "${ZET_LIST[@]}" | fzf --prompt="Select a zet: ")
id="$(get_zet_id_from_filepath "$file")"
title=$(head -n 1 "$file" | sed 's/^= //' | sed 's/^# //')
echo "$id $title" SELECTED_ZET=$(awk '{ print $1 }' <<< "$ITEM")
done | sort > "$ZET_TMP_FILE" &
} }
main "$@" show_usage() {
echo "$USAGE"
}
view_zettel() {
cat "$1/index.adoc"
}
(cd "$ZET_DIR" && main "$@")