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
+203 -17
View File
@@ -1,9 +1,9 @@
#!/bin/bash
# omarchy:summary=Set the active bar option, position, and transparency
# omarchy:summary=Configure the bar and its widget layout
# omarchy:group=bar
# omarchy:args=use <id> | reset | defaults | position <top|bottom|left|right> | transparent <true|false|toggle>
# omarchy:examples=omarchy bar use local.neon-bar | omarchy bar reset | omarchy bar defaults | omarchy bar position top | omarchy bar transparent true
# omarchy:args=use <id> | reset | defaults | position <top|bottom|left|right> | transparent <true|false|toggle> | move <id> [placement] | set <id> <key> <value> [--json] [placement]
# omarchy:examples=omarchy bar use local.neon-bar | omarchy bar move omarchy.clock --section center --index 0 | omarchy bar set omarchy.clock format HH:mm
set -euo pipefail
@@ -18,15 +18,26 @@ Usage: omarchy bar <command> [args...]
defaults Restore the default bar and service widgets
position <top|bottom|left|right> Bar position
transparent <true|false|toggle> Bar transparency
move <id> [placement] Move a widget within or between sections
set <id> <key> <value> [--json] [placement]
Set a per-widget option
Bar widgets are added, moved, removed, and configured with 'omarchy bar plugin'.
Placement:
--section <left|center|right> Target section
--index <n> Target index
--before <id> Insert before a widget
--after <id> Insert after a widget
--from-section <section> Source section
--from-index <n> Source index
Enable and disable widgets with 'omarchy plugin enable' and
'omarchy plugin disable'.
Examples:
omarchy bar use local.neon-bar
omarchy bar reset
omarchy bar defaults
omarchy bar position top
omarchy bar transparent true
omarchy bar move omarchy.media left
omarchy bar move omarchy.clock --section center --index 0
omarchy bar set omarchy.clock format HH:mm
USAGE
}
@@ -38,6 +49,87 @@ bar_option_exists() {
' >/dev/null
}
validate_section() {
[[ $1 =~ ^(left|center|right)$ ]] || fail "section must be left, center, or right"
}
validate_index() {
[[ $1 =~ ^[0-9]+$ ]] || fail "index must be a non-negative integer"
}
# --------------------------------------------------------------------- placement
PLACEMENT_SECTION=""
PLACEMENT_INDEX=""
PLACEMENT_BEFORE=""
PLACEMENT_AFTER=""
PLACEMENT_FROM_SECTION=""
PLACEMENT_FROM_INDEX=""
parse_placement() {
while (( $# > 0 )); do
case "$1" in
--section)
PLACEMENT_SECTION="${2:-}"
validate_section "$PLACEMENT_SECTION"
shift 2
;;
--index)
PLACEMENT_INDEX="${2:-}"
validate_index "$PLACEMENT_INDEX"
shift 2
;;
--before)
PLACEMENT_BEFORE="${2:-}"
[[ -n $PLACEMENT_BEFORE ]] || fail "--before requires a widget id"
shift 2
;;
--after)
PLACEMENT_AFTER="${2:-}"
[[ -n $PLACEMENT_AFTER ]] || fail "--after requires a widget id"
shift 2
;;
--from-section)
PLACEMENT_FROM_SECTION="${2:-}"
validate_section "$PLACEMENT_FROM_SECTION"
shift 2
;;
--from-index)
PLACEMENT_FROM_INDEX="${2:-}"
validate_index "$PLACEMENT_FROM_INDEX"
shift 2
;;
-h | --help)
usage
exit 0
;;
*)
fail "unknown option: $1"
;;
esac
done
[[ -z $PLACEMENT_BEFORE || -z $PLACEMENT_AFTER ]] || fail "use only one of --before or --after"
}
placement_json() {
jq -cn \
--arg section "$PLACEMENT_SECTION" \
--arg index "$PLACEMENT_INDEX" \
--arg before "$PLACEMENT_BEFORE" \
--arg after "$PLACEMENT_AFTER" \
--arg fromSection "$PLACEMENT_FROM_SECTION" \
--arg fromIndex "$PLACEMENT_FROM_INDEX" '
{}
+ (if $section == "" then {} else {section: $section} end)
+ (if $index == "" then {} else {index: ($index | tonumber)} end)
+ (if $before == "" then {} else {before: $before} end)
+ (if $after == "" then {} else {after: $after} end)
+ (if $fromSection == "" then {} else {fromSection: $fromSection} end)
+ (if $fromIndex == "" then {} else {fromIndex: ($fromIndex | tonumber)} end)
'
}
# -------------------------------------------------------------------- commands
cmd_use() {
@@ -59,15 +151,48 @@ cmd_use() {
cmd_defaults() {
(( $# == 0 )) || fail "defaults does not take arguments"
# Restore the whole default bar, then re-add widgets for services the user
# actually has installed (they aren't in the shipped default layout).
commit "$NORMALIZE | .bar = \$defaults[0].bar" --slurpfile defaults "$DEFAULTS_FILE"
local service
local catalog
local optional_widgets="[]"
local service widget
catalog=$(omarchy-plugin-catalog)
for service in dropbox tailscale; do
if "omarchy-installed-service-$service"; then
omarchy-bar-plugin add "omarchy.$service"
widget=$(jq -c --arg id "omarchy.$service" '
map(select(.id == $id))[0] as $plugin
| {
id: $id,
section: (
$plugin.barWidget.defaultSection // "center"
| if IN("left", "center", "right") then . else "center" end
)
}
' <<<"$catalog")
optional_widgets=$(jq -c --argjson widget "$widget" '. + [$widget]' <<<"$optional_widgets")
fi
done
# This remains one file mutation so it also works during the headless
# Quattro upgrade and cannot race the shell's in-memory config.
commit "$NORMALIZE
| .bar = \$defaults[0].bar
| def entry_id: if type == \"object\" then (.id // \"\" | tostring) else tostring end;
def anchor_for(\$section): { left: \"omarchy.workspaces\", center: \"omarchy.weather\", right: \"omarchy.tray\" }[\$section];
reduce \$widgets[] as \$widget (.;
.bar.layout.left = (.bar.layout.left | map(select(entry_id != \$widget.id)))
| .bar.layout.center = (.bar.layout.center | map(select(entry_id != \$widget.id)))
| .bar.layout.right = (.bar.layout.right | map(select(entry_id != \$widget.id)))
| (.bar.layout[\$widget.section] | map(entry_id) | index(anchor_for(\$widget.section))) as \$anchor
| (\$anchor | if . == null then (.bar.layout[\$widget.section] | length) else . + 1 end) as \$index
| .bar.layout[\$widget.section] = (
.bar.layout[\$widget.section][0:\$index]
+ [{id: \$widget.id}]
+ .bar.layout[\$widget.section][\$index:]
)
)
" \
--slurpfile defaults "$DEFAULTS_FILE" \
--argjson widgets "$optional_widgets"
echo "Restored the default Omarchy bar"
}
@@ -94,6 +219,67 @@ cmd_transparent() {
fi
}
cmd_move() {
local id="${1:-}"
[[ -n $id ]] || fail "move requires a widget id"
shift
local positional_section=""
if (( $# > 0 )) && [[ $1 != --* ]]; then
positional_section="$1"
validate_section "$positional_section"
shift
fi
parse_placement "$@"
[[ -z $positional_section || -z $PLACEMENT_SECTION ]] ||
fail "specify a section positionally or with --section, not both"
[[ -z $positional_section || -z $PLACEMENT_INDEX ]] ||
fail "specify a section positionally or use --index, not both"
[[ -z $positional_section || -z $PLACEMENT_BEFORE ]] ||
fail "specify a section positionally or use --before, not both"
[[ -z $positional_section || -z $PLACEMENT_AFTER ]] ||
fail "specify a section positionally or use --after, not both"
[[ -z $positional_section ]] || PLACEMENT_SECTION="$positional_section"
local result
result=$(omarchy-shell shell moveBarWidget "$id" "$(placement_json)")
[[ $result == "ok" ]] || fail "$result"
echo "Moved $id"
}
cmd_set() {
local id="${1:-}"
local key="${2:-}"
local value="${3:-}"
[[ -n $id ]] || fail "set requires a widget id"
[[ -n $key ]] || fail "set requires a setting key"
(( $# >= 3 )) || fail "set requires a value"
shift 3
local value_is_json="false"
if (( $# > 0 )) && [[ $1 == "--json" ]]; then
value_is_json="true"
shift
fi
parse_placement "$@"
[[ -z $PLACEMENT_BEFORE && -z $PLACEMENT_AFTER ]] ||
fail "set does not accept --before or --after"
local value_json
if [[ $value_is_json == "true" ]]; then
value_json=$(jq -cn --argjson value "$value" '$value') ||
fail "invalid JSON value: $value"
else
value_json=$(jq -cn --arg value "$value" '$value')
fi
local result
result=$(omarchy-shell shell setBarWidget "$id" "$key" "$value_json" "$(placement_json)")
[[ $result == "ok" ]] || fail "$result"
echo "Set $key on $id"
}
# --------------------------------------------------------------------- dispatch
command="${1:-}"
@@ -116,11 +302,11 @@ case "$command" in
transparent)
cmd_transparent "$@"
;;
plugin)
exec omarchy-bar-plugin "$@"
move)
cmd_move "$@"
;;
add | move | remove | rm | drop | set | replace)
fail "bar widgets are managed with: omarchy bar plugin $command ..."
set)
cmd_set "$@"
;;
-h | --help | help | "")
usage