@fnndsc/brasa 0.56.0 → 0.56.2
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/buildinfo.json +1 -1
- package/dist/builtins/berth/berth.d.ts +90 -3
- package/dist/builtins/berth/berth.js +129 -76
- package/dist/builtins/berth/berth.js.map +1 -1
- package/dist/builtins/berth/berthClose.d.ts +25 -6
- package/dist/builtins/berth/berthClose.js +19 -67
- package/dist/builtins/berth/berthClose.js.map +1 -1
- package/dist/builtins/berth/berthCube.js +4 -6
- package/dist/builtins/berth/berthCube.js.map +1 -1
- package/dist/builtins/berth/berthProcesses.d.ts +15 -0
- package/dist/builtins/berth/berthProcesses.js +58 -5
- package/dist/builtins/berth/berthProcesses.js.map +1 -1
- package/dist/builtins/fs/cat.js +3 -3
- package/dist/builtins/fs/cat.js.map +1 -1
- package/dist/builtins/fs/cp.js +3 -2
- package/dist/builtins/fs/cp.js.map +1 -1
- package/dist/builtins/fs/download.d.ts +31 -4
- package/dist/builtins/fs/download.js +75 -38
- package/dist/builtins/fs/download.js.map +1 -1
- package/dist/builtins/fs/ls.d.ts +69 -4
- package/dist/builtins/fs/ls.js +84 -45
- package/dist/builtins/fs/ls.js.map +1 -1
- package/dist/builtins/fs/pull.js +37 -9
- package/dist/builtins/fs/pull.js.map +1 -1
- package/dist/builtins/help.d.ts +3 -1
- package/dist/builtins/help.js +22 -33
- package/dist/builtins/help.js.map +1 -1
- package/dist/builtins/res/dicom.d.ts +3 -4
- package/dist/builtins/res/dicom.js +5 -19
- package/dist/builtins/res/dicom.js.map +1 -1
- package/dist/builtins/sys/textFilters.js +2 -2
- package/dist/builtins/sys/textFilters.js.map +1 -1
- package/dist/builtins/utils.d.ts +1 -1
- package/dist/builtins/utils.js +1 -1
- package/dist/builtins/utils.js.map +1 -1
- package/dist/chris/backend.js +2 -0
- package/dist/chris/backend.js.map +1 -1
- package/dist/chris/chrisCommands.js +6 -9
- package/dist/chris/chrisCommands.js.map +1 -1
- package/dist/chris/files.js +24 -85
- package/dist/chris/files.js.map +1 -1
- package/dist/chris/help.js +0 -64
- package/dist/chris/help.js.map +1 -1
- package/dist/chris/kinds.d.ts +9 -0
- package/dist/chris/kinds.js +42 -0
- package/dist/chris/kinds.js.map +1 -0
- package/dist/chris/promptContext.d.ts +6 -0
- package/dist/chris/promptContext.js +3 -1
- package/dist/chris/promptContext.js.map +1 -1
- package/dist/core/argumentKinds.d.ts +107 -0
- package/dist/core/argumentKinds.js +223 -0
- package/dist/core/argumentKinds.js.map +1 -0
- package/dist/core/backend.d.ts +4 -1
- package/dist/core/backend.js.map +1 -1
- package/dist/core/commandDeclaration.d.ts +363 -0
- package/dist/core/commandDeclaration.js +31 -0
- package/dist/core/commandDeclaration.js.map +1 -0
- package/dist/core/commandParse.d.ts +64 -0
- package/dist/core/commandParse.js +420 -0
- package/dist/core/commandParse.js.map +1 -0
- package/dist/core/commandRegistry.d.ts +36 -0
- package/dist/core/commandRegistry.js +72 -3
- package/dist/core/commandRegistry.js.map +1 -1
- package/dist/core/commandSchema.d.ts +32 -0
- package/dist/core/commandSchema.js +114 -0
- package/dist/core/commandSchema.js.map +1 -0
- package/dist/core/commandUsage.d.ts +47 -0
- package/dist/core/commandUsage.js +195 -0
- package/dist/core/commandUsage.js.map +1 -0
- package/dist/core/coreCommands.js +5 -4
- package/dist/core/coreCommands.js.map +1 -1
- package/dist/core/dispatch.js +15 -8
- package/dist/core/dispatch.js.map +1 -1
- package/dist/core/paths.d.ts +23 -0
- package/dist/core/paths.js +73 -2
- package/dist/core/paths.js.map +1 -1
- package/dist/core/preprocess.d.ts +10 -8
- package/dist/core/preprocess.js +11 -20
- package/dist/core/preprocess.js.map +1 -1
- package/dist/core/warmupFailures.d.ts +34 -2
- package/dist/core/warmupFailures.js +43 -2
- package/dist/core/warmupFailures.js.map +1 -1
- package/dist/lib/completer/cfsPaths.d.ts +14 -0
- package/dist/lib/completer/cfsPaths.js +91 -0
- package/dist/lib/completer/cfsPaths.js.map +1 -0
- package/dist/lib/completer/declared.d.ts +15 -0
- package/dist/lib/completer/declared.js +186 -0
- package/dist/lib/completer/declared.js.map +1 -0
- package/dist/lib/completer/index.js +33 -74
- package/dist/lib/completer/index.js.map +1 -1
- package/dist/lib/parser.d.ts +5 -0
- package/dist/lib/parser.js +2 -0
- package/dist/lib/parser.js.map +1 -1
- package/dist/lib/vfs/vfs.js +4 -2
- package/dist/lib/vfs/vfs.js.map +1 -1
- package/dist/lib/wildcard.js +2 -3
- package/dist/lib/wildcard.js.map +1 -1
- package/dist/notes.json +1 -1
- package/package.json +5 -4
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file A command's declaration: its name, the grammar its line is parsed
|
|
3
|
+
* against, the kind of every argument, its help prose, what it holds of the
|
|
4
|
+
* session, and its handler, in one record.
|
|
5
|
+
*
|
|
6
|
+
* The grammar is the shell's own: subcommands; operands in order, each
|
|
7
|
+
* optional or repeated; options with a short name, a long name, or both, and
|
|
8
|
+
* a value or none. Every argument names a kind (`argumentKinds.ts`), which
|
|
9
|
+
* checks its value and completes it. The handler receives a typed object the
|
|
10
|
+
* compiler infers from the grammar, written `as const`: its operands, its
|
|
11
|
+
* options and, for a subcommand, which one. Reading an undeclared option is a
|
|
12
|
+
* build error, and the handler never sees the words.
|
|
13
|
+
*
|
|
14
|
+
* A command whose arguments form an expression language (`find`) declares
|
|
15
|
+
* `grammar: 'expression'` instead, keeps its own parser and completion, and
|
|
16
|
+
* receives its words after references expand.
|
|
17
|
+
*
|
|
18
|
+
* Key components:
|
|
19
|
+
* - CommandGrammar: subcommands, operands and options, as a value.
|
|
20
|
+
* - CommandDeclaration: the whole record for a parsed command.
|
|
21
|
+
* - ExpressionDeclaration: the record for an expression-grammar command.
|
|
22
|
+
* - CommandArguments: the typed object a handler receives.
|
|
23
|
+
* - SubcommandArguments: one subcommand's share of it.
|
|
24
|
+
* - command_declare: declares a command, inferring its handler's argument.
|
|
25
|
+
*
|
|
26
|
+
* Typical usage:
|
|
27
|
+
* ```ts
|
|
28
|
+
* const HELLO_GRAMMAR = {
|
|
29
|
+
* operands: [{ name: 'who', kind: 'word', optional: true, summary: 'Whom to greet' }],
|
|
30
|
+
* options: { loud: { short: 'l', long: 'loud', summary: 'Shout' } },
|
|
31
|
+
* } as const satisfies CommandGrammar;
|
|
32
|
+
* export const helloCommand = command_declare({
|
|
33
|
+
* name: 'hello',
|
|
34
|
+
* grammar: HELLO_GRAMMAR,
|
|
35
|
+
* help: { summary: 'Say hello', description: 'Greets someone.' },
|
|
36
|
+
* handler: async (args) => envelope_ok(`hello ${args.operands.who ?? 'world'}${args.options.loud ? '!' : ''}\n`),
|
|
37
|
+
* });
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* Dependencies: types only (`@fnndsc/menu` for the envelope, the registry for
|
|
41
|
+
* session pieces).
|
|
42
|
+
*
|
|
43
|
+
* @module
|
|
44
|
+
*/
|
|
45
|
+
import type { CommandEnvelope } from '@fnndsc/menu';
|
|
46
|
+
import type { SessionPiece } from './commandRegistry.js';
|
|
47
|
+
/**
|
|
48
|
+
* What an argument is: the kind that checks and completes it, and that
|
|
49
|
+
* kind's parameters.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* const sortField: ArgumentGrammar = { kind: 'enum', values: ['name', 'size'] };
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export interface ArgumentGrammar {
|
|
57
|
+
/** The kind's name: a core kind (`word`, `enum`, `int`, `number`, `cfsPath`, `hostPath`, `variable`, `job`) or one a backend registers. */
|
|
58
|
+
readonly kind: string;
|
|
59
|
+
/** The words an `enum` takes. */
|
|
60
|
+
readonly values?: readonly string[];
|
|
61
|
+
/** Pathname expansion for a `cfsPath` or `hostPath` operand: a wildcard in it matches paths. */
|
|
62
|
+
readonly glob?: boolean;
|
|
63
|
+
/** The least an `int` or `number` takes. */
|
|
64
|
+
readonly min?: number;
|
|
65
|
+
/** The most an `int` or `number` takes. */
|
|
66
|
+
readonly max?: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* One operand: a word that is not an option, in its place on the line.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* const paths: OperandGrammar = { name: 'paths', kind: 'cfsPath', optional: true, repeat: true, glob: true, summary: 'What to list' };
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export interface OperandGrammar extends ArgumentGrammar {
|
|
77
|
+
/** Its name: the property the handler reads, and the word usage shows (`<path>`). */
|
|
78
|
+
readonly name: string;
|
|
79
|
+
/** One line for help and the schema. */
|
|
80
|
+
readonly summary: string;
|
|
81
|
+
/** It may be left out. */
|
|
82
|
+
readonly optional?: boolean;
|
|
83
|
+
/** It takes every word left over: at most one operand of a grammar repeats. */
|
|
84
|
+
readonly repeat?: boolean;
|
|
85
|
+
}
|
|
86
|
+
/** An option's value: an argument with the word usage shows for it (`<field>`). */
|
|
87
|
+
export interface OptionValueGrammar extends ArgumentGrammar {
|
|
88
|
+
/** The word usage shows: `--sort <field>`. */
|
|
89
|
+
readonly name: string;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* One option: `-l`, `--long`, or both; a switch, or one that takes a value.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* const sort: OptionGrammar = { long: 'sort', summary: 'Sort by', value: { name: 'field', kind: 'enum', values: ['name', 'size'] } };
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export interface OptionGrammar {
|
|
100
|
+
/** Its one-character name, without the dash. */
|
|
101
|
+
readonly short?: string;
|
|
102
|
+
/** Its long name, without the dashes. */
|
|
103
|
+
readonly long?: string;
|
|
104
|
+
/** One line for help and the schema. */
|
|
105
|
+
readonly summary: string;
|
|
106
|
+
/** What it takes; absent, it is a switch. */
|
|
107
|
+
readonly value?: OptionValueGrammar;
|
|
108
|
+
/** A value option given more than once keeps every value; otherwise the last one counts. */
|
|
109
|
+
readonly repeat?: boolean;
|
|
110
|
+
}
|
|
111
|
+
/** A grammar's options, by the property the handler reads them as. */
|
|
112
|
+
export type OptionsGrammar = {
|
|
113
|
+
readonly [key: string]: OptionGrammar;
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* A subcommand: the word after the command, with operands and options of its
|
|
117
|
+
* own. The command's own options hold after it too.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* const drop: SubcommandGrammar = { summary: 'Remove one anchor', operands: [{ name: 'name', kind: 'word', summary: 'The anchor' }] };
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
export interface SubcommandGrammar {
|
|
125
|
+
/** One line for help and the schema. */
|
|
126
|
+
readonly summary: string;
|
|
127
|
+
/** Its operands, in order. */
|
|
128
|
+
readonly operands?: readonly OperandGrammar[];
|
|
129
|
+
/** Its options. */
|
|
130
|
+
readonly options?: OptionsGrammar;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* A command's grammar: what its line may hold, as a value. Written `as const`,
|
|
134
|
+
* so the handler's argument is inferred from it.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```ts
|
|
138
|
+
* const grammar = { operands: [{ name: 'path', kind: 'cfsPath', summary: 'Where' }] } as const satisfies CommandGrammar;
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
export interface CommandGrammar {
|
|
142
|
+
/** Its operands, in order; with subcommands, the words of the bare command. */
|
|
143
|
+
readonly operands?: readonly OperandGrammar[];
|
|
144
|
+
/** Its options, which hold after any subcommand too. */
|
|
145
|
+
readonly options?: OptionsGrammar;
|
|
146
|
+
/** Its subcommands, by the word that names each. */
|
|
147
|
+
readonly subcommands?: {
|
|
148
|
+
readonly [word: string]: SubcommandGrammar;
|
|
149
|
+
};
|
|
150
|
+
/** What the command does with no subcommand; absent, a command with subcommands needs one. */
|
|
151
|
+
readonly bare?: {
|
|
152
|
+
readonly summary: string;
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* A command's help prose: what `help` shows beside the usage the grammar
|
|
157
|
+
* generates.
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```ts
|
|
161
|
+
* const prose: CommandProse = { summary: 'List directory contents', description: 'Lists…', category: 'Navigation' };
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
export interface CommandProse {
|
|
165
|
+
/** One line for listings. */
|
|
166
|
+
readonly summary: string;
|
|
167
|
+
/** What the command does, as one paragraph. */
|
|
168
|
+
readonly description: string;
|
|
169
|
+
/** Lines `help` shows under EXAMPLES; a `#` starts a comment. */
|
|
170
|
+
readonly examples?: readonly string[];
|
|
171
|
+
/** Where `help` lists it: one of the help sections. */
|
|
172
|
+
readonly category?: string;
|
|
173
|
+
/** It mirrors a Unix utility: the group `help POSIX` lists it under, and how it differs, in a line. */
|
|
174
|
+
readonly posix?: {
|
|
175
|
+
readonly group: 'Files' | 'Text' | 'System' | 'Shell';
|
|
176
|
+
readonly differs: string;
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/** A kind's value type: a number for `int` and `number`, the declared words for `enum`, else text. */
|
|
180
|
+
type KindValue<A> = A extends {
|
|
181
|
+
readonly kind: 'int' | 'number';
|
|
182
|
+
} ? number : A extends {
|
|
183
|
+
readonly kind: 'enum';
|
|
184
|
+
readonly values: readonly (infer V extends string)[];
|
|
185
|
+
} ? V : string;
|
|
186
|
+
/** An operand's value: a list when it repeats, possibly absent when optional. */
|
|
187
|
+
type OperandValue<O> = O extends {
|
|
188
|
+
readonly repeat: true;
|
|
189
|
+
} ? KindValue<O>[] : O extends {
|
|
190
|
+
readonly optional: true;
|
|
191
|
+
} ? KindValue<O> | undefined : KindValue<O>;
|
|
192
|
+
/** The operands a grammar declares, by name. */
|
|
193
|
+
type OperandsOf<G> = G extends {
|
|
194
|
+
readonly operands: readonly (infer O)[];
|
|
195
|
+
} ? {
|
|
196
|
+
readonly [P in O as P extends {
|
|
197
|
+
readonly name: infer N extends string;
|
|
198
|
+
} ? N : never]: OperandValue<P>;
|
|
199
|
+
} : Record<never, never>;
|
|
200
|
+
/** The names of a grammar's operands that expand pathnames. */
|
|
201
|
+
type GlobNamesOf<G> = G extends {
|
|
202
|
+
readonly operands: readonly (infer O)[];
|
|
203
|
+
} ? O extends {
|
|
204
|
+
readonly glob: true;
|
|
205
|
+
readonly name: infer N extends string;
|
|
206
|
+
} ? N : never : never;
|
|
207
|
+
/** Whether each globbing operand's words came from pathname expansion. */
|
|
208
|
+
type ExpandedOf<G> = {
|
|
209
|
+
readonly [N in GlobNamesOf<G>]: boolean;
|
|
210
|
+
};
|
|
211
|
+
/** An option's value: a switch is a boolean; a value option its value, or every value when it repeats. */
|
|
212
|
+
type OptionValue<O> = O extends {
|
|
213
|
+
readonly value: infer V;
|
|
214
|
+
} ? O extends {
|
|
215
|
+
readonly repeat: true;
|
|
216
|
+
} ? KindValue<V>[] : KindValue<V> | undefined : boolean;
|
|
217
|
+
/** The options a grammar declares, by property. */
|
|
218
|
+
type OptionsOf<G> = G extends {
|
|
219
|
+
readonly options: infer M;
|
|
220
|
+
} ? {
|
|
221
|
+
readonly [K in keyof M]: OptionValue<M[K]>;
|
|
222
|
+
} : Record<never, never>;
|
|
223
|
+
/** One parsed line: what a handler reads, for a grammar and the command's own options. */
|
|
224
|
+
interface ParsedLine<S, G> {
|
|
225
|
+
/** The operands, by name. */
|
|
226
|
+
readonly operands: OperandsOf<S>;
|
|
227
|
+
/** The options, by property: the subcommand's and the command's. */
|
|
228
|
+
readonly options: OptionsOf<S> & OptionsOf<G>;
|
|
229
|
+
/** For each operand that globs, whether its words came from pathname expansion. */
|
|
230
|
+
readonly expanded: ExpandedOf<S>;
|
|
231
|
+
}
|
|
232
|
+
/** The bare command's line, when the grammar allows one. */
|
|
233
|
+
type BareLine<G> = G extends {
|
|
234
|
+
readonly subcommands: object;
|
|
235
|
+
} ? G extends {
|
|
236
|
+
readonly bare: object;
|
|
237
|
+
} ? {
|
|
238
|
+
readonly subcommand: null;
|
|
239
|
+
} & ParsedLine<G, G> : never : {
|
|
240
|
+
readonly subcommand: null;
|
|
241
|
+
} & ParsedLine<G, G>;
|
|
242
|
+
/** Each subcommand's line. */
|
|
243
|
+
type SubcommandLine<G> = G extends {
|
|
244
|
+
readonly subcommands: infer S;
|
|
245
|
+
} ? {
|
|
246
|
+
[K in keyof S & string]: {
|
|
247
|
+
readonly subcommand: K;
|
|
248
|
+
} & ParsedLine<S[K], G>;
|
|
249
|
+
}[keyof S & string] : never;
|
|
250
|
+
/**
|
|
251
|
+
* The typed object a handler receives: which subcommand (null for none), its
|
|
252
|
+
* operands, its options, and which operands came from pathname expansion.
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```ts
|
|
256
|
+
* type LsArguments = CommandArguments<typeof LS_GRAMMAR>;
|
|
257
|
+
* const paths: string[] = (args as LsArguments).operands.paths;
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
export type CommandArguments<G extends CommandGrammar> = BareLine<G> | SubcommandLine<G>;
|
|
261
|
+
/**
|
|
262
|
+
* One subcommand's share of a handler's argument, for a function that runs it.
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* ```ts
|
|
266
|
+
* function drop_run(args: SubcommandArguments<typeof BERTH_GRAMMAR, 'drop'>): CommandEnvelope { … }
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
export type SubcommandArguments<G extends CommandGrammar, K extends string> = Extract<CommandArguments<G>, {
|
|
270
|
+
readonly subcommand: K;
|
|
271
|
+
}>;
|
|
272
|
+
/**
|
|
273
|
+
* A command parsed against its grammar: the one record that is its help,
|
|
274
|
+
* its completion, its schema and its dispatch.
|
|
275
|
+
*
|
|
276
|
+
* @example
|
|
277
|
+
* ```ts
|
|
278
|
+
* const declaration: CommandDeclaration<typeof HELLO_GRAMMAR> = helloCommand;
|
|
279
|
+
* ```
|
|
280
|
+
*/
|
|
281
|
+
export interface CommandDeclaration<G extends CommandGrammar = CommandGrammar> {
|
|
282
|
+
/** The word that runs it. */
|
|
283
|
+
readonly name: string;
|
|
284
|
+
/** What its line may hold. */
|
|
285
|
+
readonly grammar: G;
|
|
286
|
+
/** What `help` says of it. */
|
|
287
|
+
readonly help: CommandProse;
|
|
288
|
+
/** The pieces of the session it changes while it runs; absent, it holds the whole session. */
|
|
289
|
+
readonly holds?: readonly SessionPiece[];
|
|
290
|
+
/**
|
|
291
|
+
* Runs it, given the line parsed and checked. A method, so a record of one
|
|
292
|
+
* grammar stands where any declaration is read.
|
|
293
|
+
*
|
|
294
|
+
* @param args - The typed line.
|
|
295
|
+
* @returns Its outcome.
|
|
296
|
+
*/
|
|
297
|
+
handler(args: CommandArguments<G>): Promise<CommandEnvelope>;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* A command whose arguments are an expression language of its own (`find`):
|
|
301
|
+
* it parses and completes them itself, under a ratchet.
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* ```ts
|
|
305
|
+
* const findCommand: ExpressionDeclaration = { name: 'find', grammar: 'expression', help, handler: builtin_find };
|
|
306
|
+
* ```
|
|
307
|
+
*/
|
|
308
|
+
export interface ExpressionDeclaration {
|
|
309
|
+
/** The word that runs it. */
|
|
310
|
+
readonly name: string;
|
|
311
|
+
/** Says it parses its own words. */
|
|
312
|
+
readonly grammar: 'expression';
|
|
313
|
+
/** What `help` says of it; its usage is its own. */
|
|
314
|
+
readonly help: CommandProse & {
|
|
315
|
+
readonly usage: string;
|
|
316
|
+
};
|
|
317
|
+
/** The pieces of the session it changes while it runs. */
|
|
318
|
+
readonly holds?: readonly SessionPiece[];
|
|
319
|
+
/**
|
|
320
|
+
* Runs it over its words, references expanded and nothing globbed.
|
|
321
|
+
*
|
|
322
|
+
* @param args - The words after the command.
|
|
323
|
+
* @returns Its outcome.
|
|
324
|
+
*/
|
|
325
|
+
handler(args: string[]): Promise<CommandEnvelope>;
|
|
326
|
+
/**
|
|
327
|
+
* Completes one word of its line.
|
|
328
|
+
*
|
|
329
|
+
* @param words - The words before the one completed.
|
|
330
|
+
* @param word - The word typed so far.
|
|
331
|
+
* @returns The candidates.
|
|
332
|
+
*/
|
|
333
|
+
complete?(words: readonly string[], word: string): Promise<string[]>;
|
|
334
|
+
}
|
|
335
|
+
/** Any declaration the registry holds. */
|
|
336
|
+
export type AnyCommandDeclaration = CommandDeclaration | ExpressionDeclaration;
|
|
337
|
+
/**
|
|
338
|
+
* Declares a command. Returns its argument unchanged; what it adds is the
|
|
339
|
+
* inference: the handler's argument is typed from the grammar beside it.
|
|
340
|
+
*
|
|
341
|
+
* @param declaration - The record.
|
|
342
|
+
* @returns The same record.
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```ts
|
|
346
|
+
* export const helloCommand = command_declare({ name: 'hello', grammar: HELLO_GRAMMAR, help, handler: async (args) => … });
|
|
347
|
+
* ```
|
|
348
|
+
*/
|
|
349
|
+
export declare function command_declare<const G extends CommandGrammar>(declaration: CommandDeclaration<G>): CommandDeclaration<G>;
|
|
350
|
+
/**
|
|
351
|
+
* Whether a declaration parses its line against a grammar (rather than an
|
|
352
|
+
* expression language of its own).
|
|
353
|
+
*
|
|
354
|
+
* @param declaration - The record.
|
|
355
|
+
* @returns True for a grammar.
|
|
356
|
+
*
|
|
357
|
+
* @example
|
|
358
|
+
* ```ts
|
|
359
|
+
* if (declaration_isParsed(declaration)) declaration.grammar.operands;
|
|
360
|
+
* ```
|
|
361
|
+
*/
|
|
362
|
+
export declare function declaration_isParsed(declaration: AnyCommandDeclaration): declaration is CommandDeclaration;
|
|
363
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declares a command. Returns its argument unchanged; what it adds is the
|
|
3
|
+
* inference: the handler's argument is typed from the grammar beside it.
|
|
4
|
+
*
|
|
5
|
+
* @param declaration - The record.
|
|
6
|
+
* @returns The same record.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* export const helloCommand = command_declare({ name: 'hello', grammar: HELLO_GRAMMAR, help, handler: async (args) => … });
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export function command_declare(declaration) {
|
|
14
|
+
return declaration;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Whether a declaration parses its line against a grammar (rather than an
|
|
18
|
+
* expression language of its own).
|
|
19
|
+
*
|
|
20
|
+
* @param declaration - The record.
|
|
21
|
+
* @returns True for a grammar.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* if (declaration_isParsed(declaration)) declaration.grammar.operands;
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function declaration_isParsed(declaration) {
|
|
29
|
+
return declaration.grammar !== 'expression';
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=commandDeclaration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commandDeclaration.js","sourceRoot":"","sources":["../../src/core/commandDeclaration.ts"],"names":[],"mappings":"AAoUA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAiC,WAAkC;IAChG,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAkC;IACrE,OAAO,WAAW,CAAC,OAAO,KAAK,YAAY,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type CommandEnvelope } from '@fnndsc/menu';
|
|
2
|
+
import type { ShellWord } from '../lib/parser.js';
|
|
3
|
+
import type { CommandDeclaration } from './commandDeclaration.js';
|
|
4
|
+
/** What parsing a line came to: the handler's argument, or the refusal. */
|
|
5
|
+
export type LineParse = {
|
|
6
|
+
readonly ok: true;
|
|
7
|
+
readonly args: ParsedArguments;
|
|
8
|
+
} | {
|
|
9
|
+
readonly ok: false;
|
|
10
|
+
readonly refusal: string;
|
|
11
|
+
};
|
|
12
|
+
/** The handler's argument, before the grammar's types are put on it. */
|
|
13
|
+
export interface ParsedArguments {
|
|
14
|
+
/** The subcommand, or null for none. */
|
|
15
|
+
readonly subcommand: string | null;
|
|
16
|
+
/** The operands, by name. */
|
|
17
|
+
readonly operands: Record<string, unknown>;
|
|
18
|
+
/** The options, by property. */
|
|
19
|
+
readonly options: Record<string, unknown>;
|
|
20
|
+
/** For each operand that globs, whether its words came from pathname expansion. */
|
|
21
|
+
readonly expanded: Record<string, boolean>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parses a declared command's line into the object its handler reads.
|
|
25
|
+
*
|
|
26
|
+
* @param declaration - The command.
|
|
27
|
+
* @param words - The words after the command, references expanded, quoting kept.
|
|
28
|
+
* @returns The handler's argument, or the refusal (`ls: unrecognized option '--x'; usage: …`).
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* const parsed: LineParse = await commandLine_parse(lsCommand, [shellWord_literal('-l')]);
|
|
33
|
+
* if (parsed.ok) parsed.args.options['long']; // true
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function commandLine_parse(declaration: CommandDeclaration, words: readonly ShellWord[]): Promise<LineParse>;
|
|
37
|
+
/**
|
|
38
|
+
* Parses a line against its declaration and runs the handler on it; a bad
|
|
39
|
+
* line is refused on the error channel, the handler never called.
|
|
40
|
+
*
|
|
41
|
+
* @param declaration - The command.
|
|
42
|
+
* @param args - The words after the command.
|
|
43
|
+
* @returns The handler's envelope, or the refusal's.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* await declaredCommand_run(lsCommand, ['--nosuch']); // renderedErr: "ls: unrecognized option '--nosuch'; usage: …"
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function declaredCommand_run(declaration: CommandDeclaration, args: readonly string[]): Promise<CommandEnvelope>;
|
|
51
|
+
/**
|
|
52
|
+
* The registry's handler for a declared command: the words a line hands
|
|
53
|
+
* on, parsed against the declaration.
|
|
54
|
+
*
|
|
55
|
+
* @param declaration - The command.
|
|
56
|
+
* @returns The handler.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* const handler = declaredHandler_make(lsCommand);
|
|
61
|
+
* await handler(['-l']);
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare function declaredHandler_make(declaration: CommandDeclaration): (args: string[]) => Promise<CommandEnvelope>;
|