158 lines
4.2 KiB
Bash
Executable File
158 lines
4.2 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# omarchy:summary=Clone a built-in Omarchy shell plugin into your own config
|
|
# omarchy:group=plugin
|
|
# omarchy:args=<source-id>
|
|
|
|
set -euo pipefail
|
|
|
|
PLUGINS_DIR="$HOME/.config/omarchy/plugins"
|
|
|
|
fail() {
|
|
echo "omarchy-plugin-clone: $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
copy_plugin() {
|
|
local source_dir="$1"
|
|
local manifest="$2"
|
|
local target_dir="$3"
|
|
|
|
if [[ ${manifest##*/} == "manifest.json" ]]; then
|
|
cp -aL "$source_dir/." "$target_dir/"
|
|
return
|
|
fi
|
|
|
|
cp -aL "$manifest" "$target_dir/manifest.json"
|
|
|
|
local source target source_pattern file
|
|
while IFS=$'\t' read -r source target; do
|
|
[[ $target != /* && $target != *".."* ]] || fail "invalid clone target path: $target"
|
|
if [[ -d $source_dir/$source ]]; then
|
|
mkdir -p "$target_dir/$target"
|
|
cp -aL "$source_dir/$source/." "$target_dir/$target/"
|
|
else
|
|
mkdir -p "$(dirname "$target_dir/$target")"
|
|
cp -aL "$source_dir/$source" "$target_dir/$target"
|
|
fi
|
|
|
|
if [[ $source != "$target" ]]; then
|
|
source_pattern=${source//./\\.}
|
|
while IFS= read -r -d '' file; do
|
|
sed -i "s|$source_pattern|$target|g" "$file"
|
|
done < <(rg --files-with-matches --null --fixed-strings "$source" "$target_dir")
|
|
fi
|
|
done < <(jq -r '
|
|
[
|
|
(.entryPoints[] | {source: ., target: .}),
|
|
(.omarchy.clonePaths[]? | {source: .source, target: .target})
|
|
] | unique_by(.target)[] | [.source, .target] | @tsv
|
|
' "$manifest")
|
|
}
|
|
|
|
update_manifest() {
|
|
local target_dir="$1"
|
|
local source_id="$2"
|
|
local new_id="$3"
|
|
local display_name="$4"
|
|
local manifest="$target_dir/manifest.json"
|
|
|
|
# Keep built-in ids inside the plugin code as stable IPC targets. The shell
|
|
# uses clonedFrom to route those calls to this local manifest id.
|
|
jq \
|
|
--arg id "$new_id" \
|
|
--arg name "$display_name" \
|
|
--arg sourceId "$source_id" '
|
|
.id = $id |
|
|
.name = $name |
|
|
if (.barWidget | type) == "object" then
|
|
.barWidget.displayName = $name
|
|
else
|
|
.
|
|
end |
|
|
.omarchy = (
|
|
(if (.omarchy | type) == "object" then .omarchy else {} end) +
|
|
{ clonedFrom: $sourceId }
|
|
) |
|
|
del(.omarchy.clonePaths)
|
|
' "$manifest" >"$manifest.tmp"
|
|
mv "$manifest.tmp" "$manifest"
|
|
}
|
|
|
|
usage() {
|
|
cat <<USAGE
|
|
Usage: omarchy plugin clone <source-id>
|
|
|
|
Copies a built-in plugin into ~/.config/omarchy/plugins/local.<id>/ so you can
|
|
edit it freely. The clone keeps all of the source plugin's files and kinds and
|
|
uses "My <name>" as its display name, then replaces the built-in with the clone.
|
|
|
|
USAGE
|
|
}
|
|
|
|
source_id=""
|
|
if (( $# > 0 )) && [[ $1 != --* ]]; then
|
|
source_id="$1"
|
|
shift
|
|
fi
|
|
|
|
while (( $# > 0 )); do
|
|
case "$1" in
|
|
-h | --help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
fail "unknown clone option: $1"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
[[ -n $source_id ]] || fail "clone source is required"
|
|
|
|
source_info=$(omarchy-plugin-catalog | jq -r --arg id "$source_id" '
|
|
.[] | select(.firstParty and .id == $id)
|
|
| [
|
|
.sourceDir,
|
|
.manifestPath,
|
|
(.name // .id)
|
|
] | @tsv
|
|
')
|
|
[[ -n $source_info ]] || fail "unknown built-in plugin: $source_id"
|
|
IFS=$'\t' read -r source_dir source_manifest source_name <<<"$source_info"
|
|
|
|
new_id="local.${source_id#omarchy.}"
|
|
display_name="My $source_name"
|
|
target_dir="$PLUGINS_DIR/$new_id"
|
|
[[ ! -e $target_dir && ! -L $target_dir ]] || fail "$target_dir already exists"
|
|
|
|
mkdir -p "$PLUGINS_DIR"
|
|
stage=$(mktemp -d "$PLUGINS_DIR/.clone.XXXXXX")
|
|
clone_complete=0
|
|
cleanup() {
|
|
[[ -d ${stage:-} ]] && rm -rf "$stage"
|
|
(( clone_complete )) || rm -rf "$target_dir"
|
|
}
|
|
trap cleanup EXIT
|
|
copy_plugin "$source_dir" "$source_manifest" "$stage"
|
|
update_manifest "$stage" "$source_id" "$new_id" "$display_name"
|
|
mv "$stage" "$target_dir"
|
|
stage=""
|
|
|
|
omarchy-shell shell rescanPlugins >/dev/null
|
|
discovered=0
|
|
for (( attempt = 0; attempt < 40; attempt++ )); do
|
|
if omarchy-plugin-list --json | jq -e --arg id "$new_id" 'any(.[]; .id == $id)' >/dev/null; then
|
|
discovered=1
|
|
break
|
|
fi
|
|
sleep 0.05
|
|
done
|
|
(( discovered )) || fail "cloned plugin '$new_id' was not discovered"
|
|
omarchy-plugin-enable "$new_id" >/dev/null
|
|
clone_complete=1
|
|
omarchy-notification-send -g \
|
|
"Editing Cloned Plugin" \
|
|
"Original plugin has been replace by clone."
|
|
echo "Cloned $source_id to $target_dir and switched to $new_id"
|