Recently Written · git

sbm

dmenu bookmarks. Instantly fuzzy search thousands of bookmarks and plumb them. LOOKING FOR SUCKLESS SOFTWARE EDITION? GO TO sbm-suckless INSTEAD

git clone https://github.com/equwal/sbm

Log | Files | Refs


commit 64867ada81fd939d50111898fd1f17b7521dfcc0
Spenser Truex <truex@equwal.com>
2026-09-21 02:05:17 -0700

bm: offer the tags of the tag file in the Ctrl-T menu

The Ctrl-T menu offered only the tags that bookmarks use. The default
tags of $USERTAGS were missing, but the tags that bm-import makes from
browser folders were there, because the imported bookmarks use them.
Now the menu offers the tags of $USERTAGS too.

The menu also took words from comment lines as tags, because cut -f3
passes a line without a tab through whole. It now skips comment lines.

 bm          | 11 +++++++++--
 test/run.sh | 15 +++++++++++++++
 2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/bm b/bm
index 92cb64c..15dfe36 100755
--- a/bm
+++ b/bm
@@ -466,9 +466,16 @@ nextorder () {
     esac
 }
 
+# alltags: the tags of $USERTAGS and the tags that the bookmarks use. A tag
+# that no bookmark uses yet is a tag too.
+alltags () {
+    { sed 's/[ |].*//' "$USERTAGS" 2>/dev/null
+      awk -F'\t' 'NF && !/^#/ { print $3 }' "$BOOKMARKS" | tr ' ' '\n'
+    } | sed '/^$/d' | sort -u
+}
+
 picktag () {
-    tag=$( { printf '(all)\n'; cut -f3 "$BOOKMARKS" | tr ' ' '\n' \
-             | sed '/^$/d' | sort -u; } | pick 'tag:')
+    tag=$( { printf '(all)\n'; alltags; } | pick 'tag:')
     case $tag in
         '')      ;;
         '(all)') tagfilter= ;;
diff --git a/test/run.sh b/test/run.sh
index b61e96f..a5964d1 100755
--- a/test/run.sh
+++ b/test/run.sh
@@ -693,6 +693,21 @@ answers 'ctrl-t:' 'sec' 'enter:example'
 fz </dev/null
 eq 'browse: ctrl-t narrows to a tag' "$(cat "$work/opened")" 'https://a.example'
 
+# The fake fzf gives the first tag that contains the typed text, else the
+# typed text. No bookmark has i2p, but the tag file has it.
+: > "$SBM_TEST_LOG"
+answers 'ctrl-t:' 'i2' ''
+fz </dev/null
+eq 'browse: ctrl-t offers the tags of the tag file too' \
+    "$(grep -o 'tag \[[^]]*\]' "$SBM_TEST_LOG" | paste -sd ' ' -)" 'tag [all] tag [i2p]'
+printf '# zzcomment\n' >> "$BOOKMARKS"
+: > "$SBM_TEST_LOG"
+answers 'ctrl-t:' 'zzcom' ''
+fz </dev/null
+eq 'browse: ctrl-t takes no tags from comment lines' \
+    "$(grep -o 'tag \[[^]]*\]' "$SBM_TEST_LOG" | paste -sd ' ' -)" 'tag [all] tag [zzcom]'
+seed
+
 answers 'ctrl-d:Zed' ''
 printf 'n\n' | fz 2>/dev/null
 eq 'browse: ctrl-d asks first' "$(grep -c . "$BOOKMARKS")" '3'