politty 0.4.0 → 0.4.1
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/index.cjs +4 -3
- package/dist/completion/index.cjs.map +1 -1
- package/dist/completion/index.d.cts +2 -2
- package/dist/completion/index.d.cts.map +1 -1
- package/dist/completion/index.d.ts +2 -2
- package/dist/completion/index.d.ts.map +1 -1
- package/dist/completion/index.js +3 -3
- package/dist/completion/index.js.map +1 -1
- package/dist/docs/index.cjs +2 -2
- package/dist/docs/index.js +2 -2
- package/dist/{extractor-JfoYSoMk.js → extractor-DO-FDKkW.js} +397 -295
- package/dist/extractor-DO-FDKkW.js.map +1 -0
- package/dist/{extractor-CqfDnGKd.cjs → extractor-cjruDqQ2.cjs} +404 -296
- package/dist/extractor-cjruDqQ2.cjs.map +1 -0
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/dist/{runner-9dLE13Dv.cjs → runner-0yr2HFay.cjs} +2 -2
- package/dist/{runner-9dLE13Dv.cjs.map → runner-0yr2HFay.cjs.map} +1 -1
- package/dist/{runner-LJRI4haB.js → runner-BoZpJtIR.js} +2 -2
- package/dist/{runner-LJRI4haB.js.map → runner-BoZpJtIR.js.map} +1 -1
- package/dist/schema-extractor-CHiBRT39.d.ts.map +1 -1
- package/dist/{schema-extractor-CP3ar0Wi.js → schema-extractor-DAkmmrOy.js} +5 -1
- package/dist/schema-extractor-DAkmmrOy.js.map +1 -0
- package/dist/schema-extractor-DyfK21m_.d.cts.map +1 -1
- package/dist/{schema-extractor-Cv7ipqLS.cjs → schema-extractor-Mk1MHBkQ.cjs} +5 -1
- package/dist/schema-extractor-Mk1MHBkQ.cjs.map +1 -0
- package/dist/{extractor-DsJ6hYqQ.d.cts → value-completion-resolver-0xf8_07p.d.cts} +56 -11
- package/dist/value-completion-resolver-0xf8_07p.d.cts.map +1 -0
- package/dist/{extractor-CCi4rjSI.d.ts → value-completion-resolver-CUKbibx-.d.ts} +56 -11
- package/dist/value-completion-resolver-CUKbibx-.d.ts.map +1 -0
- package/package.json +6 -5
- package/dist/extractor-CCi4rjSI.d.ts.map +0 -1
- package/dist/extractor-CqfDnGKd.cjs.map +0 -1
- package/dist/extractor-DsJ6hYqQ.d.cts.map +0 -1
- package/dist/extractor-JfoYSoMk.js.map +0 -1
- package/dist/schema-extractor-CP3ar0Wi.js.map +0 -1
- package/dist/schema-extractor-Cv7ipqLS.cjs.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { a as arg, t as extractFields } from "./schema-extractor-
|
|
1
|
+
import { a as arg, t as extractFields } from "./schema-extractor-DAkmmrOy.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
3
4
|
|
|
4
5
|
//#region src/core/command.ts
|
|
5
6
|
function defineCommand(config) {
|
|
@@ -21,7 +22,12 @@ function defineCommand(config) {
|
|
|
21
22
|
/**
|
|
22
23
|
* Generate bash completion script for a command
|
|
23
24
|
*
|
|
24
|
-
* Generates a
|
|
25
|
+
* Generates a minimal script that delegates all logic to the CLI's __complete command.
|
|
26
|
+
* The shell script only handles:
|
|
27
|
+
* - Getting current command line tokens
|
|
28
|
+
* - Calling __complete with --shell bash
|
|
29
|
+
* - Setting COMPREPLY from the output
|
|
30
|
+
* - Falling back to native file/directory completion when directed
|
|
25
31
|
*/
|
|
26
32
|
function generateBashCompletion(_command, options) {
|
|
27
33
|
const programName = options.programName;
|
|
@@ -30,99 +36,126 @@ function generateBashCompletion(_command, options) {
|
|
|
30
36
|
# Generated by politty
|
|
31
37
|
|
|
32
38
|
_${programName}_completions() {
|
|
33
|
-
|
|
34
|
-
local
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
COMPREPLY=()
|
|
40
|
+
local IFS=$'\\n'
|
|
41
|
+
|
|
42
|
+
# Rejoin words split by '=' in COMP_WORDBREAKS (e.g. --opt=value)
|
|
43
|
+
local -a _words=()
|
|
44
|
+
local _i=1
|
|
45
|
+
while (( _i <= COMP_CWORD )); do
|
|
46
|
+
if [[ "\${COMP_WORDS[_i]}" == "=" && \${#_words[@]} -gt 0 ]]; then
|
|
47
|
+
_words[\${#_words[@]}-1]+="=\${COMP_WORDS[_i+1]:-}"
|
|
48
|
+
(( _i += 2 ))
|
|
49
|
+
else
|
|
50
|
+
_words+=("\${COMP_WORDS[_i]}")
|
|
51
|
+
(( _i++ ))
|
|
52
|
+
fi
|
|
53
|
+
done
|
|
37
54
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
fi
|
|
55
|
+
local lines prev_opts="$-"
|
|
56
|
+
set -f
|
|
57
|
+
lines=($(${programName} __complete --shell bash -- "\${_words[@]}" 2>/dev/null))
|
|
58
|
+
[[ "$prev_opts" != *f* ]] && set +f
|
|
43
59
|
|
|
44
|
-
#
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
# Backward compatibility for CLIs exposing only completion
|
|
48
|
-
output=$(${programName} completion __complete -- "\${args[@]}" 2>/dev/null)
|
|
60
|
+
local count=\${#lines[@]}
|
|
61
|
+
if (( count == 0 )); then
|
|
62
|
+
return 0
|
|
49
63
|
fi
|
|
50
64
|
|
|
51
|
-
local
|
|
65
|
+
local last="\${lines[count-1]}"
|
|
52
66
|
local directive=0
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
while IFS=$'\\t' read -r name desc; do
|
|
58
|
-
if [[ "$name" == :* ]]; then
|
|
59
|
-
directive="\${name:1}"
|
|
60
|
-
elif [[ "$name" == __command:* ]]; then
|
|
61
|
-
command_completion="\${name#__command:}"
|
|
62
|
-
elif [[ "$name" == __extensions:* ]]; then
|
|
63
|
-
file_extensions="\${name#__extensions:}"
|
|
64
|
-
elif [[ -n "$name" ]]; then
|
|
65
|
-
candidates+=("$name")
|
|
66
|
-
fi
|
|
67
|
-
done <<< "$output"
|
|
68
|
-
|
|
69
|
-
# Execute shellCommand completion if requested by __complete
|
|
70
|
-
if [[ -n "$command_completion" ]]; then
|
|
71
|
-
while IFS= read -r command_candidate; do
|
|
72
|
-
if [[ -n "$command_candidate" ]]; then
|
|
73
|
-
candidates+=("$command_candidate")
|
|
74
|
-
fi
|
|
75
|
-
done < <(eval "$command_completion" 2>/dev/null)
|
|
67
|
+
if [[ "$last" == :* ]]; then
|
|
68
|
+
directive="\${last:1}"
|
|
69
|
+
unset 'lines[count-1]'
|
|
70
|
+
(( count-- ))
|
|
76
71
|
fi
|
|
77
72
|
|
|
78
|
-
#
|
|
79
|
-
|
|
80
|
-
if ((
|
|
81
|
-
|
|
73
|
+
# Parse @ext: metadata (extension filter for native file completion)
|
|
74
|
+
local extensions=""
|
|
75
|
+
if (( count > 0 )); then
|
|
76
|
+
local maybe_ext="\${lines[count-1]}"
|
|
77
|
+
if [[ "$maybe_ext" == @ext:* ]]; then
|
|
78
|
+
extensions="\${maybe_ext:5}"
|
|
79
|
+
unset 'lines[count-1]'
|
|
80
|
+
fi
|
|
81
|
+
fi
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
local -a extension_list=()
|
|
86
|
-
local file_candidate ext
|
|
83
|
+
local cur=""
|
|
84
|
+
(( \${#_words[@]} > 0 )) && cur="\${_words[\${#_words[@]}-1]}"
|
|
87
85
|
|
|
88
|
-
|
|
86
|
+
# Strip --opt= prefix for native file/directory completion
|
|
87
|
+
local inline_prefix=""
|
|
88
|
+
if [[ "$cur" == --*=* ]]; then
|
|
89
|
+
inline_prefix="\${cur%%=*}="
|
|
90
|
+
cur="\${cur#*=}"
|
|
91
|
+
fi
|
|
89
92
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
# 16 = FileCompletion: delegate entirely to native file completion
|
|
94
|
+
if (( directive & 16 )); then
|
|
95
|
+
local -a entries=($(compgen -f -- "$cur"))
|
|
96
|
+
if [[ -n "$inline_prefix" ]]; then
|
|
97
|
+
local i
|
|
98
|
+
for (( i=0; i<\${#entries[@]}; i++ )); do
|
|
99
|
+
entries[$i]="\${inline_prefix}\${entries[$i]}"
|
|
100
|
+
done
|
|
101
|
+
fi
|
|
102
|
+
COMPREPLY=("\${entries[@]}")
|
|
103
|
+
compopt -o filenames
|
|
104
|
+
return 0
|
|
105
|
+
fi
|
|
95
106
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
107
|
+
# Extension-filtered file completion: keep matching files + directories
|
|
108
|
+
if [[ -n "$extensions" ]]; then
|
|
109
|
+
local -a all_entries=($(compgen -f -- "$cur"))
|
|
110
|
+
local IFS=','
|
|
111
|
+
local -a ext_arr=($extensions)
|
|
112
|
+
IFS=$'\\n'
|
|
113
|
+
for f in "\${all_entries[@]}"; do
|
|
114
|
+
if [[ -d "$f" ]]; then
|
|
115
|
+
COMPREPLY+=("\${inline_prefix}$f")
|
|
116
|
+
else
|
|
117
|
+
for ext in "\${ext_arr[@]}"; do
|
|
118
|
+
if [[ "$f" == *".$ext" ]]; then
|
|
119
|
+
COMPREPLY+=("\${inline_prefix}$f")
|
|
99
120
|
break
|
|
100
121
|
fi
|
|
101
122
|
done
|
|
102
|
-
|
|
123
|
+
fi
|
|
124
|
+
done
|
|
125
|
+
compopt -o filenames
|
|
126
|
+
compopt +o default 2>/dev/null
|
|
127
|
+
return 0
|
|
128
|
+
fi
|
|
103
129
|
|
|
104
|
-
|
|
130
|
+
# Start with JS candidates
|
|
131
|
+
if (( \${#lines[@]} > 0 )); then
|
|
132
|
+
COMPREPLY=("\${lines[@]}")
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
# 32 = DirectoryCompletion: merge native directory matches
|
|
136
|
+
if (( directive & 32 )); then
|
|
137
|
+
local -a dirs=($(compgen -d -- "$cur"))
|
|
138
|
+
if [[ -n "$inline_prefix" ]]; then
|
|
139
|
+
local i
|
|
140
|
+
for (( i=0; i<\${#dirs[@]}; i++ )); do
|
|
141
|
+
dirs[$i]="\${inline_prefix}\${dirs[$i]}"
|
|
142
|
+
done
|
|
105
143
|
fi
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
elif [[ \${#candidates[@]} -gt 0 ]]; then
|
|
109
|
-
COMPREPLY=($(compgen -W "\${candidates[*]}" -- "$completion_cur"))
|
|
144
|
+
COMPREPLY+=("\${dirs[@]}")
|
|
145
|
+
compopt -o filenames
|
|
110
146
|
fi
|
|
111
147
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
prefixed+=("$completion_prefix$candidate")
|
|
117
|
-
done
|
|
118
|
-
COMPREPLY=("\${prefixed[@]}")
|
|
148
|
+
# 2 = NoFileCompletion, 32 = DirectoryCompletion:
|
|
149
|
+
# suppress -o default file fallback when completions are restricted
|
|
150
|
+
if (( directive & 2 )) || (( directive & 32 )); then
|
|
151
|
+
compopt +o default 2>/dev/null
|
|
119
152
|
fi
|
|
120
153
|
|
|
121
154
|
return 0
|
|
122
155
|
}
|
|
123
156
|
|
|
124
157
|
# Register the completion function
|
|
125
|
-
complete -F _${programName}_completions ${programName}
|
|
158
|
+
complete -o default -F _${programName}_completions ${programName}
|
|
126
159
|
`,
|
|
127
160
|
shell: "bash",
|
|
128
161
|
installInstructions: `# To enable completions, add the following to your ~/.bashrc:
|
|
@@ -141,6 +174,9 @@ source ~/.bashrc`
|
|
|
141
174
|
//#endregion
|
|
142
175
|
//#region src/completion/dynamic/candidate-generator.ts
|
|
143
176
|
/**
|
|
177
|
+
* Generate completion candidates based on context
|
|
178
|
+
*/
|
|
179
|
+
/**
|
|
144
180
|
* Completion directive flags (bitwise)
|
|
145
181
|
*/
|
|
146
182
|
const CompletionDirective = {
|
|
@@ -170,14 +206,61 @@ function generateCandidates(context) {
|
|
|
170
206
|
};
|
|
171
207
|
}
|
|
172
208
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
209
|
+
/**
|
|
210
|
+
* Execute a shell command and return results as candidates
|
|
211
|
+
*/
|
|
212
|
+
function executeShellCommand(command) {
|
|
213
|
+
try {
|
|
214
|
+
return execSync(command, {
|
|
215
|
+
encoding: "utf-8",
|
|
216
|
+
timeout: 5e3
|
|
217
|
+
}).split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map((line) => ({
|
|
218
|
+
value: line,
|
|
219
|
+
type: "value"
|
|
220
|
+
}));
|
|
221
|
+
} catch {
|
|
222
|
+
return [];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Resolve value completion, executing shell commands and file lookups in JS
|
|
227
|
+
*/
|
|
228
|
+
function resolveValueCandidates(vc, candidates, _currentWord, description) {
|
|
229
|
+
let directive = CompletionDirective.FilterPrefix;
|
|
230
|
+
let fileExtensions;
|
|
231
|
+
switch (vc.type) {
|
|
232
|
+
case "choices":
|
|
233
|
+
if (vc.choices) for (const choice of vc.choices) candidates.push({
|
|
234
|
+
value: choice,
|
|
235
|
+
description,
|
|
236
|
+
type: "value"
|
|
237
|
+
});
|
|
238
|
+
directive |= CompletionDirective.NoFileCompletion;
|
|
239
|
+
break;
|
|
240
|
+
case "file":
|
|
241
|
+
if (vc.extensions && vc.extensions.length > 0) {
|
|
242
|
+
fileExtensions = Array.from(new Set(vc.extensions.map((ext) => ext.trim().replace(/^\./, "")).filter((ext) => ext.length > 0)));
|
|
243
|
+
if (fileExtensions.length === 0) {
|
|
244
|
+
fileExtensions = void 0;
|
|
245
|
+
directive |= CompletionDirective.FileCompletion;
|
|
246
|
+
}
|
|
247
|
+
} else directive |= CompletionDirective.FileCompletion;
|
|
248
|
+
break;
|
|
249
|
+
case "directory":
|
|
250
|
+
directive |= CompletionDirective.DirectoryCompletion;
|
|
251
|
+
break;
|
|
252
|
+
case "command":
|
|
253
|
+
if (vc.shellCommand) candidates.push(...executeShellCommand(vc.shellCommand));
|
|
254
|
+
directive |= CompletionDirective.NoFileCompletion;
|
|
255
|
+
break;
|
|
256
|
+
case "none":
|
|
257
|
+
directive |= CompletionDirective.NoFileCompletion;
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
directive,
|
|
262
|
+
fileExtensions
|
|
263
|
+
};
|
|
181
264
|
}
|
|
182
265
|
/**
|
|
183
266
|
* Generate subcommand candidates
|
|
@@ -236,43 +319,20 @@ function generateOptionNameCandidates(context) {
|
|
|
236
319
|
*/
|
|
237
320
|
function generateOptionValueCandidates(context) {
|
|
238
321
|
const candidates = [];
|
|
239
|
-
let directive = CompletionDirective.FilterPrefix;
|
|
240
322
|
if (!context.targetOption) return {
|
|
241
323
|
candidates,
|
|
242
|
-
directive
|
|
324
|
+
directive: CompletionDirective.FilterPrefix
|
|
243
325
|
};
|
|
244
326
|
const vc = context.targetOption.valueCompletion;
|
|
245
327
|
if (!vc) return {
|
|
246
328
|
candidates,
|
|
247
|
-
directive
|
|
329
|
+
directive: CompletionDirective.FilterPrefix
|
|
248
330
|
};
|
|
249
|
-
|
|
250
|
-
case "choices":
|
|
251
|
-
if (vc.choices) for (const choice of vc.choices) candidates.push({
|
|
252
|
-
value: choice,
|
|
253
|
-
type: "value"
|
|
254
|
-
});
|
|
255
|
-
break;
|
|
256
|
-
case "file":
|
|
257
|
-
directive |= CompletionDirective.FileCompletion;
|
|
258
|
-
addFileExtensionMetadata(candidates, vc.extensions);
|
|
259
|
-
break;
|
|
260
|
-
case "directory":
|
|
261
|
-
directive |= CompletionDirective.DirectoryCompletion;
|
|
262
|
-
break;
|
|
263
|
-
case "command":
|
|
264
|
-
if (vc.shellCommand) candidates.push({
|
|
265
|
-
value: `__command:${vc.shellCommand}`,
|
|
266
|
-
type: "value"
|
|
267
|
-
});
|
|
268
|
-
break;
|
|
269
|
-
case "none":
|
|
270
|
-
directive |= CompletionDirective.NoFileCompletion;
|
|
271
|
-
break;
|
|
272
|
-
}
|
|
331
|
+
const { directive, fileExtensions } = resolveValueCandidates(vc, candidates, context.currentWord);
|
|
273
332
|
return {
|
|
274
333
|
candidates,
|
|
275
|
-
directive
|
|
334
|
+
directive,
|
|
335
|
+
fileExtensions
|
|
276
336
|
};
|
|
277
337
|
}
|
|
278
338
|
/**
|
|
@@ -280,71 +340,36 @@ function generateOptionValueCandidates(context) {
|
|
|
280
340
|
*/
|
|
281
341
|
function generatePositionalCandidates(context) {
|
|
282
342
|
const candidates = [];
|
|
283
|
-
let directive = CompletionDirective.FilterPrefix;
|
|
284
343
|
const positionalIndex = context.positionalIndex ?? 0;
|
|
285
|
-
const positional = context.positionals[positionalIndex];
|
|
344
|
+
const positional = context.positionals[positionalIndex] ?? (context.positionals.at(-1)?.variadic ? context.positionals.at(-1) : void 0);
|
|
286
345
|
if (!positional) return {
|
|
287
346
|
candidates,
|
|
288
|
-
directive
|
|
347
|
+
directive: CompletionDirective.FilterPrefix
|
|
289
348
|
};
|
|
290
349
|
const vc = positional.valueCompletion;
|
|
291
350
|
if (!vc) return {
|
|
292
351
|
candidates,
|
|
293
|
-
directive
|
|
352
|
+
directive: CompletionDirective.FilterPrefix
|
|
294
353
|
};
|
|
295
|
-
|
|
296
|
-
case "choices":
|
|
297
|
-
if (vc.choices) for (const choice of vc.choices) candidates.push({
|
|
298
|
-
value: choice,
|
|
299
|
-
description: positional.description,
|
|
300
|
-
type: "value"
|
|
301
|
-
});
|
|
302
|
-
break;
|
|
303
|
-
case "file":
|
|
304
|
-
directive |= CompletionDirective.FileCompletion;
|
|
305
|
-
addFileExtensionMetadata(candidates, vc.extensions);
|
|
306
|
-
break;
|
|
307
|
-
case "directory":
|
|
308
|
-
directive |= CompletionDirective.DirectoryCompletion;
|
|
309
|
-
break;
|
|
310
|
-
case "command":
|
|
311
|
-
if (vc.shellCommand) candidates.push({
|
|
312
|
-
value: `__command:${vc.shellCommand}`,
|
|
313
|
-
type: "value"
|
|
314
|
-
});
|
|
315
|
-
break;
|
|
316
|
-
case "none":
|
|
317
|
-
directive |= CompletionDirective.NoFileCompletion;
|
|
318
|
-
break;
|
|
319
|
-
}
|
|
354
|
+
const { directive, fileExtensions } = resolveValueCandidates(vc, candidates, context.currentWord, positional.description);
|
|
320
355
|
return {
|
|
321
356
|
candidates,
|
|
322
|
-
directive
|
|
357
|
+
directive,
|
|
358
|
+
fileExtensions
|
|
323
359
|
};
|
|
324
360
|
}
|
|
325
|
-
/**
|
|
326
|
-
* Format candidates as shell completion output
|
|
327
|
-
*
|
|
328
|
-
* Format: value\tdescription (tab-separated)
|
|
329
|
-
* Last line: :directive_code
|
|
330
|
-
*/
|
|
331
|
-
function formatOutput(result) {
|
|
332
|
-
const lines = [];
|
|
333
|
-
for (const candidate of result.candidates) if (candidate.description) lines.push(`${candidate.value}\t${candidate.description}`);
|
|
334
|
-
else lines.push(candidate.value);
|
|
335
|
-
lines.push(`:${result.directive}`);
|
|
336
|
-
return lines.join("\n");
|
|
337
|
-
}
|
|
338
361
|
|
|
339
362
|
//#endregion
|
|
340
|
-
//#region src/completion/
|
|
341
|
-
/**
|
|
342
|
-
* Parse completion context from partial command line
|
|
343
|
-
*/
|
|
363
|
+
//#region src/completion/value-completion-resolver.ts
|
|
344
364
|
/**
|
|
345
365
|
* Resolve value completion from field metadata
|
|
366
|
+
*
|
|
367
|
+
* Priority:
|
|
368
|
+
* 1. Explicit custom completion (choices or shellCommand)
|
|
369
|
+
* 2. Explicit completion type (file, directory, none)
|
|
370
|
+
* 3. Auto-detected enum values from schema
|
|
346
371
|
*/
|
|
347
|
-
function resolveValueCompletion
|
|
372
|
+
function resolveValueCompletion(field) {
|
|
348
373
|
const meta = field.completion;
|
|
349
374
|
if (meta?.custom) {
|
|
350
375
|
if (meta.custom.choices && meta.custom.choices.length > 0) return {
|
|
@@ -369,6 +394,12 @@ function resolveValueCompletion$1(field) {
|
|
|
369
394
|
choices: field.enumValues
|
|
370
395
|
};
|
|
371
396
|
}
|
|
397
|
+
|
|
398
|
+
//#endregion
|
|
399
|
+
//#region src/completion/dynamic/context-parser.ts
|
|
400
|
+
/**
|
|
401
|
+
* Parse completion context from partial command line
|
|
402
|
+
*/
|
|
372
403
|
/**
|
|
373
404
|
* Extract options from a command
|
|
374
405
|
*/
|
|
@@ -382,7 +413,7 @@ function extractOptions$1(command) {
|
|
|
382
413
|
takesValue: field.type !== "boolean",
|
|
383
414
|
valueType: field.type,
|
|
384
415
|
required: field.required,
|
|
385
|
-
valueCompletion: resolveValueCompletion
|
|
416
|
+
valueCompletion: resolveValueCompletion(field)
|
|
386
417
|
}));
|
|
387
418
|
}
|
|
388
419
|
/**
|
|
@@ -396,7 +427,8 @@ function extractPositionalsForContext(command) {
|
|
|
396
427
|
position: index,
|
|
397
428
|
description: field.description,
|
|
398
429
|
required: field.required,
|
|
399
|
-
|
|
430
|
+
variadic: field.type === "array",
|
|
431
|
+
valueCompletion: resolveValueCompletion(field)
|
|
400
432
|
}));
|
|
401
433
|
}
|
|
402
434
|
/**
|
|
@@ -505,7 +537,11 @@ function parseCompletionContext(argv, rootCommand) {
|
|
|
505
537
|
if (opt && opt.takesValue) {
|
|
506
538
|
completionType = "option-value";
|
|
507
539
|
targetOption = opt;
|
|
508
|
-
} else
|
|
540
|
+
} else if (currentWord.startsWith("-")) completionType = "option-name";
|
|
541
|
+
else {
|
|
542
|
+
completionType = determineDefaultCompletionType(currentWord, subcommands, positionals, positionalCount);
|
|
543
|
+
if (completionType === "positional") positionalIndex = positionalCount;
|
|
544
|
+
}
|
|
509
545
|
} else if (!afterDoubleDash && currentWord.startsWith("--") && hasInlineValue(currentWord)) {
|
|
510
546
|
const optName = parseOptionName(currentWord);
|
|
511
547
|
const opt = findOption(options, optName);
|
|
@@ -515,7 +551,7 @@ function parseCompletionContext(argv, rootCommand) {
|
|
|
515
551
|
} else completionType = "option-name";
|
|
516
552
|
} else if (!afterDoubleDash && currentWord.startsWith("-")) completionType = "option-name";
|
|
517
553
|
else {
|
|
518
|
-
completionType = determineDefaultCompletionType(currentWord, subcommands, positionals, positionalCount);
|
|
554
|
+
completionType = determineDefaultCompletionType(currentWord, subcommands, positionals, positionalCount, afterDoubleDash);
|
|
519
555
|
if (completionType === "positional") positionalIndex = positionalCount;
|
|
520
556
|
}
|
|
521
557
|
return {
|
|
@@ -536,15 +572,99 @@ function parseCompletionContext(argv, rootCommand) {
|
|
|
536
572
|
/**
|
|
537
573
|
* Determine default completion type when not completing an option
|
|
538
574
|
*/
|
|
539
|
-
function determineDefaultCompletionType(currentWord, subcommands, positionals, positionalCount) {
|
|
575
|
+
function determineDefaultCompletionType(currentWord, subcommands, positionals, positionalCount, afterDoubleDash) {
|
|
576
|
+
if (afterDoubleDash) return "positional";
|
|
540
577
|
if (subcommands.length > 0) {
|
|
541
578
|
if (subcommands.filter((s) => s.startsWith(currentWord)).length > 0 || currentWord === "") return "subcommand";
|
|
542
579
|
}
|
|
543
580
|
if (positionalCount < positionals.length) return "positional";
|
|
544
|
-
if (positionals.length > 0) return "positional";
|
|
581
|
+
if (positionals.length > 0 && positionals[positionals.length - 1].variadic) return "positional";
|
|
545
582
|
return "subcommand";
|
|
546
583
|
}
|
|
547
584
|
|
|
585
|
+
//#endregion
|
|
586
|
+
//#region src/completion/dynamic/shell-formatter.ts
|
|
587
|
+
/**
|
|
588
|
+
* Format completion candidates for the specified shell
|
|
589
|
+
*
|
|
590
|
+
* @returns Shell-ready output string (lines separated by newline, last line is :directive)
|
|
591
|
+
*/
|
|
592
|
+
function formatForShell(result, options) {
|
|
593
|
+
switch (options.shell) {
|
|
594
|
+
case "bash": return formatForBash(result, options);
|
|
595
|
+
case "zsh": return formatForZsh(result, options);
|
|
596
|
+
case "fish": return formatForFish(result, options);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Check if the FilterPrefix directive is set
|
|
601
|
+
*/
|
|
602
|
+
function shouldFilterPrefix(directive) {
|
|
603
|
+
return (directive & CompletionDirective.FilterPrefix) !== 0;
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Filter candidates by prefix
|
|
607
|
+
*/
|
|
608
|
+
function filterByPrefix(candidates, prefix) {
|
|
609
|
+
if (!prefix) return candidates;
|
|
610
|
+
return candidates.filter((c) => c.value.startsWith(prefix));
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Append extension metadata and directive to output lines
|
|
614
|
+
*/
|
|
615
|
+
function appendMetadata(lines, result) {
|
|
616
|
+
if (result.fileExtensions && result.fileExtensions.length > 0) lines.push(`@ext:${result.fileExtensions.join(",")}`);
|
|
617
|
+
lines.push(`:${result.directive}`);
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Format for bash
|
|
621
|
+
*
|
|
622
|
+
* - Pre-filters candidates by currentWord prefix (replaces compgen -W)
|
|
623
|
+
* - Handles --opt=value inline values by prepending prefix
|
|
624
|
+
* - Outputs plain values only (no descriptions - bash COMPREPLY doesn't support them)
|
|
625
|
+
* - Last line: :directive
|
|
626
|
+
*/
|
|
627
|
+
function formatForBash(result, options) {
|
|
628
|
+
let { candidates } = result;
|
|
629
|
+
if (shouldFilterPrefix(result.directive)) candidates = filterByPrefix(candidates, options.currentWord);
|
|
630
|
+
const lines = candidates.map((c) => {
|
|
631
|
+
if (options.inlinePrefix) return `${options.inlinePrefix}${c.value}`;
|
|
632
|
+
return c.value;
|
|
633
|
+
});
|
|
634
|
+
appendMetadata(lines, result);
|
|
635
|
+
return lines.join("\n");
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Format for zsh
|
|
639
|
+
*
|
|
640
|
+
* - Outputs value:description pairs for _describe
|
|
641
|
+
* - Colons in values/descriptions are escaped with backslash
|
|
642
|
+
* - Last line: :directive
|
|
643
|
+
*/
|
|
644
|
+
function formatForZsh(result, _options) {
|
|
645
|
+
const lines = result.candidates.map((c) => {
|
|
646
|
+
const escapedValue = c.value.replace(/:/g, "\\:");
|
|
647
|
+
if (c.description) return `${escapedValue}:${c.description.replace(/:/g, "\\:")}`;
|
|
648
|
+
return escapedValue;
|
|
649
|
+
});
|
|
650
|
+
appendMetadata(lines, result);
|
|
651
|
+
return lines.join("\n");
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Format for fish
|
|
655
|
+
*
|
|
656
|
+
* - Outputs value\tdescription pairs
|
|
657
|
+
* - Last line: :directive
|
|
658
|
+
*/
|
|
659
|
+
function formatForFish(result, _options) {
|
|
660
|
+
const lines = result.candidates.map((c) => {
|
|
661
|
+
if (c.description) return `${c.value}\t${c.description}`;
|
|
662
|
+
return c.value;
|
|
663
|
+
});
|
|
664
|
+
appendMetadata(lines, result);
|
|
665
|
+
return lines.join("\n");
|
|
666
|
+
}
|
|
667
|
+
|
|
548
668
|
//#endregion
|
|
549
669
|
//#region src/completion/dynamic/complete-command.ts
|
|
550
670
|
/**
|
|
@@ -553,24 +673,35 @@ function determineDefaultCompletionType(currentWord, subcommands, positionals, p
|
|
|
553
673
|
* This creates a hidden `__complete` command that outputs completion candidates
|
|
554
674
|
* for shell scripts to consume. Usage:
|
|
555
675
|
*
|
|
556
|
-
* mycli __complete -- build --fo
|
|
557
|
-
* mycli __complete -- plugin add
|
|
676
|
+
* mycli __complete --shell bash -- build --fo
|
|
677
|
+
* mycli __complete --shell zsh -- plugin add
|
|
558
678
|
*
|
|
559
|
-
* Output format:
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
* :
|
|
679
|
+
* Output format depends on the target shell:
|
|
680
|
+
* bash: plain values (pre-filtered by prefix), last line :directive
|
|
681
|
+
* zsh: value:description pairs, last line :directive
|
|
682
|
+
* fish: value\tdescription pairs, last line :directive
|
|
683
|
+
*/
|
|
684
|
+
/**
|
|
685
|
+
* Detect inline option-value prefix (e.g., "--format=" from "--format=json")
|
|
563
686
|
*/
|
|
687
|
+
function detectInlinePrefix(currentWord) {
|
|
688
|
+
if (currentWord.startsWith("--") && currentWord.includes("=")) return currentWord.slice(0, currentWord.indexOf("=") + 1);
|
|
689
|
+
}
|
|
564
690
|
/**
|
|
565
691
|
* Schema for the __complete command
|
|
566
|
-
*
|
|
567
|
-
* Arguments after -- are collected as the completion arguments
|
|
568
692
|
*/
|
|
569
|
-
const completeArgsSchema = z.object({
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
693
|
+
const completeArgsSchema = z.object({
|
|
694
|
+
shell: arg(z.enum([
|
|
695
|
+
"bash",
|
|
696
|
+
"zsh",
|
|
697
|
+
"fish"
|
|
698
|
+
]), { description: "Target shell for output formatting" }),
|
|
699
|
+
args: arg(z.array(z.string()).default([]), {
|
|
700
|
+
positional: true,
|
|
701
|
+
description: "Arguments to complete",
|
|
702
|
+
variadic: true
|
|
703
|
+
})
|
|
704
|
+
});
|
|
574
705
|
/**
|
|
575
706
|
* Create the dynamic completion command
|
|
576
707
|
*
|
|
@@ -583,8 +714,15 @@ function createDynamicCompleteCommand(rootCommand, _programName) {
|
|
|
583
714
|
name: "__complete",
|
|
584
715
|
args: completeArgsSchema,
|
|
585
716
|
run(args) {
|
|
586
|
-
const
|
|
587
|
-
|
|
717
|
+
const context = parseCompletionContext(args.args, rootCommand);
|
|
718
|
+
const result = generateCandidates(context);
|
|
719
|
+
const inlinePrefix = detectInlinePrefix(context.currentWord);
|
|
720
|
+
const output = formatForShell(result, {
|
|
721
|
+
shell: args.shell,
|
|
722
|
+
currentWord: inlinePrefix ? context.currentWord.slice(inlinePrefix.length) : context.currentWord,
|
|
723
|
+
inlinePrefix
|
|
724
|
+
});
|
|
725
|
+
console.log(output);
|
|
588
726
|
}
|
|
589
727
|
});
|
|
590
728
|
}
|
|
@@ -600,81 +738,75 @@ function hasCompleteCommand(command) {
|
|
|
600
738
|
/**
|
|
601
739
|
* Generate fish completion script for a command
|
|
602
740
|
*
|
|
603
|
-
* Generates a
|
|
741
|
+
* Generates a minimal script that delegates all logic to the CLI's __complete command.
|
|
742
|
+
* The shell script only handles:
|
|
743
|
+
* - Getting current command line tokens
|
|
744
|
+
* - Calling __complete with --shell fish
|
|
745
|
+
* - Echoing output as completions
|
|
746
|
+
* - Falling back to native file/directory completion when directed
|
|
604
747
|
*/
|
|
605
748
|
function generateFishCompletion(_command, options) {
|
|
606
749
|
const programName = options.programName;
|
|
607
750
|
return {
|
|
608
751
|
script: `# Fish completion for ${programName}
|
|
609
752
|
# Generated by politty
|
|
610
|
-
# This script calls the CLI to generate completions dynamically
|
|
611
753
|
|
|
612
754
|
function __fish_${programName}_complete
|
|
613
|
-
# Get current command line arguments
|
|
614
755
|
set -l args (commandline -opc)
|
|
615
|
-
# Remove the program name
|
|
616
756
|
set -e args[1]
|
|
617
|
-
|
|
618
|
-
# Call the CLI to get completions
|
|
619
757
|
set -l directive 0
|
|
620
|
-
set -l
|
|
621
|
-
|
|
758
|
+
set -l extensions ""
|
|
759
|
+
|
|
760
|
+
# commandline -opc excludes the current token; always include it
|
|
761
|
+
set -l ct (commandline -ct)
|
|
762
|
+
if test (count $ct) -eq 0
|
|
763
|
+
set -a args ""
|
|
764
|
+
else
|
|
765
|
+
set -a args $ct
|
|
766
|
+
end
|
|
622
767
|
|
|
623
|
-
for line in (${programName} __complete -- $args 2>/dev/null)
|
|
768
|
+
for line in (${programName} __complete --shell fish -- $args 2>/dev/null)
|
|
624
769
|
if string match -q ':*' -- $line
|
|
625
|
-
# Parse directive
|
|
626
770
|
set directive (string sub -s 2 -- $line)
|
|
627
|
-
else if string match -q '
|
|
628
|
-
|
|
629
|
-
set command_completion (string sub -s 11 -- $line)
|
|
630
|
-
else if string match -q '__extensions:*' -- $line
|
|
631
|
-
# Parse optional file extension metadata
|
|
632
|
-
set file_extensions (string sub -s 14 -- $line)
|
|
771
|
+
else if string match -q '@ext:*' -- $line
|
|
772
|
+
set extensions (string sub -s 6 -- $line)
|
|
633
773
|
else if test -n "$line"
|
|
634
|
-
|
|
635
|
-
set -l parts (string split \\t -- $line)
|
|
636
|
-
if test (count $parts) -ge 2
|
|
637
|
-
echo $parts[1]\\t$parts[2]
|
|
638
|
-
else
|
|
639
|
-
echo $parts[1]
|
|
640
|
-
end
|
|
774
|
+
echo $line
|
|
641
775
|
end
|
|
642
776
|
end
|
|
643
777
|
|
|
644
|
-
#
|
|
645
|
-
if test
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
778
|
+
# 16 = FileCompletion: delegate entirely to native file completion
|
|
779
|
+
if test (math "bitand($directive, 16)") -ne 0
|
|
780
|
+
__fish_complete_path
|
|
781
|
+
return
|
|
782
|
+
end
|
|
783
|
+
|
|
784
|
+
# Extension-filtered file completion: keep matching files + directories
|
|
785
|
+
if test -n "$extensions"
|
|
786
|
+
set -l cur (commandline -ct)
|
|
787
|
+
test (count $cur) -eq 0; and set cur ""
|
|
788
|
+
__fish_complete_directories "$cur"
|
|
789
|
+
for ext in (string split "," -- $extensions)
|
|
790
|
+
for f in "$cur"*.$ext
|
|
791
|
+
if test -f "$f"
|
|
792
|
+
echo $f
|
|
793
|
+
end
|
|
649
794
|
end
|
|
650
795
|
end
|
|
796
|
+
return
|
|
651
797
|
end
|
|
652
798
|
|
|
653
|
-
#
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
echo "__directive:file"
|
|
657
|
-
else if test (math "$directive & 32") -ne 0
|
|
658
|
-
echo "__directive:directory"
|
|
799
|
+
# 32 = DirectoryCompletion: add native directory matches
|
|
800
|
+
if test (math "bitand($directive, 32)") -ne 0
|
|
801
|
+
__fish_complete_directories
|
|
659
802
|
end
|
|
660
803
|
end
|
|
661
804
|
|
|
662
805
|
# Clear existing completions
|
|
663
806
|
complete -e -c ${programName}
|
|
664
807
|
|
|
665
|
-
#
|
|
666
|
-
complete -c ${programName} -f -a '(
|
|
667
|
-
set -l completions (__fish_${programName}_complete)
|
|
668
|
-
for c in $completions
|
|
669
|
-
if string match -q "__directive:file" -- $c
|
|
670
|
-
__fish_complete_path
|
|
671
|
-
else if string match -q "__directive:directory" -- $c
|
|
672
|
-
__fish_complete_directories
|
|
673
|
-
else
|
|
674
|
-
echo $c
|
|
675
|
-
end
|
|
676
|
-
end
|
|
677
|
-
)'
|
|
808
|
+
# Register completion
|
|
809
|
+
complete -c ${programName} -f -a '(__fish_${programName}_complete)'
|
|
678
810
|
`,
|
|
679
811
|
shell: "fish",
|
|
680
812
|
installInstructions: `# To enable completions, run one of the following:
|
|
@@ -696,7 +828,12 @@ source ~/.config/fish/completions/${programName}.fish`
|
|
|
696
828
|
/**
|
|
697
829
|
* Generate zsh completion script for a command
|
|
698
830
|
*
|
|
699
|
-
* Generates a
|
|
831
|
+
* Generates a minimal script that delegates all logic to the CLI's __complete command.
|
|
832
|
+
* The shell script only handles:
|
|
833
|
+
* - Getting current command line tokens
|
|
834
|
+
* - Calling __complete with --shell zsh
|
|
835
|
+
* - Passing output directly to _describe
|
|
836
|
+
* - Falling back to native file/directory completion when directed
|
|
700
837
|
*/
|
|
701
838
|
function generateZshCompletion(_command, options) {
|
|
702
839
|
const programName = options.programName;
|
|
@@ -708,57 +845,55 @@ function generateZshCompletion(_command, options) {
|
|
|
708
845
|
|
|
709
846
|
_${programName}() {
|
|
710
847
|
local -a candidates
|
|
711
|
-
local
|
|
712
|
-
local
|
|
713
|
-
local
|
|
714
|
-
|
|
715
|
-
# Get the current words being completed
|
|
716
|
-
local -a args
|
|
717
|
-
args=("\${words[@]:1}")
|
|
718
|
-
|
|
719
|
-
# Call the CLI to get completions
|
|
720
|
-
output=("\${(@f)$(${programName} __complete -- "\${args[@]}" 2>/dev/null)}")
|
|
848
|
+
local line directive=0
|
|
849
|
+
local -a args=("\${words[@]:1}")
|
|
850
|
+
local -a output=("\${(@f)$(${programName} __complete --shell zsh -- "\${args[@]}" 2>/dev/null)}")
|
|
721
851
|
|
|
722
|
-
|
|
852
|
+
local extensions=""
|
|
723
853
|
for line in "\${output[@]}"; do
|
|
724
854
|
if [[ "$line" == :* ]]; then
|
|
725
855
|
directive="\${line:1}"
|
|
726
|
-
elif [[ "$line" ==
|
|
727
|
-
|
|
728
|
-
elif [[ "$line" == __extensions:* ]]; then
|
|
729
|
-
file_extensions="\${line#__extensions:}"
|
|
856
|
+
elif [[ "$line" == @ext:* ]]; then
|
|
857
|
+
extensions="\${line:5}"
|
|
730
858
|
elif [[ -n "$line" ]]; then
|
|
731
|
-
|
|
732
|
-
local desc="\${line#*$'\\t'}"
|
|
733
|
-
if [[ "$name" == "$desc" ]]; then
|
|
734
|
-
candidates+=("$name")
|
|
735
|
-
else
|
|
736
|
-
candidates+=("$name:$desc")
|
|
737
|
-
fi
|
|
859
|
+
candidates+=("$line")
|
|
738
860
|
fi
|
|
739
861
|
done
|
|
740
862
|
|
|
741
|
-
#
|
|
742
|
-
if
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
863
|
+
# 16 = FileCompletion: delegate entirely to native file completion
|
|
864
|
+
if (( directive & 16 )); then
|
|
865
|
+
_files
|
|
866
|
+
return 0
|
|
867
|
+
fi
|
|
868
|
+
|
|
869
|
+
# Extension-filtered file completion: call _files -g per extension
|
|
870
|
+
if [[ -n "$extensions" ]]; then
|
|
871
|
+
local ext
|
|
872
|
+
for ext in \${(s:,:)extensions}; do
|
|
873
|
+
_files -g "*.$ext"
|
|
748
874
|
done
|
|
875
|
+
return 0
|
|
749
876
|
fi
|
|
750
877
|
|
|
751
|
-
#
|
|
752
|
-
# 16 = FileCompletion, 32 = DirectoryCompletion
|
|
753
|
-
if (( directive & 16 )); then
|
|
754
|
-
_files
|
|
755
|
-
elif (( directive & 32 )); then
|
|
756
|
-
_files -/
|
|
757
|
-
elif (( \${#candidates[@]} > 0 )); then
|
|
878
|
+
if (( \${#candidates[@]} > 0 )); then
|
|
758
879
|
_describe 'completions' candidates
|
|
759
880
|
fi
|
|
881
|
+
|
|
882
|
+
# 32 = DirectoryCompletion: add native directory matches
|
|
883
|
+
if (( directive & 32 )); then
|
|
884
|
+
_files -/
|
|
885
|
+
fi
|
|
886
|
+
|
|
887
|
+
# 2 = NoFileCompletion, 32 = DirectoryCompletion:
|
|
888
|
+
# prevent fallback to default completers (e.g. file completion)
|
|
889
|
+
if (( directive & 2 )) || (( directive & 32 )); then
|
|
890
|
+
return 0
|
|
891
|
+
fi
|
|
760
892
|
}
|
|
761
893
|
|
|
894
|
+
# Prevent _files -g from falling back to showing all files when no pattern matches
|
|
895
|
+
zstyle ':completion:*:*:${programName}:*' file-patterns '%p:globbed-files *(-/):directories'
|
|
896
|
+
|
|
762
897
|
compdef _${programName} ${programName}
|
|
763
898
|
`,
|
|
764
899
|
shell: "zsh",
|
|
@@ -785,39 +920,6 @@ source ~/.zshrc`
|
|
|
785
920
|
* Extract completion data from commands
|
|
786
921
|
*/
|
|
787
922
|
/**
|
|
788
|
-
* Resolve value completion from field metadata
|
|
789
|
-
*
|
|
790
|
-
* Priority:
|
|
791
|
-
* 1. Explicit custom completion (choices or shellCommand)
|
|
792
|
-
* 2. Explicit completion type (file, directory, none)
|
|
793
|
-
* 3. Auto-detected enum values from schema
|
|
794
|
-
*/
|
|
795
|
-
function resolveValueCompletion(field) {
|
|
796
|
-
const meta = field.completion;
|
|
797
|
-
if (meta?.custom) {
|
|
798
|
-
if (meta.custom.choices && meta.custom.choices.length > 0) return {
|
|
799
|
-
type: "choices",
|
|
800
|
-
choices: meta.custom.choices
|
|
801
|
-
};
|
|
802
|
-
if (meta.custom.shellCommand) return {
|
|
803
|
-
type: "command",
|
|
804
|
-
shellCommand: meta.custom.shellCommand
|
|
805
|
-
};
|
|
806
|
-
}
|
|
807
|
-
if (meta?.type) {
|
|
808
|
-
if (meta.type === "file") return meta.extensions ? {
|
|
809
|
-
type: "file",
|
|
810
|
-
extensions: meta.extensions
|
|
811
|
-
} : { type: "file" };
|
|
812
|
-
if (meta.type === "directory") return { type: "directory" };
|
|
813
|
-
if (meta.type === "none") return { type: "none" };
|
|
814
|
-
}
|
|
815
|
-
if (field.enumValues && field.enumValues.length > 0) return {
|
|
816
|
-
type: "choices",
|
|
817
|
-
choices: field.enumValues
|
|
818
|
-
};
|
|
819
|
-
}
|
|
820
|
-
/**
|
|
821
923
|
* Convert a resolved field to a completable option
|
|
822
924
|
*/
|
|
823
925
|
function fieldToOption(field) {
|
|
@@ -894,5 +996,5 @@ function extractCompletionData(command, programName) {
|
|
|
894
996
|
}
|
|
895
997
|
|
|
896
998
|
//#endregion
|
|
897
|
-
export { createDynamicCompleteCommand as a,
|
|
898
|
-
//# sourceMappingURL=extractor-
|
|
999
|
+
export { createDynamicCompleteCommand as a, parseCompletionContext as c, generateCandidates as d, generateBashCompletion as f, generateFishCompletion as i, resolveValueCompletion as l, extractPositionals as n, hasCompleteCommand as o, defineCommand as p, generateZshCompletion as r, formatForShell as s, extractCompletionData as t, CompletionDirective as u };
|
|
1000
|
+
//# sourceMappingURL=extractor-DO-FDKkW.js.map
|