@johannes.latzel/terminal 0.1.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/LICENSE +7 -0
- package/README.md +35 -0
- package/dist/command-arguments.d.ts +120 -0
- package/dist/command-arguments.d.ts.map +1 -0
- package/dist/command-arguments.js +155 -0
- package/dist/command-arguments.js.map +1 -0
- package/dist/command-factory.d.ts +17 -0
- package/dist/command-factory.d.ts.map +1 -0
- package/dist/command-factory.js +43 -0
- package/dist/command-factory.js.map +1 -0
- package/dist/command-tree.d.ts +40 -0
- package/dist/command-tree.d.ts.map +1 -0
- package/dist/command-tree.js +77 -0
- package/dist/command-tree.js.map +1 -0
- package/dist/commands/clear.d.ts +10 -0
- package/dist/commands/clear.d.ts.map +1 -0
- package/dist/commands/clear.js +13 -0
- package/dist/commands/clear.js.map +1 -0
- package/dist/commands/exit.d.ts +10 -0
- package/dist/commands/exit.d.ts.map +1 -0
- package/dist/commands/exit.js +13 -0
- package/dist/commands/exit.js.map +1 -0
- package/dist/commands/help.d.ts +40 -0
- package/dist/commands/help.d.ts.map +1 -0
- package/dist/commands/help.js +136 -0
- package/dist/commands/help.js.map +1 -0
- package/dist/completion/completer.d.ts +22 -0
- package/dist/completion/completer.d.ts.map +1 -0
- package/dist/completion/completer.js +55 -0
- package/dist/completion/completer.js.map +1 -0
- package/dist/errors.d.ts +18 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +28 -0
- package/dist/errors.js.map +1 -0
- package/dist/hook.d.ts +11 -0
- package/dist/hook.d.ts.map +1 -0
- package/dist/hook.js +16 -0
- package/dist/hook.js.map +1 -0
- package/dist/hooks.d.ts +21 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +17 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/input/args-parser.d.ts +22 -0
- package/dist/input/args-parser.d.ts.map +1 -0
- package/dist/input/args-parser.js +52 -0
- package/dist/input/args-parser.js.map +1 -0
- package/dist/input/parser.d.ts +14 -0
- package/dist/input/parser.d.ts.map +1 -0
- package/dist/input/parser.js +65 -0
- package/dist/input/parser.js.map +1 -0
- package/dist/terminal-hook-builder.d.ts +42 -0
- package/dist/terminal-hook-builder.d.ts.map +1 -0
- package/dist/terminal-hook-builder.js +48 -0
- package/dist/terminal-hook-builder.js.map +1 -0
- package/dist/terminal.d.ts +86 -0
- package/dist/terminal.d.ts.map +1 -0
- package/dist/terminal.js +274 -0
- package/dist/terminal.js.map +1 -0
- package/dist/types.d.ts +80 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +85 -0
- package/dist/types.js.map +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { Command, CommandContainer } from '../types.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
/** Left-pad a string with spaces to a minimum width. */
|
|
4
|
+
function leftPad(str, len) {
|
|
5
|
+
return str + ' '.repeat(Math.max(0, len - str.length));
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Render a global help listing for a set of root commands.
|
|
9
|
+
* Each command is shown as `name description`, names are
|
|
10
|
+
* left-aligned to the longest command name.
|
|
11
|
+
*/
|
|
12
|
+
export function globalHelp(commands) {
|
|
13
|
+
const maxNameLen = Math.max(...commands.map((c) => c.name().length), 0);
|
|
14
|
+
const lines = ['Commands:'];
|
|
15
|
+
for (const cmd of commands) {
|
|
16
|
+
const desc = cmd.description() ?? '';
|
|
17
|
+
lines.push(` ${leftPad(cmd.name(), maxNameLen)} ${desc}`);
|
|
18
|
+
}
|
|
19
|
+
return lines.join('\n');
|
|
20
|
+
}
|
|
21
|
+
function renderCommandArgumentDefinitions(argDefs) {
|
|
22
|
+
if (argDefs.length === 0)
|
|
23
|
+
return [];
|
|
24
|
+
const lines = ['', 'Arguments:'];
|
|
25
|
+
const maxNameLen = Math.max(...argDefs.map((a) => a.name.length));
|
|
26
|
+
for (const arg of argDefs) {
|
|
27
|
+
const label = `--${arg.name}`;
|
|
28
|
+
const required = arg.required ? ' (required)' : '';
|
|
29
|
+
const desc = arg.description ?? '';
|
|
30
|
+
lines.push(` ${leftPad(label, maxNameLen + 2)} ${desc}${required}`);
|
|
31
|
+
}
|
|
32
|
+
return lines;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Render detailed help for a single command, including its
|
|
36
|
+
* name, description, argument definitions, and subcommands.
|
|
37
|
+
*/
|
|
38
|
+
export function commandHelp(command) {
|
|
39
|
+
const lines = [];
|
|
40
|
+
const globalDesc = command.description();
|
|
41
|
+
if (globalDesc) {
|
|
42
|
+
lines.push(`${command.name()} - ${globalDesc}`);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
lines.push(command.name());
|
|
46
|
+
}
|
|
47
|
+
lines.push(...renderCommandArgumentDefinitions(command.definitions()));
|
|
48
|
+
if (command instanceof CommandContainer) {
|
|
49
|
+
const subs = command.commands();
|
|
50
|
+
if (subs.length > 0) {
|
|
51
|
+
const maxNameLen = Math.max(...subs.map((c) => c.name().length));
|
|
52
|
+
lines.push('');
|
|
53
|
+
lines.push('Subcommands:');
|
|
54
|
+
for (const sub of subs) {
|
|
55
|
+
const desc = sub.description() ?? '';
|
|
56
|
+
lines.push(` ${leftPad(sub.name(), maxNameLen)} ${desc}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return lines.join('\n');
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Resolve a token path against a command list and render
|
|
64
|
+
* help for the resolved command. Returns an error message
|
|
65
|
+
* if the path does not match any command.
|
|
66
|
+
*/
|
|
67
|
+
export function scopedHelp(commands, pathTokens) {
|
|
68
|
+
const resolved = resolveCommand(commands, pathTokens);
|
|
69
|
+
if (!resolved) {
|
|
70
|
+
return `Unknown command: ${pathTokens.join(' ')}`;
|
|
71
|
+
}
|
|
72
|
+
return commandHelp(resolved);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Walk the command tree matching each token to a command name.
|
|
76
|
+
* Returns the deepest matching command, or `undefined` if a token
|
|
77
|
+
* cannot be matched or extra tokens trail a leaf node.
|
|
78
|
+
*/
|
|
79
|
+
export function resolveCommand(commands, tokens) {
|
|
80
|
+
let level = commands;
|
|
81
|
+
let matched;
|
|
82
|
+
for (const token of tokens) {
|
|
83
|
+
matched = level.find((c) => c.name() === token);
|
|
84
|
+
if (!matched)
|
|
85
|
+
return undefined;
|
|
86
|
+
if (matched instanceof CommandContainer) {
|
|
87
|
+
const subs = matched.commands();
|
|
88
|
+
if (subs.length > 0) {
|
|
89
|
+
level = subs;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (token !== tokens[tokens.length - 1]) {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return matched;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Built-in `help` command. Lists all commands or shows detailed
|
|
101
|
+
* help for a specific command by name.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```
|
|
105
|
+
* > help # list all commands
|
|
106
|
+
* > help --command config # show help for the "config" command
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
export class HelpCommand extends Command {
|
|
110
|
+
constructor() {
|
|
111
|
+
super('help', 'Show help', [
|
|
112
|
+
{
|
|
113
|
+
name: 'command',
|
|
114
|
+
description: 'Show help for a specific command',
|
|
115
|
+
required: false,
|
|
116
|
+
schema: z.string()
|
|
117
|
+
}
|
|
118
|
+
]);
|
|
119
|
+
}
|
|
120
|
+
async execute(ctx, args) {
|
|
121
|
+
const roots = ctx.terminal.getRootCommands();
|
|
122
|
+
if (args.has('command')) {
|
|
123
|
+
const cmdName = await args.require('command');
|
|
124
|
+
const cmd = roots.find((c) => c.name() === cmdName);
|
|
125
|
+
if (!cmd) {
|
|
126
|
+
ctx.stdout.write(`Unknown command: ${cmdName}\n`);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
ctx.stdout.write(commandHelp(cmd) + '\n');
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
ctx.stdout.write(globalHelp(roots) + '\n');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=help.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/commands/help.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CommandTree } from '../command-tree.js';
|
|
2
|
+
export interface Completion {
|
|
3
|
+
/** Matching command names. */
|
|
4
|
+
matches: string[];
|
|
5
|
+
/** The partial token that was matched against. */
|
|
6
|
+
partial: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Tab-completion engine powered by the command tree.
|
|
10
|
+
* Walks the tree to find commands matching the current input
|
|
11
|
+
* prefix, supporting multi-level completion through containers
|
|
12
|
+
* and --flag completion for commands with argument definitions.
|
|
13
|
+
*/
|
|
14
|
+
export declare class Completer {
|
|
15
|
+
private tree;
|
|
16
|
+
constructor(tree: CommandTree);
|
|
17
|
+
/**
|
|
18
|
+
* Compute completions for a partial input line.
|
|
19
|
+
*/
|
|
20
|
+
complete(line: string): Completion;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=completer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completer.d.ts","sourceRoot":"","sources":["../../src/completion/completer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,MAAM,WAAW,UAAU;IACvB,8BAA8B;IAC9B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,qBAAa,SAAS;IACN,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,WAAW;IAErC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU;CAwCrC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { CommandContainer } from '../types.js';
|
|
2
|
+
import { tokenize } from '../input/parser.js';
|
|
3
|
+
/**
|
|
4
|
+
* Tab-completion engine powered by the command tree.
|
|
5
|
+
* Walks the tree to find commands matching the current input
|
|
6
|
+
* prefix, supporting multi-level completion through containers
|
|
7
|
+
* and --flag completion for commands with argument definitions.
|
|
8
|
+
*/
|
|
9
|
+
export class Completer {
|
|
10
|
+
tree;
|
|
11
|
+
constructor(tree) {
|
|
12
|
+
this.tree = tree;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Compute completions for a partial input line.
|
|
16
|
+
*/
|
|
17
|
+
complete(line) {
|
|
18
|
+
const tokens = tokenize(line);
|
|
19
|
+
const trailingSpace = line.endsWith(' ');
|
|
20
|
+
if (tokens.length === 0 && !trailingSpace) {
|
|
21
|
+
return { matches: this.tree.getRoots().map((c) => c.name()), partial: '' };
|
|
22
|
+
}
|
|
23
|
+
const partial = trailingSpace ? '' : tokens[tokens.length - 1];
|
|
24
|
+
const prefix = trailingSpace ? tokens : tokens.slice(0, -1);
|
|
25
|
+
let lastMatched = null;
|
|
26
|
+
let commands = this.tree.getRoots();
|
|
27
|
+
for (const token of prefix) {
|
|
28
|
+
if (token.startsWith('--'))
|
|
29
|
+
continue;
|
|
30
|
+
const cmd = commands.find((command) => command.name() === token);
|
|
31
|
+
if (!cmd)
|
|
32
|
+
return { matches: [], partial: line };
|
|
33
|
+
lastMatched = cmd;
|
|
34
|
+
if (!(cmd instanceof CommandContainer))
|
|
35
|
+
break;
|
|
36
|
+
commands = cmd.commands();
|
|
37
|
+
}
|
|
38
|
+
if (lastMatched && !(lastMatched instanceof CommandContainer)) {
|
|
39
|
+
const flagPartial = partial.startsWith('--') ? partial : partial === '' ? '--' : null;
|
|
40
|
+
if (flagPartial !== null) {
|
|
41
|
+
const matches = lastMatched
|
|
42
|
+
.definitions()
|
|
43
|
+
.filter((a) => `--${a.name}`.startsWith(flagPartial))
|
|
44
|
+
.map((a) => `--${a.name}`);
|
|
45
|
+
return { matches, partial };
|
|
46
|
+
}
|
|
47
|
+
return { matches: [], partial };
|
|
48
|
+
}
|
|
49
|
+
const matches = commands
|
|
50
|
+
.filter((command) => command.name().startsWith(partial))
|
|
51
|
+
.map((c) => c.name());
|
|
52
|
+
return { matches, partial };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=completer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completer.js","sourceRoot":"","sources":["../../src/completion/completer.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Thrown when no command matches the input tokens. */
|
|
2
|
+
export declare class CommandNotFoundError extends Error {
|
|
3
|
+
readonly suggestions: string[];
|
|
4
|
+
/**
|
|
5
|
+
* @param message - Human-readable error description.
|
|
6
|
+
* @param suggestions - Prefix-matched command names to suggest.
|
|
7
|
+
*/
|
|
8
|
+
constructor(message: string, suggestions?: string[]);
|
|
9
|
+
}
|
|
10
|
+
/** Thrown when a command receives invalid arguments. */
|
|
11
|
+
export declare class InvalidArgumentsError extends Error {
|
|
12
|
+
constructor(message: string);
|
|
13
|
+
}
|
|
14
|
+
/** Thrown when input cannot be tokenized (e.g. unclosed quotes). */
|
|
15
|
+
export declare class ParseError extends Error {
|
|
16
|
+
constructor(message: string);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,qBAAa,oBAAqB,SAAQ,KAAK;aAOvB,WAAW,EAAE,MAAM,EAAE;IANzC;;;OAGG;gBAEC,OAAO,EAAE,MAAM,EACC,WAAW,GAAE,MAAM,EAAO;CAKjD;AAED,wDAAwD;AACxD,qBAAa,qBAAsB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI9B;AAED,oEAAoE;AACpE,qBAAa,UAAW,SAAQ,KAAK;gBACrB,OAAO,EAAE,MAAM;CAI9B"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Thrown when no command matches the input tokens. */
|
|
2
|
+
export class CommandNotFoundError extends Error {
|
|
3
|
+
suggestions;
|
|
4
|
+
/**
|
|
5
|
+
* @param message - Human-readable error description.
|
|
6
|
+
* @param suggestions - Prefix-matched command names to suggest.
|
|
7
|
+
*/
|
|
8
|
+
constructor(message, suggestions = []) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.suggestions = suggestions;
|
|
11
|
+
this.name = 'CommandNotFoundError';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/** Thrown when a command receives invalid arguments. */
|
|
15
|
+
export class InvalidArgumentsError extends Error {
|
|
16
|
+
constructor(message) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.name = 'InvalidArgumentsError';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Thrown when input cannot be tokenized (e.g. unclosed quotes). */
|
|
22
|
+
export class ParseError extends Error {
|
|
23
|
+
constructor(message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = 'ParseError';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAOvB;IANpB;;;OAGG;IACH,YACI,OAAe,EACC,cAAwB,EAAE;QAE1C,KAAK,CAAC,OAAO,CAAC,CAAC;QAFC,gBAAW,GAAX,WAAW,CAAe;QAG1C,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACvC,CAAC;CACJ;AAED,wDAAwD;AACxD,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC5C,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACxC,CAAC;CACJ;AAED,oEAAoE;AACpE,MAAM,OAAO,UAAW,SAAQ,KAAK;IACjC,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC7B,CAAC;CACJ"}
|
package/dist/hook.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Base class for all hooks. Call {@link dispose} to unsubscribe. */
|
|
2
|
+
export declare abstract class Hook {
|
|
3
|
+
private _disposed;
|
|
4
|
+
/** Unsubscribe this hook. Safe to call multiple times. */
|
|
5
|
+
dispose(): void;
|
|
6
|
+
/** Whether this hook has been disposed. */
|
|
7
|
+
protected isDisposed(): boolean;
|
|
8
|
+
/** Override to clean up subscriptions. Called once by {@link dispose}. */
|
|
9
|
+
protected abstract onDispose(): void;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,8BAAsB,IAAI;IACtB,OAAO,CAAC,SAAS,CAAS;IAE1B,0DAA0D;IAC1D,OAAO,IAAI,IAAI;IAMf,2CAA2C;IAC3C,SAAS,CAAC,UAAU,IAAI,OAAO;IAI/B,0EAA0E;IAC1E,SAAS,CAAC,QAAQ,CAAC,SAAS,IAAI,IAAI;CACvC"}
|
package/dist/hook.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Base class for all hooks. Call {@link dispose} to unsubscribe. */
|
|
2
|
+
export class Hook {
|
|
3
|
+
_disposed = false;
|
|
4
|
+
/** Unsubscribe this hook. Safe to call multiple times. */
|
|
5
|
+
dispose() {
|
|
6
|
+
if (this._disposed)
|
|
7
|
+
return;
|
|
8
|
+
this._disposed = true;
|
|
9
|
+
this.onDispose();
|
|
10
|
+
}
|
|
11
|
+
/** Whether this hook has been disposed. */
|
|
12
|
+
isDisposed() {
|
|
13
|
+
return this._disposed;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=hook.js.map
|
package/dist/hook.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.js","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,MAAM,OAAgB,IAAI;IACd,SAAS,GAAG,KAAK,CAAC;IAE1B,0DAA0D;IAC1D,OAAO;QACH,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,SAAS,EAAE,CAAC;IACrB,CAAC;IAED,2CAA2C;IACjC,UAAU;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;CAIJ"}
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Hook } from './hook.js';
|
|
2
|
+
import type { Command, CommandContext } from './types.js';
|
|
3
|
+
import type { CommandArguments } from './command-arguments.js';
|
|
4
|
+
export declare class TypedHook<TArgs extends any[], TReturn> extends Hook {
|
|
5
|
+
private readonly fn;
|
|
6
|
+
private readonly onDisposeCb;
|
|
7
|
+
constructor(fn: (...args: TArgs) => TReturn, onDisposeCb: () => void);
|
|
8
|
+
exec(...args: TArgs): TReturn;
|
|
9
|
+
protected onDispose(): void;
|
|
10
|
+
}
|
|
11
|
+
export type BeforeParseHook = TypedHook<[string], string | Promise<string>>;
|
|
12
|
+
export type AfterParseHook = TypedHook<[string[]], string[] | Promise<string[]>>;
|
|
13
|
+
export type BeforeExecuteHook = TypedHook<[
|
|
14
|
+
Command,
|
|
15
|
+
CommandContext,
|
|
16
|
+
CommandArguments
|
|
17
|
+
], void | false | Promise<void | false>>;
|
|
18
|
+
export type AfterExecuteHook = TypedHook<[unknown], void | Promise<void>>;
|
|
19
|
+
export type BeforeExitHook = TypedHook<[], void | Promise<void>>;
|
|
20
|
+
export type OnErrorHook = TypedHook<[Error], void | boolean | Promise<void | boolean>>;
|
|
21
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,qBAAa,SAAS,CAAC,KAAK,SAAS,GAAG,EAAE,EAAE,OAAO,CAAE,SAAQ,IAAI;IAEzD,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,WAAW;gBADX,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,EAC/B,WAAW,EAAE,MAAM,IAAI;IAK5C,IAAI,CAAC,GAAG,IAAI,EAAE,KAAK,GAAG,OAAO;IAI7B,SAAS,CAAC,SAAS,IAAI,IAAI;CAG9B;AAED,MAAM,MAAM,eAAe,GAAG,SAAS,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAC5E,MAAM,MAAM,cAAc,GAAG,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AACjF,MAAM,MAAM,iBAAiB,GAAG,SAAS,CACrC;IAAC,OAAO;IAAE,cAAc;IAAE,gBAAgB;CAAC,EAC3C,IAAI,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC,CACvC,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1E,MAAM,MAAM,cAAc,GAAG,SAAS,CAAC,EAAE,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AACjE,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,KAAK,CAAC,EAAE,IAAI,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC"}
|
package/dist/hooks.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Hook } from './hook.js';
|
|
2
|
+
export class TypedHook extends Hook {
|
|
3
|
+
fn;
|
|
4
|
+
onDisposeCb;
|
|
5
|
+
constructor(fn, onDisposeCb) {
|
|
6
|
+
super();
|
|
7
|
+
this.fn = fn;
|
|
8
|
+
this.onDisposeCb = onDisposeCb;
|
|
9
|
+
}
|
|
10
|
+
exec(...args) {
|
|
11
|
+
return this.fn(...args);
|
|
12
|
+
}
|
|
13
|
+
onDispose() {
|
|
14
|
+
this.onDisposeCb();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,MAAM,OAAO,SAAwC,SAAQ,IAAI;IAExC;IACA;IAFrB,YACqB,EAA+B,EAC/B,WAAuB;QAExC,KAAK,EAAE,CAAC;QAHS,OAAE,GAAF,EAAE,CAA6B;QAC/B,gBAAW,GAAX,WAAW,CAAY;IAG5C,CAAC;IAED,IAAI,CAAC,GAAG,IAAW;QACf,OAAO,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5B,CAAC;IAES,SAAS;QACf,IAAI,CAAC,WAAW,EAAE,CAAC;IACvB,CAAC;CACJ"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { Terminal } from './terminal.js';
|
|
2
|
+
export { CommandArguments } from './command-arguments.js';
|
|
3
|
+
export { InvalidArgumentsError, CommandNotFoundError, ParseError } from './errors.js';
|
|
4
|
+
export { Hook } from './hook.js';
|
|
5
|
+
export { TerminalHookBuilder } from './terminal-hook-builder.js';
|
|
6
|
+
export { Command, CommandContainer } from './types.js';
|
|
7
|
+
export { command, container, arg } from './command-factory.js';
|
|
8
|
+
export type { CommandArgumentDefinition } from './command-arguments.js';
|
|
9
|
+
export type { CommandContext, Logger, TerminalOptions } from './types.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAC/D,YAAY,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACxE,YAAY,EAAE,cAAc,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { Terminal } from './terminal.js';
|
|
2
|
+
export { CommandArguments } from './command-arguments.js';
|
|
3
|
+
export { InvalidArgumentsError, CommandNotFoundError, ParseError } from './errors.js';
|
|
4
|
+
export { Hook } from './hook.js';
|
|
5
|
+
export { TerminalHookBuilder } from './terminal-hook-builder.js';
|
|
6
|
+
export { Command, CommandContainer } from './types.js';
|
|
7
|
+
export { command, container, arg } from './command-factory.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CommandArgumentDefinition } from '../command-arguments.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parse an array of tokens into a record of `--name value` pairs.
|
|
4
|
+
*
|
|
5
|
+
* - `--name value` produces `{ name: "value" }`
|
|
6
|
+
* - `--flag` (no next token or next token starts with `--`) produces
|
|
7
|
+
* `{ flag: "true" }` (boolean-shorthand)
|
|
8
|
+
* - When `argDefs` is provided, tokens not starting with `--` are
|
|
9
|
+
* matched against argument definitions with a `position` index
|
|
10
|
+
* and consumed in position order.
|
|
11
|
+
*
|
|
12
|
+
* @param tokens - Tokens remaining after command matching.
|
|
13
|
+
* @param argDefs - Optional argument definitions; those with a
|
|
14
|
+
* `position` field are treated as positional (bare token) args.
|
|
15
|
+
* @returns A record mapping argument names (without `--` prefix) to
|
|
16
|
+
* their string values.
|
|
17
|
+
* @throws {InvalidArgumentsError} When a token does not start with
|
|
18
|
+
* `--` (and no positional definition matches), or an empty `--`
|
|
19
|
+
* is encountered.
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseFlags(tokens: string[], argDefs?: CommandArgumentDefinition[]): Record<string, string>;
|
|
22
|
+
//# sourceMappingURL=args-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args-parser.d.ts","sourceRoot":"","sources":["../../src/input/args-parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAEzE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CACtB,MAAM,EAAE,MAAM,EAAE,EAChB,OAAO,CAAC,EAAE,yBAAyB,EAAE,GACtC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkCxB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { InvalidArgumentsError } from '../errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parse an array of tokens into a record of `--name value` pairs.
|
|
4
|
+
*
|
|
5
|
+
* - `--name value` produces `{ name: "value" }`
|
|
6
|
+
* - `--flag` (no next token or next token starts with `--`) produces
|
|
7
|
+
* `{ flag: "true" }` (boolean-shorthand)
|
|
8
|
+
* - When `argDefs` is provided, tokens not starting with `--` are
|
|
9
|
+
* matched against argument definitions with a `position` index
|
|
10
|
+
* and consumed in position order.
|
|
11
|
+
*
|
|
12
|
+
* @param tokens - Tokens remaining after command matching.
|
|
13
|
+
* @param argDefs - Optional argument definitions; those with a
|
|
14
|
+
* `position` field are treated as positional (bare token) args.
|
|
15
|
+
* @returns A record mapping argument names (without `--` prefix) to
|
|
16
|
+
* their string values.
|
|
17
|
+
* @throws {InvalidArgumentsError} When a token does not start with
|
|
18
|
+
* `--` (and no positional definition matches), or an empty `--`
|
|
19
|
+
* is encountered.
|
|
20
|
+
*/
|
|
21
|
+
export function parseFlags(tokens, argDefs) {
|
|
22
|
+
const args = {};
|
|
23
|
+
const positionalDefs = (argDefs ?? [])
|
|
24
|
+
.filter((d) => d.position !== undefined)
|
|
25
|
+
.sort((a, b) => a.position - b.position);
|
|
26
|
+
let positionalIdx = 0;
|
|
27
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
28
|
+
const token = tokens[i];
|
|
29
|
+
if (!token.startsWith('--')) {
|
|
30
|
+
if (positionalIdx < positionalDefs.length) {
|
|
31
|
+
args[positionalDefs[positionalIdx].name] = token;
|
|
32
|
+
positionalIdx++;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
throw new InvalidArgumentsError(`Unexpected token "${token}", expected --argument`);
|
|
36
|
+
}
|
|
37
|
+
const name = token.slice(2);
|
|
38
|
+
if (name.length === 0) {
|
|
39
|
+
throw new InvalidArgumentsError('Empty argument name (--)');
|
|
40
|
+
}
|
|
41
|
+
const next = tokens[i + 1];
|
|
42
|
+
if (next !== undefined && !next.startsWith('--')) {
|
|
43
|
+
args[name] = next;
|
|
44
|
+
i++;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
args[name] = 'true';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return args;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=args-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args-parser.js","sourceRoot":"","sources":["../../src/input/args-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAGrD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,UAAU,CACtB,MAAgB,EAChB,OAAqC;IAErC,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,MAAM,cAAc,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;SACjC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC;SACvC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAS,GAAG,CAAC,CAAC,QAAS,CAAC,CAAC;IAC/C,IAAI,aAAa,GAAG,CAAC,CAAC;IAEtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QAEzB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,IAAI,aAAa,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC;gBACxC,IAAI,CAAC,cAAc,CAAC,aAAa,CAAE,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;gBAClD,aAAa,EAAE,CAAC;gBAChB,SAAS;YACb,CAAC;YACD,MAAM,IAAI,qBAAqB,CAAC,qBAAqB,KAAK,wBAAwB,CAAC,CAAC;QACxF,CAAC;QAED,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,qBAAqB,CAAC,0BAA0B,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3B,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/C,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YAClB,CAAC,EAAE,CAAC;QACR,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;QACxB,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Split a raw input line into tokens, respecting single and double quotes.
|
|
3
|
+
* Leading and trailing whitespace is trimmed; empty or whitespace-only
|
|
4
|
+
* input produces an empty array.
|
|
5
|
+
*
|
|
6
|
+
* Quoted segments are treated as a single token (quotes stripped).
|
|
7
|
+
* Both quote types support `\` escapes and are treated identically.
|
|
8
|
+
* Adjacent non-whitespace characters around quotes are rejected.
|
|
9
|
+
*
|
|
10
|
+
* @param input - Raw input string from the terminal.
|
|
11
|
+
* @throws {ParseError} When quotes are unclosed or adjacent to non-whitespace.
|
|
12
|
+
*/
|
|
13
|
+
export declare function tokenize(input: string): string[];
|
|
14
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/input/parser.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA0DhD"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { ParseError } from '../errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Split a raw input line into tokens, respecting single and double quotes.
|
|
4
|
+
* Leading and trailing whitespace is trimmed; empty or whitespace-only
|
|
5
|
+
* input produces an empty array.
|
|
6
|
+
*
|
|
7
|
+
* Quoted segments are treated as a single token (quotes stripped).
|
|
8
|
+
* Both quote types support `\` escapes and are treated identically.
|
|
9
|
+
* Adjacent non-whitespace characters around quotes are rejected.
|
|
10
|
+
*
|
|
11
|
+
* @param input - Raw input string from the terminal.
|
|
12
|
+
* @throws {ParseError} When quotes are unclosed or adjacent to non-whitespace.
|
|
13
|
+
*/
|
|
14
|
+
export function tokenize(input) {
|
|
15
|
+
const trimmed = input.trim();
|
|
16
|
+
if (trimmed.length === 0)
|
|
17
|
+
return [];
|
|
18
|
+
const tokens = [];
|
|
19
|
+
let current = '';
|
|
20
|
+
let inQuote = null;
|
|
21
|
+
for (let i = 0; i < trimmed.length; i++) {
|
|
22
|
+
const ch = trimmed[i];
|
|
23
|
+
if (inQuote && ch === '\\' && i + 1 < trimmed.length) {
|
|
24
|
+
current += trimmed[++i];
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (ch === '"' || ch === "'") {
|
|
28
|
+
if (inQuote === null && current.length > 0) {
|
|
29
|
+
throw new ParseError(`Unexpected characters before quote: "${current}"`);
|
|
30
|
+
}
|
|
31
|
+
if (inQuote === ch) {
|
|
32
|
+
inQuote = null;
|
|
33
|
+
tokens.push(current);
|
|
34
|
+
current = '';
|
|
35
|
+
const next = trimmed[i + 1];
|
|
36
|
+
if (next !== undefined && !/\s/.test(next)) {
|
|
37
|
+
throw new ParseError(`Unexpected character "${next}" after closing quote`);
|
|
38
|
+
}
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (inQuote === null) {
|
|
42
|
+
inQuote = ch;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
current += ch;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (/\s/.test(ch) && inQuote === null) {
|
|
49
|
+
if (current.length > 0) {
|
|
50
|
+
tokens.push(current);
|
|
51
|
+
current = '';
|
|
52
|
+
}
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
current += ch;
|
|
56
|
+
}
|
|
57
|
+
if (current.length > 0) {
|
|
58
|
+
tokens.push(current);
|
|
59
|
+
}
|
|
60
|
+
if (inQuote !== null) {
|
|
61
|
+
throw new ParseError(`Unclosed ${inQuote} quote`);
|
|
62
|
+
}
|
|
63
|
+
return tokens;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/input/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAa;IAClC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEpC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,OAAO,GAAqB,IAAI,CAAC;IAErC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC;QAEvB,IAAI,OAAO,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YACnD,OAAO,IAAI,OAAO,CAAC,EAAE,CAAC,CAAE,CAAC;YACzB,SAAS;QACb,CAAC;QAED,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAC3B,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzC,MAAM,IAAI,UAAU,CAAC,wCAAwC,OAAO,GAAG,CAAC,CAAC;YAC7E,CAAC;YACD,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;gBACjB,OAAO,GAAG,IAAI,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrB,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC5B,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBACzC,MAAM,IAAI,UAAU,CAAC,yBAAyB,IAAI,uBAAuB,CAAC,CAAC;gBAC/E,CAAC;gBACD,SAAS;YACb,CAAC;YACD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACnB,OAAO,GAAG,EAAE,CAAC;gBACb,SAAS;YACb,CAAC;YACD,OAAO,IAAI,EAAE,CAAC;YACd,SAAS;QACb,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACpC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrB,OAAO,GAAG,EAAE,CAAC;YACjB,CAAC;YACD,SAAS;QACb,CAAC;QAED,OAAO,IAAI,EAAE,CAAC;IAClB,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAED,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,UAAU,CAAC,YAAY,OAAO,QAAQ,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Hook } from './hook.js';
|
|
2
|
+
import type { Command, CommandContext } from './types.js';
|
|
3
|
+
import type { CommandArguments } from './command-arguments.js';
|
|
4
|
+
type HookRegistrations = {
|
|
5
|
+
beforeParse: (fn: (input: string) => string | Promise<string>) => Hook;
|
|
6
|
+
afterParse: (fn: (tokens: string[]) => string[] | Promise<string[]>) => Hook;
|
|
7
|
+
beforeExecute: (fn: (command: Command, ctx: CommandContext, args: CommandArguments) => void | false | Promise<void | false>) => Hook;
|
|
8
|
+
afterExecute: (fn: (result: unknown) => void | Promise<void>) => Hook;
|
|
9
|
+
beforeExit: (fn: () => void | Promise<void>) => Hook;
|
|
10
|
+
onError: (fn: (error: Error) => void | boolean | Promise<void | boolean>) => Hook;
|
|
11
|
+
};
|
|
12
|
+
declare class HookBuilder<T extends (...args: any[]) => any> {
|
|
13
|
+
private _reg;
|
|
14
|
+
constructor(_reg: (fn: T) => Hook);
|
|
15
|
+
do(callback: T): Hook;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Entry point for registering terminal lifecycle hooks.
|
|
19
|
+
*
|
|
20
|
+
* Created by calling {@link Terminal.hook}. Select an event with one of the
|
|
21
|
+
* selector methods, then call {@link do} to register the callback.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* const h = term.hook()
|
|
26
|
+
* .beforeExecute()
|
|
27
|
+
* .do((command) => console.log(command.name()));
|
|
28
|
+
* // later: h.dispose();
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare class TerminalHookBuilder {
|
|
32
|
+
private _regs;
|
|
33
|
+
constructor(_regs: HookRegistrations);
|
|
34
|
+
beforeParse(): HookBuilder<(input: string) => string | Promise<string>>;
|
|
35
|
+
afterParse(): HookBuilder<(tokens: string[]) => string[] | Promise<string[]>>;
|
|
36
|
+
beforeExecute(): HookBuilder<(command: Command, ctx: CommandContext, args: CommandArguments) => void | false | Promise<void | false>>;
|
|
37
|
+
afterExecute(): HookBuilder<(result: unknown) => void | Promise<void>>;
|
|
38
|
+
beforeExit(): HookBuilder<() => void | Promise<void>>;
|
|
39
|
+
onError(): HookBuilder<(error: Error) => void | boolean | Promise<void | boolean>>;
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=terminal-hook-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-hook-builder.d.ts","sourceRoot":"","sources":["../src/terminal-hook-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,KAAK,iBAAiB,GAAG;IACrB,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IACvE,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;IAC7E,aAAa,EAAE,CACX,EAAE,EAAE,CACA,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,gBAAgB,KACrB,IAAI,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC,KACxC,IAAI,CAAC;IACV,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;IACtE,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;IACrD,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC;CACrF,CAAC;AAEF,cAAM,WAAW,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG;IACnC,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI;IACzC,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI;CAGxB;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,mBAAmB;IAChB,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,iBAAiB;IAE5C,WAAW,IAAI,WAAW,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAIvE,UAAU,IAAI,WAAW,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAI7E,aAAa,IAAI,WAAW,CACxB,CACI,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,gBAAgB,KACrB,IAAI,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC,CAC5C;IAID,YAAY,IAAI,WAAW,CAAC,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAItE,UAAU,IAAI,WAAW,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAIrD,OAAO,IAAI,WAAW,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC;CAGrF"}
|