utilium 0.7.10 → 0.8.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.
@@ -0,0 +1,37 @@
1
+ import type { Terminal } from '@xterm/xterm';
2
+ export interface ShellOptions {
3
+ /**
4
+ * The terminal associated with the context
5
+ */
6
+ terminal: Terminal;
7
+ /**
8
+ * The prompt to use, can be a getter.
9
+ */
10
+ readonly prompt?: string;
11
+ /**
12
+ * The handler for when a line is parsed
13
+ */
14
+ onLine?(this: void, line: string): unknown;
15
+ }
16
+ export interface ShellContext extends Required<ShellOptions> {
17
+ /**
18
+ * The input currently being shown
19
+ */
20
+ input: string;
21
+ /**
22
+ * The index for which input is being shown
23
+ */
24
+ index: number;
25
+ /**
26
+ * The current, uncached input
27
+ */
28
+ currentInput: string;
29
+ /**
30
+ * array of previous inputs
31
+ */
32
+ inputs: string[];
33
+ }
34
+ /**
35
+ * Creates a new shell using the provided options
36
+ */
37
+ export declare function createShell({ terminal, prompt, onLine }: ShellOptions): ShellContext;
package/dist/shell.js ADDED
@@ -0,0 +1,79 @@
1
+ function handleData($, data) {
2
+ if ($.index == -1) {
3
+ $.currentInput = $.input;
4
+ }
5
+ function clear() {
6
+ $.terminal.write('\x1b[2K\r' + $.prompt);
7
+ }
8
+ const x = $.terminal.buffer.active.cursorX - $.prompt.length;
9
+ switch (data) {
10
+ case 'ArrowUp':
11
+ case '\x1b[A':
12
+ clear();
13
+ if ($.index < $.inputs.length - 1) {
14
+ $.input = $.inputs[++$.index];
15
+ }
16
+ $.terminal.write($.input);
17
+ break;
18
+ case 'ArrowDown':
19
+ case '\x1b[B':
20
+ clear();
21
+ if ($.index >= 0) {
22
+ $.input = $.index-- == 0 ? $.currentInput : $.inputs[$.index];
23
+ }
24
+ $.terminal.write($.input);
25
+ break;
26
+ case '\x1b[D':
27
+ if (x > 0) {
28
+ $.terminal.write(data);
29
+ }
30
+ break;
31
+ case '\x1b[C':
32
+ if (x < $.currentInput.length) {
33
+ $.terminal.write(data);
34
+ }
35
+ break;
36
+ case '\x1b[F':
37
+ $.terminal.write(`\x1b[${$.prompt.length + $.currentInput.length + 1}G`);
38
+ break;
39
+ case '\x1b[H':
40
+ $.terminal.write(`\x1b[${$.prompt.length + 1}G`);
41
+ break;
42
+ case '\x7f':
43
+ if (x <= 0) {
44
+ return;
45
+ }
46
+ $.terminal.write('\b\x1b[P');
47
+ $.input = $.input.slice(0, x - 1) + $.input.slice(x);
48
+ break;
49
+ case '\r':
50
+ if ($.input != $.inputs[0]) {
51
+ $.inputs.unshift($.input);
52
+ }
53
+ $.index = -1;
54
+ $.input = '';
55
+ $.terminal.write('\r\n');
56
+ $.onLine($.currentInput);
57
+ $.terminal.write($.prompt);
58
+ break;
59
+ default:
60
+ $.terminal.write(data);
61
+ $.input = $.input.slice(0, x) + data + $.input.slice(x);
62
+ }
63
+ }
64
+ /**
65
+ * Creates a new shell using the provided options
66
+ */
67
+ export function createShell({ terminal, prompt = '', onLine = () => { } }) {
68
+ const context = {
69
+ terminal,
70
+ prompt,
71
+ onLine,
72
+ input: '',
73
+ index: -1,
74
+ currentInput: '',
75
+ inputs: [],
76
+ };
77
+ terminal.onData(data => handleData(context, data));
78
+ return context;
79
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "utilium",
3
- "version": "0.7.10",
4
- "description": "Typescript utilies",
3
+ "version": "0.8.0",
4
+ "description": "Typescript utilities",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "type": "module",
@@ -49,5 +49,8 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "eventemitter3": "^5.0.1"
52
+ },
53
+ "optionalDependencies": {
54
+ "@xterm/xterm": "^5.5.0"
52
55
  }
