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

335
zet
View file

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