Files
omarchycn/bin/omarchy-plugin-edit
T
David Heinemeier Hansson 055ffaccd4 Split omarchy-plugin into siblings and consolidate bar config into omarchy-bar
omarchy-plugin mixed plugin lifecycle, clone/edit, and bar-layout mutation.
The bar layout was mutated by two separate engines (an embedded Python
mutate_bar here and jq in omarchy-config-shell-bar), each with its own
manifest walker.

- omarchy-plugin is now a ~220-line router; clone and edit move to
  omarchy-plugin-clone and omarchy-plugin-edit, matching the existing
  plugin-{source,add,update,remove,available,validate,scan} sibling pattern
- omarchy-config-shell-bar is replaced by omarchy-bar, the single bar engine
  (show/layout/list/options/use/reset/add/move/remove/set/replace/position/
  transparent/settings) with one jq pipeline; the Python mutate_bar and its
  python3 dependency are gone
- omarchy-plugin-catalog is the shared manifest scanner used by omarchy-bar
  (widget/option enumeration, add validation) and omarchy-plugin-clone
  (source enumeration), replacing three find|jq re-implementations
- service install/remove and refresh-shell call omarchy-bar; docs and tests
  updated to the new command surface
2026-07-02 11:10:24 -07:00

158 lines
4.2 KiB
Bash
Executable File

#!/bin/bash
# omarchy:summary=Open a user Omarchy shell plugin directory in a shell
# omarchy:group=plugin
# omarchy:args=[plugin-id]
# omarchy:examples=omarchy plugin edit | omarchy plugin edit local.clock
set -euo pipefail
PLUGINS_DIR="$HOME/.config/omarchy/plugins"
fail() {
echo "omarchy-plugin-edit: $*" >&2
exit 1
}
require_command() {
command -v "$1" >/dev/null 2>&1 || fail "$1 is required"
}
interactive() {
[[ -t 0 && -t 1 ]]
}
canonical_widget_id() {
printf '%s' "$1"
}
slug_id() {
tr '[:upper:]' '[:lower:]' <<<"$1" | sed -E 's/^omarchy\.//; s/[^a-z0-9]+/-/g; s/^-+//; s/-+$//'
}
require_omarchy_path() {
[[ -n ${OMARCHY_PATH:-} ]] || fail "OMARCHY_PATH is not set"
}
# A built-in id is one the catalog knows as first-party (or an omarchy.* id).
builtin_id_known() {
local id="$1"
require_command jq
require_omarchy_path
omarchy-plugin-catalog | jq -e --arg id "$id" \
'any(.[]; .id == $id and .firstParty)' >/dev/null 2>&1
}
validate_user_plugin_dir() {
local dir="$1"
local requested_id="${2:-}"
local root="$PLUGINS_DIR"
local dir_abs root_abs manifest_id
require_command jq
require_command python3
[[ -d $dir ]] || fail "plugin directory not found: $dir"
dir_abs=$(python3 -c 'from pathlib import Path; import sys; print(Path(sys.argv[1]).expanduser().resolve(strict=False))' "$dir")
root_abs=$(python3 -c 'from pathlib import Path; import sys; print(Path(sys.argv[1]).expanduser().resolve(strict=False))' "$root")
[[ $dir_abs == $root_abs/* ]] || fail "plugin edit only opens user plugins under $root"
[[ -f $dir_abs/manifest.json ]] || fail "plugin directory missing manifest.json: $dir_abs"
manifest_id=$(jq -r '.id // empty' "$dir_abs/manifest.json" 2>/dev/null || true)
[[ -n $manifest_id ]] || fail "plugin manifest missing id: $dir_abs/manifest.json"
[[ $manifest_id != omarchy.* && $(canonical_widget_id "$manifest_id") == $manifest_id ]] \
|| fail "$manifest_id is built in; clone it first with: omarchy plugin clone $manifest_id local.$(slug_id "$manifest_id")"
if [[ -n $requested_id && $manifest_id != $requested_id ]]; then
fail "plugin id mismatch: requested $requested_id but manifest declares $manifest_id"
fi
printf '%s' "$dir_abs"
}
plugin_dir_for_id() {
local id="$1"
if [[ $id == */* ]]; then
validate_user_plugin_dir "$id"
return
fi
id=$(canonical_widget_id "$id")
if builtin_id_known "$id" || [[ $id == omarchy.* ]]; then
fail "$id is built in; clone it first with: omarchy plugin clone $id local.$(slug_id "$id")"
fi
validate_user_plugin_dir "$PLUGINS_DIR/$id" "$id"
}
edit_source_options() {
[[ -d $PLUGINS_DIR ]] || return 0
find "$PLUGINS_DIR" -mindepth 1 -maxdepth 1 \( -type d -o -type l \) 2>/dev/null | sort | while IFS= read -r dir; do
[[ -f $dir/manifest.json ]] || continue
id=$(jq -r '.id // empty' "$dir/manifest.json" 2>/dev/null || true)
name=$(jq -r '.name // .id // empty' "$dir/manifest.json" 2>/dev/null || true)
[[ -n $id ]] && printf '%s\t%s\t%s\n' "$id" "${name:-$id}" "$dir"
done
}
choose_edit_source() {
local selected
selected=$(edit_source_options | awk -F '\t' '{ printf "%-32s %s\n", $2, $1 }' \
| gum filter --header "Edit plugin" --placeholder "Search user plugins..." --limit 1) || return 1
awk '{ print $NF }' <<<"$selected"
}
usage() {
cat <<USAGE
Usage: omarchy plugin edit [plugin-id]
Opens a user plugin directory (~/.config/omarchy/plugins/<id>) in a shell so you
can edit it. Built-in plugins must be cloned first with 'omarchy plugin clone'.
Without an id in a terminal, an interactive picker lists your user plugins.
Examples:
omarchy plugin edit
omarchy plugin edit local.clock
USAGE
}
edit_command() {
local id=""
if (( $# > 0 )) && [[ $1 != --* ]]; then
id="$1"
shift
fi
while (( $# > 0 )); do
case "$1" in
-h | --help)
usage
return
;;
*)
fail "unknown edit option: $1"
;;
esac
done
if [[ -z $id ]]; then
if interactive; then
id=$(choose_edit_source) || fail "edit cancelled"
else
fail "plugin id is required"
fi
fi
local dir
dir=$(plugin_dir_for_id "$id")
if interactive; then
cd "$dir"
exec "${SHELL:-bash}"
fi
printf '%s\n' "$dir"
}
edit_command "$@"