Skip to content

Let menu extensions declare their own providers - #43

Open
villekivela wants to merge 1 commit into
typecraft-dev:mainfrom
villekivela:extension-providers
Open

villekivela wants to merge 1 commit into
typecraft-dev:mainfrom
villekivela:extension-providers

Conversation

@villekivela

Copy link
Copy Markdown

Summary

Mirrors omacom/omarchy#14277, which lets an Omarchy menu extension declare its own provider as an object instead of naming one the shell defines. oma-cast keeps its own copy of the provider table, so without this change those rows would show in Super+Space but not in oma-cast.

// ~/.config/omarchy/extensions/omarchy-menu.jsonc
"notes": {"label": "Notes", "provider": {"command": "ls ~/notes", "action": "omarchy-launch-editor ~/notes/{value}", "volatile": true}}

command prints label\tvalue\tcurrent\tdescription rows. action runs with every {value} replaced by the row's value, already shell-quoted. These are the same rules as #14277.

 OmarchyMenu.normalizeItem
-  provider: String(raw.provider)        // an object became "[object Object]"
+  provider: normalizeProvider(raw.provider)
+    name → kept
+    {command, action with {value}} → {command, action, icon, volatile}
+    anything else → ""
 OmarchyMenuSource.startNextProvider
-  spec = PROVIDERS[item.provider]
+  spec = providerSpec(item.provider)    // a name → PROVIDERS, an object → {script, icon, actionFor}
 OmarchyMenu.providerItems
+  reads the optional 4th column into the row's description (searchable)

The first user is Omaweb, which lists its open tabs this way (villekivela/omaweb#554). Typing a tab's title in oma-cast then switches to that tab.

Evidence

Live on Omarchy 4.0.6, with Omaweb's tab row from villekivela/omaweb#554 in the menu file, running oma-cast call rootSearch.search '{"query":"tailscale"}':

  • Before: Results: Tailscale (Remove › Services)
    After: Results: Tailscale (Remove › Services), then Machines - Tailscale (Omaweb tabs), whose action is omaweb focus --raise 'fd04b388-…'

node --test tests/*.test.js: 108 pass. New tests in tests/omarchy-menu.test.js:

an extension can declare its own provider object
  keeps {command, action, icon, volatile}; drops one without a command,
  one whose action has no {value}, and a non-object; only true is volatile
an extension provider object survives the merge with the default menu
extension provider rows run the chosen value as one literal word
  bash -c row.action prints "it's $(touch …) `id` \ \"q\"" unchanged
an extension provider's command runs and feeds its rows

omarchy plugin validate plugin passes, and the shell log shows no QML errors after oma-cast reload.

Merge Danger

Door: two-way

Nothing changes for a menu file without object providers. Named providers (fonts, power-profiles) take the same path through providerSpec.

Blast Radius: small

A user's provider command runs in bash on every launcher open, like the built-in providers. The menu file already runs shell through action, when and checked, so this adds no new trust boundary. volatile is accepted but changes nothing here: oma-cast already reruns every provider on each open, and it keeps the old rows until the new ones arrive, so the list doesn't flicker. Omarchy's menu clears them first, so for the moment it takes for a provider to answer, a just-closed tab can still be picked here. Picking it runs the action on a value that no longer exists.

🤖 Generated with Claude Code

Mirrors omacom/omarchy#14277: a menu row's provider can be an object
with a command printing label/value/current/description rows and an
action run with {value} replaced by the row's quoted value. A named
provider still comes from PROVIDERS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant