UNPKG

21.1 kBTypeScriptView Raw
1import { NodeType } from './constants';
2export declare function debug(str: string): void;
3export type StateMachine = {
4 nodes: Array<Node>;
5};
6export type TokenBase = {
7 segmentIndex: number;
8};
9export type PathToken = TokenBase & {
10 type: `path`;
11 slice?: undefined;
12};
13export type PositionalToken = TokenBase & {
14 type: `positional`;
15 slice?: undefined;
16};
17export type OptionToken = TokenBase & {
18 type: `option`;
19 slice?: [number, number];
20 option: string;
21};
22export type AssignToken = TokenBase & {
23 type: `assign`;
24 slice: [number, number];
25};
26export type ValueToken = TokenBase & {
27 type: `value`;
28 slice?: [number, number];
29};
30export type Token = PathToken | PositionalToken | OptionToken | AssignToken | ValueToken;
31export type RunState = {
32 candidateUsage: string | null;
33 requiredOptions: Array<Array<string>>;
34 errorMessage: string | null;
35 ignoreOptions: boolean;
36 options: Array<{
37 name: string;
38 value: any;
39 }>;
40 path: Array<string>;
41 positionals: Array<{
42 value: string;
43 extra: boolean | typeof NoLimits;
44 }>;
45 remainder: string | null;
46 selectedIndex: number | null;
47 tokens: Array<Token>;
48};
49export declare function makeStateMachine(): StateMachine;
50export declare function makeAnyOfMachine(inputs: Array<StateMachine>): StateMachine;
51export declare function injectNode(machine: StateMachine, node: Node): number;
52export declare function simplifyMachine(input: StateMachine): void;
53export declare function debugMachine(machine: StateMachine, { prefix }?: {
54 prefix?: string;
55}): void;
56export declare function runMachineInternal(machine: StateMachine, input: Array<string>, partial?: boolean): {
57 node: number;
58 state: RunState;
59}[];
60export declare function trimSmallerBranches(branches: Array<{
61 node: number;
62 state: RunState;
63}>): {
64 node: number;
65 state: RunState;
66}[];
67export declare function selectBestState(input: Array<string>, states: Array<RunState>): RunState;
68export declare function aggregateHelpStates(states: Array<RunState>): RunState[];
69type Transition = {
70 to: number;
71 reducer?: Callback<keyof typeof reducers, typeof reducers>;
72};
73type Node = {
74 dynamics: Array<[Callback<keyof typeof tests, typeof tests>, Transition]>;
75 shortcuts: Array<Transition>;
76 statics: {
77 [segment: string]: Array<Transition>;
78 };
79};
80export declare function makeNode(): Node;
81export declare function isTerminalNode(node: number): boolean;
82export declare function cloneTransition(input: Transition, offset?: number): {
83 to: number;
84 reducer: "setCandidateState" | "setSelectedIndex" | "pushBatch" | "pushBound" | "pushPath" | "pushPositional" | "pushExtra" | "pushExtraNoLimits" | "pushTrue" | "pushFalse" | "pushUndefined" | "pushStringValue" | "setStringValue" | "inhibateOptions" | "useHelp" | "setError" | "setOptionArityError" | ["setCandidateState" | "setSelectedIndex" | "pushBatch" | "pushBound" | "pushPath" | "pushPositional" | "pushExtra" | "pushExtraNoLimits" | "pushTrue" | "pushFalse" | "pushUndefined" | "pushStringValue" | "setStringValue" | "inhibateOptions" | "useHelp" | "setError" | "setOptionArityError"] | ["setCandidateState" | "setSelectedIndex" | "pushBatch" | "pushBound" | "pushPath" | "pushPositional" | "pushExtra" | "pushExtraNoLimits" | "pushTrue" | "pushFalse" | "pushUndefined" | "pushStringValue" | "setStringValue" | "inhibateOptions" | "useHelp" | "setError" | "setOptionArityError", candidateState: Partial<RunState>] | ["setCandidateState" | "setSelectedIndex" | "pushBatch" | "pushBound" | "pushPath" | "pushPositional" | "pushExtra" | "pushExtraNoLimits" | "pushTrue" | "pushFalse" | "pushUndefined" | "pushStringValue" | "setStringValue" | "inhibateOptions" | "useHelp" | "setError" | "setOptionArityError", index: number] | ["setCandidateState" | "setSelectedIndex" | "pushBatch" | "pushBound" | "pushPath" | "pushPositional" | "pushExtra" | "pushExtraNoLimits" | "pushTrue" | "pushFalse" | "pushUndefined" | "pushStringValue" | "setStringValue" | "inhibateOptions" | "useHelp" | "setError" | "setOptionArityError", names: Map<string, string>] | ["setCandidateState" | "setSelectedIndex" | "pushBatch" | "pushBound" | "pushPath" | "pushPositional" | "pushExtra" | "pushExtraNoLimits" | "pushTrue" | "pushFalse" | "pushUndefined" | "pushStringValue" | "setStringValue" | "inhibateOptions" | "useHelp" | "setError" | "setOptionArityError", name: string] | ["setCandidateState" | "setSelectedIndex" | "pushBatch" | "pushBound" | "pushPath" | "pushPositional" | "pushExtra" | "pushExtraNoLimits" | "pushTrue" | "pushFalse" | "pushUndefined" | "pushStringValue" | "setStringValue" | "inhibateOptions" | "useHelp" | "setError" | "setOptionArityError", name: string] | ["setCandidateState" | "setSelectedIndex" | "pushBatch" | "pushBound" | "pushPath" | "pushPositional" | "pushExtra" | "pushExtraNoLimits" | "pushTrue" | "pushFalse" | "pushUndefined" | "pushStringValue" | "setStringValue" | "inhibateOptions" | "useHelp" | "setError" | "setOptionArityError", name: string] | ["setCandidateState" | "setSelectedIndex" | "pushBatch" | "pushBound" | "pushPath" | "pushPositional" | "pushExtra" | "pushExtraNoLimits" | "pushTrue" | "pushFalse" | "pushUndefined" | "pushStringValue" | "setStringValue" | "inhibateOptions" | "useHelp" | "setError" | "setOptionArityError", command: number] | ["setCandidateState" | "setSelectedIndex" | "pushBatch" | "pushBound" | "pushPath" | "pushPositional" | "pushExtra" | "pushExtraNoLimits" | "pushTrue" | "pushFalse" | "pushUndefined" | "pushStringValue" | "setStringValue" | "inhibateOptions" | "useHelp" | "setError" | "setOptionArityError", errorMessage: string] | undefined;
85};
86export declare function cloneNode(input: Node, offset?: number): Node;
87export declare function registerDynamic<T extends keyof typeof tests, R extends keyof typeof reducers>(machine: StateMachine, from: NodeType | number, test: Callback<T, typeof tests>, to: NodeType | number, reducer?: Callback<R, typeof reducers>): void;
88export declare function registerShortcut<R extends keyof typeof reducers>(machine: StateMachine, from: NodeType | number, to: NodeType | number, reducer?: Callback<R, typeof reducers>): void;
89export declare function registerStatic<R extends keyof typeof reducers>(machine: StateMachine, from: NodeType | number, test: string, to: NodeType | number, reducer?: Callback<R, typeof reducers>): void;
90type UndefinedKeys<T> = {
91 [P in keyof T]-?: undefined extends T[P] ? P : never;
92}[keyof T];
93type UndefinedTupleKeys<T extends Array<unknown>> = UndefinedKeys<Omit<T, keyof []>>;
94type TupleKeys<T> = Exclude<keyof T, keyof []>;
95export type CallbackFn<P extends Array<any>, R> = (state: RunState, segment: string, segmentIndex: number, ...args: P) => R;
96export type CallbackFnParameters<T extends CallbackFn<any, any>> = T extends ((state: RunState, segment: string, segmentIndex: number, ...args: infer P) => any) ? P : never;
97export type CallbackStore<T extends string, R> = Record<T, CallbackFn<any, R>>;
98export type Callback<T extends string, S extends CallbackStore<T, any>> = [
99 TupleKeys<CallbackFnParameters<S[T]>>
100] extends [UndefinedTupleKeys<CallbackFnParameters<S[T]>>] ? (T | [T, ...CallbackFnParameters<S[T]>]) : [T, ...CallbackFnParameters<S[T]>];
101export declare function execute<T extends string, R, S extends CallbackStore<T, R>>(store: S, callback: Callback<T, S>, state: RunState, segment: string, segmentIndex: number): R;
102export declare const tests: {
103 always: () => boolean;
104 isOptionLike: (state: RunState, segment: string) => boolean;
105 isNotOptionLike: (state: RunState, segment: string) => boolean;
106 isOption: (state: RunState, segment: string, segmentIndex: number, name: string) => boolean;
107 isBatchOption: (state: RunState, segment: string, segmentIndex: number, names: Map<string, string>) => boolean;
108 isBoundOption: (state: RunState, segment: string, segmentIndex: number, names: Map<string, string>, options: Array<OptDefinition>) => boolean;
109 isNegatedOption: (state: RunState, segment: string, segmentIndex: number, name: string) => boolean;
110 isHelp: (state: RunState, segment: string) => boolean;
111 isUnsupportedOption: (state: RunState, segment: string, segmentIndex: number, names: Map<string, string>) => boolean;
112 isInvalidOption: (state: RunState, segment: string) => boolean;
113};
114export declare const reducers: {
115 setCandidateState: (state: RunState, segment: string, segmentIndex: number, candidateState: Partial<RunState>) => {
116 candidateUsage: string | null;
117 requiredOptions: Array<Array<string>>;
118 errorMessage: string | null;
119 ignoreOptions: boolean;
120 options: Array<{
121 name: string;
122 value: any;
123 }>;
124 path: Array<string>;
125 positionals: Array<{
126 value: string;
127 extra: boolean | typeof NoLimits;
128 }>;
129 remainder: string | null;
130 selectedIndex: number | null;
131 tokens: Array<Token>;
132 };
133 setSelectedIndex: (state: RunState, segment: string, segmentIndex: number, index: number) => {
134 selectedIndex: number;
135 candidateUsage: string | null;
136 requiredOptions: Array<Array<string>>;
137 errorMessage: string | null;
138 ignoreOptions: boolean;
139 options: Array<{
140 name: string;
141 value: any;
142 }>;
143 path: Array<string>;
144 positionals: Array<{
145 value: string;
146 extra: boolean | typeof NoLimits;
147 }>;
148 remainder: string | null;
149 tokens: Array<Token>;
150 };
151 pushBatch: (state: RunState, segment: string, segmentIndex: number, names: Map<string, string>) => {
152 options: {
153 name: string;
154 value: any;
155 }[];
156 tokens: Token[];
157 candidateUsage: string | null;
158 requiredOptions: Array<Array<string>>;
159 errorMessage: string | null;
160 ignoreOptions: boolean;
161 path: Array<string>;
162 positionals: Array<{
163 value: string;
164 extra: boolean | typeof NoLimits;
165 }>;
166 remainder: string | null;
167 selectedIndex: number | null;
168 };
169 pushBound: (state: RunState, segment: string, segmentIndex: number) => {
170 options: {
171 name: string;
172 value: any;
173 }[];
174 tokens: Token[];
175 candidateUsage: string | null;
176 requiredOptions: Array<Array<string>>;
177 errorMessage: string | null;
178 ignoreOptions: boolean;
179 path: Array<string>;
180 positionals: Array<{
181 value: string;
182 extra: boolean | typeof NoLimits;
183 }>;
184 remainder: string | null;
185 selectedIndex: number | null;
186 };
187 pushPath: (state: RunState, segment: string, segmentIndex: number) => {
188 path: string[];
189 tokens: Token[];
190 candidateUsage: string | null;
191 requiredOptions: Array<Array<string>>;
192 errorMessage: string | null;
193 ignoreOptions: boolean;
194 options: Array<{
195 name: string;
196 value: any;
197 }>;
198 positionals: Array<{
199 value: string;
200 extra: boolean | typeof NoLimits;
201 }>;
202 remainder: string | null;
203 selectedIndex: number | null;
204 };
205 pushPositional: (state: RunState, segment: string, segmentIndex: number) => {
206 positionals: {
207 value: string;
208 extra: boolean | typeof NoLimits;
209 }[];
210 tokens: Token[];
211 candidateUsage: string | null;
212 requiredOptions: Array<Array<string>>;
213 errorMessage: string | null;
214 ignoreOptions: boolean;
215 options: Array<{
216 name: string;
217 value: any;
218 }>;
219 path: Array<string>;
220 remainder: string | null;
221 selectedIndex: number | null;
222 };
223 pushExtra: (state: RunState, segment: string, segmentIndex: number) => {
224 positionals: {
225 value: string;
226 extra: boolean | typeof NoLimits;
227 }[];
228 tokens: Token[];
229 candidateUsage: string | null;
230 requiredOptions: Array<Array<string>>;
231 errorMessage: string | null;
232 ignoreOptions: boolean;
233 options: Array<{
234 name: string;
235 value: any;
236 }>;
237 path: Array<string>;
238 remainder: string | null;
239 selectedIndex: number | null;
240 };
241 pushExtraNoLimits: (state: RunState, segment: string, segmentIndex: number) => {
242 positionals: {
243 value: string;
244 extra: boolean | typeof NoLimits;
245 }[];
246 tokens: Token[];
247 candidateUsage: string | null;
248 requiredOptions: Array<Array<string>>;
249 errorMessage: string | null;
250 ignoreOptions: boolean;
251 options: Array<{
252 name: string;
253 value: any;
254 }>;
255 path: Array<string>;
256 remainder: string | null;
257 selectedIndex: number | null;
258 };
259 pushTrue: (state: RunState, segment: string, segmentIndex: number, name: string) => {
260 options: {
261 name: string;
262 value: any;
263 }[];
264 tokens: Token[];
265 candidateUsage: string | null;
266 requiredOptions: Array<Array<string>>;
267 errorMessage: string | null;
268 ignoreOptions: boolean;
269 path: Array<string>;
270 positionals: Array<{
271 value: string;
272 extra: boolean | typeof NoLimits;
273 }>;
274 remainder: string | null;
275 selectedIndex: number | null;
276 };
277 pushFalse: (state: RunState, segment: string, segmentIndex: number, name: string) => {
278 options: {
279 name: string;
280 value: any;
281 }[];
282 tokens: Token[];
283 candidateUsage: string | null;
284 requiredOptions: Array<Array<string>>;
285 errorMessage: string | null;
286 ignoreOptions: boolean;
287 path: Array<string>;
288 positionals: Array<{
289 value: string;
290 extra: boolean | typeof NoLimits;
291 }>;
292 remainder: string | null;
293 selectedIndex: number | null;
294 };
295 pushUndefined: (state: RunState, segment: string, segmentIndex: number, name: string) => {
296 options: {
297 name: string;
298 value: any;
299 }[];
300 tokens: Token[];
301 candidateUsage: string | null;
302 requiredOptions: Array<Array<string>>;
303 errorMessage: string | null;
304 ignoreOptions: boolean;
305 path: Array<string>;
306 positionals: Array<{
307 value: string;
308 extra: boolean | typeof NoLimits;
309 }>;
310 remainder: string | null;
311 selectedIndex: number | null;
312 };
313 pushStringValue: (state: RunState, segment: string, segmentIndex: number) => {
314 options: {
315 name: string;
316 value: any;
317 }[];
318 tokens: Token[];
319 candidateUsage: string | null;
320 requiredOptions: Array<Array<string>>;
321 errorMessage: string | null;
322 ignoreOptions: boolean;
323 path: Array<string>;
324 positionals: Array<{
325 value: string;
326 extra: boolean | typeof NoLimits;
327 }>;
328 remainder: string | null;
329 selectedIndex: number | null;
330 };
331 setStringValue: (state: RunState, segment: string, segmentIndex: number) => {
332 options: {
333 name: string;
334 value: any;
335 }[];
336 tokens: Token[];
337 candidateUsage: string | null;
338 requiredOptions: Array<Array<string>>;
339 errorMessage: string | null;
340 ignoreOptions: boolean;
341 path: Array<string>;
342 positionals: Array<{
343 value: string;
344 extra: boolean | typeof NoLimits;
345 }>;
346 remainder: string | null;
347 selectedIndex: number | null;
348 };
349 inhibateOptions: (state: RunState) => {
350 ignoreOptions: boolean;
351 candidateUsage: string | null;
352 requiredOptions: Array<Array<string>>;
353 errorMessage: string | null;
354 options: Array<{
355 name: string;
356 value: any;
357 }>;
358 path: Array<string>;
359 positionals: Array<{
360 value: string;
361 extra: boolean | typeof NoLimits;
362 }>;
363 remainder: string | null;
364 selectedIndex: number | null;
365 tokens: Array<Token>;
366 };
367 useHelp: (state: RunState, segment: string, segmentIndex: number, command: number) => {
368 options: {
369 name: string;
370 value: string;
371 }[];
372 candidateUsage: string | null;
373 requiredOptions: Array<Array<string>>;
374 errorMessage: string | null;
375 ignoreOptions: boolean;
376 path: Array<string>;
377 positionals: Array<{
378 value: string;
379 extra: boolean | typeof NoLimits;
380 }>;
381 remainder: string | null;
382 selectedIndex: number | null;
383 tokens: Array<Token>;
384 };
385 setError: (state: RunState, segment: string, segmentIndex: number, errorMessage: string) => {
386 errorMessage: string;
387 candidateUsage: string | null;
388 requiredOptions: Array<Array<string>>;
389 ignoreOptions: boolean;
390 options: Array<{
391 name: string;
392 value: any;
393 }>;
394 path: Array<string>;
395 positionals: Array<{
396 value: string;
397 extra: boolean | typeof NoLimits;
398 }>;
399 remainder: string | null;
400 selectedIndex: number | null;
401 tokens: Array<Token>;
402 };
403 setOptionArityError: (state: RunState, segment: string) => {
404 errorMessage: string;
405 candidateUsage: string | null;
406 requiredOptions: Array<Array<string>>;
407 ignoreOptions: boolean;
408 options: Array<{
409 name: string;
410 value: any;
411 }>;
412 path: Array<string>;
413 positionals: Array<{
414 value: string;
415 extra: boolean | typeof NoLimits;
416 }>;
417 remainder: string | null;
418 selectedIndex: number | null;
419 tokens: Array<Token>;
420 };
421};
422export declare const NoLimits: unique symbol;
423export type ArityDefinition = {
424 leading: Array<string>;
425 extra: Array<string> | typeof NoLimits;
426 trailing: Array<string>;
427 proxy: boolean;
428};
429export type OptDefinition = {
430 preferredName: string;
431 nameSet: Array<string>;
432 description?: string;
433 arity: number;
434 hidden: boolean;
435 required: boolean;
436 allowBinding: boolean;
437};
438export declare class CommandBuilder<Context> {
439 readonly cliIndex: number;
440 readonly cliOpts: Readonly<CliOptions>;
441 readonly allOptionNames: Map<string, string>;
442 readonly arity: ArityDefinition;
443 readonly options: Array<OptDefinition>;
444 readonly paths: Array<Array<string>>;
445 private context?;
446 constructor(cliIndex: number, cliOpts: CliOptions);
447 addPath(path: Array<string>): void;
448 setArity({ leading, trailing, extra, proxy }: Partial<ArityDefinition>): void;
449 addPositional({ name, required }?: {
450 name?: string;
451 required?: boolean;
452 }): void;
453 addRest({ name, required }?: {
454 name?: string;
455 required?: number;
456 }): void;
457 addProxy({ required }?: {
458 name?: string;
459 required?: number;
460 }): void;
461 addOption({ names: nameSet, description, arity, hidden, required, allowBinding }: Partial<OptDefinition> & {
462 names: Array<string>;
463 }): void;
464 setContext(context: Context): void;
465 usage({ detailed, inlineOptions }?: {
466 detailed?: boolean;
467 inlineOptions?: boolean;
468 }): {
469 usage: string;
470 options: {
471 preferredName: string;
472 nameSet: Array<string>;
473 definition: string;
474 description: string;
475 required: boolean;
476 }[];
477 };
478 compile(): {
479 machine: StateMachine;
480 context: Context & ({} | null);
481 };
482 private registerOptions;
483}
484export type CliOptions = {
485 binaryName: string;
486};
487export type CliBuilderCallback<Context> = (command: CommandBuilder<Context>) => CommandBuilder<Context> | void;
488export declare class CliBuilder<Context> {
489 private readonly opts;
490 private readonly builders;
491 static build<Context>(cbs: Array<CliBuilderCallback<Context>>, opts?: Partial<CliOptions>): {
492 machine: StateMachine;
493 contexts: ((Context & null) | (Context & {}))[];
494 process: (input: string[], { partial }?: {
495 partial?: boolean | undefined;
496 }) => RunState;
497 };
498 constructor({ binaryName }?: Partial<CliOptions>);
499 getBuilderByIndex(n: number): CommandBuilder<Context>;
500 commands(cbs: Array<CliBuilderCallback<Context>>): this;
501 command(): CommandBuilder<Context>;
502 compile(): {
503 machine: StateMachine;
504 contexts: ((Context & null) | (Context & {}))[];
505 process: (input: Array<string>, { partial }?: {
506 partial?: boolean | undefined;
507 }) => RunState;
508 };
509}
510export {};