mirror of
https://github.com/wnlen/clash-for-linux.git
synced 2026-10-10 04:03:04 +08:00
feat(completion): add bash and zsh completions
This commit is contained in:
@@ -30,6 +30,7 @@ mark_install_plan || true
|
||||
mark_install_port_plan || true
|
||||
|
||||
install_clashctl_entry
|
||||
install_clashctl_completion
|
||||
install_shell_alias_entry
|
||||
install_runtime_entry
|
||||
install_local_dashboard_assets
|
||||
|
||||
@@ -7,6 +7,7 @@ PROJECT_DIR="$(cd "$(dirname "$SCRIPT_PATH")/../.." && pwd)"
|
||||
source "$PROJECT_DIR/scripts/core/common.sh"
|
||||
source "$PROJECT_DIR/scripts/core/runtime.sh"
|
||||
source "$PROJECT_DIR/scripts/core/config.sh"
|
||||
source "$PROJECT_DIR/scripts/core/completion.sh"
|
||||
source "$PROJECT_DIR/scripts/core/proxy.sh"
|
||||
source "$PROJECT_DIR/scripts/core/update.sh"
|
||||
source "$PROJECT_DIR/scripts/init/systemd.sh"
|
||||
@@ -42,6 +43,7 @@ Usage:
|
||||
status 🔍️ 查看状态总览
|
||||
boot 🚦 管理开机代理接管
|
||||
log/logs 📜 查看日志
|
||||
completion 💡 导出 Bash / Zsh 补全脚本
|
||||
|
||||
💡 更多高级能力:clashctl help advanced
|
||||
EOF
|
||||
@@ -71,6 +73,7 @@ usage_advanced() {
|
||||
boot proxy on|off|status 📜 仅管理开机代理保持
|
||||
upgrade 🚀 升级当前或指定内核
|
||||
update 🔄 更新项目代码
|
||||
completion bash|zsh 💡 导出 Shell 补全脚本
|
||||
dev reset 🧪 恢复到安装前状态(保留项目目录和已下载文件)
|
||||
|
||||
📌 Advanced Examples:
|
||||
@@ -2976,6 +2979,7 @@ cmd_ui_help_summary() {
|
||||
printf ' %-18s %s\n' "clashctl sub" "🧩 订阅高级管理(启用 / 禁用 / 重命名 / 删除)"
|
||||
printf ' %-18s %s\n' "clashctl upgrade" "🚀 升级当前或指定内核"
|
||||
printf ' %-18s %s\n' "clashctl update" "🔄 更新项目代码"
|
||||
printf ' %-18s %s\n' "clashctl completion" "💡 导出 Bash / Zsh 补全脚本"
|
||||
echo "📜 日志"
|
||||
printf ' %-18s %s\n' "clashctl doctor" "🩺 诊断面板"
|
||||
printf ' %-18s %s\n' "clashctl log/logs" "📜 查看日志"
|
||||
@@ -7275,6 +7279,7 @@ case "$cmd" in
|
||||
proxy) cmd_proxy "$@" ;;
|
||||
upgrade) cmd_upgrade "$@" ;;
|
||||
update) cmd_update "$@" ;;
|
||||
completion) cmd_completion "$@" ;;
|
||||
start-direct) cmd_start_direct "$@" ;;
|
||||
stop-direct) cmd_stop_direct "$@" ;;
|
||||
restart-direct) cmd_restart_direct "$@" ;;
|
||||
|
||||
+58
-1
@@ -2307,6 +2307,30 @@ alias_source_file() {
|
||||
echo "$PROJECT_DIR/scripts/core/alias.sh"
|
||||
}
|
||||
|
||||
completion_dir() {
|
||||
if [ "$INSTALL_SCOPE" = "system" ]; then
|
||||
echo "/etc/profile.d"
|
||||
else
|
||||
echo "$HOME/.config/clash-for-linux"
|
||||
fi
|
||||
}
|
||||
|
||||
bash_completion_entry_file() {
|
||||
if [ "$INSTALL_SCOPE" = "system" ]; then
|
||||
echo "$(completion_dir)/clash-for-linux-completion.bash"
|
||||
else
|
||||
echo "$(completion_dir)/completion.bash"
|
||||
fi
|
||||
}
|
||||
|
||||
zsh_completion_entry_file() {
|
||||
if [ "$INSTALL_SCOPE" = "system" ]; then
|
||||
echo "$(completion_dir)/clash-for-linux-completion.zsh"
|
||||
else
|
||||
echo "$(completion_dir)/completion.zsh"
|
||||
fi
|
||||
}
|
||||
|
||||
clashctl_entry_target() {
|
||||
echo "$(command_install_dir)/clashctl"
|
||||
}
|
||||
@@ -2411,12 +2435,14 @@ cleanup_legacy_shell_entries() {
|
||||
}
|
||||
|
||||
install_shell_alias_entry() {
|
||||
local profile_file alias_file shell_rc
|
||||
local profile_file alias_file shell_rc bash_completion_file zsh_completion_file
|
||||
|
||||
cleanup_legacy_shell_entries
|
||||
|
||||
profile_file="$(profile_entry_file)"
|
||||
alias_file="$(alias_source_file)"
|
||||
bash_completion_file="$(bash_completion_entry_file)"
|
||||
zsh_completion_file="$(zsh_completion_entry_file)"
|
||||
|
||||
mkdir -p "$(dirname "$profile_file")"
|
||||
[ -f "$alias_file" ] || die "未找到 alias 脚本:$alias_file"
|
||||
@@ -2430,6 +2456,18 @@ if [ -n "\${BASH_VERSION:-}" ] && [ -z "\${CLASH_FOR_LINUX_SHELL_LOADED:-}" ]; t
|
||||
export CLASH_FOR_LINUX_SHELL_LOADED="1"
|
||||
source "$alias_file"
|
||||
fi
|
||||
|
||||
case "\$-" in
|
||||
*i*)
|
||||
if [ -n "\${BASH_VERSION:-}" ] && [ -z "\${CLASH_FOR_LINUX_BASH_COMPLETION_LOADED:-}" ] && [ -f "$bash_completion_file" ]; then
|
||||
export CLASH_FOR_LINUX_BASH_COMPLETION_LOADED="1"
|
||||
source "$bash_completion_file"
|
||||
elif [ -n "\${ZSH_VERSION:-}" ] && [ -z "\${CLASH_FOR_LINUX_ZSH_COMPLETION_LOADED:-}" ] && [ -f "$zsh_completion_file" ]; then
|
||||
export CLASH_FOR_LINUX_ZSH_COMPLETION_LOADED="1"
|
||||
source "$zsh_completion_file"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
EOF
|
||||
chmod +x "$profile_file"
|
||||
|
||||
@@ -2440,6 +2478,21 @@ EOF
|
||||
install_alias_command_wrappers
|
||||
}
|
||||
|
||||
install_clashctl_completion() {
|
||||
local bash_target zsh_target
|
||||
|
||||
bash_target="$(bash_completion_entry_file)"
|
||||
zsh_target="$(zsh_completion_entry_file)"
|
||||
|
||||
mkdir -p "$(dirname "$bash_target")"
|
||||
mkdir -p "$(dirname "$zsh_target")"
|
||||
|
||||
bash "$PROJECT_DIR/scripts/core/clashctl.sh" completion bash > "$bash_target"
|
||||
bash "$PROJECT_DIR/scripts/core/clashctl.sh" completion zsh > "$zsh_target"
|
||||
|
||||
chmod +x "$bash_target" "$zsh_target" 2>/dev/null || true
|
||||
}
|
||||
|
||||
remove_clashctl_entry() {
|
||||
rm -f "$(clashctl_entry_target)" "$(clashctl_bin_entry_target)" 2>/dev/null || true
|
||||
remove_alias_command_wrappers
|
||||
@@ -2461,6 +2514,10 @@ remove_shell_alias_entry() {
|
||||
fi
|
||||
}
|
||||
|
||||
remove_clashctl_completion() {
|
||||
rm -f "$(bash_completion_entry_file)" "$(zsh_completion_entry_file)" 2>/dev/null || true
|
||||
}
|
||||
|
||||
install_has_subscription() {
|
||||
[ -n "$(subscription_url 2>/dev/null || true)" ]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,419 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
completion_emit_script_body() {
|
||||
printf '_clash_for_linux_project_dir=%q\n' "$PROJECT_DIR"
|
||||
cat <<'EOF'
|
||||
_clash_for_linux_runtime_dir="${_clash_for_linux_project_dir}/runtime"
|
||||
_clash_for_linux_subscription_file="${_clash_for_linux_runtime_dir}/subscriptions.yaml"
|
||||
_clash_for_linux_mixin_file="${_clash_for_linux_runtime_dir}/mixin.yaml"
|
||||
_clash_for_linux_local_subscription_dir="${_clash_for_linux_runtime_dir}/subscriptions"
|
||||
_clash_for_linux_yq_bin="${_clash_for_linux_runtime_dir}/bin/yq"
|
||||
|
||||
# Hard constraints for completion:
|
||||
# - local-only and offline
|
||||
# - no controller or network access
|
||||
# - low-latency best effort with immediate silent fallback
|
||||
# - skip YAML-based dynamic completion when yq is missing or fails
|
||||
|
||||
_clash_for_linux_add_matches() {
|
||||
local cur="$1"
|
||||
local candidate
|
||||
shift
|
||||
|
||||
for candidate in "$@"; do
|
||||
[ -n "${candidate:-}" ] || continue
|
||||
if [ -z "$cur" ] || [ "${candidate:0:${#cur}}" = "$cur" ]; then
|
||||
COMPREPLY+=("$candidate")
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
_clash_for_linux_add_stream_matches() {
|
||||
local cur="$1"
|
||||
local candidate
|
||||
|
||||
while IFS= read -r candidate; do
|
||||
[ -n "${candidate:-}" ] || continue
|
||||
[ "$candidate" = "null" ] && continue
|
||||
if [ -z "$cur" ] || [ "${candidate:0:${#cur}}" = "$cur" ]; then
|
||||
COMPREPLY+=("$candidate")
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
_clash_for_linux_add_subscription_matches() {
|
||||
local cur="$1"
|
||||
|
||||
[ -x "$_clash_for_linux_yq_bin" ] || return 0
|
||||
[ -s "$_clash_for_linux_subscription_file" ] || return 0
|
||||
|
||||
_clash_for_linux_add_stream_matches "$cur" < <(
|
||||
"$_clash_for_linux_yq_bin" eval '.sources | keys | .[]' "$_clash_for_linux_subscription_file" 2>/dev/null
|
||||
)
|
||||
}
|
||||
|
||||
_clash_for_linux_add_relay_matches() {
|
||||
local cur="$1"
|
||||
|
||||
[ -x "$_clash_for_linux_yq_bin" ] || return 0
|
||||
[ -s "$_clash_for_linux_mixin_file" ] || return 0
|
||||
|
||||
_clash_for_linux_add_stream_matches "$cur" < <(
|
||||
"$_clash_for_linux_yq_bin" eval '(.append["proxy-groups"] // [])[] | select(.type == "relay") | .name' "$_clash_for_linux_mixin_file" 2>/dev/null
|
||||
)
|
||||
}
|
||||
|
||||
_clash_for_linux_add_local_subscription_matches() {
|
||||
local cur="$1"
|
||||
local path
|
||||
|
||||
[ -d "$_clash_for_linux_local_subscription_dir" ] || return 0
|
||||
|
||||
while IFS= read -r path; do
|
||||
[ -n "${path:-}" ] || continue
|
||||
if [ -z "$cur" ] || [ "${path:0:${#cur}}" = "$cur" ]; then
|
||||
COMPREPLY+=("$path")
|
||||
fi
|
||||
done < <(
|
||||
for path in "$_clash_for_linux_local_subscription_dir"/*; do
|
||||
[ -f "$path" ] || continue
|
||||
printf '%s\n' "${path##*/}"
|
||||
done 2>/dev/null
|
||||
)
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_add() {
|
||||
local cur="$1"
|
||||
local rel_index="$2"
|
||||
local arg1="${3:-}"
|
||||
|
||||
COMPREPLY=()
|
||||
|
||||
if [ "$rel_index" -eq 1 ]; then
|
||||
_clash_for_linux_add_matches "$cur" local
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$arg1" = "local" ]; then
|
||||
_clash_for_linux_add_local_subscription_matches "$cur"
|
||||
fi
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_use() {
|
||||
local cur="$1"
|
||||
|
||||
COMPREPLY=()
|
||||
_clash_for_linux_add_matches "$cur" --recommend -r --verbose -v
|
||||
|
||||
case "$cur" in
|
||||
-*) return 0 ;;
|
||||
esac
|
||||
|
||||
_clash_for_linux_add_subscription_matches "$cur"
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_health() {
|
||||
local cur="$1"
|
||||
|
||||
COMPREPLY=()
|
||||
_clash_for_linux_add_matches "$cur" --verbose -v
|
||||
|
||||
case "$cur" in
|
||||
-*) return 0 ;;
|
||||
esac
|
||||
|
||||
_clash_for_linux_add_subscription_matches "$cur"
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_status() {
|
||||
local cur="$1"
|
||||
|
||||
COMPREPLY=()
|
||||
_clash_for_linux_add_matches "$cur" --verbose -v
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_boot() {
|
||||
local cur="$1"
|
||||
local rel_index="$2"
|
||||
local arg1="${3:-}"
|
||||
|
||||
COMPREPLY=()
|
||||
|
||||
if [ "$rel_index" -eq 1 ]; then
|
||||
_clash_for_linux_add_matches "$cur" on off status runtime proxy help -h --help
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "$arg1" in
|
||||
runtime|proxy)
|
||||
if [ "$rel_index" -eq 2 ]; then
|
||||
_clash_for_linux_add_matches "$cur" on off status
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_config() {
|
||||
local cur="$1"
|
||||
local rel_index="$2"
|
||||
local arg1="${3:-}"
|
||||
|
||||
COMPREPLY=()
|
||||
|
||||
if [ "$rel_index" -eq 1 ]; then
|
||||
_clash_for_linux_add_matches "$cur" show explain regen kernel
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$arg1" = "kernel" ] && [ "$rel_index" -eq 2 ]; then
|
||||
_clash_for_linux_add_matches "$cur" mihomo clash
|
||||
fi
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_mixin() {
|
||||
local cur="$1"
|
||||
local rel_index="$2"
|
||||
|
||||
COMPREPLY=()
|
||||
|
||||
if [ "$rel_index" -eq 1 ]; then
|
||||
_clash_for_linux_add_matches "$cur" edit raw runtime help -e -c -r --edit --raw --runtime -h --help
|
||||
fi
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_relay() {
|
||||
local cur="$1"
|
||||
local rel_index="$2"
|
||||
local arg1="${3:-}"
|
||||
|
||||
COMPREPLY=()
|
||||
|
||||
if [ "$rel_index" -eq 1 ]; then
|
||||
_clash_for_linux_add_matches "$cur" add list ls remove rm delete help -h --help
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "$arg1" in
|
||||
remove|rm|delete)
|
||||
if [ "$rel_index" -eq 2 ]; then
|
||||
_clash_for_linux_add_relay_matches "$cur"
|
||||
fi
|
||||
;;
|
||||
add)
|
||||
_clash_for_linux_add_matches "$cur" --domain --match
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_sub() {
|
||||
local cur="$1"
|
||||
local rel_index="$2"
|
||||
local arg1="${3:-}"
|
||||
|
||||
COMPREPLY=()
|
||||
|
||||
if [ "$rel_index" -eq 1 ]; then
|
||||
_clash_for_linux_add_matches "$cur" list use set enable disable rename remove rm del health help -h --help
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "$arg1" in
|
||||
use|enable|disable|remove|rm|del)
|
||||
if [ "$rel_index" -eq 2 ]; then
|
||||
_clash_for_linux_add_subscription_matches "$cur"
|
||||
fi
|
||||
;;
|
||||
rename)
|
||||
if [ "$rel_index" -eq 2 ]; then
|
||||
_clash_for_linux_add_subscription_matches "$cur"
|
||||
fi
|
||||
;;
|
||||
health)
|
||||
_clash_for_linux_add_matches "$cur" --verbose -v
|
||||
if [ "$rel_index" -eq 2 ]; then
|
||||
case "$cur" in
|
||||
-*) return 0 ;;
|
||||
esac
|
||||
_clash_for_linux_add_subscription_matches "$cur"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_tun() {
|
||||
local cur="$1"
|
||||
local rel_index="$2"
|
||||
|
||||
COMPREPLY=()
|
||||
|
||||
if [ "$rel_index" -eq 1 ]; then
|
||||
_clash_for_linux_add_matches "$cur" status on off doctor
|
||||
fi
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_upgrade() {
|
||||
local cur="$1"
|
||||
|
||||
COMPREPLY=()
|
||||
_clash_for_linux_add_matches "$cur" mihomo clash -v --verbose
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_update() {
|
||||
local cur="$1"
|
||||
|
||||
COMPREPLY=()
|
||||
_clash_for_linux_add_matches "$cur" --force --regenerate
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_dev() {
|
||||
local cur="$1"
|
||||
local rel_index="$2"
|
||||
|
||||
COMPREPLY=()
|
||||
|
||||
if [ "$rel_index" -eq 1 ]; then
|
||||
_clash_for_linux_add_matches "$cur" reset
|
||||
fi
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_completion() {
|
||||
local cur="$1"
|
||||
local rel_index="$2"
|
||||
|
||||
COMPREPLY=()
|
||||
|
||||
if [ "$rel_index" -eq 1 ]; then
|
||||
_clash_for_linux_add_matches "$cur" bash zsh
|
||||
fi
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_help() {
|
||||
local cur="$1"
|
||||
local rel_index="$2"
|
||||
|
||||
COMPREPLY=()
|
||||
|
||||
if [ "$rel_index" -eq 1 ]; then
|
||||
_clash_for_linux_add_matches "$cur" advanced
|
||||
fi
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_top_level() {
|
||||
local cur="$1"
|
||||
|
||||
COMPREPLY=()
|
||||
_clash_for_linux_add_matches "$cur" \
|
||||
add use ls health select on off status status-next \
|
||||
boot log logs doctor ui secret tun dev config mixin \
|
||||
relay profile sub proxy upgrade update completion help \
|
||||
-h --help
|
||||
}
|
||||
|
||||
_clash_for_linux_complete_command() {
|
||||
local root cur canonical rel_index
|
||||
local arg1="" arg2="" arg3=""
|
||||
|
||||
root="${COMP_WORDS[0]##*/}"
|
||||
cur="${COMP_WORDS[COMP_CWORD]:-}"
|
||||
|
||||
case "$root" in
|
||||
clashctl)
|
||||
if [ "$COMP_CWORD" -eq 1 ]; then
|
||||
_clash_for_linux_complete_top_level "$cur"
|
||||
return 0
|
||||
fi
|
||||
canonical="${COMP_WORDS[1]:-}"
|
||||
rel_index=$((COMP_CWORD - 1))
|
||||
arg1="${COMP_WORDS[2]:-}"
|
||||
arg2="${COMP_WORDS[3]:-}"
|
||||
arg3="${COMP_WORDS[4]:-}"
|
||||
;;
|
||||
clashrelay)
|
||||
canonical="relay"
|
||||
rel_index=$COMP_CWORD
|
||||
arg1="${COMP_WORDS[1]:-}"
|
||||
arg2="${COMP_WORDS[2]:-}"
|
||||
arg3="${COMP_WORDS[3]:-}"
|
||||
;;
|
||||
clashmixin)
|
||||
canonical="mixin"
|
||||
rel_index=$COMP_CWORD
|
||||
arg1="${COMP_WORDS[1]:-}"
|
||||
;;
|
||||
clashsecret)
|
||||
canonical="secret"
|
||||
rel_index=$COMP_CWORD
|
||||
arg1="${COMP_WORDS[1]:-}"
|
||||
;;
|
||||
clashupgrade)
|
||||
canonical="upgrade"
|
||||
rel_index=$COMP_CWORD
|
||||
arg1="${COMP_WORDS[1]:-}"
|
||||
;;
|
||||
clashtun)
|
||||
canonical="tun"
|
||||
rel_index=$COMP_CWORD
|
||||
arg1="${COMP_WORDS[1]:-}"
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=()
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$canonical" in
|
||||
add) _clash_for_linux_complete_add "$cur" "$rel_index" "$arg1" ;;
|
||||
use) _clash_for_linux_complete_use "$cur" ;;
|
||||
health) _clash_for_linux_complete_health "$cur" ;;
|
||||
status) _clash_for_linux_complete_status "$cur" ;;
|
||||
boot) _clash_for_linux_complete_boot "$cur" "$rel_index" "$arg1" ;;
|
||||
config) _clash_for_linux_complete_config "$cur" "$rel_index" "$arg1" ;;
|
||||
mixin) _clash_for_linux_complete_mixin "$cur" "$rel_index" ;;
|
||||
relay) _clash_for_linux_complete_relay "$cur" "$rel_index" "$arg1" ;;
|
||||
sub) _clash_for_linux_complete_sub "$cur" "$rel_index" "$arg1" ;;
|
||||
tun) _clash_for_linux_complete_tun "$cur" "$rel_index" ;;
|
||||
upgrade) _clash_for_linux_complete_upgrade "$cur" ;;
|
||||
update) _clash_for_linux_complete_update "$cur" ;;
|
||||
dev) _clash_for_linux_complete_dev "$cur" "$rel_index" ;;
|
||||
completion) _clash_for_linux_complete_completion "$cur" "$rel_index" ;;
|
||||
help) _clash_for_linux_complete_help "$cur" "$rel_index" ;;
|
||||
*)
|
||||
COMPREPLY=()
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
complete -F _clash_for_linux_complete_command clashctl
|
||||
complete -F _clash_for_linux_complete_command clashrelay
|
||||
complete -F _clash_for_linux_complete_command clashmixin
|
||||
complete -F _clash_for_linux_complete_command clashsecret
|
||||
complete -F _clash_for_linux_complete_command clashupgrade
|
||||
complete -F _clash_for_linux_complete_command clashtun
|
||||
EOF
|
||||
}
|
||||
|
||||
completion_emit_bash_script() {
|
||||
completion_emit_script_body
|
||||
}
|
||||
|
||||
completion_emit_zsh_script() {
|
||||
cat <<'EOF'
|
||||
autoload -Uz bashcompinit 2>/dev/null || return 0
|
||||
bashcompinit >/dev/null 2>&1 || return 0
|
||||
EOF
|
||||
completion_emit_script_body
|
||||
}
|
||||
|
||||
cmd_completion() {
|
||||
case "${1:-}" in
|
||||
bash)
|
||||
completion_emit_bash_script
|
||||
;;
|
||||
zsh)
|
||||
completion_emit_zsh_script
|
||||
;;
|
||||
*)
|
||||
die_usage "completion 参数不合法" "clashctl completion bash|zsh"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@@ -41,6 +41,7 @@ detect_install_scope auto
|
||||
service_stop || true
|
||||
remove_runtime_entry || true
|
||||
remove_clashctl_entry || true
|
||||
remove_clashctl_completion || true
|
||||
remove_shell_alias_entry || true
|
||||
clear_shell_proxy_persist_state || true
|
||||
|
||||
|
||||
Reference in New Issue
Block a user