53
56
  }
package/readme.md CHANGED
@@ -10,3 +10,4 @@ A bunch of utilies for Typescript. This includes:
10
10
  - `List`, a class that combines the best aspects of `Set` and arrays
11
11
  - `JSONFileMap` and `FolderMap`
12
12
  - Version utilities
13
+ - Xterm.js shell handling (arrows, home/end, prompting, etc.)
package/src/shell.ts ADDED
@@ -0,0 +1,123 @@
1
+ /* A simple wrapper for xterm.js that makes implementing shells easier */
2
+ import type { Terminal } from '@xterm/xterm';
3
+
4
+ export interface ShellOptions {
5
+ /**
6
+ * The terminal associated with the context
7
+ */
8
+ terminal: Terminal;
9
+
10
+ /**
11
+ * The prompt to use, can be a getter.
12
+ */
13
+ readonly prompt?: string;
14
+
15
+ /**
16
+ * The handler for when a line is parsed
17
+ */
18
+ onLine?(this: void, line: string): unknown;
19
+ }
20
+
21
+ export interface ShellContext extends Required<ShellOptions> {
22
+ /**
23
+ * The input currently being shown
24
+ */
25
+ input: string;
26
+
27
+ /**
28
+ * The index for which input is being shown
29
+ */
30
+ index: number;
31
+
32
+ /**
33
+ * The current, uncached input
34
+ */
35
+ currentInput: string;
36
+
37
+ /**
38
+ * array of previous inputs
39
+ */
40
+ inputs: string[];
41
+ }
42
+
43
+ function handleData($: ShellContext, data: string) {
44
+ if ($.index == -1) {
45
+ $.currentInput = $.input;
46
+ }
47
+
48
+ function clear(): void {
49
+ $.terminal.write('\x1b[2K\r' + $.prompt);
50
+ }
51
+ const x = $.terminal.buffer.active.cursorX - $.prompt.length;
52
+ switch (data) {
53
+ case 'ArrowUp':
54
+ case '\x1b[A':
55
+ clear();
56
+ if ($.index < $.inputs.length - 1) {
57
+ $.input = $.inputs[++$.index];
58
+ }
59
+ $.terminal.write($.input);
60
+ break;
61
+ case 'ArrowDown':
62
+ case '\x1b[B':
63
+ clear();
64
+ if ($.index >= 0) {
65
+ $.input = $.index-- == 0 ? $.currentInput : $.inputs[$.index];
66
+ }
67
+ $.terminal.write($.input);
68
+ break;
69
+ case '\x1b[D':
70
+ if (x > 0) {
71
+ $.terminal.write(data);
72
+ }
73
+ break;
74
+ case '\x1b[C':
75
+ if (x < $.currentInput.length) {
76
+ $.terminal.write(data);
77
+ }
78
+ break;
79
+ case '\x1b[F':
80
+ $.terminal.write(`\x1b[${$.prompt.length + $.currentInput.length + 1}G`);
81
+ break;
82
+ case '\x1b[H':
83
+ $.terminal.write(`\x1b[${$.prompt.length + 1}G`);
84
+ break;
85
+ case '\x7f':
86
+ if (x <= 0) {
87
+ return;
88
+ }
89
+ $.terminal.write('\b\x1b[P');
90
+ $.input = $.input.slice(0, x - 1) + $.input.slice(x);
91
+ break;
92
+ case '\r':
93
+ if ($.input != $.inputs[0]) {
94
+ $.inputs.unshift($.input);
95
+ }
96
+ $.index = -1;
97
+ $.input = '';
98
+ $.terminal.write('\r\n');
99
+ $.onLine($.currentInput);
100
+ $.terminal.write($.prompt);
101
+ break;
102
+ default:
103
+ $.terminal.write(data);
104
+ $.input = $.input.slice(0, x) + data + $.input.slice(x);
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Creates a new shell using the provided options
110
+ */
111
+ export function createShell({ terminal, prompt = '', onLine = () => {} }: ShellOptions): ShellContext {
112
+ const context: ShellContext = {
113
+ terminal,
114
+ prompt,
115
+ onLine,
116
+ input: '',
117
+ index: -1,
118
+ currentInput: '',
119
+ inputs: [],
120
+ };
121
+ terminal.onData(data => handleData(context, data));
122
+ return context;
123
+ }