#!/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 <) 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 "$@"