Files
broodcicada-glitch 7154ed7fa5 Add Cursor generator plugin with slash commands and installers. (#417)
Ship a first-class Cursor adaptation (commands, skill, rules, marketplace manifest, CI installer tests) and document generator vs Hub consumer install paths in README/README_CN.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-21 15:25:52 +08:00

103 lines
3.1 KiB
Bash

# Shared helpers for CLI-Anything Cursor plugin install/uninstall (bash).
# shellcheck shell=bash
normalize_path_key() {
printf '%s' "${1}" | tr '[:upper:]' '[:lower:]' | tr '\\' '/' | sed 's:/*$::'
}
# Convert Git Bash / MSYS / Cygwin / WSL-style paths to Windows host paths for Cursor tools.
to_host_path() {
local p="${1}"
if command -v cygpath >/dev/null 2>&1; then
cygpath -w "${p}"
return 0
fi
case "$(uname -s 2>/dev/null || true)" in
MINGW*|MSYS*|CYGWIN*|Linux)
if [[ "${p}" =~ ^/([a-zA-Z])/(.*)$ ]]; then
local drive rest
drive="$(printf '%s' "${BASH_REMATCH[1]}" | tr '[:lower:]' '[:upper:]')"
rest="${BASH_REMATCH[2]//\//\\}"
printf '%s:\\%s' "${drive}" "${rest}"
return 0
fi
if [[ "${p}" =~ ^/mnt/([a-zA-Z])/(.*)$ ]]; then
local drive rest
drive="$(printf '%s' "${BASH_REMATCH[1]}" | tr '[:lower:]' '[:upper:]')"
rest="${BASH_REMATCH[2]//\//\\}"
printf '%s:\\%s' "${drive}" "${rest}"
return 0
fi
;;
esac
printf '%s' "${p}"
}
# Resolve CURSOR_PLUGINS_HOME / default plugins root.
# Second arg: "create" to mkdir (install), anything else skips creating.
resolve_plugins_home() {
local raw="${1}"
local mode="${2:-}"
if [[ -z "${raw}" || "${raw}" == "." || "${raw}" == ".." ]]; then
echo "Invalid CURSOR_PLUGINS_HOME: ${raw}" >&2
return 1
fi
# Canonicalize without creating the path (abspath collapses ".." safely).
if command -v python3 >/dev/null 2>&1; then
raw="$(python3 -c 'import os,sys; print(os.path.abspath(os.path.expanduser(sys.argv[1])))' "${raw}")"
elif command -v python >/dev/null 2>&1; then
raw="$(python -c 'import os,sys; print(os.path.abspath(os.path.expanduser(sys.argv[1])))' "${raw}")"
else
if [[ "${raw}" == "~"* ]]; then
raw="${HOME}${raw:1}"
fi
if [[ "${raw}" != /* && "${raw}" != [A-Za-z]:* && "${raw}" != \\* ]]; then
raw="$(pwd)/${raw}"
fi
case "${raw}" in
*..*)
echo "Invalid CURSOR_PLUGINS_HOME (refuses '..' without python): ${raw}" >&2
return 1
;;
esac
fi
if [[ "$(basename "${raw}")" != "plugins" ]]; then
echo "CURSOR_PLUGINS_HOME must resolve to a directory named 'plugins' (got: ${raw})" >&2
echo "Example: ~/.cursor/plugins or /custom/path/plugins" >&2
return 1
fi
if [[ "${mode}" == "create" ]]; then
mkdir -p "${raw}"
if command -v realpath >/dev/null 2>&1; then
raw="$(realpath "${raw}")"
else
raw="$(cd "${raw}" && pwd -P)"
fi
elif [[ -d "${raw}" ]]; then
if command -v realpath >/dev/null 2>&1; then
raw="$(realpath "${raw}")"
else
raw="$(cd "${raw}" && pwd -P)"
fi
fi
printf '%s' "${raw}"
}
# True when path is .../local/cli-anything (slash or backslash).
is_cli_anything_install_path() {
local key
key="$(normalize_path_key "${1}")"
[[ "$(basename "${key}")" == "cli-anything" ]] || return 1
case "${key}" in
*/local/cli-anything) return 0 ;;
*) return 1 ;;
esac
}
discovery_pointer_path() {
printf '%s' "${HOME}/.cursor/cli-anything-generator.root"
}