#!/usr/bin/env bash ############################################################################### # bm — Bookmark manager CLI # # Usage: # bm add [name] [category] [tags] — add a bookmark # bm rm — remove a bookmark # bm ls [category] — list bookmarks # bm cats — list categories # bm search — search by name/url/tags # bm edit — edit a bookmark in $EDITOR ############################################################################### DB="${XDG_DATA_HOME:-$HOME/.local/share}/karbs/bookmarks.db" sq() { printf '%s' "${1//\'/\'\'}"; } cmd="${1:-ls}" shift case "$cmd" in add) url="${1:?usage: bm add [name] [category] [tags]}" name="${2:-$(printf '%s' "$url" | sed 's|https\?://||; s|^www\.||; s|/$||; s|/.*||')}" category="${3:-Uncategorized}" tags="${4:-}" safe_url=$(sq "$url"); safe_name=$(sq "$name") safe_cat=$(sq "$category"); safe_tags=$(sq "$tags") sqlite3 "$DB" "INSERT OR REPLACE INTO bookmarks (name,url,category,tags) VALUES ('${safe_name}','${safe_url}','${safe_cat}','${safe_tags}');" echo "Added: [${category}] ${name}" ;; rm) term="${1:?usage: bm rm }" safe=$(sq "$term") sqlite3 "$DB" "DELETE FROM bookmarks WHERE url='${safe}' OR name='${safe}';" echo "Removed: ${term}" ;; ls) filter="${1:-}" if [ -n "$filter" ]; then safe=$(sq "$filter") sqlite3 "$DB" -column -header \ "SELECT id,category,name,url,tags FROM bookmarks WHERE category='${safe}' ORDER BY name;" else sqlite3 "$DB" -column -header \ "SELECT id,category,name,url,tags FROM bookmarks ORDER BY category,name;" fi ;; cats) sqlite3 "$DB" "SELECT category, COUNT(*) as count FROM bookmarks GROUP BY category ORDER BY category;" ;; search) query="${1:?usage: bm search }" safe=$(sq "$query") sqlite3 "$DB" -column -header " SELECT category, name, url, tags FROM bookmarks WHERE name LIKE '%${safe}%' OR url LIKE '%${safe}%' OR tags LIKE '%${safe}%' OR category LIKE '%${safe}%' ORDER BY category, name;" ;; edit) term="${1:?usage: bm edit }" safe=$(sq "$term") row=$(sqlite3 "$DB" -separator $'\t' \ "SELECT id,name,url,category,tags,description FROM bookmarks WHERE url='${safe}' OR name='${safe}' LIMIT 1;") [ -z "$row" ] && echo "Not found: $term" && exit 1 id=$(cut -f1 <<< "$row") tmp=$(mktemp /tmp/bm-edit.XXXXXX) printf '%s' "$row" | awk -F'\t' '{ print "name: " $2 print "url: " $3 print "category: " $4 print "tags: " $5 print "description: " $6 }' > "$tmp" ${EDITOR:-nvim} "$tmp" name=$(grep '^name:' "$tmp" | sed 's/^name: *//') url=$(grep '^url:' "$tmp" | sed 's/^url: *//') cat=$(grep '^category:' "$tmp" | sed 's/^category: *//') tags=$(grep '^tags:' "$tmp" | sed 's/^tags: *//') desc=$(grep '^description:' "$tmp" | sed 's/^description: *//') rm -f "$tmp" sn=$(sq "$name"); su=$(sq "$url"); sc=$(sq "$cat"); st=$(sq "$tags"); sd=$(sq "$desc") sqlite3 "$DB" "UPDATE bookmarks SET name='${sn}',url='${su}',category='${sc}',tags='${st}',description='${sd}' WHERE id=${id};" echo "Updated: [${cat}] ${name}" ;; *) echo "Usage: bm [args]" exit 1 ;; esac