#!/bin/sh # pin - bookmark manager with dmenu integration # Usage: pin add | pin list | pin open [-url URL] PINS_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/scripts/pins/pins.ini" BROWSER="${BROWSER:-firefox}" die() { printf '%s\n' "$1" >&2; exit 1; } # Get all section names from pins.ini sections() { grep '^\[' "$PINS_FILE" | tr -d '[]' } # Get entries for a given section (title = url pairs) entries() { sed -n "/^\[$1\]/,/^\[/{/^\[/d;/^$/d;p}" "$PINS_FILE" } cmd_add() { section=$(sections | dmenu -i -l 20 -p "Section:") [ -z "$section" ] && exit 0 title=$(printf '' | dmenu -l 1 -p "Title:") [ -z "$title" ] && exit 0 url=$(printf '' | dmenu -l 1 -p "URL:") [ -z "$url" ] && exit 0 # Check if section exists if grep -q "^\[$section\]" "$PINS_FILE"; then # Append under existing section (before next section or EOF) sed -i "/^\[$section\]/,/^\[/{ /^\[.*\]/!{ \$a\\ $title = $url } }" "$PINS_FILE" # Simpler: just find the section and append after last entry # Use awk for reliability awk -v sec="$section" -v entry="$title = $url" ' BEGIN { found=0; added=0 } /^\[/ { if (found && !added) { print entry; added=1 } found=0 } $0 ~ "^\\[" sec "\\]" { found=1 } { print } END { if (found && !added) print entry } ' "$PINS_FILE" > "$PINS_FILE.tmp" && mv "$PINS_FILE.tmp" "$PINS_FILE" else # New section — append at end of file printf '\n[%s]\n%s = %s\n' "$section" "$title" "$url" >> "$PINS_FILE" fi notify-send "Pin added" "$title → $section" } cmd_list() { printf '\033[1m%-20s %-25s %s\033[0m\n' "SECTION" "TITLE" "URL" printf '%-20s %-25s %s\n' "--------------------" "-------------------------" "---" current="" while IFS= read -r line; do case "$line" in "["*"]") current=$(printf '%s' "$line" | tr -d '[]') ;; *" = "*) title="${line%% = *}" url="${line#* = }" printf '\033[33m%-20s\033[0m %-25s \033[2m%s\033[0m\n' "$current" "$title" "$url" ;; esac done < "$PINS_FILE" } cmd_open() { # Direct URL mode: pin open -url if [ "$1" = "-url" ] && [ -n "$2" ]; then $BROWSER "$2" & exit 0 fi # Interactive dmenu mode section=$(sections | dmenu -i -l 20 -p "Section:" || exit 0) [ -z "$section" ] && exit 0 selected=$(entries "$section" | dmenu -i -l 20 -p "$section:" || exit 0) [ -z "$selected" ] && exit 0 url="${selected#* = }" $BROWSER "$url" & } case "$1" in add) cmd_add ;; list) cmd_list ;; open) shift; cmd_open "$@" ;; -h|help) printf 'pin Open a pin in browser (dmenu)\npin add Add a new pin (dmenu)\npin list List all pins\npin open -url Open a specific URL\n' ;; "") cmd_open ;; *) printf 'Unknown command: %s (try pin -h)\n' "$1" ;; esac