Skip to content

Commit bc3143d

Browse files
committed
feat(scripts): add support for path with environment variables
Signed-off-by: wxiwnd <[email protected]>
1 parent be47adf commit bc3143d

File tree

1 file changed

+109
-2
lines changed

1 file changed

+109
-2
lines changed

scripts/bash_pinyin_completion

Lines changed: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,101 @@ fi
1212
# Backup the original function
1313
eval "function __bak_comp_compgen__call_builtin() { $(declare -f _comp_compgen__call_builtin | tail -n +2) }"
1414

15+
# Expand environment references ("$VAR", "${VAR}") inside completion prefixes
16+
__expand_env_refs() {
17+
local input="$1"
18+
# accumulate the expanded characters here
19+
local result=""
20+
local len=${#input}
21+
local i=0
22+
23+
# Walk through every character
24+
while (( i < len )); do
25+
local ch="${input:i:1}"
26+
# Preserve escaped characters verbatim
27+
# "\$HOME" stays "$HOME"
28+
if [[ "$ch" == "\\" ]]; then
29+
((i++))
30+
if (( i < len )); then
31+
result+="${input:i:1}"
32+
((i++))
33+
fi
34+
continue
35+
fi
36+
37+
# Handle environment references beginning with '$'
38+
if [[ "$ch" == '$' ]]; then
39+
((i++))
40+
if (( i >= len )); then
41+
result+='$'
42+
break
43+
fi
44+
45+
ch="${input:i:1}"
46+
# Expand braces style
47+
# "${VAR}"
48+
if [[ "$ch" == '{' ]]; then
49+
((i++))
50+
local start=$i
51+
# Consume [A-Za-z0-9_] until we hit '}' or something else
52+
while (( i < len )); do
53+
ch="${input:i:1}"
54+
if [[ "$ch" =~ [A-Za-z0-9_] ]]; then
55+
((i++))
56+
continue
57+
fi
58+
break
59+
done
60+
local var_name="${input:start:i-start}"
61+
if [[ -z "$var_name" ]]; then
62+
result+='$'
63+
result+='{'
64+
continue
65+
fi
66+
if (( i < len )) && [[ "${input:i:1}" == '}' ]]; then
67+
((i++))
68+
# ${VAR} -> ${!VAR-} returns value or empty string.
69+
result+="${!var_name-}"
70+
else
71+
result+='$'
72+
result+='{'
73+
i=$start
74+
fi
75+
continue
76+
fi
77+
78+
if [[ "$ch" =~ [A-Za-z_] ]]; then
79+
local start=$i
80+
while (( i < len )) && [[ "${input:i:1}" =~ [A-Za-z0-9_] ]]; do
81+
((i++))
82+
done
83+
local var_name="${input:start:i-start}"
84+
result+="${!var_name-}"
85+
continue
86+
fi
87+
88+
# Handle positional parameters ($1)
89+
# or a few common special vars
90+
if [[ "$ch" =~ [0-9@*#?] ]]; then
91+
local special_name="$ch"
92+
((i++))
93+
result+="${!special_name-}"
94+
continue
95+
fi
96+
97+
# Any other symbol
98+
result+='$'
99+
continue
100+
fi
101+
102+
# Normal characters are copied through.
103+
result+="$ch"
104+
((i++))
105+
done
106+
107+
printf '%s' "$result"
108+
}
109+
15110

16111
_comp_compgen__call_builtin() {
17112
__bak_comp_compgen__call_builtin "$@"
@@ -85,6 +180,18 @@ _add_completion() {
85180
fi
86181

87182
[[ "$dirpart" == "." && "${cur:0:2}" != "./" ]] && dirpart=""
183+
184+
# Expand environemnt variables
185+
# dirpart_lookup: save the true path after expanded
186+
# NOTE: in the end, the path prefix will be rollbacked to "snapshot".
187+
local dirpart_lookup="$dirpart"
188+
if [[ -n "$dirpart_lookup" && "$dirpart_lookup" == *'$'* ]]; then
189+
local expanded_lookup
190+
expanded_lookup="$(__expand_env_refs "$dirpart_lookup")"
191+
if [[ -n "$expanded_lookup" ]]; then
192+
dirpart_lookup="$expanded_lookup"
193+
fi
194+
fi
88195

89196
local savedPWD="$PWD"
90197
local resolved_dir
@@ -99,10 +206,10 @@ _add_completion() {
99206
fi
100207
done
101208

102-
if [[ -n "$dirpart" ]]; then
209+
if [[ -n "$dirpart_lookup" ]]; then
103210
# Resolve the working directory for compgen use realpath, but remember
104211
# the original textual prefix so completions can stay aligned with what the user typed.
105-
resolved_dir="$(realpath -- "$dirpart" 2>/dev/null)"
212+
resolved_dir="$(realpath -- "$dirpart_lookup" 2>/dev/null)"
106213
if [[ -d "$resolved_dir" ]]; then
107214
cd -- "$resolved_dir" 2>/dev/null || return
108215
else

0 commit comments

Comments
 (0)