1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#!/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 <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