diff --git a/config/omarchy/plugins/omacom.elsewhen b/config/omarchy/plugins/omacom.elsewhen new file mode 120000 index 00000000..19840c51 --- /dev/null +++ b/config/omarchy/plugins/omacom.elsewhen @@ -0,0 +1 @@ +/usr/share/omarchy/plugins/omacom.elsewhen \ No newline at end of file diff --git a/config/omarchy/shell.json b/config/omarchy/shell.json index e6202da8..b8aa5de4 100644 --- a/config/omarchy/shell.json +++ b/config/omarchy/shell.json @@ -21,6 +21,9 @@ { "id": "omarchy.indicators" }, + { + "id": "omacom.elsewhen" + }, { "id": "omarchy.clock", "format": "dddd HH:mm", diff --git a/docs/omarchy-shell.md b/docs/omarchy-shell.md index d62ff743..d62661a7 100644 --- a/docs/omarchy-shell.md +++ b/docs/omarchy-shell.md @@ -88,6 +88,10 @@ bar from the CLI — `use | reset | defaults | position | transparent | put | move | set`, with placement flags such as `--section` and `--index`. The lower-level IPC methods remain available through `omarchy-shell shell ...`. +## Elsewhen + +Elsewhen (`omacom.elsewhen`) ships in the `elsewhen` package at `/usr/share/omarchy/plugins/omacom.elsewhen`. A symlink in `~/.config/omarchy/plugins/` makes it available to the shell. New installs place it immediately before the clock; the migration uses `omarchy bar put omacom.elsewhen --before omarchy.clock`, which preserves an existing placement and uses Elsewhen's normal right-side placement if the clock is absent. Existing plugin directories and symlinks are left intact. The normal update flow restarts the shell after migrations; the migration does not interrupt plugin loading with an immediate restart. + ## IPC The shell exposes a `shell` target (the host also registers diff --git a/install/omarchy-base.packages b/install/omarchy-base.packages index 76e74110..0a8e27cc 100644 --- a/install/omarchy-base.packages +++ b/install/omarchy-base.packages @@ -26,6 +26,7 @@ docker-compose dosfstools dotnet-runtime dua-cli +elsewhen evince exfatprogs expac diff --git a/migrations/1789581661.sh b/migrations/1789581661.sh new file mode 100644 index 00000000..5c022e1c --- /dev/null +++ b/migrations/1789581661.sh @@ -0,0 +1,12 @@ +echo "Install Elsewhen, the world clock plugin" + +omarchy-pkg-add elsewhen + +plugin="$HOME/.config/omarchy/plugins/omacom.elsewhen" +mkdir -p "$(dirname "$plugin")" +if [[ ! -e $plugin && ! -L $plugin ]]; then + ln -s /usr/share/omarchy/plugins/omacom.elsewhen "$plugin" +fi + +omarchy-shell shell rescanPlugins +omarchy-bar put omacom.elsewhen --before omarchy.clock diff --git a/test/shell.d/config-test.sh b/test/shell.d/config-test.sh index 355ca26b..82a51e6f 100755 --- a/test/shell.d/config-test.sh +++ b/test/shell.d/config-test.sh @@ -33,6 +33,15 @@ jq -e ' ' "$ROOT/config/omarchy/shell.json" >/dev/null pass "default center anchor exists in center layout" +jq -e ' + def ids: map(.id // .); + (.bar.layout.center | ids) as $ids | + ($ids | index("omacom.elsewhen")) as $elsewhen | + ($ids | index("omarchy.clock")) as $clock | + $elsewhen != null and $clock == $elsewhen + 1 +' "$ROOT/config/omarchy/shell.json" >/dev/null +pass "default center layout puts elsewhen immediately before the clock" + jq -e ' any(.bar.layout.center[]; (.id // .) == "omarchy.clock" and (.formatAlt // "") == "d MMMM \u0027W\u0027ww yyyy") ' "$ROOT/config/omarchy/shell.json" >/dev/null diff --git a/test/shell.d/elsewhen-default-migration-test.sh b/test/shell.d/elsewhen-default-migration-test.sh new file mode 100644 index 00000000..c0a2de8f --- /dev/null +++ b/test/shell.d/elsewhen-default-migration-test.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +set -euo pipefail + +source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh" +require_command jq + +test_dir=$(mktemp -d) +trap 'rm -rf "$test_dir"' EXIT +mkdir -p "$test_dir/bin" "$test_dir/home" +export CALL_LOG="$test_dir/calls" + +cat >"$test_dir/bin/omarchy-pkg-add" <<'SH' +#!/bin/bash +printf 'package %s\n' "$*" >>"$CALL_LOG" +exit "${PACKAGE_STATUS:-0}" +SH +cat >"$test_dir/bin/omarchy-shell" <<'SH' +#!/bin/bash +printf '%s\n' "$*" >>"$CALL_LOG" +[[ $2 != "rescanPlugins" ]] || exit "${SCAN_STATUS:-0}" +printf '%s\n' "${TEST_PUT_RESULT:-ok}" +SH +cat >"$test_dir/bin/omarchy-restart-shell" <<'SH' +#!/bin/bash +echo 'migration must leave the restart to omarchy update' >&2 +exit 1 +SH +chmod +x "$test_dir/bin/"* + +plugin="$test_dir/home/.config/omarchy/plugins/omacom.elsewhen" +run_migration() { + : >"$CALL_LOG" + HOME="$test_dir/home" OMARCHY_PATH="$ROOT" PATH="$test_dir/bin:$ROOT/bin:$PATH" \ + bash -euo pipefail "$ROOT/migrations/1789581661.sh" >"$test_dir/output" 2>&1 +} + +if PACKAGE_STATUS=1 run_migration; then + fail "package failure stops the migration" +fi +[[ ! -e $plugin && ! -L $plugin && $(cat "$CALL_LOG") == "package elsewhen" ]] || + fail "package failure leaves the plugin and shell untouched" +pass "package failure stops before linking or changing the shell" + +run_migration +[[ $(readlink "$plugin") == /usr/share/omarchy/plugins/omacom.elsewhen ]] || fail "package link is installed" +[[ $(readlink "$ROOT/config/omarchy/plugins/omacom.elsewhen") == "$(readlink "$plugin")" ]] || fail "fresh installs use the same package link" +pass "migration and fresh installs link to the package" + +expected=$'package elsewhen\nshell rescanPlugins\nshell putBarWidget omacom.elsewhen {"before":"omarchy.clock"}' +[[ $(cat "$CALL_LOG") == "$expected" ]] || fail "install, scan and placement run in order" "$(cat "$CALL_LOG")" +pass "real bar helper enables and places before the clock without restarting during reload" + +run_migration +[[ $(cat "$CALL_LOG") == "$expected" ]] || fail "migration can be rerun" +pass "migration can be rerun with its package link present" + +rm "$plugin" +mkdir "$plugin" +printf 'local work\n' >"$plugin/notes" +run_migration +[[ ! -L $plugin && $(cat "$plugin/notes") == "local work" ]] || fail "existing checkout is preserved" +pass "existing checkout and local files are preserved" + +rm "$plugin/notes" +rmdir "$plugin" +ln -s "$test_dir/custom-plugin" "$plugin" +run_migration +[[ $(readlink "$plugin") == "$test_dir/custom-plugin" ]] || fail "existing symlink is preserved" +pass "existing symlink is preserved, including a missing target" + +for failure in 'SCAN_STATUS=1' 'TEST_PUT_RESULT=unknown'; do + if env "$failure" HOME="$test_dir/home" OMARCHY_PATH="$ROOT" PATH="$test_dir/bin:$ROOT/bin:$PATH" \ + bash -euo pipefail "$ROOT/migrations/1789581661.sh" >"$test_dir/output" 2>&1; then + fail "$failure must leave the migration pending" + fi + pass "$failure leaves the migration pending" +done