Show plugin ids as subtext in the plugin picker menus

Select-menu options gain an optional third field rendered under the
label, filtered alongside it, and returned with the selection. The
plugin picker uses it to show every plugin's id and act on the id the
selection hands back, replacing the duplicate-name label suffix.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
David Heinemeier Hansson
2026-08-07 02:38:06 -07:00
co-authored by Claude Fable 5
parent 9cb3640c9f
commit bc75b03114
5 changed files with 48 additions and 62 deletions
+12 -32
View File
@@ -65,8 +65,8 @@ pick() {
CALLS=$(cat "$TMPDIR/calls")
}
# Two plugins can declare the same display name. When both are eligible for the
# same verb, neither row can stand on the name alone.
# Two plugins can declare the same display name. The id rides along as row
# subtext and comes back with the selection, so the pick resolves by id.
cat >"$TMPDIR/plugins.json" <<'JSON'
[
{"id": "omarchy.clock", "name": "Clock", "kinds": ["bar-widget"], "enabled": false, "active": false, "canDisable": true, "firstParty": true},
@@ -74,46 +74,26 @@ cat >"$TMPDIR/plugins.json" <<'JSON'
]
JSON
pick enable "Clock (tester.clock)"
[[ $ROWS == *"Clock (omarchy.clock)"* && $ROWS == *"Clock (tester.clock)"* ]] \
|| fail "picker tells two plugins of the same name apart" "$ROWS"
pass "picker tells two plugins of the same name apart"
pick enable "$(printf 'Clock\ttester.clock')"
[[ $ROWS == *"$(printf 'Clock\tomarchy.clock')"* && $ROWS == *"$(printf 'Clock\ttester.clock')"* ]] \
|| fail "picker offers the id as subtext on every row" "$ROWS"
pass "picker offers the id as subtext on every row"
[[ $CALLS == *"omarchy-plugin-enable tester.clock"* ]] \
|| fail "picker acts on the row that was picked, not the one that shares its name" "$CALLS"
pass "picker acts on the row that was picked, not the one that shares its name"
# Only one of them is eligible, so the row needs no id -- but resolving it by
# name alone would still find the wrong plugin, since the other one exists.
cat >"$TMPDIR/plugins.json" <<'JSON'
[
{"id": "omarchy.clock", "name": "Clock", "kinds": ["bar-widget"], "enabled": true, "active": false, "canDisable": true, "firstParty": true},
{"id": "tester.clock", "name": "Clock", "kinds": ["bar-widget"], "enabled": false, "active": false, "canDisable": true, "firstParty": false}
]
JSON
pick enable "Clock"
[[ $ROWS != *"("* ]] || fail "picker adorns a row only when its name is taken twice over" "$ROWS"
pass "picker adorns a row only when its name is taken twice over"
[[ $CALLS == *"omarchy-plugin-enable tester.clock"* ]] \
|| fail "picker resolves a lone row to the plugin the verb offered, not a namesake it filtered out" "$CALLS"
pass "picker resolves a lone row to the plugin the verb offered, not a namesake it filtered out"
pick remove "Clock"
pick remove "$(printf 'Clock\ttester.clock')"
[[ $CALLS == *"omarchy-plugin-remove tester.clock"* ]] \
|| fail "picker removes the plugin whose row was picked" "$CALLS"
pass "picker removes the plugin whose row was picked"
# A name that stands alone is left alone: no id trailing a row that needs none.
cat >"$TMPDIR/plugins.json" <<'JSON'
[
{"id": "acme.weather", "name": "Weather", "kinds": ["bar-widget"], "enabled": false, "active": false, "canDisable": true, "firstParty": false}
]
JSON
pick enable "Weather"
[[ $ROWS == *"Weather"* && $ROWS != *"acme.weather)"* ]] \
|| fail "picker leaves an unambiguous name unadorned" "$ROWS"
pass "picker leaves an unambiguous name unadorned"
pick enable "$(printf 'Weather\tacme.weather')"
[[ $CALLS == *"omarchy-plugin-enable acme.weather"* ]] \
|| fail "picker delegates plugin enablement to the plugin command" "$CALLS"
pass "picker delegates plugin enablement to the plugin command"
@@ -127,7 +107,7 @@ cat >"$TMPDIR/plugins.json" <<'JSON'
]
JSON
pick clone "Clock"
pick clone "$(printf 'Clock\tomarchy.clock')"
[[ $ROWS == *"Clock"* && $ROWS != *"Weather"* ]] ||
fail "clone picker offers only built-in plugins" "$ROWS"
pass "clone picker offers built-in plugins"
@@ -157,7 +137,7 @@ cat >"$TMPDIR/plugins.json" <<'JSON'
]
JSON
pick enable "Fancy"
pick enable "$(printf 'Fancy\tacme.fancy')"
[[ $CALLS == *"omarchy-plugin-enable acme.fancy"* && $CALLS != *"--section"* ]] \
|| fail "picker delegates kind-specific enablement" "$CALLS"
pass "picker delegates kind-specific enablement"
@@ -171,7 +151,7 @@ cat >"$TMPDIR/plugins.json" <<'JSON'
]
JSON
pick disable "Clock"
pick disable "$(printf 'Clock\tomarchy.clock')"
[[ $ROWS == *"Clock"* && $ROWS != *"Fancy"* ]] \
|| fail "picker keeps a bar out of disable" "$ROWS"
pass "picker keeps a bar out of disable"
@@ -184,7 +164,7 @@ cat >"$TMPDIR/plugins.json" <<'JSON'
]
JSON
pick enable "Bar"
pick enable "$(printf 'Bar\tomarchy.bar')"
[[ $ROWS == *"Bar"* && $ROWS != *"Neon Bar"* ]] \
|| fail "picker offers every bar except the one already running" "$ROWS"
pass "picker offers every bar except the one already running"
+8 -8
View File
@@ -291,18 +291,18 @@ assert(
/"omarchy-plugin-\$1" "\$id"/.test(pluginPicker),
'plugin picker delegates enable and disable without interpreting plugin kinds'
)
// Icons ride along as "<glyph>\tlabel"; the menu shows the glyph and hands
// back the label, so nothing downstream has to strip one off. The id rides in
// a third field, cut off before the menu is ever shown it. What the picker
// Icons ride along as "<glyph>\tlabel\tsubtext"; the menu shows the glyph,
// renders the subtext under the label, and hands back "label\tsubtext" so the
// picker can act on the id without resolving a display name. What the picker
// then does with the row it gets back is checked in menu-plugin-test.sh.
assert(
/\$label \+ \\"\\\\t\\" \+ \.id/.test(pluginPicker)
&& /omarchy-menu-select "\$\{1\^\} plugin" < <\(cut -f1,2 <<<"\$rows"\)/.test(pluginPicker),
'plugin picker labels its rows with glyphs and keeps the id out of the label'
/\.name \+ \\"\\\\t\\" \+ \.id/.test(pluginPicker)
&& /id=\$\(cut -f2 <<<"\$selection"\)/.test(pluginPicker),
'plugin picker shows the id as row subtext and acts on the id the selection hands back'
)
assert(
/var icon = parts\.length > 1 \? parts\.shift\(\) : ""\s*\n\s*var label = parts\.join\("\\t"\)/.test(menuQml),
'menu select mode reads a leading icon off an option and filters on the label alone'
/var icon = parts\.length > 1 \? parts\.shift\(\) : ""\s*\n\s*var label = parts\.shift\(\) \|\| ""\s*\n\s*var detail = parts\.join\("\\t"\)/.test(menuQml),
'menu select mode reads a leading icon and a trailing subtext off an option'
)
assert(
/omarchy-launch-floating-terminal-with-presentation "omarchy-plugin-remove/.test(pluginPicker),