padrone 1.1.0 → 1.3.0
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/CHANGELOG.md +97 -1
- package/LICENSE +1 -1
- package/README.md +60 -30
- package/dist/args-DFEI7_G_.mjs +197 -0
- package/dist/args-DFEI7_G_.mjs.map +1 -0
- package/dist/chunk-y_GBKt04.mjs +5 -0
- package/dist/codegen/index.d.mts +305 -0
- package/dist/codegen/index.d.mts.map +1 -0
- package/dist/codegen/index.mjs +1358 -0
- package/dist/codegen/index.mjs.map +1 -0
- package/dist/completion.d.mts +64 -0
- package/dist/completion.d.mts.map +1 -0
- package/dist/completion.mjs +417 -0
- package/dist/completion.mjs.map +1 -0
- package/dist/docs/index.d.mts +34 -0
- package/dist/docs/index.d.mts.map +1 -0
- package/dist/docs/index.mjs +405 -0
- package/dist/docs/index.mjs.map +1 -0
- package/dist/formatter-XroimS3Q.d.mts +83 -0
- package/dist/formatter-XroimS3Q.d.mts.map +1 -0
- package/dist/help-CgGP7hQU.mjs +1229 -0
- package/dist/help-CgGP7hQU.mjs.map +1 -0
- package/dist/index.d.mts +120 -546
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1220 -1204
- package/dist/index.mjs.map +1 -1
- package/dist/test.d.mts +112 -0
- package/dist/test.d.mts.map +1 -0
- package/dist/test.mjs +138 -0
- package/dist/test.mjs.map +1 -0
- package/dist/types-BS7RP5Ls.d.mts +1059 -0
- package/dist/types-BS7RP5Ls.d.mts.map +1 -0
- package/dist/update-check-EbNDkzyV.mjs +146 -0
- package/dist/update-check-EbNDkzyV.mjs.map +1 -0
- package/package.json +61 -21
- package/src/args.ts +457 -0
- package/src/cli/completions.ts +29 -0
- package/src/cli/docs.ts +86 -0
- package/src/cli/doctor.ts +330 -0
- package/src/cli/index.ts +159 -0
- package/src/cli/init.ts +135 -0
- package/src/cli/link.ts +320 -0
- package/src/cli/wrap.ts +152 -0
- package/src/codegen/README.md +118 -0
- package/src/codegen/code-builder.ts +226 -0
- package/src/codegen/discovery.ts +232 -0
- package/src/codegen/file-emitter.ts +73 -0
- package/src/codegen/generators/barrel-file.ts +16 -0
- package/src/codegen/generators/command-file.ts +197 -0
- package/src/codegen/generators/command-tree.ts +124 -0
- package/src/codegen/index.ts +33 -0
- package/src/codegen/parsers/fish.ts +163 -0
- package/src/codegen/parsers/help.ts +378 -0
- package/src/codegen/parsers/merge.ts +158 -0
- package/src/codegen/parsers/zsh.ts +221 -0
- package/src/codegen/schema-to-code.ts +199 -0
- package/src/codegen/template.ts +69 -0
- package/src/codegen/types.ts +143 -0
- package/src/colorizer.ts +2 -2
- package/src/command-utils.ts +504 -0
- package/src/completion.ts +110 -97
- package/src/create.ts +1048 -308
- package/src/docs/index.ts +607 -0
- package/src/errors.ts +131 -0
- package/src/formatter.ts +195 -73
- package/src/help.ts +159 -58
- package/src/index.ts +12 -15
- package/src/interactive.ts +169 -0
- package/src/parse.ts +52 -21
- package/src/repl-loop.ts +317 -0
- package/src/runtime.ts +304 -0
- package/src/shell-utils.ts +83 -0
- package/src/test.ts +285 -0
- package/src/type-helpers.ts +10 -10
- package/src/type-utils.ts +124 -14
- package/src/types.ts +752 -154
- package/src/update-check.ts +244 -0
- package/src/wrap.ts +44 -40
- package/src/zod.d.ts +2 -2
- package/src/options.ts +0 -180
package/src/completion.ts
CHANGED
|
@@ -1,46 +1,8 @@
|
|
|
1
|
-
import { extractSchemaMetadata } from './
|
|
1
|
+
import { extractSchemaMetadata } from './args.ts';
|
|
2
|
+
import { detectShell, getRcFile, type ShellType, writeToRcFile } from './shell-utils.ts';
|
|
2
3
|
import type { AnyPadroneCommand } from './types.ts';
|
|
3
4
|
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Detects the current shell from environment variables and process info.
|
|
8
|
-
* @returns The detected shell type, or undefined if unknown
|
|
9
|
-
*/
|
|
10
|
-
export function detectShell(): ShellType | undefined {
|
|
11
|
-
if (typeof process === 'undefined') return undefined;
|
|
12
|
-
|
|
13
|
-
// Method 1: Check SHELL environment variable (most common)
|
|
14
|
-
const shellEnv = process.env.SHELL || '';
|
|
15
|
-
if (shellEnv.includes('zsh')) return 'zsh';
|
|
16
|
-
if (shellEnv.includes('bash')) return 'bash';
|
|
17
|
-
if (shellEnv.includes('fish')) return 'fish';
|
|
18
|
-
|
|
19
|
-
// Method 2: Check Windows-specific shells
|
|
20
|
-
if (process.env.PSModulePath || process.env.POWERSHELL_DISTRIBUTION_CHANNEL) {
|
|
21
|
-
return 'powershell';
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Method 3: Check parent process on Unix-like systems
|
|
25
|
-
try {
|
|
26
|
-
const { execSync } = require('node:child_process');
|
|
27
|
-
const ppid = process.ppid;
|
|
28
|
-
if (ppid) {
|
|
29
|
-
const processName = execSync(`ps -p ${ppid} -o comm=`, {
|
|
30
|
-
encoding: 'utf-8',
|
|
31
|
-
stdio: ['pipe', 'pipe', 'ignore'],
|
|
32
|
-
}).trim();
|
|
33
|
-
|
|
34
|
-
if (processName.includes('zsh')) return 'zsh';
|
|
35
|
-
if (processName.includes('bash')) return 'bash';
|
|
36
|
-
if (processName.includes('fish')) return 'fish';
|
|
37
|
-
}
|
|
38
|
-
} catch {
|
|
39
|
-
// Ignore errors (e.g., ps not available)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return undefined;
|
|
43
|
-
}
|
|
5
|
+
export { detectShell, escapeRegExp, getRcFile, type ShellType, writeToRcFile } from './shell-utils.ts';
|
|
44
6
|
|
|
45
7
|
/**
|
|
46
8
|
* Collects all commands from a program recursively.
|
|
@@ -61,29 +23,29 @@ function collectAllCommands(cmd: AnyPadroneCommand): AnyPadroneCommand[] {
|
|
|
61
23
|
}
|
|
62
24
|
|
|
63
25
|
/**
|
|
64
|
-
* Extracts all
|
|
26
|
+
* Extracts all argument names from a command's schema.
|
|
65
27
|
*/
|
|
66
|
-
function
|
|
67
|
-
const
|
|
28
|
+
function extractArguments(cmd: AnyPadroneCommand): { name: string; alias?: string; isBoolean: boolean }[] {
|
|
29
|
+
const argList: { name: string; alias?: string; isBoolean: boolean }[] = [];
|
|
68
30
|
|
|
69
|
-
if (!cmd.
|
|
31
|
+
if (!cmd.argsSchema) return argList;
|
|
70
32
|
|
|
71
33
|
try {
|
|
72
|
-
const
|
|
73
|
-
const { aliases } = extractSchemaMetadata(cmd.
|
|
34
|
+
const argsMeta = cmd.meta?.fields;
|
|
35
|
+
const { aliases } = extractSchemaMetadata(cmd.argsSchema, argsMeta, cmd.meta?.autoAlias);
|
|
74
36
|
|
|
75
|
-
// Reverse aliases map (alias ->
|
|
76
|
-
const
|
|
77
|
-
for (const [
|
|
78
|
-
|
|
37
|
+
// Reverse aliases map (alias -> arg name)
|
|
38
|
+
const aliasToArgument: Record<string, string> = {};
|
|
39
|
+
for (const [arg, alias] of Object.entries(aliases)) {
|
|
40
|
+
aliasToArgument[alias] = arg;
|
|
79
41
|
}
|
|
80
42
|
|
|
81
|
-
const jsonSchema = cmd.
|
|
43
|
+
const jsonSchema = cmd.argsSchema['~standard'].jsonSchema.input({ target: 'draft-2020-12' }) as Record<string, any>;
|
|
82
44
|
|
|
83
45
|
if (jsonSchema.type === 'object' && jsonSchema.properties) {
|
|
84
46
|
for (const [key, prop] of Object.entries(jsonSchema.properties as Record<string, any>)) {
|
|
85
|
-
const alias = Object.entries(aliases).find(([
|
|
86
|
-
|
|
47
|
+
const alias = Object.entries(aliases).find(([arg]) => arg === key)?.[1];
|
|
48
|
+
argList.push({
|
|
87
49
|
name: key,
|
|
88
50
|
alias: alias,
|
|
89
51
|
isBoolean: prop?.type === 'boolean',
|
|
@@ -94,7 +56,7 @@ function extractOptions(cmd: AnyPadroneCommand): { name: string; alias?: string;
|
|
|
94
56
|
// Ignore schema parsing errors
|
|
95
57
|
}
|
|
96
58
|
|
|
97
|
-
return
|
|
59
|
+
return argList;
|
|
98
60
|
}
|
|
99
61
|
|
|
100
62
|
/**
|
|
@@ -105,19 +67,19 @@ export function generateBashCompletion(program: AnyPadroneCommand): string {
|
|
|
105
67
|
const commands = collectAllCommands(program);
|
|
106
68
|
const commandNames = commands.map((c) => c.name).join(' ');
|
|
107
69
|
|
|
108
|
-
// Collect all
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
70
|
+
// Collect all args from all commands
|
|
71
|
+
const allArguments = new Set<string>();
|
|
72
|
+
allArguments.add('--help');
|
|
73
|
+
allArguments.add('--version');
|
|
112
74
|
|
|
113
75
|
for (const cmd of [program, ...commands]) {
|
|
114
|
-
for (const
|
|
115
|
-
|
|
116
|
-
if (
|
|
76
|
+
for (const arg of extractArguments(cmd)) {
|
|
77
|
+
allArguments.add(`--${arg.name}`);
|
|
78
|
+
if (arg.alias) allArguments.add(`-${arg.alias}`);
|
|
117
79
|
}
|
|
118
80
|
}
|
|
119
81
|
|
|
120
|
-
const
|
|
82
|
+
const argsList = Array.from(allArguments).join(' ');
|
|
121
83
|
|
|
122
84
|
return `###-begin-${programName}-completion-###
|
|
123
85
|
#
|
|
@@ -141,11 +103,11 @@ if type complete &>/dev/null; then
|
|
|
141
103
|
prev="\${words[cword-1]}"
|
|
142
104
|
|
|
143
105
|
local commands="${commandNames}"
|
|
144
|
-
local
|
|
106
|
+
local args="${argsList}"
|
|
145
107
|
|
|
146
|
-
# Complete
|
|
108
|
+
# Complete args when current word starts with -
|
|
147
109
|
if [[ "$cur" == -* ]]; then
|
|
148
|
-
COMPREPLY=($(compgen -W "$
|
|
110
|
+
COMPREPLY=($(compgen -W "$args" -- "$cur"))
|
|
149
111
|
return 0
|
|
150
112
|
fi
|
|
151
113
|
|
|
@@ -157,10 +119,10 @@ elif type compdef &>/dev/null; then
|
|
|
157
119
|
_${programName}_completion() {
|
|
158
120
|
local si=$IFS
|
|
159
121
|
local commands="${commandNames}"
|
|
160
|
-
local
|
|
122
|
+
local args="${argsList}"
|
|
161
123
|
|
|
162
124
|
if [[ "\${words[CURRENT]}" == -* ]]; then
|
|
163
|
-
compadd -- \${=
|
|
125
|
+
compadd -- \${=args}
|
|
164
126
|
else
|
|
165
127
|
compadd -- \${=commands}
|
|
166
128
|
fi
|
|
@@ -170,10 +132,10 @@ elif type compdef &>/dev/null; then
|
|
|
170
132
|
elif type compctl &>/dev/null; then
|
|
171
133
|
_${programName}_completion() {
|
|
172
134
|
local commands="${commandNames}"
|
|
173
|
-
local
|
|
135
|
+
local args="${argsList}"
|
|
174
136
|
|
|
175
137
|
if [[ "\${words[CURRENT]}" == -* ]]; then
|
|
176
|
-
reply=(\${=
|
|
138
|
+
reply=(\${=args})
|
|
177
139
|
else
|
|
178
140
|
reply=(\${=commands})
|
|
179
141
|
fi
|
|
@@ -199,25 +161,25 @@ export function generateZshCompletion(program: AnyPadroneCommand): string {
|
|
|
199
161
|
})
|
|
200
162
|
.join('\n');
|
|
201
163
|
|
|
202
|
-
// Collect all
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
164
|
+
// Collect all args with descriptions
|
|
165
|
+
const argumentCompletions: string[] = [];
|
|
166
|
+
argumentCompletions.push(" '--help[Show help information]'");
|
|
167
|
+
argumentCompletions.push(" '--version[Show version number]'");
|
|
206
168
|
|
|
207
|
-
const
|
|
169
|
+
const seenArgs = new Set<string>(['help', 'version']);
|
|
208
170
|
|
|
209
171
|
for (const cmd of [program, ...commands]) {
|
|
210
|
-
for (const
|
|
211
|
-
if (
|
|
212
|
-
|
|
172
|
+
for (const arg of extractArguments(cmd)) {
|
|
173
|
+
if (seenArgs.has(arg.name)) continue;
|
|
174
|
+
seenArgs.add(arg.name);
|
|
213
175
|
|
|
214
|
-
const desc = cmd.meta?.
|
|
176
|
+
const desc = cmd.meta?.fields?.[arg.name]?.description || '';
|
|
215
177
|
const escapedDesc = desc.replace(/'/g, "'\\''").replace(/\[/g, '\\[').replace(/\]/g, '\\]');
|
|
216
178
|
|
|
217
|
-
if (
|
|
218
|
-
|
|
179
|
+
if (arg.alias) {
|
|
180
|
+
argumentCompletions.push(` {-${arg.alias},--${arg.name}}'[${escapedDesc}]'`);
|
|
219
181
|
} else {
|
|
220
|
-
|
|
182
|
+
argumentCompletions.push(` '--${arg.name}[${escapedDesc}]'`);
|
|
221
183
|
}
|
|
222
184
|
}
|
|
223
185
|
}
|
|
@@ -233,18 +195,18 @@ export function generateZshCompletion(program: AnyPadroneCommand): string {
|
|
|
233
195
|
|
|
234
196
|
_${programName}() {
|
|
235
197
|
local -a commands
|
|
236
|
-
local -a
|
|
198
|
+
local -a args
|
|
237
199
|
|
|
238
200
|
commands=(
|
|
239
201
|
${commandCompletions}
|
|
240
202
|
)
|
|
241
203
|
|
|
242
|
-
|
|
243
|
-
${
|
|
204
|
+
args=(
|
|
205
|
+
${argumentCompletions.join('\n')}
|
|
244
206
|
)
|
|
245
207
|
|
|
246
208
|
_arguments -s \\
|
|
247
|
-
$
|
|
209
|
+
$args \\
|
|
248
210
|
'1: :->command' \\
|
|
249
211
|
'*::arg:->args'
|
|
250
212
|
|
|
@@ -287,24 +249,24 @@ export function generateFishCompletion(program: AnyPadroneCommand): string {
|
|
|
287
249
|
}
|
|
288
250
|
|
|
289
251
|
lines.push('');
|
|
290
|
-
lines.push('# Global
|
|
252
|
+
lines.push('# Global arguments');
|
|
291
253
|
lines.push(`complete -c ${programName} -l help -d 'Show help information'`);
|
|
292
254
|
lines.push(`complete -c ${programName} -l version -d 'Show version number'`);
|
|
293
255
|
|
|
294
|
-
const
|
|
256
|
+
const seenArgs = new Set<string>(['help', 'version']);
|
|
295
257
|
|
|
296
258
|
for (const cmd of [program, ...commands]) {
|
|
297
|
-
for (const
|
|
298
|
-
if (
|
|
299
|
-
|
|
259
|
+
for (const arg of extractArguments(cmd)) {
|
|
260
|
+
if (seenArgs.has(arg.name)) continue;
|
|
261
|
+
seenArgs.add(arg.name);
|
|
300
262
|
|
|
301
|
-
const desc = cmd.meta?.
|
|
263
|
+
const desc = cmd.meta?.fields?.[arg.name]?.description || '';
|
|
302
264
|
const escapedDesc = desc.replace(/'/g, "\\'");
|
|
303
265
|
|
|
304
|
-
if (
|
|
305
|
-
lines.push(`complete -c ${programName} -s ${
|
|
266
|
+
if (arg.alias) {
|
|
267
|
+
lines.push(`complete -c ${programName} -s ${arg.alias} -l ${arg.name} -d '${escapedDesc}'`);
|
|
306
268
|
} else {
|
|
307
|
-
lines.push(`complete -c ${programName} -l ${
|
|
269
|
+
lines.push(`complete -c ${programName} -l ${arg.name} -d '${escapedDesc}'`);
|
|
308
270
|
}
|
|
309
271
|
}
|
|
310
272
|
}
|
|
@@ -334,10 +296,10 @@ Register-ArgumentCompleter -Native -CommandName ${programName} -ScriptBlock {
|
|
|
334
296
|
param($wordToComplete, $commandAst, $cursorPosition)
|
|
335
297
|
|
|
336
298
|
$commands = @(${commandNames})
|
|
337
|
-
$
|
|
299
|
+
$args = @('--help', '--version')
|
|
338
300
|
|
|
339
301
|
if ($wordToComplete -like '-*') {
|
|
340
|
-
$
|
|
302
|
+
$args | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
|
|
341
303
|
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
|
|
342
304
|
}
|
|
343
305
|
} else {
|
|
@@ -445,3 +407,54 @@ ${script}`;
|
|
|
445
407
|
# ${programName} completion fish > ~/.config/fish/completions/${programName}.fish
|
|
446
408
|
# ${programName} completion powershell >> $PROFILE`;
|
|
447
409
|
}
|
|
410
|
+
|
|
411
|
+
export interface SetupCompletionsResult {
|
|
412
|
+
/** The file that was written to. */
|
|
413
|
+
file: string;
|
|
414
|
+
/** Whether an existing completion block was replaced (true) or a new one was appended (false). */
|
|
415
|
+
updated: boolean;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Sets up shell completions by writing an eval snippet to the appropriate shell config file.
|
|
420
|
+
* Uses marker comments for idempotency — re-running replaces the existing block.
|
|
421
|
+
*/
|
|
422
|
+
export function setupCompletions(programName: string, shell: ShellType): SetupCompletionsResult {
|
|
423
|
+
const { existsSync, mkdirSync, writeFileSync } = require('node:fs') as typeof import('node:fs');
|
|
424
|
+
const { join } = require('node:path') as typeof import('node:path');
|
|
425
|
+
const { homedir } = require('node:os') as typeof import('node:os');
|
|
426
|
+
|
|
427
|
+
const beginMarker = `###-begin-${programName}-completion-###`;
|
|
428
|
+
const endMarker = `###-end-${programName}-completion-###`;
|
|
429
|
+
const snippet = buildSetupSnippet(programName, shell, beginMarker, endMarker);
|
|
430
|
+
|
|
431
|
+
if (shell === 'fish') {
|
|
432
|
+
const completionsDir = join(homedir(), '.config', 'fish', 'completions');
|
|
433
|
+
const filePath = join(completionsDir, `${programName}.fish`);
|
|
434
|
+
mkdirSync(completionsDir, { recursive: true });
|
|
435
|
+
const existed = existsSync(filePath);
|
|
436
|
+
writeFileSync(filePath, `${snippet}\n`);
|
|
437
|
+
return { file: filePath, updated: existed };
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const rcFile = getRcFile(shell);
|
|
441
|
+
if (!rcFile) {
|
|
442
|
+
throw new Error(`Could not determine config file for ${shell}.`);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return writeToRcFile(rcFile, snippet, beginMarker, endMarker);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function buildSetupSnippet(programName: string, shell: ShellType, beginMarker: string, endMarker: string): string {
|
|
449
|
+
const evalCmd = `${programName} completion ${shell}`;
|
|
450
|
+
|
|
451
|
+
switch (shell) {
|
|
452
|
+
case 'bash':
|
|
453
|
+
case 'zsh':
|
|
454
|
+
return `${beginMarker}\neval "$(${evalCmd})"\n${endMarker}`;
|
|
455
|
+
case 'fish':
|
|
456
|
+
return `${beginMarker}\n${evalCmd} | source\n${endMarker}`;
|
|
457
|
+
case 'powershell':
|
|
458
|
+
return `${beginMarker}\n${evalCmd} | Invoke-Expression\n${endMarker}`;
|
|
459
|
+
}
|
|
460
|
+
}
|