bm (3015 bytes)
1 #!/bin/sh 2 3 # Don't forget to set $BOOKMARKS and $USERTAGS to files somewhere. 4 # TODO: 5 # - prevent duplicate URLs 6 # - make the top tag a null tag so a user accidentally pressing ENTER twice doesn't close out the tag dialogue 7 8 DMENULINES=15 9 10 check () { 11 [ -z "$1" ] && exit 1 12 } 13 14 help () { 15 printf 'Call without an argument to be prompted with dmenu.\n' 16 printf 'Flags:\n-h, --help\n-c, --copy\n-a, --add\n-e, --edit\n' 17 } 18 19 # lock: take the write lock of $BOOKMARKS, a directory beside it. bm-sync 20 # takes it too, so that neither writes over a change of the other. The lock 21 # of a process that is gone is taken over. bm waits $SBM_LOCK_WAIT seconds 22 # (default 10) for it. 23 lock () { 24 waited=0 25 until mkdir "$BOOKMARKS.lock" 2>/dev/null; do 26 pid=$(cat "$BOOKMARKS.lock/pid" 2>/dev/null) 27 if [ -n "$pid" ] && ! kill -0 "$pid" 2>/dev/null; then 28 [ "$(cat "$BOOKMARKS.lock/pid" 2>/dev/null)" != "$pid" ] || rm -rf "$BOOKMARKS.lock" 29 continue 30 fi 31 if [ "$waited" -ge "${SBM_LOCK_WAIT:-10}" ]; then 32 printf 'bm: %s is in use. If no bm-sync runs, remove %s.lock\n' \ 33 "$BOOKMARKS" "$BOOKMARKS" >&2 34 exit 1 35 fi 36 sleep 1 37 waited=$((waited + 1)) 38 done 39 echo $$ > "$BOOKMARKS.lock/pid" 40 trap 'rm -rf "$BOOKMARKS.lock"' EXIT 41 trap 'exit 1' HUP INT TERM 42 } 43 44 unlock () { 45 rm -rf "$BOOKMARKS.lock" 46 trap - EXIT 47 } 48 49 copy () { 50 sort -t2 "$BOOKMARKS" | dmenu -i -l $DMENULINES -p "bookmark:" | awk '{ print $1 }' | xclip -i -selection clipboard 51 } 52 53 add () { 54 url="$(xclip -o | dmenu -p 'url: ')" 55 check "$url" 56 desc="$(printf "" | dmenu -p 'description: ')" 57 tag="" 58 tags="" 59 while [ "$tag" != "done" ] ; do 60 tags="$tags $tag" 61 tag="$(printf "done | (choose when done)\n$(cat $USERTAGS)" \ 62 | dmenu -i -l $DMENULINES -p 'tags: ' | sed 's/ *|.*$//')" 63 done 64 tags="$(printf "$tags" | tr ' ' '\n' | sort | uniq | tr '\n' ' ' \ 65 | sed 's/ $//')" 66 67 lock 68 printf "%s %s | %s\\n" "$url" "$desc" "$tags" >> "$BOOKMARKS" 69 unlock 70 # bm-sync, if installed, sends the bookmark to your other devices. 71 if command -v bm-sync >/dev/null 2>&1; then bm-sync -q >/dev/null 2>&1 & fi 72 } 73 74 edit () { 75 echo "Not implemented. Edit \$BOOKMARKS yourself at $BOOKMARKS." && exit 1 76 } 77 78 plumb () { 79 echo "Not implemented" && exit 1 80 } 81 82 promptflag () { 83 action="$(printf 'copy\nadd\nedit (not implemented)\nplumb (not implemented)' | dmenu -l 4 -p 'action:')" 84 [ "$action" = "copy" ] && copy 85 [ "$action" = "edit" ] && edit 86 [ "$action" = "add" ] && add 87 [ "$action" = "plumb" ] && plumb 88 89 exit 0 90 } 91 92 [ "$1" = '-h' ] || [ "$1" = '--help' ] && help 93 [ "$1" = '-c' ] || [ "$1" = '--copy' ] && copy 94 [ "$1" = '-a' ] || [ "$1" = '--add' ] && add 95 [ "$1" = '-e' ] || [ "$1" = '--edit' ] && edit 96 [ "$1" = '-e' ] || [ "$1" = '--plumb' ] && plumb 97 [ -z "$1" ] && promptflag 98 [ -n "$2" ] && echo "Too many arguments: use one or none." && exit 1