Simplify bar plugin management (#6435)

This commit is contained in:
David Heinemeier Hansson
2026-07-29 22:39:55 -04:00
committed by GitHub
parent 3304b79c92
commit 57ea0b4cd0
26 changed files with 886 additions and 835 deletions
+62 -108
View File
@@ -208,14 +208,27 @@ pass "Hyprland bootstrap reloads cached Omarchy config modules"
TMPDIR=$(mktemp -d)
mkdir -p "$TMPDIR/home/.config/omarchy"
ipc_mock_bin="$TMPDIR/ipc-mock"
mkdir -p "$ipc_mock_bin"
cat >"$ipc_mock_bin/omarchy-shell" <<'SH'
#!/bin/bash
set -euo pipefail
mkdir -p "$HOME/.local/state/omarchy"
printf '%s\n' "$*" >>"$HOME/.local/state/omarchy/shell-ipc-calls"
printf 'ok\n'
SH
chmod +x "$ipc_mock_bin/omarchy-shell"
export PATH="$ipc_mock_bin:$PATH"
cat >"$TMPDIR/home/.config/omarchy/shell.json" <<'JSON'
{
"version": 1,
"bar": {
"layout": {
"left": [{ "id": "omarchy.menu" }, { "id": "omarchy.workspaces" }],
"center": [{ "id": "omarchy.clock" }, { "id": "omarchy.weather" }],
"right": [{ "id": "omarchy.tray" }, { "id": "omarchy.bluetooth" }]
"left": [{ "id": "omarchy.menu" }, { "id": "omarchy.workspaces" }, { "id": "omarchy.active-window" }],
"center": [{ "id": "omarchy.clock" }, { "id": "omarchy.weather" }, { "id": "omarchy.system-update" }, { "id": "omarchy.tailscale" }],
"right": [{ "id": "omarchy.tray" }, { "id": "omarchy.microphone" }, { "id": "omarchy.bluetooth" }]
}
},
"plugins": []
@@ -250,75 +263,20 @@ HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar reset
jq -e '.bar.id == null' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
pass "shell config resets to built-in bar option"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin add omarchy.tailscale
jq -e '
def ids: map(.id // .);
.bar.layout.center | ids == ["omarchy.clock", "omarchy.weather", "omarchy.tailscale"]
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
pass "shell config defaults widgets without a section to center"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar move omarchy.active-window right
grep -Fqx 'shell moveBarWidget omarchy.active-window {"section":"right"}' \
"$TMPDIR/home/.local/state/omarchy/shell-ipc-calls"
pass "bar move accepts a positional target section"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin add omarchy.active-window
jq -e '
def ids: map(.id // .);
.bar.layout.left | ids == ["omarchy.menu", "omarchy.workspaces", "omarchy.active-window"]
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
pass "shell config uses a widget's default section"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar move omarchy.active-window left
grep -Fqx 'shell moveBarWidget omarchy.active-window {"section":"left"}' \
"$TMPDIR/home/.local/state/omarchy/shell-ipc-calls"
pass "bar move can restore a widget with positional syntax"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin add omarchy.media
jq -e '
def ids: map(.id // .);
.bar.layout.center | ids == ["omarchy.clock", "omarchy.weather", "omarchy.media", "omarchy.tailscale"]
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin remove omarchy.media >/dev/null
pass "shell config honors a center default section"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin add omarchy.dropbox
jq -e '
def ids: map(.id // .);
.bar.layout.right | ids == ["omarchy.tray", "omarchy.dropbox", "omarchy.bluetooth"]
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin remove omarchy.dropbox >/dev/null
pass "shell config honors a right default section"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin add omarchy.system-update center
jq -e '
def ids: map(.id // .);
.bar.layout.center | ids == ["omarchy.clock", "omarchy.weather", "omarchy.system-update", "omarchy.tailscale"]
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
pass "shell config appends center widgets after weather"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin add omarchy.microphone right
jq -e '
def ids: map(.id // .);
.bar.layout.right | ids == ["omarchy.tray", "omarchy.microphone", "omarchy.bluetooth"]
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
pass "shell config moves existing widgets without duplicates"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin move omarchy.active-window right
jq -e '
def ids: map(.id // .);
(.bar.layout.left | ids == ["omarchy.menu", "omarchy.workspaces"]) and
(.bar.layout.right | ids == ["omarchy.tray", "omarchy.active-window", "omarchy.microphone", "omarchy.bluetooth"])
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
pass "bar plugin move accepts a positional target section"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin move omarchy.active-window left
jq -e '
def ids: map(.id // .);
(.bar.layout.left | ids == ["omarchy.menu", "omarchy.workspaces", "omarchy.active-window"]) and
(.bar.layout.right | ids == ["omarchy.tray", "omarchy.microphone", "omarchy.bluetooth"])
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
pass "bar plugin move can restore a widget with positional syntax"
if HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin move omarchy.active-window left --section right 2>/dev/null; then
fail "bar plugin move accepted positional and flagged target sections"
if HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar move omarchy.active-window left --section right 2>/dev/null; then
fail "bar move accepted positional and flagged target sections"
fi
pass "bar plugin move rejects conflicting target section syntax"
if HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin add local.nonexistent-widget 2>/dev/null; then
fail "bar plugin add accepted an unknown widget"
fi
pass "bar plugin add rejects an unknown widget"
pass "bar move rejects conflicting target section syntax"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar position bottom
jq -e '
@@ -339,43 +297,25 @@ HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar transparent toggle
jq -e '.bar.transparent == false' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
pass "shell config toggles bar transparency"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin drop omarchy.active-window
jq -e '
def ids: map(.id // .);
(.bar.layout.left | ids == ["omarchy.menu", "omarchy.workspaces"]) and
(.bar.layout.center | ids == ["omarchy.clock", "omarchy.weather", "omarchy.system-update", "omarchy.tailscale"]) and
(.bar.layout.right | ids == ["omarchy.tray", "omarchy.microphone", "omarchy.bluetooth"])
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
pass "shell config drops widgets from any section"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar set omarchy.bluetooth enabled false --json
grep -Fqx 'shell setBarWidget omarchy.bluetooth enabled false {}' \
"$TMPDIR/home/.local/state/omarchy/shell-ipc-calls"
pass "bar set accepts false JSON values"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin remove omarchy.system-update
jq -e '
def ids: map(.id // .);
.bar.layout.center | ids == ["omarchy.clock", "omarchy.weather", "omarchy.tailscale"]
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
pass "shell config removes widgets with remove alias"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar set omarchy.bluetooth optional null --json
grep -Fqx 'shell setBarWidget omarchy.bluetooth optional null {}' \
"$TMPDIR/home/.local/state/omarchy/shell-ipc-calls"
pass "bar set accepts null JSON values"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin set omarchy.bluetooth enabled false --json
jq -e '
any(.bar.layout.right[]; .id == "omarchy.bluetooth" and .enabled == false)
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
pass "bar plugin set accepts false JSON values"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin set omarchy.bluetooth optional null --json
jq -e '
any(.bar.layout.right[]; .id == "omarchy.bluetooth" and has("optional") and .optional == null)
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
pass "bar plugin set accepts null JSON values"
if HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin set omarchy.bluetooth broken '{' --json 2>/dev/null; then
fail "bar plugin set accepted malformed JSON"
if HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar set omarchy.bluetooth broken '{' --json 2>/dev/null; then
fail "bar set accepted malformed JSON"
fi
pass "bar plugin set rejects malformed JSON"
pass "bar set rejects malformed JSON"
if HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar-plugin set omarchy.bluetooth broken 'false null' --json 2>/dev/null; then
fail "bar plugin set accepted multiple JSON values"
if HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" omarchy-bar set omarchy.bluetooth broken 'false null' --json 2>/dev/null; then
fail "bar set accepted multiple JSON values"
fi
pass "bar plugin set rejects multiple JSON values"
pass "bar set rejects multiple JSON values"
mock_bin="$TMPDIR/mock-bin"
mkdir -p "$mock_bin"
@@ -400,7 +340,8 @@ SH
cat >"$mock_bin/omarchy-shell" <<'SH'
#!/bin/bash
exit 0
[[ ${OMARCHY_TEST_SHELL_DOWN:-0} == "1" ]] && exit 1
printf 'ok\n'
SH
cat >"$mock_bin/omarchy-installed-service-dropbox" <<'SH'
@@ -430,10 +371,22 @@ pass "bar defaults restores the stock bar"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" PATH="$mock_path" OMARCHY_TEST_DROPBOX=1 OMARCHY_TEST_TAILSCALE=1 omarchy-bar defaults
jq -e '
def ids: map(.id // .);
(.bar.layout.right | ids | index("omarchy.dropbox") != null) and
(.bar.layout.center | ids | index("omarchy.tailscale") != null)
(.bar.layout.center | ids) as $center |
(.bar.layout.right | ids | index("omarchy.dropbox") == 1) and
($center | index("omarchy.tailscale") == (($center | index("omarchy.weather")) + 1))
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
pass "bar defaults adds widgets for running optional services"
pass "bar defaults places plugins for running optional services"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" PATH="$mock_path" \
OMARCHY_TEST_SHELL_DOWN=1 OMARCHY_TEST_DROPBOX=1 OMARCHY_TEST_TAILSCALE=1 \
omarchy-bar defaults
jq -e '
def ids: map(.id // .);
(.bar.layout.center | ids) as $center |
(.bar.layout.right | ids | index("omarchy.dropbox") == 1) and
($center | index("omarchy.tailscale") == (($center | index("omarchy.weather")) + 1))
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
pass "bar defaults places service widgets without a running shell"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" PATH="$mock_path" OMARCHY_TEST_DROPBOX=0 OMARCHY_TEST_TAILSCALE=0 omarchy-refresh-shell
jq -e '
@@ -446,11 +399,12 @@ pass "shell refresh keeps optional service widgets absent when services are unav
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" PATH="$mock_path" OMARCHY_TEST_DROPBOX=1 OMARCHY_TEST_TAILSCALE=1 omarchy-refresh-shell
jq -e '
def ids: map(.id // .);
(.bar.layout.right | ids | index("omarchy.dropbox") != null) and
(.bar.layout.center | ids | index("omarchy.tailscale") != null)
(.bar.layout.center | ids) as $center |
(.bar.layout.right | ids | index("omarchy.dropbox") == 1) and
($center | index("omarchy.tailscale") == (($center | index("omarchy.weather")) + 1))
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
[[ -f $TMPDIR/home/.local/state/omarchy/restart-shell-called ]] || fail "shell refresh restarts shell"
pass "shell refresh adds optional service widgets when services are available"
pass "shell refresh places optional service widgets when services are available"
if grep -RIl 'upgrade-to-quattro\|Omarchy 4\.0 is upgraded' "$ROOT/migrations" >/dev/null; then
fail "4.0 upgrade is not modeled as a migration"
+135 -2
View File
@@ -85,9 +85,20 @@ ShellRoot {
scan += block("firstparty", "/first/hybrid", manifest("omarchy.hybrid", ["menu", "bar-widget"], { menu: "Menu.qml", barWidget: "Widget.qml" }))
scan += block("thirdparty", "/third/panel", manifest("third.panel", ["panel"], { panel: "Panel.qml" }))
scan += block("thirdparty", "/third/widget", manifest("third.widget", ["bar-widget"], { barWidget: "Widget.qml" }, { defaultSection: "left" }))
scan += block("thirdparty", "/third/center-widget", manifest("third.center-widget", ["bar-widget"], { barWidget: "Widget.qml" }))
scan += block("thirdparty", "/third/right-widget", manifest("third.right-widget", ["bar-widget"], { barWidget: "Widget.qml" }, { defaultSection: "right" }))
var localWidget = manifest("local.first-widget", ["bar-widget"], { barWidget: "Widget.qml" })
localWidget.omarchy = { clonedFrom: "omarchy.first-widget" }
scan += block("thirdparty", "/third/local-widget", localWidget)
var localHybrid = manifest("local.hybrid", ["menu", "bar-widget"], { menu: "Menu.qml", barWidget: "Widget.qml" })
localHybrid.omarchy = { clonedFrom: "omarchy.hybrid" }
scan += block("thirdparty", "/third/local-hybrid", localHybrid)
var localPanel = manifest("local.grouped-panel", ["panel"], { panel: "Panel.qml" })
localPanel.omarchy = { clonedFrom: "omarchy.grouped-panel" }
scan += block("thirdparty", "/third/local-panel", localPanel)
var localBar = manifest("local.bar", ["bar"], { bar: "Bar.qml" })
localBar.omarchy = { clonedFrom: "omarchy.bar" }
scan += block("thirdparty", "/third/local-bar", localBar)
scan += block("thirdparty", "/third/bar", manifest("third.bar", ["bar"], { bar: "Bar.qml" }))
scan += block("thirdparty", "/third/shadow", manifest("omarchy.first-widget", ["panel"], { panel: "Panel.qml" }))
scan += block("thirdparty", "/third/reserved", manifest("omarchy.reserved", ["panel"], { panel: "Panel.qml" }))
@@ -100,13 +111,18 @@ ShellRoot {
registry.parseScanOutput(scan)
root.assertDeepEqual(pluginIds(), [
"local.bar",
"local.first-widget",
"local.grouped-panel",
"local.hybrid",
"omarchy.bar",
"omarchy.first-widget",
"omarchy.grouped-panel",
"omarchy.hybrid",
"third.bar",
"third.center-widget",
"third.panel",
"third.right-widget",
"third.widget"
], "registry merges valid first-party and third-party manifests")
@@ -148,9 +164,126 @@ ShellRoot {
registry.setEnabled("third.widget", false)
root.assertDeepEqual(root.config.bar.layout.left, [], "disabling bar widgets removes layout entry")
root.config = {
version: 1,
bar: {
layout: {
left: [{ id: "omarchy.workspaces" }, { id: "omarchy.menu" }],
center: [{ id: "omarchy.weather" }, { id: "omarchy.clock" }],
right: [{ id: "omarchy.tray" }]
}
},
plugins: []
}
registry.setEnabled("third.widget", true)
root.assertDeepEqual(
root.config.bar.layout.left,
[{ id: "omarchy.workspaces" }, { id: "third.widget" }, { id: "omarchy.menu" }],
"enabling a widget inserts it after its section anchor"
)
registry.setEnabled("third.center-widget", true)
root.assertDeepEqual(
root.config.bar.layout.center,
[{ id: "omarchy.weather" }, { id: "third.center-widget" }, { id: "omarchy.clock" }],
"widgets without a default section use the center anchor"
)
registry.setEnabled("third.right-widget", true)
root.assertDeepEqual(
root.config.bar.layout.right,
[{ id: "omarchy.tray" }, { id: "third.right-widget" }],
"right widgets use the right anchor"
)
root.config = { version: 1, bar: { layout: { left: [], center: [], right: [] } }, plugins: [] }
registry.setEnabled("third.right-widget", true)
root.assertDeepEqual(root.config.bar.layout.right, [{ id: "third.right-widget" }], "widgets append when their section anchor is absent")
root.config = {
version: 1,
bar: { layout: { left: [{ id: "third.widget", size: 3 }], center: [], right: [] } },
plugins: []
}
root.assertEqual(registry.moveBarWidget("third.widget", { section: "right" }), "", "registry moves widgets")
root.assertDeepEqual(root.config.bar.layout.right, [{ id: "third.widget", size: 3 }], "registry move preserves widget settings")
root.assertEqual(registry.setBarWidget("third.widget", "size", 7, {}), "", "registry sets widget options")
root.assertEqual(root.config.bar.layout.right[0].size, 7, "registry persists widget options")
root.config = { version: 1, bar: { layout: { left: [], center: [], right: [] } }, plugins: [] }
registry.setEnabled("third.widget", true, { section: "right", index: 0 })
root.assertDeepEqual(root.config.bar.layout.right, [{ id: "third.widget" }], "enabling with placement is one registry transition")
root.config = {
version: 1,
bar: { layout: { left: [], center: [{ id: "omarchy.first-widget", size: 4 }], right: [] } },
plugins: []
}
registry.setEnabled("local.first-widget", true)
root.assertDeepEqual(
root.config.bar.layout.center,
[{ id: "local.first-widget", size: 4 }],
"enabling a widget clone replaces its source in place"
)
root.assertEqual(registry.resolveEnabledId("omarchy.first-widget"), "local.first-widget", "enabled clones receive calls made to their source id")
registry.setEnabled("omarchy.first-widget", true)
root.assertDeepEqual(
root.config.bar.layout.center,
[{ id: "omarchy.first-widget", size: 4 }],
"enabling a clone source switches back without duplicates"
)
registry.setEnabled("local.first-widget", true)
registry.setEnabled("local.first-widget", false)
root.assertDeepEqual(
root.config.bar.layout.center,
[{ id: "omarchy.first-widget", size: 4 }],
"disabling a widget clone restores its source in place"
)
root.config = {
version: 1,
bar: { layout: { left: [], center: ["omarchy.first-widget"], right: [] } },
plugins: []
}
registry.setEnabled("local.first-widget", true)
root.assertDeepEqual(root.config.bar.layout.center, [{ id: "local.first-widget" }], "clone replacement normalizes string entries")
registry.setEnabled("local.first-widget", false)
root.assertDeepEqual(root.config.bar.layout.center, [{ id: "omarchy.first-widget" }], "clone restoration normalizes string entries")
root.config = {
version: 1,
bar: { layout: { left: [{ id: "omarchy.hybrid" }], center: [], right: [] } },
plugins: []
}
registry.setEnabled("local.hybrid", true)
root.assertDeepEqual(root.config.bar.layout.left, [{ id: "local.hybrid" }], "enabling a multi-kind clone replaces its widget")
root.assertDeepEqual(root.config.disabledPlugins, ["omarchy.hybrid"], "enabling a multi-kind clone disables the source")
registry.setEnabled("local.hybrid", false)
root.assertDeepEqual(root.config.bar.layout.left, [{ id: "omarchy.hybrid" }], "disabling a multi-kind clone restores its widget")
root.assertTrue(root.config.disabledPlugins === undefined, "disabling a multi-kind clone enables the source")
root.config = { version: 1, bar: { layout: { left: [], center: [], right: [] } }, plugins: [] }
registry.setEnabled("local.grouped-panel", true)
root.assertDeepEqual(root.config.plugins, [{ id: "local.grouped-panel" }], "enabling an ordinary clone adds it")
root.assertDeepEqual(root.config.disabledPlugins, ["omarchy.grouped-panel"], "enabling an ordinary clone disables the source")
registry.setEnabled("local.grouped-panel", false)
root.assertDeepEqual(root.config.plugins, [], "disabling an ordinary clone removes it")
root.assertTrue(root.config.disabledPlugins === undefined, "disabling an ordinary clone restores the source")
root.config = {
version: 1,
bar: { layout: { left: [], center: [], right: [] } },
plugins: [],
disabledPlugins: ["omarchy.grouped-panel"]
}
registry.setEnabled("local.grouped-panel", true)
root.assertDeepEqual(root.config.disabledPlugins, ["omarchy.grouped-panel"], "cloning an already-disabled source keeps it disabled")
root.assertTrue(root.config.cloneSourceRestores === undefined, "an already-disabled source is not marked for restoration")
registry.setEnabled("local.grouped-panel", false)
root.assertDeepEqual(root.config.disabledPlugins, ["omarchy.grouped-panel"], "disabling the clone preserves the source's prior disabled state")
registry.setEnabled("local.bar", true)
root.assertEqual(root.config.bar.id, "local.bar", "enabling a cloned bar selects it")
registry.setEnabled("local.bar", false)
root.assertTrue(root.config.bar.id === undefined, "disabling a cloned built-in bar restores it")
root.config = {
version: 1,
@@ -201,8 +334,8 @@ ShellRoot {
}
registry.setEnabled("omarchy.hybrid", false)
root.assertDeepEqual(root.config.bar.layout.left, [], "disabling a multi-kind built-in removes its widget")
root.assertDeepEqual(root.config.disabledPlugins, ["omarchy.hybrid"], "disabling a multi-kind built-in unloads its other kinds")
root.assertTrue(!registry.isEnabled("omarchy.hybrid"), "a disabled multi-kind built-in is not loadable")
root.assertTrue(root.config.disabledPlugins === undefined, "disabling a multi-kind widget records nothing else")
root.assertTrue(registry.isEnabled("omarchy.hybrid"), "a multi-kind built-in remains loadable without its widget")
var localBase = registry.pluginsDir + "/local.clock"
root.assertEqual(registry.localPluginIdForPath(localBase + "/BarWidget.qml"), "local.clock", "local clone changes are watched")
+1 -1
View File
@@ -221,7 +221,7 @@ const pluginAdd = fs.readFileSync(path.join(root, 'bin/omarchy-plugin-add'), 'ut
const pluginEnable = fs.readFileSync(path.join(root, 'bin/omarchy-plugin-enable'), 'utf8')
assert(
/Now using \$id as the bar/.test(pluginEnable)
&& /Now using \$id as the bar[\s\S]*?place_bar_widget/.test(pluginAdd),
&& /omarchy-plugin-enable "\$id" "\$\{ENABLE_PLACEMENT\[@\]\}"/.test(pluginAdd),
'plugin enable reports a bar as replacing the one in use, whether enabled or freshly added'
)
assert(
+23 -55
View File
@@ -24,19 +24,14 @@ elif [[ $* == *"listPlugins"* ]]; then
find "$HOME/.config/omarchy/plugins" -mindepth 2 -maxdepth 2 -name manifest.json -print0 |
xargs -0 -r jq -s 'map({id: .id, enabled: true})'
fi
elif [[ $* == *"setPluginEnabled"* ]]; then
printf 'omarchy-shell %s\n' "$*" >>"$FAKE_CALLS"
printf 'ok\n'
fi
exit 0
SH
for command in omarchy-bar omarchy-bar-plugin; do
cat >"$TMPDIR/bin/$command" <<'SH'
#!/bin/bash
printf '%s %s\n' "${0##*/}" "$*" >>"$FAKE_CALLS"
exec "$OMARCHY_TEST_ROOT/bin/${0##*/}" "$@"
SH
done
for command in omarchy-plugin-enable omarchy-plugin-disable omarchy-notification-send; do
for command in omarchy-plugin-enable omarchy-notification-send; do
cat >"$TMPDIR/bin/$command" <<'SH'
#!/bin/bash
printf '%s %s\n' "${0##*/}" "$*" >>"$FAKE_CALLS"
@@ -87,36 +82,16 @@ jq -e '
' "$clock/manifest.json" >/dev/null || fail "clock clone manifest is incorrect"
pass "clone updates identity without replacing the manifest"
grep -qx 'omarchy-bar-plugin replace omarchy.clock local.clock' "$CALLS" ||
fail "clone does not replace an active bar widget"
grep -qx 'omarchy-plugin-enable local.clock' "$CALLS" ||
fail "clone does not enable the editable copy"
grep -qx 'omarchy-notification-send -g 󰐱 Editing Cloned Plugin Original plugin has been replace by clone.' "$CALLS" ||
fail "clone does not notify that the editable clone is active"
jq -e '
any(.bar.layout.center[];
.id == "local.clock" and
.format == "dddd HH:mm" and
.formatAlt == "d MMMM \u0027W\u0027ww yyyy")
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null ||
fail "clone does not preserve the active widget's placement and settings"
pass "clone switches bar widgets in place and confirms the editable clone"
pass "clone enables bar widgets and confirms the editable clone"
jq '.bar.layout.center += ["omarchy.keyboard-layout"]' \
"$TMPDIR/home/.config/omarchy/shell.json" >"$TMPDIR/shell.json"
mv "$TMPDIR/shell.json" "$TMPDIR/home/.config/omarchy/shell.json"
FAKE_CLONE_CONFIG='{
"bar": {
"layout": {
"left": [],
"center": ["omarchy.keyboard-layout"],
"right": []
}
}
}' clone_plugin omarchy.keyboard-layout >/dev/null
jq -e '
any(.bar.layout.center[]; .id == "local.keyboard-layout")
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null ||
fail "clone does not replace a string-form bar entry"
pass "clone replaces legacy string-form bar entries"
clone_plugin omarchy.keyboard-layout >/dev/null
grep -qx 'omarchy-plugin-enable local.keyboard-layout' "$CALLS" ||
fail "clone does not enable a clone of a legacy string-form bar entry"
pass "clone enables clones of legacy string-form bar entries"
clone_plugin omarchy.menu >/dev/null
menu="$TMPDIR/home/.config/omarchy/plugins/local.menu"
@@ -130,29 +105,26 @@ jq -e '
.entryPoints.menu == "Menu.qml" and
.entryPoints.barWidget == "BarWidget.qml"
' "$menu/manifest.json" >/dev/null || fail "menu clone loses plugin kinds"
grep -qx 'omarchy-plugin-disable omarchy.menu' "$CALLS" ||
fail "clone leaves the built-in half of a multi-kind plugin enabled"
pass "clone preserves multi-kind plugins"
grep -qx 'omarchy-plugin-enable local.menu' "$CALLS" ||
fail "clone does not enable a multi-kind plugin"
pass "clone preserves and enables multi-kind plugins"
HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" PATH="$TMPDIR/bin:$ROOT/bin:$PATH" \
remove_output=$(HOME="$TMPDIR/home" OMARCHY_PATH="$ROOT" PATH="$TMPDIR/bin:$ROOT/bin:$PATH" \
FAKE_CALLS="$CALLS" OMARCHY_TEST_ROOT="$ROOT" \
omarchy-plugin-remove local.menu --yes >/dev/null
grep -qx 'omarchy-bar-plugin replace local.menu omarchy.menu' "$CALLS" &&
grep -qx 'omarchy-plugin-enable omarchy.menu' "$CALLS" ||
fail "removing a clone does not restore its built-in source"
pass "removing a clone restores its built-in source"
omarchy-plugin-remove local.menu --yes)
grep -qx 'omarchy-shell shell setPluginEnabled local.menu false' "$CALLS" ||
fail "removing an enabled clone does not disable it first"
grep -q 'Restored omarchy.menu.' <<<"$remove_output" ||
fail "removing a clone does not report its restored source"
pass "removing an enabled clone goes through plugin disable and reports its source"
clone_plugin omarchy.active-window >/dev/null
[[ -f $TMPDIR/home/.config/omarchy/plugins/local.active-window/ActiveWindow.qml ]] ||
fail "flat bar plugin clone is incomplete"
pass "flat bar plugins clone from adjacent manifests"
grep -qx 'omarchy-bar-plugin add local.active-window' "$CALLS" ||
grep -qx 'omarchy-plugin-enable local.active-window' "$CALLS" ||
fail "clone does not activate a bar widget whose source is absent"
jq -e '
any(.bar.layout.left[]; .id == "local.active-window")
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null ||
fail "clone does not add the absent widget using its default placement"
pass "clone activates an absent bar widget"
clone_plugin omarchy.indicators >/dev/null
@@ -170,17 +142,13 @@ clone_plugin omarchy.tray >/dev/null
pass "flat bar plugins keep local script dependencies"
clone_plugin omarchy.bar >/dev/null
grep -qx 'omarchy-bar use local.bar' "$CALLS" ||
grep -qx 'omarchy-plugin-enable local.bar' "$CALLS" ||
fail "clone does not select a cloned bar"
jq -e '.bar.id == "local.bar"' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null ||
fail "clone does not persist the cloned bar as active"
pass "clone switches full bars"
clone_plugin omarchy.background >/dev/null
grep -qx 'omarchy-plugin-enable local.background' "$CALLS" ||
fail "clone does not enable an ordinary cloned plugin"
grep -qx 'omarchy-plugin-disable omarchy.background' "$CALLS" ||
fail "clone does not disable the ordinary source plugin"
pass "clone switches ordinary plugins"
mkdir -p "$TMPDIR/home/.config/omarchy/plugins/acme.example"
+45
View File
@@ -0,0 +1,45 @@
#!/bin/bash
set -euo pipefail
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
TMPDIR=$(mktemp -d)
trap 'rm -rf "$TMPDIR"' EXIT
mkdir -p "$TMPDIR/home" "$TMPDIR/bin"
calls="$TMPDIR/calls"
cat >"$TMPDIR/bin/omarchy-shell" <<'SH'
#!/bin/bash
printf '%s\n' "$*" >>"$OMARCHY_TEST_CALLS"
printf 'ok\n'
SH
chmod +x "$TMPDIR/bin/omarchy-shell"
run_enable() {
HOME="$TMPDIR/home" \
OMARCHY_PATH="$ROOT" \
OMARCHY_TEST_CALLS="$calls" \
PATH="$TMPDIR/bin:$ROOT/bin:$PATH" \
omarchy-plugin-enable "$@"
}
run_enable omarchy.active-window --section right >/dev/null
grep -Fqx 'shell enablePlugin omarchy.active-window {"section":"right"}' "$calls" ||
fail "plugin enable did not combine activation and placement"
pass "plugin enable combines activation and placement in one shell mutation"
run_enable omarchy.clock --before omarchy.weather >/dev/null
grep -Fqx 'shell enablePlugin omarchy.clock {"before":"omarchy.weather"}' "$calls" ||
fail "plugin enable did not preserve relative placement"
pass "plugin enable forwards relative placement"
run_enable omarchy.dropbox >/dev/null
grep -Fqx 'shell enablePlugin omarchy.dropbox {}' "$calls" ||
fail "plugin enable did not use manifest-default placement"
pass "plugin enable leaves default placement to the registry"
if run_enable omarchy.bar --section right >/dev/null 2>&1; then
fail "plugin enable accepted placement for a full bar"
fi
pass "plugin enable rejects placement for full bars"
+2 -2
View File
@@ -296,7 +296,7 @@ if (( worst > screens - 1 )); then
fi
pass "each widget registers its IPC handler once per screen"
HOME="$test_home" OMARCHY_PATH="$test_root" PATH="$ROOT/bin:$PATH" "$ROOT/bin/omarchy-bar-plugin" remove omarchy.audio
HOME="$test_home" OMARCHY_PATH="$test_root" PATH="$ROOT/bin:$PATH" "$ROOT/bin/omarchy-plugin-disable" omarchy.audio
for _ in {1..80}; do
shell_config=$(shell_ipc shell listShellConfig 2>/dev/null || true)
@@ -313,7 +313,7 @@ done
jq -e 'all(.bar.layout.right[]; (.id // .) != "omarchy.audio")' <<<"$shell_config" >/dev/null || {
printf 'Shell config after reload:\n%s\n' "$shell_config" | jq . >&2
fail_with_log "bar remove reloads shell config"
fail_with_log "plugin disable reloads shell config"
}
jq -e 'all(.[]; .id != "omarchy.audio")' <<<"$geometry" >/dev/null || {