mirror of
https://github.com/wnlen/clash-for-linux.git
synced 2026-10-10 04:03:04 +08:00
fix(ui): restore utf-8 encoding and remove mojibake in select output
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{sh,yaml,yml,env,md}]
|
||||||
|
charset = utf-8
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
*.sh text eol=lf
|
*.sh text eol=lf working-tree-encoding=UTF-8
|
||||||
*.yaml text eol=lf
|
*.yaml text eol=lf
|
||||||
*.yml text eol=lf
|
*.yml text eol=lf
|
||||||
*.env text eol=lf
|
*.env text eol=lf
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
export LANG=C.UTF-8
|
||||||
|
export LC_ALL=C.UTF-8
|
||||||
|
|
||||||
|
if grep -R -n '馃\|鑺\|绛\|閫\|璇\|摝\|殌' scripts/; then
|
||||||
|
echo "Detected mojibake text in scripts/" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
python3 - <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
|
|
||||||
|
bad = []
|
||||||
|
for path in Path("scripts").rglob("*.sh"):
|
||||||
|
data = path.read_bytes()
|
||||||
|
if data.startswith(b"\xef\xbb\xbf"):
|
||||||
|
bad.append(f"{path}: UTF-8 BOM is not allowed")
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
data.decode("utf-8")
|
||||||
|
except UnicodeDecodeError as exc:
|
||||||
|
bad.append(f"{path}: invalid UTF-8 ({exc})")
|
||||||
|
|
||||||
|
if bad:
|
||||||
|
print("\n".join(bad), file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
PY
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
name: Text Encoding
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
utf8:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
LANG: C.UTF-8
|
||||||
|
LC_ALL: C.UTF-8
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Check mojibake and UTF-8 encoding
|
||||||
|
run: bash .github/scripts/check-text-encoding.sh
|
||||||
+51
-51
@@ -6962,13 +6962,13 @@ print_select_feedback() {
|
|||||||
|
|
||||||
current="$(proxy_group_current_display "$group" 2>/dev/null || true)"
|
current="$(proxy_group_current_display "$group" 2>/dev/null || true)"
|
||||||
|
|
||||||
ui_title "馃殌 鑺傜偣鍒囨崲瀹屾垚"
|
ui_title "🚀 节点切换完成"
|
||||||
|
|
||||||
if [ -n "${group:-}" ]; then
|
if [ -n "${group:-}" ]; then
|
||||||
ui_kv "馃摝" "宸插垏鎹㈢瓥鐣ョ粍" "$group"
|
ui_kv "📦" "已切换策略组" "$group"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ui_kv "馃殌" "褰撳墠鑺傜偣" "${current:-<unknown>}"
|
ui_kv "🚀" "当前节点" "${current:-<unknown>}"
|
||||||
|
|
||||||
main_feedback_runtime_state
|
main_feedback_runtime_state
|
||||||
ui_next "clashctl status"
|
ui_next "clashctl status"
|
||||||
@@ -6986,12 +6986,12 @@ status_current_proxy_brief() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "鏈惎鍔?"
|
echo "未启动"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! proxy_controller_reachable 2>/dev/null; then
|
if ! proxy_controller_reachable 2>/dev/null; then
|
||||||
echo "鎺у埗鍣ㄤ笉鍙闂?"
|
echo "控制器不可访问"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -7009,7 +7009,7 @@ status_current_proxy_brief() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "鏆傛棤鍙垏鎹㈢瓥鐣ョ粍"
|
echo "暂无可切换策略组"
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_proxy_groups() {
|
cmd_proxy_groups() {
|
||||||
@@ -7018,25 +7018,25 @@ cmd_proxy_groups() {
|
|||||||
prepare
|
prepare
|
||||||
|
|
||||||
if ! status_is_running; then
|
if ! status_is_running; then
|
||||||
die_state "浠g悊鍐呮牳鏈繍琛?" "clashon"
|
die_state "代理内核未运行" "clashon"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! proxy_controller_reachable 2>/dev/null; then
|
if ! proxy_controller_reachable 2>/dev/null; then
|
||||||
die_state "鎺у埗鍣ㄤ笉鍙闂?" "clashctl doctor"
|
die_state "控制器不可访问" "clashctl doctor"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ui_title "馃摝 绛栫暐缁勫垪琛?"
|
ui_title "📦 策略组列表"
|
||||||
echo " 馃摝 鍚嶇О 绫诲瀷 褰撳墠鑺傜偣"
|
echo " 📦 名称 类型 当前节点"
|
||||||
while IFS= read -r group; do
|
while IFS= read -r group; do
|
||||||
[ -n "${group:-}" ] || continue
|
[ -n "${group:-}" ] || continue
|
||||||
found="true"
|
found="true"
|
||||||
type="$(proxy_group_type "$group" 2>/dev/null || echo "unknown")"
|
type="$(proxy_group_type "$group" 2>/dev/null || echo "unknown")"
|
||||||
current="$(proxy_group_current_display "$group" 2>/dev/null || true)"
|
current="$(proxy_group_current_display "$group" 2>/dev/null || true)"
|
||||||
printf ' 馃摝 %-20s %-12s %s\n' "$group" "$type" "${current:-<unknown>}"
|
printf ' 📦 %-20s %-12s %s\n' "$group" "$type" "${current:-<unknown>}"
|
||||||
done < <(proxy_group_list)
|
done < <(proxy_group_list)
|
||||||
|
|
||||||
if [ "$found" != "true" ]; then
|
if [ "$found" != "true" ]; then
|
||||||
echo " 馃摥 鏆傛棤鍙垏鎹㈢瓥鐣ョ粍"
|
echo " 📭 暂无可切换策略组"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ui_blank
|
ui_blank
|
||||||
@@ -7050,33 +7050,33 @@ cmd_proxy_current() {
|
|||||||
prepare
|
prepare
|
||||||
|
|
||||||
if ! status_is_running; then
|
if ! status_is_running; then
|
||||||
die_state "浠g悊鍐呮牳鏈繍琛?" "clashon"
|
die_state "代理内核未运行" "clashon"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! proxy_controller_reachable 2>/dev/null; then
|
if ! proxy_controller_reachable 2>/dev/null; then
|
||||||
die_state "鎺у埗鍣ㄤ笉鍙闂?" "clashctl doctor"
|
die_state "控制器不可访问" "clashctl doctor"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${1:-}" ]; then
|
if [ -n "${1:-}" ]; then
|
||||||
group="$1"
|
group="$1"
|
||||||
current="$(proxy_group_current_display "$group" 2>/dev/null || true)"
|
current="$(proxy_group_current_display "$group" 2>/dev/null || true)"
|
||||||
ui_title "馃殌 褰撳墠鑺傜偣"
|
ui_title "🚀 当前节点"
|
||||||
ui_kv "馃摝" "绛栫暐缁?" "$group"
|
ui_kv "📦" "策略组" "$group"
|
||||||
ui_kv "馃殌" "褰撳墠鑺傜偣" "${current:-<unknown>}"
|
ui_kv "🚀" "当前节点" "${current:-<unknown>}"
|
||||||
ui_blank
|
ui_blank
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ui_title "馃殌 褰撳墠鑺傜偣鎬昏"
|
ui_title "🚀 当前节点总览"
|
||||||
while IFS= read -r group; do
|
while IFS= read -r group; do
|
||||||
[ -n "${group:-}" ] || continue
|
[ -n "${group:-}" ] || continue
|
||||||
found="true"
|
found="true"
|
||||||
current="$(proxy_group_current_display "$group" 2>/dev/null || true)"
|
current="$(proxy_group_current_display "$group" 2>/dev/null || true)"
|
||||||
printf ' 馃殌 %-20s %s\n' "$group" "${current:-<unknown>}"
|
printf ' 🚀 %-20s %s\n' "$group" "${current:-<unknown>}"
|
||||||
done < <(proxy_group_list)
|
done < <(proxy_group_list)
|
||||||
|
|
||||||
if [ "$found" != "true" ]; then
|
if [ "$found" != "true" ]; then
|
||||||
echo " 馃摥 鏆傛棤鍙垏鎹㈢瓥鐣ョ粍"
|
echo " 📭 暂无可切换策略组"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ui_blank
|
ui_blank
|
||||||
@@ -7087,35 +7087,35 @@ cmd_proxy_nodes() {
|
|||||||
local current node found="false"
|
local current node found="false"
|
||||||
|
|
||||||
prepare
|
prepare
|
||||||
[ -n "${group:-}" ] || die "璇蜂娇鐢?clashctl select 鍒囨崲鑺傜偣"
|
[ -n "${group:-}" ] || die "请使用 clashctl select 切换节点"
|
||||||
|
|
||||||
if ! status_is_running; then
|
if ! status_is_running; then
|
||||||
die_state "浠g悊鍐呮牳鏈繍琛?" "clashon"
|
die_state "代理内核未运行" "clashon"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! proxy_controller_reachable 2>/dev/null; then
|
if ! proxy_controller_reachable 2>/dev/null; then
|
||||||
die_state "鎺у埗鍣ㄤ笉鍙闂?" "clashctl doctor"
|
die_state "控制器不可访问" "clashctl doctor"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
current="$(proxy_group_current_display "$group" 2>/dev/null || true)"
|
current="$(proxy_group_current_display "$group" 2>/dev/null || true)"
|
||||||
|
|
||||||
ui_title "馃殌 鍊欓€夎妭鐐瑰垪琛?"
|
ui_title "🚀 候选节点列表"
|
||||||
ui_kv "馃摝" "绛栫暐缁?" "$group"
|
ui_kv "📦" "策略组" "$group"
|
||||||
ui_kv "馃殌" "褰撳墠鑺傜偣" "${current:-<unknown>}"
|
ui_kv "🚀" "当前节点" "${current:-<unknown>}"
|
||||||
ui_blank
|
ui_blank
|
||||||
|
|
||||||
while IFS= read -r node; do
|
while IFS= read -r node; do
|
||||||
[ -n "${node:-}" ] || continue
|
[ -n "${node:-}" ] || continue
|
||||||
found="true"
|
found="true"
|
||||||
if [ "$node" = "$current" ]; then
|
if [ "$node" = "$current" ]; then
|
||||||
printf ' * 馃殌 %s\n' "$node"
|
printf ' * 🚀 %s\n' "$node"
|
||||||
else
|
else
|
||||||
printf ' 馃殌 %s\n' "$node"
|
printf ' 🚀 %s\n' "$node"
|
||||||
fi
|
fi
|
||||||
done < <(proxy_group_selectable_nodes "$group")
|
done < <(proxy_group_selectable_nodes "$group")
|
||||||
|
|
||||||
if [ "$found" != "true" ]; then
|
if [ "$found" != "true" ]; then
|
||||||
echo " 馃摥 该策略组暂无可切换真实节点"
|
echo " 📭 该策略组暂无可切换真实节点"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ui_blank
|
ui_blank
|
||||||
@@ -7133,7 +7133,7 @@ proxy_pick_group_for_select() {
|
|||||||
groups+=("$group")
|
groups+=("$group")
|
||||||
done < <(proxy_group_display_list)
|
done < <(proxy_group_display_list)
|
||||||
|
|
||||||
for group in "鑺傜偣閫夋嫨" "鑷姩閫夋嫨"; do
|
for group in "节点选择" "自动选择"; do
|
||||||
if printf '%s\n' "${groups[@]}" | grep -Fxq "$group"; then
|
if printf '%s\n' "${groups[@]}" | grep -Fxq "$group"; then
|
||||||
ordered_groups+=("$group")
|
ordered_groups+=("$group")
|
||||||
fi
|
fi
|
||||||
@@ -7141,7 +7141,7 @@ proxy_pick_group_for_select() {
|
|||||||
|
|
||||||
for group in "${groups[@]}"; do
|
for group in "${groups[@]}"; do
|
||||||
case "$group" in
|
case "$group" in
|
||||||
鑺傜偣閫夋嫨|鑷姩閫夋嫨)
|
节点选择|自动选择)
|
||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -7151,18 +7151,18 @@ proxy_pick_group_for_select() {
|
|||||||
groups=("${ordered_groups[@]}")
|
groups=("${ordered_groups[@]}")
|
||||||
|
|
||||||
count="${#groups[@]}"
|
count="${#groups[@]}"
|
||||||
[ "$count" -gt 0 ] || die "馃摥 鏆傛棤鍙垏鎹㈢瓥鐣ョ粍"
|
[ "$count" -gt 0 ] || die "📭 暂无可切换策略组"
|
||||||
|
|
||||||
echo "馃摝 璇烽€夋嫨绛栫暐缁勶細" >&2
|
echo "📦 请选择策略组:" >&2
|
||||||
echo "馃挕 閫氬父浼樺厛閫夋嫨锛氳妭鐐归€夋嫨" >&2
|
echo "💡 通常优先选择:节点选择" >&2
|
||||||
idx=1
|
idx=1
|
||||||
for group in "${groups[@]}"; do
|
for group in "${groups[@]}"; do
|
||||||
current="$(proxy_group_current_display "$group" 2>/dev/null || true)"
|
current="$(proxy_group_current_display "$group" 2>/dev/null || true)"
|
||||||
type="$(proxy_group_type_label "$group" 2>/dev/null || echo "unknown")"
|
type="$(proxy_group_type_label "$group" 2>/dev/null || echo "unknown")"
|
||||||
printf ' %s) 馃摝 %s [%s] -> 馃殌 %s\n' "$idx" "$group" "$type" "${current:-<unknown>}" >&2
|
printf ' %s) 📦 %s [%s] -> 🚀 %s\n' "$idx" "$group" "$type" "${current:-<unknown>}" >&2
|
||||||
idx=$((idx + 1))
|
idx=$((idx + 1))
|
||||||
done
|
done
|
||||||
echo " q) 閫€鍑?" >&2
|
echo " q) 退出" >&2
|
||||||
echo >&2
|
echo >&2
|
||||||
|
|
||||||
idx="$(proxy_pick_index "$count")" || return 1
|
idx="$(proxy_pick_index "$count")" || return 1
|
||||||
@@ -7178,15 +7178,15 @@ proxy_select_interactive_guarded() {
|
|||||||
prepare
|
prepare
|
||||||
|
|
||||||
if ! status_is_running; then
|
if ! status_is_running; then
|
||||||
die_state "浠g悊鍐呮牳鏈繍琛?" "clashon"
|
die_state "代理内核未运行" "clashon"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! proxy_controller_reachable 2>/dev/null; then
|
if ! proxy_controller_reachable 2>/dev/null; then
|
||||||
die_state "鎺у埗鍣ㄤ笉鍙闂?" "clashctl doctor"
|
die_state "控制器不可访问" "clashctl doctor"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "${group:-}" ]; then
|
if [ -z "${group:-}" ]; then
|
||||||
ui_title "馃殌 鑺傜偣鍒囨崲"
|
ui_title "🚀 节点切换"
|
||||||
choose_group="true"
|
choose_group="true"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -7195,7 +7195,7 @@ proxy_select_interactive_guarded() {
|
|||||||
group="$(proxy_pick_group_for_select)" || return 0
|
group="$(proxy_pick_group_for_select)" || return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
proxy_group_exists "$group" || die "绛栫暐缁勪笉瀛樺湪锛?group"
|
proxy_group_exists "$group" || die "策略组不存在:$group"
|
||||||
|
|
||||||
current="$(proxy_group_current_display "$group" 2>/dev/null || true)"
|
current="$(proxy_group_current_display "$group" 2>/dev/null || true)"
|
||||||
nodes=()
|
nodes=()
|
||||||
@@ -7207,8 +7207,8 @@ proxy_select_interactive_guarded() {
|
|||||||
count="${#nodes[@]}"
|
count="${#nodes[@]}"
|
||||||
if [ "$count" -le 0 ]; then
|
if [ "$count" -le 0 ]; then
|
||||||
ui_warn "该策略组暂无可切换真实节点"
|
ui_warn "该策略组暂无可切换真实节点"
|
||||||
ui_kv "馃摝" "绛栫暐缁?" "$group"
|
ui_kv "📦" "策略组" "$group"
|
||||||
ui_kv "馃殌" "褰撳墠鑺傜偣" "${current:-<unknown>}"
|
ui_kv "🚀" "当前节点" "${current:-<unknown>}"
|
||||||
ui_blank
|
ui_blank
|
||||||
if [ "$choose_group" = "true" ]; then
|
if [ "$choose_group" = "true" ]; then
|
||||||
group=""
|
group=""
|
||||||
@@ -7220,25 +7220,25 @@ proxy_select_interactive_guarded() {
|
|||||||
total_count="$(select_total_node_count 2>/dev/null || true)"
|
total_count="$(select_total_node_count 2>/dev/null || true)"
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "馃摝 褰撳墠绛栫暐缁勶細$group"
|
echo "📦 当前策略组:$group"
|
||||||
echo "馃殌 褰撳墠鑺傜偣锛?${current:-<unknown>}"
|
echo "🚀 当前节点:${current:-<unknown>}"
|
||||||
echo "馃摝 褰撳墠绛栫暐缁勫€欓€夋暟锛?count"
|
echo "📦 当前策略组候选数:$count"
|
||||||
[ -n "${total_count:-}" ] && echo "馃敘 鍏ㄩ儴鑺傜偣鎬绘暟锛?total_count"
|
[ -n "${total_count:-}" ] && echo "🔢 全部节点总数:$total_count"
|
||||||
echo "鈩癸笍 浠ヤ笅浠呮樉绀哄綋鍓嶇瓥鐣ョ粍鍙垏鎹㈣妭鐐?"
|
echo "ℹ️ 以下仅显示当前策略组可切换节点"
|
||||||
echo
|
echo
|
||||||
echo "馃殌 璇烽€夋嫨鑺傜偣锛?"
|
echo "🚀 请选择节点:"
|
||||||
|
|
||||||
idx=1
|
idx=1
|
||||||
for node in "${nodes[@]}"; do
|
for node in "${nodes[@]}"; do
|
||||||
if [ "$node" = "$current" ]; then
|
if [ "$node" = "$current" ]; then
|
||||||
printf ' %s) 馃殌 %s [褰撳墠]\n' "$idx" "$node"
|
printf ' %s) 🚀 %s [当前]\n' "$idx" "$node"
|
||||||
else
|
else
|
||||||
printf ' %s) 馃殌 %s\n' "$idx" "$node"
|
printf ' %s) 🚀 %s\n' "$idx" "$node"
|
||||||
fi
|
fi
|
||||||
idx=$((idx + 1))
|
idx=$((idx + 1))
|
||||||
done
|
done
|
||||||
|
|
||||||
echo " q) 閫€鍑?"
|
echo " q) 退出"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
idx="$(proxy_pick_index "$count")" || return 0
|
idx="$(proxy_pick_index "$count")" || return 0
|
||||||
|
|||||||
@@ -849,10 +849,10 @@ proxy_group_select() {
|
|||||||
local code response_file response_body
|
local code response_file response_body
|
||||||
local available_node found
|
local available_node found
|
||||||
|
|
||||||
[ -n "${group:-}" ] || die "绛栫暐缁勫悕绉颁笉鑳戒负绌?"
|
[ -n "${group:-}" ] || die "策略组名称不能为空"
|
||||||
[ -n "${node:-}" ] || die "鑺傜偣鍚嶇О涓嶈兘涓虹┖"
|
[ -n "${node:-}" ] || die "节点名称不能为空"
|
||||||
|
|
||||||
proxy_group_exists "$group" || die "绛栫暐缁勪笉瀛樺湪锛?group"
|
proxy_group_exists "$group" || die "策略组不存在:$group"
|
||||||
proxy_group_can_show_candidates "$group" || die "$(proxy_group_manual_pick_error_message "$group")"
|
proxy_group_can_show_candidates "$group" || die "$(proxy_group_manual_pick_error_message "$group")"
|
||||||
proxy_node_is_selectable_candidate "$node" || die "节点不是可切换节点:$node"
|
proxy_node_is_selectable_candidate "$node" || die "节点不是可切换节点:$node"
|
||||||
|
|
||||||
@@ -866,7 +866,7 @@ proxy_group_select() {
|
|||||||
done < <(proxy_group_selectable_nodes "$group")
|
done < <(proxy_group_selectable_nodes "$group")
|
||||||
|
|
||||||
if [ "$found" != "true" ]; then
|
if [ "$found" != "true" ]; then
|
||||||
die "鑺傜偣涓嶅瓨鍦ㄤ簬绛栫暐缁勪腑锛?group -> $node"
|
die "节点不存在于策略组中:$group -> $node"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
base="$(controller_api_base)"
|
base="$(controller_api_base)"
|
||||||
@@ -886,7 +886,7 @@ proxy_group_select() {
|
|||||||
if [ -n "${response_body:-}" ]; then
|
if [ -n "${response_body:-}" ]; then
|
||||||
die "controller 原始错误:$response_body"
|
die "controller 原始错误:$response_body"
|
||||||
fi
|
fi
|
||||||
die "鑺傜偣鍒囨崲澶辫触锛歝ontroller 杩斿洖 HTTP $code"
|
die "节点切换失败:controller 返回 HTTP $code"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -f "$response_file" 2>/dev/null || true
|
rm -f "$response_file" 2>/dev/null || true
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
exec bash .github/scripts/check-text-encoding.sh "$@"
|
||||||
Reference in New Issue
Block a user