#!/usr/bin/env bash set -euo pipefail ############################################################################### # DEDIT — dmenu metadata editor for krisyotam.com # # Maintainer: Kris Yotam # License: MIT # Created: 2026-02-15 # Description: Edit content metadata via dmenu. Select type, entry, field, # and new value through dmenu prompts. ############################################################################### DB="/home/krisyotam/dev/krisyotam.com/public/data/content.db" declare -A TYPE_ICONS=( [blog]="󰬞" [diary]="󰃮" [essays]="󰬝" [fiction]="󰂺" [news]="󰎕" [notes]="󰏪" [ocs]="󰏫" [papers]="󰈙" [progymnasmata]="󰑴" [reviews]="󰓥" [verse]="󱗝" ) CONTENT_TYPES=(blog diary essays fiction news notes ocs papers progymnasmata reviews verse) sql() { sqlite3 "$DB" "$1"; } notify() { notify-send "dedit" "$1" 2>/dev/null || true; } # Select content type select_type() { local entries="" for t in "${CONTENT_TYPES[@]}"; do entries+="${TYPE_ICONS[$t]:-󰈙} $t"$'\n' done echo "$entries" | dmenu -i -l 11 -p "edit:" | awk '{print $2}' } # Select entry from type select_entry() { local type="$1" sql "SELECT title || ' [' || slug || ']' FROM $type ORDER BY title" | dmenu -i -l 20 -p "$type:" | sed 's/.*\[\(.*\)\]/\1/' } # Select field to edit select_field() { local type="$1" local fields="title preview category_slug tags state" if [[ "$type" != "diary" ]]; then fields+=" status confidence importance" fi echo "$fields" | dmenu -i -l 10 -p "field:" } # Edit a field edit_field() { local type="$1" slug="$2" field="$3" local current new_value case "$field" in title|preview) current="$(sql "SELECT $field FROM $type WHERE slug='$slug'")" new_value="$(echo "$current" | dmenu -p "$field:")" [[ -z "$new_value" ]] && return new_value="${new_value//\'/\'\'}" sql "UPDATE $type SET $field='$new_value', updated_at=datetime('now') WHERE slug='$slug'" notify "Updated $field" ;; category_slug) new_value="$(sql "SELECT slug FROM categories ORDER BY slug" | dmenu -i -l 15 -p "category:")" [[ -z "$new_value" ]] && return sql "UPDATE $type SET category_slug='$new_value', updated_at=datetime('now') WHERE slug='$slug'" notify "Category: $new_value" ;; tags) local id id="$(sql "SELECT id FROM $type WHERE slug='$slug'")" local action action="$(printf "add\nremove" | dmenu -i -p "tags:")" [[ -z "$action" ]] && return if [[ "$action" == "add" ]]; then local tag tag="$(sql "SELECT slug FROM tags ORDER BY slug" | dmenu -i -l 20 -p "add tag:")" [[ -z "$tag" ]] && return local tag_id tag_id="$(sql "SELECT id FROM tags WHERE slug='$tag'")" [[ -z "$tag_id" ]] && return sql "INSERT OR IGNORE INTO content_tags (content_type, content_id, tag_id) VALUES ('$type', $id, $tag_id)" notify "Added tag: $tag" else local tag tag="$(sql "SELECT t.slug FROM tags t JOIN content_tags ct ON ct.tag_id=t.id WHERE ct.content_type='$type' AND ct.content_id=$id ORDER BY t.slug" | dmenu -i -l 10 -p "remove:")" [[ -z "$tag" ]] && return sql "DELETE FROM content_tags WHERE content_type='$type' AND content_id=$id AND tag_id=(SELECT id FROM tags WHERE slug='$tag')" notify "Removed tag: $tag" fi ;; status) new_value="$(printf "Notes\nDraft\nIn Progress\nFinished\nAbandoned" | dmenu -i -l 5 -p "status:")" [[ -z "$new_value" ]] && return sql "UPDATE $type SET status='$new_value', updated_at=datetime('now') WHERE slug='$slug'" notify "Status: $new_value" ;; confidence) new_value="$(printf "certain\nhighly likely\nlikely\npossible\nunlikely\nhighly unlikely\nremote\nimpossible" | dmenu -i -l 8 -p "confidence:")" [[ -z "$new_value" ]] && return sql "UPDATE $type SET confidence='$new_value', updated_at=datetime('now') WHERE slug='$slug'" notify "Confidence: $new_value" ;; importance) new_value="$(seq 1 10 | dmenu -i -l 10 -p "importance:")" [[ -z "$new_value" ]] && return sql "UPDATE $type SET importance=$new_value, updated_at=datetime('now') WHERE slug='$slug'" notify "Importance: $new_value" ;; state) new_value="$(printf "active\nhidden" | dmenu -i -l 2 -p "state:")" [[ -z "$new_value" ]] && return sql "UPDATE $type SET state='$new_value', updated_at=datetime('now') WHERE slug='$slug'" notify "State: $new_value" ;; esac } # Main loop — keep editing until user cancels type="$(select_type)" [[ -z "$type" ]] && exit 0 slug="$(select_entry "$type")" [[ -z "$slug" ]] && exit 0 while true; do field="$(select_field "$type")" [[ -z "$field" ]] && break edit_field "$type" "$slug" "$field" done