@optique/core 1.0.14 → 1.0.15-dev.2777
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/completion.cjs +137 -17
- package/dist/completion.js +137 -17
- package/package.json +1 -1
package/dist/completion.cjs
CHANGED
|
@@ -67,7 +67,44 @@ const bash = {
|
|
|
67
67
|
return `
|
|
68
68
|
function _${programName} () {
|
|
69
69
|
COMPREPLY=()
|
|
70
|
-
local
|
|
70
|
+
local __raw_current="\${COMP_WORDS[COMP_CWORD]}"
|
|
71
|
+
local current="" __quote="" __char __next __index __quote_offset=0
|
|
72
|
+
local __file_mode=0
|
|
73
|
+
if [[ $(type -t compopt) == builtin ]]; then
|
|
74
|
+
compopt +o filenames 2>/dev/null || true
|
|
75
|
+
fi
|
|
76
|
+
# Dequote the shell word without evaluating filename contents. Readline
|
|
77
|
+
# returns escaped words after Tab, and users may start with an open quote.
|
|
78
|
+
for ((__index=0; __index<\${#__raw_current}; __index++)); do
|
|
79
|
+
__char="\${__raw_current:__index:1}"
|
|
80
|
+
if [[ -z "$__quote" ]]; then
|
|
81
|
+
case "$__char" in
|
|
82
|
+
\\\\) ((++__index)); current+="\${__raw_current:__index:1}" ;;
|
|
83
|
+
\\'|\\") __quote="$__char"; __quote_offset=\${#current} ;;
|
|
84
|
+
*) current+="$__char" ;;
|
|
85
|
+
esac
|
|
86
|
+
elif [[ "$__quote" == "'" ]]; then
|
|
87
|
+
if [[ "$__char" == "'" ]]; then
|
|
88
|
+
__quote=""
|
|
89
|
+
else
|
|
90
|
+
current+="$__char"
|
|
91
|
+
fi
|
|
92
|
+
else
|
|
93
|
+
case "$__char" in
|
|
94
|
+
\\") __quote="" ;;
|
|
95
|
+
\\\\)
|
|
96
|
+
__next="\${__raw_current:__index+1:1}"
|
|
97
|
+
case "$__next" in
|
|
98
|
+
\\$|\\\`|\\"|\\\\)
|
|
99
|
+
((++__index)); current+="$__next" ;;
|
|
100
|
+
*) current+="$__char" ;;
|
|
101
|
+
esac ;;
|
|
102
|
+
*) current+="$__char" ;;
|
|
103
|
+
esac
|
|
104
|
+
fi
|
|
105
|
+
done
|
|
106
|
+
local __tilde_pattern='^(~[a-zA-Z0-9_.+-]*)(/.*)$'
|
|
107
|
+
local __tilde_glob_pattern='^(~[a-zA-Z0-9_.+-]*)(/.*)?$'
|
|
71
108
|
local prev=("\${COMP_WORDS[@]:1:COMP_CWORD-1}")
|
|
72
109
|
while IFS= read -r line; do
|
|
73
110
|
if [[ "$line" == __FILE__:* ]]; then
|
|
@@ -75,6 +112,13 @@ function _${programName} () {
|
|
|
75
112
|
IFS=':' read -r _ type extensions pattern hidden <<< "$line"
|
|
76
113
|
extensions="\${extensions//,\\./,}"; extensions="\${extensions#.}"
|
|
77
114
|
pattern="\${pattern//%3A/:}"; pattern="\${pattern//%25/%}"
|
|
115
|
+
local __reply_start=\${#COMPREPLY[@]}
|
|
116
|
+
|
|
117
|
+
# path() echoes the raw shell word as its pattern. Once dequoted,
|
|
118
|
+
# use the literal current-word prefix instead of the escaped pattern.
|
|
119
|
+
if [[ "$pattern" == "$__raw_current" && "$current" != "$__raw_current" ]]; then
|
|
120
|
+
pattern=""
|
|
121
|
+
fi
|
|
78
122
|
|
|
79
123
|
# Save and adjust glob/shell options for safe file completion
|
|
80
124
|
local __dotglob_was_set=0 __failglob_was_set=0 __noglob_was_set=0
|
|
@@ -91,7 +135,7 @@ function _${programName} () {
|
|
|
91
135
|
|
|
92
136
|
# Expand tilde prefix for file globbing
|
|
93
137
|
local __glob_current="$current" __tilde_prefix="" __tilde_expanded=""
|
|
94
|
-
if [[ "$
|
|
138
|
+
if [[ "$__raw_current" == "~"* && "$current" =~ $__tilde_pattern ]]; then
|
|
95
139
|
__tilde_prefix="\${BASH_REMATCH[1]}"
|
|
96
140
|
eval "__tilde_expanded=\$__tilde_prefix" 2>/dev/null || true
|
|
97
141
|
if [[ -n "$__tilde_expanded" && "$__tilde_expanded" != "$__tilde_prefix" ]]; then
|
|
@@ -128,7 +172,7 @@ function _${programName} () {
|
|
|
128
172
|
__tilde_prefix=""
|
|
129
173
|
__tilde_expanded=""
|
|
130
174
|
__glob_current="$pattern"
|
|
131
|
-
if [[ "$pattern" =~
|
|
175
|
+
if [[ "$pattern" =~ $__tilde_glob_pattern ]]; then
|
|
132
176
|
__tilde_prefix="\${BASH_REMATCH[1]}"
|
|
133
177
|
eval "__tilde_expanded=\$__tilde_prefix" 2>/dev/null || true
|
|
134
178
|
if [[ -n "$__tilde_expanded" && "$__tilde_expanded" != "$__tilde_prefix" ]]; then
|
|
@@ -197,10 +241,11 @@ function _${programName} () {
|
|
|
197
241
|
if [[ -n "$extensions" ]]; then
|
|
198
242
|
# Files with extension filtering + directories
|
|
199
243
|
local ext_pattern="\${extensions//,/|}"
|
|
244
|
+
ext_pattern='\\.('"$ext_pattern"')$'
|
|
200
245
|
for item in "\${__candidates[@]}"; do
|
|
201
246
|
if [[ -d "$item" ]]; then
|
|
202
247
|
COMPREPLY+=("$item/")
|
|
203
|
-
elif [[ -f "$item" && "$item" =~
|
|
248
|
+
elif [[ -f "$item" && "$item" =~ $ext_pattern ]]; then
|
|
204
249
|
COMPREPLY+=("$item")
|
|
205
250
|
fi
|
|
206
251
|
done
|
|
@@ -227,10 +272,11 @@ function _${programName} () {
|
|
|
227
272
|
# Files with extension filtering + directories
|
|
228
273
|
# Files with extension filtering
|
|
229
274
|
local ext_pattern="\${extensions//,/|}"
|
|
275
|
+
ext_pattern='\\.('"$ext_pattern"')$'
|
|
230
276
|
for item in "\${__candidates[@]}"; do
|
|
231
277
|
if [[ -d "$item" ]]; then
|
|
232
278
|
COMPREPLY+=("$item/")
|
|
233
|
-
elif [[ ( -e "$item" || -L "$item" ) && "$item" =~
|
|
279
|
+
elif [[ ( -e "$item" || -L "$item" ) && "$item" =~ $ext_pattern ]]; then
|
|
234
280
|
COMPREPLY+=("$item")
|
|
235
281
|
fi
|
|
236
282
|
done
|
|
@@ -249,7 +295,8 @@ function _${programName} () {
|
|
|
249
295
|
esac
|
|
250
296
|
|
|
251
297
|
# Restore tilde prefix in completion results
|
|
252
|
-
if [[ -n "$__tilde_prefix"
|
|
298
|
+
if [[ -n "$__tilde_prefix" &&
|
|
299
|
+
( -z "$__quote" || $__quote_offset -gt 0 ) ]]; then
|
|
253
300
|
local __i
|
|
254
301
|
for __i in "\${!COMPREPLY[@]}"; do
|
|
255
302
|
COMPREPLY[\$__i]="\${COMPREPLY[\$__i]/#\$__tilde_expanded/\$__tilde_prefix}"
|
|
@@ -264,24 +311,96 @@ function _${programName} () {
|
|
|
264
311
|
if [[ "$__failglob_was_set" == "1" ]]; then shopt -s failglob; fi
|
|
265
312
|
if [[ "$__noglob_was_set" == "1" ]]; then set -f; fi
|
|
266
313
|
|
|
314
|
+
# Readline appends directory separators when it receives the full path.
|
|
315
|
+
# Midword quotes still need ours because replies omit the typed prefix.
|
|
316
|
+
if [[ -n "$__quote" && $__quote_offset -eq 0 ]]; then
|
|
317
|
+
local __reply_index
|
|
318
|
+
for ((__reply_index=__reply_start; __reply_index<\${#COMPREPLY[@]}; __reply_index++)); do
|
|
319
|
+
COMPREPLY[__reply_index]="\${COMPREPLY[__reply_index]%/}"
|
|
320
|
+
done
|
|
321
|
+
fi
|
|
322
|
+
|
|
323
|
+
# Readline replaces only the text after an open quote. Remove the
|
|
324
|
+
# already typed prefix so it is not inserted a second time.
|
|
325
|
+
if [[ -n "$__quote" && $__quote_offset -gt 0 ]]; then
|
|
326
|
+
local __quote_prefix="\${current:0:__quote_offset}"
|
|
327
|
+
local __reply_index
|
|
328
|
+
for ((__reply_index=__reply_start; __reply_index<\${#COMPREPLY[@]}; __reply_index++)); do
|
|
329
|
+
COMPREPLY[__reply_index]="\${COMPREPLY[__reply_index]#"$__quote_prefix"}"
|
|
330
|
+
done
|
|
331
|
+
fi
|
|
332
|
+
|
|
333
|
+
# Readline expands a leading tilde in a returned filename even when the
|
|
334
|
+
# user did not type one. Keep such local paths explicitly relative.
|
|
335
|
+
if [[ "$__raw_current" != "~"* && -z "$__tilde_prefix" ]]; then
|
|
336
|
+
local __reply_index
|
|
337
|
+
for ((__reply_index=__reply_start; __reply_index<\${#COMPREPLY[@]}; __reply_index++)); do
|
|
338
|
+
if [[ "\${COMPREPLY[__reply_index]}" =~ $__tilde_glob_pattern ]]; then
|
|
339
|
+
COMPREPLY[__reply_index]="./\${COMPREPLY[__reply_index]}"
|
|
340
|
+
fi
|
|
341
|
+
done
|
|
342
|
+
fi
|
|
343
|
+
|
|
344
|
+
# Bash 5.3 leaves substitutions unescaped inside an open double quote.
|
|
345
|
+
# Earlier versions already escape them during filename processing.
|
|
346
|
+
if [[ "$__quote" == '"' &&
|
|
347
|
+
( \${BASH_VERSINFO[0]} -gt 5 ||
|
|
348
|
+
( \${BASH_VERSINFO[0]} -eq 5 && \${BASH_VERSINFO[1]} -ge 3 ) ) &&
|
|
349
|
+
$(type -t compopt) == builtin ]]; then
|
|
350
|
+
local __escaped_reply __escape_index __reply_index
|
|
351
|
+
for ((__reply_index=__reply_start; __reply_index<\${#COMPREPLY[@]}; __reply_index++)); do
|
|
352
|
+
__escaped_reply=""
|
|
353
|
+
for ((__escape_index=0; __escape_index<\${#COMPREPLY[__reply_index]}; __escape_index++)); do
|
|
354
|
+
__char="\${COMPREPLY[__reply_index]:__escape_index:1}"
|
|
355
|
+
__next="\${COMPREPLY[__reply_index]:__escape_index+1:1}"
|
|
356
|
+
if [[ "$__char" == '\\' &&
|
|
357
|
+
( "$__next" == '$' || "$__next" == '\`' ) ]]; then
|
|
358
|
+
__escaped_reply+="\\\\$__char"
|
|
359
|
+
elif [[ "$__char" == '$' || "$__char" == '\`' ]]; then
|
|
360
|
+
__escaped_reply+="\\\\$__char"
|
|
361
|
+
else
|
|
362
|
+
__escaped_reply+="$__char"
|
|
363
|
+
fi
|
|
364
|
+
done
|
|
365
|
+
COMPREPLY[__reply_index]="$__escaped_reply"
|
|
366
|
+
done
|
|
367
|
+
fi
|
|
368
|
+
|
|
267
369
|
# Filter out hidden files unless requested
|
|
268
370
|
if [[ "$hidden" != "1" && "$__inside_hidden_path" == "0" && "$__prefix_targets_hidden" == "0" ]]; then
|
|
269
371
|
local filtered=()
|
|
270
|
-
local __name
|
|
372
|
+
local __name __filter_index __kept_before=0
|
|
373
|
+
__filter_index=0
|
|
271
374
|
for item in "\${COMPREPLY[@]}"; do
|
|
272
375
|
__name="\${item%/}"; __name="\${__name##*/}"
|
|
273
|
-
[[ "$__name" != .* ]]
|
|
376
|
+
if [[ "$__name" != .* ]]; then
|
|
377
|
+
filtered+=("$item")
|
|
378
|
+
if [[ $__filter_index -lt $__reply_start ]]; then
|
|
379
|
+
__kept_before=$((__kept_before + 1))
|
|
380
|
+
fi
|
|
381
|
+
fi
|
|
382
|
+
__filter_index=$((__filter_index + 1))
|
|
274
383
|
done
|
|
275
384
|
COMPREPLY=("\${filtered[@]}")
|
|
385
|
+
__reply_start=$__kept_before
|
|
276
386
|
fi
|
|
387
|
+
if [[ \${#COMPREPLY[@]} -gt $__reply_start ]]; then __file_mode=1; fi
|
|
277
388
|
else
|
|
278
389
|
# Regular literal completion
|
|
279
390
|
COMPREPLY+=("$line")
|
|
280
391
|
fi
|
|
281
|
-
done < <(${programName} ${escapedArgs} "\${prev[@]}" "$
|
|
392
|
+
done < <(${programName} ${escapedArgs} "\${prev[@]}" "$__raw_current" 2>/dev/null)
|
|
393
|
+
if [[ $__file_mode == 1 && $(type -t compopt) == builtin ]]; then
|
|
394
|
+
compopt -o filenames 2>/dev/null || true
|
|
395
|
+
fi
|
|
282
396
|
}
|
|
283
397
|
|
|
284
|
-
|
|
398
|
+
# Bash 3.2 has no compopt: use filename quoting for all candidates there.
|
|
399
|
+
if [[ $(type -t compopt) == builtin ]]; then
|
|
400
|
+
complete -F _${programName} -- ${programName}
|
|
401
|
+
else
|
|
402
|
+
complete -o filenames -F _${programName} -- ${programName}
|
|
403
|
+
fi
|
|
285
404
|
`;
|
|
286
405
|
},
|
|
287
406
|
*encodeSuggestions(suggestions) {
|
|
@@ -576,8 +695,8 @@ ${escapedArgs ? ` set -l output (${programName} ${escapedArgs} $prev $current
|
|
|
576
695
|
# dotfiles, so also scan .* when the filter targets them.
|
|
577
696
|
for __item in $__glob_dir/*
|
|
578
697
|
if test -e "$__item"
|
|
579
|
-
set -l __bn (basename "$__item")
|
|
580
|
-
if string match -q "$__glob_filter"
|
|
698
|
+
set -l __bn (basename -- "$__item")
|
|
699
|
+
if string match -q -- "$__glob_filter" "$__bn"
|
|
581
700
|
set -a __candidates "$__item"
|
|
582
701
|
end
|
|
583
702
|
end
|
|
@@ -585,11 +704,11 @@ ${escapedArgs ? ` set -l output (${programName} ${escapedArgs} $prev $current
|
|
|
585
704
|
if string match -q '.*' -- "$__glob_filter"
|
|
586
705
|
for __item in $__glob_dir/.*
|
|
587
706
|
if test -e "$__item"
|
|
588
|
-
set -l __bn (basename "$__item")
|
|
707
|
+
set -l __bn (basename -- "$__item")
|
|
589
708
|
if test "$__bn" = "." -o "$__bn" = ".."
|
|
590
709
|
continue
|
|
591
710
|
end
|
|
592
|
-
if string match -q "$__glob_filter"
|
|
711
|
+
if string match -q -- "$__glob_filter" "$__bn"
|
|
593
712
|
set -a __candidates "$__item"
|
|
594
713
|
end
|
|
595
714
|
end
|
|
@@ -703,7 +822,7 @@ ${escapedArgs ? ` set -l output (${programName} ${escapedArgs} $prev $current
|
|
|
703
822
|
if test "$hidden" != "1" -a (string sub -l 1 -- $__glob_basename) != "."
|
|
704
823
|
set -l filtered
|
|
705
824
|
for item in $items
|
|
706
|
-
set -l basename (basename $item)
|
|
825
|
+
set -l basename (basename -- "$item")
|
|
707
826
|
if not string match -q '.*' -- $basename
|
|
708
827
|
set -a filtered $item
|
|
709
828
|
end
|
|
@@ -720,9 +839,10 @@ ${escapedArgs ? ` set -l output (${programName} ${escapedArgs} $prev $current
|
|
|
720
839
|
set items $restored
|
|
721
840
|
end
|
|
722
841
|
|
|
723
|
-
# Output file completions
|
|
842
|
+
# Output file completions. Use printf rather than echo, which
|
|
843
|
+
# would take filenames like -n or -e as its own options.
|
|
724
844
|
for item in $items
|
|
725
|
-
|
|
845
|
+
printf '%s\\n' $item
|
|
726
846
|
end
|
|
727
847
|
else
|
|
728
848
|
# Regular literal completion - split by tab
|
package/dist/completion.js
CHANGED
|
@@ -67,7 +67,44 @@ const bash = {
|
|
|
67
67
|
return `
|
|
68
68
|
function _${programName} () {
|
|
69
69
|
COMPREPLY=()
|
|
70
|
-
local
|
|
70
|
+
local __raw_current="\${COMP_WORDS[COMP_CWORD]}"
|
|
71
|
+
local current="" __quote="" __char __next __index __quote_offset=0
|
|
72
|
+
local __file_mode=0
|
|
73
|
+
if [[ $(type -t compopt) == builtin ]]; then
|
|
74
|
+
compopt +o filenames 2>/dev/null || true
|
|
75
|
+
fi
|
|
76
|
+
# Dequote the shell word without evaluating filename contents. Readline
|
|
77
|
+
# returns escaped words after Tab, and users may start with an open quote.
|
|
78
|
+
for ((__index=0; __index<\${#__raw_current}; __index++)); do
|
|
79
|
+
__char="\${__raw_current:__index:1}"
|
|
80
|
+
if [[ -z "$__quote" ]]; then
|
|
81
|
+
case "$__char" in
|
|
82
|
+
\\\\) ((++__index)); current+="\${__raw_current:__index:1}" ;;
|
|
83
|
+
\\'|\\") __quote="$__char"; __quote_offset=\${#current} ;;
|
|
84
|
+
*) current+="$__char" ;;
|
|
85
|
+
esac
|
|
86
|
+
elif [[ "$__quote" == "'" ]]; then
|
|
87
|
+
if [[ "$__char" == "'" ]]; then
|
|
88
|
+
__quote=""
|
|
89
|
+
else
|
|
90
|
+
current+="$__char"
|
|
91
|
+
fi
|
|
92
|
+
else
|
|
93
|
+
case "$__char" in
|
|
94
|
+
\\") __quote="" ;;
|
|
95
|
+
\\\\)
|
|
96
|
+
__next="\${__raw_current:__index+1:1}"
|
|
97
|
+
case "$__next" in
|
|
98
|
+
\\$|\\\`|\\"|\\\\)
|
|
99
|
+
((++__index)); current+="$__next" ;;
|
|
100
|
+
*) current+="$__char" ;;
|
|
101
|
+
esac ;;
|
|
102
|
+
*) current+="$__char" ;;
|
|
103
|
+
esac
|
|
104
|
+
fi
|
|
105
|
+
done
|
|
106
|
+
local __tilde_pattern='^(~[a-zA-Z0-9_.+-]*)(/.*)$'
|
|
107
|
+
local __tilde_glob_pattern='^(~[a-zA-Z0-9_.+-]*)(/.*)?$'
|
|
71
108
|
local prev=("\${COMP_WORDS[@]:1:COMP_CWORD-1}")
|
|
72
109
|
while IFS= read -r line; do
|
|
73
110
|
if [[ "$line" == __FILE__:* ]]; then
|
|
@@ -75,6 +112,13 @@ function _${programName} () {
|
|
|
75
112
|
IFS=':' read -r _ type extensions pattern hidden <<< "$line"
|
|
76
113
|
extensions="\${extensions//,\\./,}"; extensions="\${extensions#.}"
|
|
77
114
|
pattern="\${pattern//%3A/:}"; pattern="\${pattern//%25/%}"
|
|
115
|
+
local __reply_start=\${#COMPREPLY[@]}
|
|
116
|
+
|
|
117
|
+
# path() echoes the raw shell word as its pattern. Once dequoted,
|
|
118
|
+
# use the literal current-word prefix instead of the escaped pattern.
|
|
119
|
+
if [[ "$pattern" == "$__raw_current" && "$current" != "$__raw_current" ]]; then
|
|
120
|
+
pattern=""
|
|
121
|
+
fi
|
|
78
122
|
|
|
79
123
|
# Save and adjust glob/shell options for safe file completion
|
|
80
124
|
local __dotglob_was_set=0 __failglob_was_set=0 __noglob_was_set=0
|
|
@@ -91,7 +135,7 @@ function _${programName} () {
|
|
|
91
135
|
|
|
92
136
|
# Expand tilde prefix for file globbing
|
|
93
137
|
local __glob_current="$current" __tilde_prefix="" __tilde_expanded=""
|
|
94
|
-
if [[ "$
|
|
138
|
+
if [[ "$__raw_current" == "~"* && "$current" =~ $__tilde_pattern ]]; then
|
|
95
139
|
__tilde_prefix="\${BASH_REMATCH[1]}"
|
|
96
140
|
eval "__tilde_expanded=\$__tilde_prefix" 2>/dev/null || true
|
|
97
141
|
if [[ -n "$__tilde_expanded" && "$__tilde_expanded" != "$__tilde_prefix" ]]; then
|
|
@@ -128,7 +172,7 @@ function _${programName} () {
|
|
|
128
172
|
__tilde_prefix=""
|
|
129
173
|
__tilde_expanded=""
|
|
130
174
|
__glob_current="$pattern"
|
|
131
|
-
if [[ "$pattern" =~
|
|
175
|
+
if [[ "$pattern" =~ $__tilde_glob_pattern ]]; then
|
|
132
176
|
__tilde_prefix="\${BASH_REMATCH[1]}"
|
|
133
177
|
eval "__tilde_expanded=\$__tilde_prefix" 2>/dev/null || true
|
|
134
178
|
if [[ -n "$__tilde_expanded" && "$__tilde_expanded" != "$__tilde_prefix" ]]; then
|
|
@@ -197,10 +241,11 @@ function _${programName} () {
|
|
|
197
241
|
if [[ -n "$extensions" ]]; then
|
|
198
242
|
# Files with extension filtering + directories
|
|
199
243
|
local ext_pattern="\${extensions//,/|}"
|
|
244
|
+
ext_pattern='\\.('"$ext_pattern"')$'
|
|
200
245
|
for item in "\${__candidates[@]}"; do
|
|
201
246
|
if [[ -d "$item" ]]; then
|
|
202
247
|
COMPREPLY+=("$item/")
|
|
203
|
-
elif [[ -f "$item" && "$item" =~
|
|
248
|
+
elif [[ -f "$item" && "$item" =~ $ext_pattern ]]; then
|
|
204
249
|
COMPREPLY+=("$item")
|
|
205
250
|
fi
|
|
206
251
|
done
|
|
@@ -227,10 +272,11 @@ function _${programName} () {
|
|
|
227
272
|
# Files with extension filtering + directories
|
|
228
273
|
# Files with extension filtering
|
|
229
274
|
local ext_pattern="\${extensions//,/|}"
|
|
275
|
+
ext_pattern='\\.('"$ext_pattern"')$'
|
|
230
276
|
for item in "\${__candidates[@]}"; do
|
|
231
277
|
if [[ -d "$item" ]]; then
|
|
232
278
|
COMPREPLY+=("$item/")
|
|
233
|
-
elif [[ ( -e "$item" || -L "$item" ) && "$item" =~
|
|
279
|
+
elif [[ ( -e "$item" || -L "$item" ) && "$item" =~ $ext_pattern ]]; then
|
|
234
280
|
COMPREPLY+=("$item")
|
|
235
281
|
fi
|
|
236
282
|
done
|
|
@@ -249,7 +295,8 @@ function _${programName} () {
|
|
|
249
295
|
esac
|
|
250
296
|
|
|
251
297
|
# Restore tilde prefix in completion results
|
|
252
|
-
if [[ -n "$__tilde_prefix"
|
|
298
|
+
if [[ -n "$__tilde_prefix" &&
|
|
299
|
+
( -z "$__quote" || $__quote_offset -gt 0 ) ]]; then
|
|
253
300
|
local __i
|
|
254
301
|
for __i in "\${!COMPREPLY[@]}"; do
|
|
255
302
|
COMPREPLY[\$__i]="\${COMPREPLY[\$__i]/#\$__tilde_expanded/\$__tilde_prefix}"
|
|
@@ -264,24 +311,96 @@ function _${programName} () {
|
|
|
264
311
|
if [[ "$__failglob_was_set" == "1" ]]; then shopt -s failglob; fi
|
|
265
312
|
if [[ "$__noglob_was_set" == "1" ]]; then set -f; fi
|
|
266
313
|
|
|
314
|
+
# Readline appends directory separators when it receives the full path.
|
|
315
|
+
# Midword quotes still need ours because replies omit the typed prefix.
|
|
316
|
+
if [[ -n "$__quote" && $__quote_offset -eq 0 ]]; then
|
|
317
|
+
local __reply_index
|
|
318
|
+
for ((__reply_index=__reply_start; __reply_index<\${#COMPREPLY[@]}; __reply_index++)); do
|
|
319
|
+
COMPREPLY[__reply_index]="\${COMPREPLY[__reply_index]%/}"
|
|
320
|
+
done
|
|
321
|
+
fi
|
|
322
|
+
|
|
323
|
+
# Readline replaces only the text after an open quote. Remove the
|
|
324
|
+
# already typed prefix so it is not inserted a second time.
|
|
325
|
+
if [[ -n "$__quote" && $__quote_offset -gt 0 ]]; then
|
|
326
|
+
local __quote_prefix="\${current:0:__quote_offset}"
|
|
327
|
+
local __reply_index
|
|
328
|
+
for ((__reply_index=__reply_start; __reply_index<\${#COMPREPLY[@]}; __reply_index++)); do
|
|
329
|
+
COMPREPLY[__reply_index]="\${COMPREPLY[__reply_index]#"$__quote_prefix"}"
|
|
330
|
+
done
|
|
331
|
+
fi
|
|
332
|
+
|
|
333
|
+
# Readline expands a leading tilde in a returned filename even when the
|
|
334
|
+
# user did not type one. Keep such local paths explicitly relative.
|
|
335
|
+
if [[ "$__raw_current" != "~"* && -z "$__tilde_prefix" ]]; then
|
|
336
|
+
local __reply_index
|
|
337
|
+
for ((__reply_index=__reply_start; __reply_index<\${#COMPREPLY[@]}; __reply_index++)); do
|
|
338
|
+
if [[ "\${COMPREPLY[__reply_index]}" =~ $__tilde_glob_pattern ]]; then
|
|
339
|
+
COMPREPLY[__reply_index]="./\${COMPREPLY[__reply_index]}"
|
|
340
|
+
fi
|
|
341
|
+
done
|
|
342
|
+
fi
|
|
343
|
+
|
|
344
|
+
# Bash 5.3 leaves substitutions unescaped inside an open double quote.
|
|
345
|
+
# Earlier versions already escape them during filename processing.
|
|
346
|
+
if [[ "$__quote" == '"' &&
|
|
347
|
+
( \${BASH_VERSINFO[0]} -gt 5 ||
|
|
348
|
+
( \${BASH_VERSINFO[0]} -eq 5 && \${BASH_VERSINFO[1]} -ge 3 ) ) &&
|
|
349
|
+
$(type -t compopt) == builtin ]]; then
|
|
350
|
+
local __escaped_reply __escape_index __reply_index
|
|
351
|
+
for ((__reply_index=__reply_start; __reply_index<\${#COMPREPLY[@]}; __reply_index++)); do
|
|
352
|
+
__escaped_reply=""
|
|
353
|
+
for ((__escape_index=0; __escape_index<\${#COMPREPLY[__reply_index]}; __escape_index++)); do
|
|
354
|
+
__char="\${COMPREPLY[__reply_index]:__escape_index:1}"
|
|
355
|
+
__next="\${COMPREPLY[__reply_index]:__escape_index+1:1}"
|
|
356
|
+
if [[ "$__char" == '\\' &&
|
|
357
|
+
( "$__next" == '$' || "$__next" == '\`' ) ]]; then
|
|
358
|
+
__escaped_reply+="\\\\$__char"
|
|
359
|
+
elif [[ "$__char" == '$' || "$__char" == '\`' ]]; then
|
|
360
|
+
__escaped_reply+="\\\\$__char"
|
|
361
|
+
else
|
|
362
|
+
__escaped_reply+="$__char"
|
|
363
|
+
fi
|
|
364
|
+
done
|
|
365
|
+
COMPREPLY[__reply_index]="$__escaped_reply"
|
|
366
|
+
done
|
|
367
|
+
fi
|
|
368
|
+
|
|
267
369
|
# Filter out hidden files unless requested
|
|
268
370
|
if [[ "$hidden" != "1" && "$__inside_hidden_path" == "0" && "$__prefix_targets_hidden" == "0" ]]; then
|
|
269
371
|
local filtered=()
|
|
270
|
-
local __name
|
|
372
|
+
local __name __filter_index __kept_before=0
|
|
373
|
+
__filter_index=0
|
|
271
374
|
for item in "\${COMPREPLY[@]}"; do
|
|
272
375
|
__name="\${item%/}"; __name="\${__name##*/}"
|
|
273
|
-
[[ "$__name" != .* ]]
|
|
376
|
+
if [[ "$__name" != .* ]]; then
|
|
377
|
+
filtered+=("$item")
|
|
378
|
+
if [[ $__filter_index -lt $__reply_start ]]; then
|
|
379
|
+
__kept_before=$((__kept_before + 1))
|
|
380
|
+
fi
|
|
381
|
+
fi
|
|
382
|
+
__filter_index=$((__filter_index + 1))
|
|
274
383
|
done
|
|
275
384
|
COMPREPLY=("\${filtered[@]}")
|
|
385
|
+
__reply_start=$__kept_before
|
|
276
386
|
fi
|
|
387
|
+
if [[ \${#COMPREPLY[@]} -gt $__reply_start ]]; then __file_mode=1; fi
|
|
277
388
|
else
|
|
278
389
|
# Regular literal completion
|
|
279
390
|
COMPREPLY+=("$line")
|
|
280
391
|
fi
|
|
281
|
-
done < <(${programName} ${escapedArgs} "\${prev[@]}" "$
|
|
392
|
+
done < <(${programName} ${escapedArgs} "\${prev[@]}" "$__raw_current" 2>/dev/null)
|
|
393
|
+
if [[ $__file_mode == 1 && $(type -t compopt) == builtin ]]; then
|
|
394
|
+
compopt -o filenames 2>/dev/null || true
|
|
395
|
+
fi
|
|
282
396
|
}
|
|
283
397
|
|
|
284
|
-
|
|
398
|
+
# Bash 3.2 has no compopt: use filename quoting for all candidates there.
|
|
399
|
+
if [[ $(type -t compopt) == builtin ]]; then
|
|
400
|
+
complete -F _${programName} -- ${programName}
|
|
401
|
+
else
|
|
402
|
+
complete -o filenames -F _${programName} -- ${programName}
|
|
403
|
+
fi
|
|
285
404
|
`;
|
|
286
405
|
},
|
|
287
406
|
*encodeSuggestions(suggestions) {
|
|
@@ -576,8 +695,8 @@ ${escapedArgs ? ` set -l output (${programName} ${escapedArgs} $prev $current
|
|
|
576
695
|
# dotfiles, so also scan .* when the filter targets them.
|
|
577
696
|
for __item in $__glob_dir/*
|
|
578
697
|
if test -e "$__item"
|
|
579
|
-
set -l __bn (basename "$__item")
|
|
580
|
-
if string match -q "$__glob_filter"
|
|
698
|
+
set -l __bn (basename -- "$__item")
|
|
699
|
+
if string match -q -- "$__glob_filter" "$__bn"
|
|
581
700
|
set -a __candidates "$__item"
|
|
582
701
|
end
|
|
583
702
|
end
|
|
@@ -585,11 +704,11 @@ ${escapedArgs ? ` set -l output (${programName} ${escapedArgs} $prev $current
|
|
|
585
704
|
if string match -q '.*' -- "$__glob_filter"
|
|
586
705
|
for __item in $__glob_dir/.*
|
|
587
706
|
if test -e "$__item"
|
|
588
|
-
set -l __bn (basename "$__item")
|
|
707
|
+
set -l __bn (basename -- "$__item")
|
|
589
708
|
if test "$__bn" = "." -o "$__bn" = ".."
|
|
590
709
|
continue
|
|
591
710
|
end
|
|
592
|
-
if string match -q "$__glob_filter"
|
|
711
|
+
if string match -q -- "$__glob_filter" "$__bn"
|
|
593
712
|
set -a __candidates "$__item"
|
|
594
713
|
end
|
|
595
714
|
end
|
|
@@ -703,7 +822,7 @@ ${escapedArgs ? ` set -l output (${programName} ${escapedArgs} $prev $current
|
|
|
703
822
|
if test "$hidden" != "1" -a (string sub -l 1 -- $__glob_basename) != "."
|
|
704
823
|
set -l filtered
|
|
705
824
|
for item in $items
|
|
706
|
-
set -l basename (basename $item)
|
|
825
|
+
set -l basename (basename -- "$item")
|
|
707
826
|
if not string match -q '.*' -- $basename
|
|
708
827
|
set -a filtered $item
|
|
709
828
|
end
|
|
@@ -720,9 +839,10 @@ ${escapedArgs ? ` set -l output (${programName} ${escapedArgs} $prev $current
|
|
|
720
839
|
set items $restored
|
|
721
840
|
end
|
|
722
841
|
|
|
723
|
-
# Output file completions
|
|
842
|
+
# Output file completions. Use printf rather than echo, which
|
|
843
|
+
# would take filenames like -n or -e as its own options.
|
|
724
844
|
for item in $items
|
|
725
|
-
|
|
845
|
+
printf '%s\\n' $item
|
|
726
846
|
end
|
|
727
847
|
else
|
|
728
848
|
# Regular literal completion - split by tab
|