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
158 lines
4.2 KiB
Bash
Executable File
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 "$@"
|