browser-terminal-cli 1.0.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 +21 -0
- package/README.md +1130 -0
- package/dist/CommandRegistry.d.ts +18 -0
- package/dist/HistoryManager.d.ts +14 -0
- package/dist/OutputManager.d.ts +20 -0
- package/dist/Terminal.d.ts +62 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.esm.js +1038 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +1048 -0
- package/dist/index.js.map +1 -0
- package/dist/index.umd.js +2 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/styles.d.ts +2 -0
- package/dist/themes.d.ts +3 -0
- package/dist/types.d.ts +81 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,1130 @@
|
|
|
1
|
+
# Browser Terminal CLI
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/browser-terminal-cli)
|
|
4
|
+
[](https://www.npmjs.com/package/browser-terminal-cli)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](#)
|
|
8
|
+
|
|
9
|
+
A powerful, customizable, and lightweight terminal/CLI interface for browser-side JavaScript applications. Create beautiful command-line interfaces in your web apps with ease.
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<img src="https://raw.githubusercontent.com/yourusername/browser-terminal-cli/main/demo.gif" alt="Browser Terminal CLI Demo" width="700">
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
## ✨ Features
|
|
16
|
+
|
|
17
|
+
- 🎨 **9 Built-in Themes** - Dracula, Monokai, Matrix, Ubuntu, Solarized, and more
|
|
18
|
+
- ⌨️ **Command History** - Navigate with arrow keys, persistent storage ready
|
|
19
|
+
- 📝 **Tab Completion** - Auto-complete command names
|
|
20
|
+
- 🔌 **Easy Command Registration** - Simple API for adding custom commands
|
|
21
|
+
- 🎯 **Full TypeScript Support** - Complete type definitions included
|
|
22
|
+
- 📦 **Zero Dependencies** - Lightweight (~15KB minified)
|
|
23
|
+
- ⚡ **Keyboard Shortcuts** - Ctrl+C, Ctrl+L, Ctrl+U support
|
|
24
|
+
- 📊 **Rich Output** - Tables, colors, styled text, HTML support
|
|
25
|
+
- 🎭 **Customizable** - Prompts, themes, fonts, cursor styles
|
|
26
|
+
- 🔄 **Async Commands** - Full Promise/async-await support
|
|
27
|
+
- 📱 **Responsive** - Works on desktop and mobile browsers
|
|
28
|
+
|
|
29
|
+
## 📦 Installation
|
|
30
|
+
|
|
31
|
+
### NPM
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install browser-terminal-cli
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Yarn
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
yarn add browser-terminal-cli
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### PNPM
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pnpm add browser-terminal-cli
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### CDN
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
<!-- UMD Build -->
|
|
53
|
+
<script src="https://unpkg.com/browser-terminal-cli/dist/index.umd.js"></script>
|
|
54
|
+
|
|
55
|
+
<!-- ESM Build -->
|
|
56
|
+
<script type="module">
|
|
57
|
+
import { Terminal } from 'https://unpkg.com/browser-terminal-cli/dist/index.esm.js';
|
|
58
|
+
</script>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 🚀 Quick Start
|
|
62
|
+
|
|
63
|
+
### ES Modules
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
import { Terminal } from 'browser-terminal-cli';
|
|
67
|
+
|
|
68
|
+
const terminal = new Terminal({
|
|
69
|
+
container: '#terminal',
|
|
70
|
+
prompt: '❯ ',
|
|
71
|
+
welcomeMessage: 'Welcome! Type "help" for available commands.',
|
|
72
|
+
theme: 'dracula',
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Add a simple command
|
|
76
|
+
terminal.addCommand('hello', () => {
|
|
77
|
+
return 'Hello, World!';
|
|
78
|
+
}, 'Say hello');
|
|
79
|
+
|
|
80
|
+
// Add a command with arguments
|
|
81
|
+
terminal.addCommand('greet', ({ args }) => {
|
|
82
|
+
const name = args[0] || 'stranger';
|
|
83
|
+
return `Hello, ${name}!`;
|
|
84
|
+
}, 'Greet someone by name');
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### HTML Setup
|
|
88
|
+
|
|
89
|
+
```html
|
|
90
|
+
<!DOCTYPE html>
|
|
91
|
+
<html>
|
|
92
|
+
<head>
|
|
93
|
+
<style>
|
|
94
|
+
#terminal {
|
|
95
|
+
width: 800px;
|
|
96
|
+
height: 400px;
|
|
97
|
+
border-radius: 8px;
|
|
98
|
+
overflow: hidden;
|
|
99
|
+
}
|
|
100
|
+
</style>
|
|
101
|
+
</head>
|
|
102
|
+
<body>
|
|
103
|
+
<div id="terminal"></div>
|
|
104
|
+
|
|
105
|
+
<script type="module">
|
|
106
|
+
import { Terminal } from 'browser-terminal-cli';
|
|
107
|
+
|
|
108
|
+
const terminal = new Terminal({
|
|
109
|
+
container: '#terminal',
|
|
110
|
+
theme: 'monokai',
|
|
111
|
+
});
|
|
112
|
+
</script>
|
|
113
|
+
</body>
|
|
114
|
+
</html>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### UMD (Script Tag)
|
|
118
|
+
|
|
119
|
+
```html
|
|
120
|
+
<script src="https://unpkg.com/browser-terminal-cli/dist/index.umd.js"></script>
|
|
121
|
+
<script>
|
|
122
|
+
const terminal = new BrowserTerminal.Terminal({
|
|
123
|
+
container: '#terminal',
|
|
124
|
+
});
|
|
125
|
+
</script>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## 📖 API Reference
|
|
129
|
+
|
|
130
|
+
### Constructor Options
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
const terminal = new Terminal(options: TerminalOptions);
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
| Option | Type | Default | Description |
|
|
137
|
+
|--------|------|---------|-------------|
|
|
138
|
+
| `container` | `HTMLElement \| string` | **required** | Container element or CSS selector |
|
|
139
|
+
| `prompt` | `string` | `'$ '` | Command prompt string |
|
|
140
|
+
| `welcomeMessage` | `string \| string[]` | `''` | Welcome message displayed on init |
|
|
141
|
+
| `theme` | `string \| TerminalTheme` | `'default'` | Theme name or custom theme object |
|
|
142
|
+
| `fontSize` | `number` | `14` | Font size in pixels |
|
|
143
|
+
| `fontFamily` | `string` | `'Cascadia Code', monospace` | Font family |
|
|
144
|
+
| `cursorStyle` | `'block' \| 'underline' \| 'bar'` | `'block'` | Cursor style |
|
|
145
|
+
| `cursorBlink` | `boolean` | `true` | Enable cursor blinking |
|
|
146
|
+
| `history` | `boolean` | `true` | Enable command history |
|
|
147
|
+
| `historySize` | `number` | `100` | Maximum history entries |
|
|
148
|
+
| `autoFocus` | `boolean` | `true` | Auto-focus terminal on init |
|
|
149
|
+
| `scrollback` | `number` | `1000` | Maximum output lines to keep |
|
|
150
|
+
| `tabSize` | `number` | `4` | Tab character width |
|
|
151
|
+
|
|
152
|
+
### Output Methods
|
|
153
|
+
|
|
154
|
+
#### `write(text, options?)`
|
|
155
|
+
|
|
156
|
+
Write text without a newline.
|
|
157
|
+
|
|
158
|
+
```javascript
|
|
159
|
+
terminal.write('Hello ');
|
|
160
|
+
terminal.write('World!');
|
|
161
|
+
// Output: Hello World!
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
#### `writeln(text, options?)`
|
|
165
|
+
|
|
166
|
+
Write text with a newline.
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
terminal.writeln('Line 1');
|
|
170
|
+
terminal.writeln('Line 2');
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
#### `writeError(text)`
|
|
174
|
+
|
|
175
|
+
Write error message (red color).
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
terminal.writeError('Something went wrong!');
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### `writeSuccess(text)`
|
|
182
|
+
|
|
183
|
+
Write success message (green color).
|
|
184
|
+
|
|
185
|
+
```javascript
|
|
186
|
+
terminal.writeSuccess('Operation completed!');
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### `writeWarning(text)`
|
|
190
|
+
|
|
191
|
+
Write warning message (yellow color).
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
terminal.writeWarning('This is deprecated');
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
#### `writeInfo(text)`
|
|
198
|
+
|
|
199
|
+
Write info message (blue color).
|
|
200
|
+
|
|
201
|
+
```javascript
|
|
202
|
+
terminal.writeInfo('Tip: Use help for more commands');
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
#### `writeTable(data, columns?)`
|
|
206
|
+
|
|
207
|
+
Write formatted table.
|
|
208
|
+
|
|
209
|
+
```javascript
|
|
210
|
+
terminal.writeTable([
|
|
211
|
+
{ name: 'John', age: 30, city: 'NYC' },
|
|
212
|
+
{ name: 'Jane', age: 25, city: 'LA' },
|
|
213
|
+
{ name: 'Bob', age: 35, city: 'Chicago' },
|
|
214
|
+
]);
|
|
215
|
+
|
|
216
|
+
// Output:
|
|
217
|
+
// name | age | city
|
|
218
|
+
// -----+-----+--------
|
|
219
|
+
// John | 30 | NYC
|
|
220
|
+
// Jane | 25 | LA
|
|
221
|
+
// Bob | 35 | Chicago
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
#### `clear()`
|
|
225
|
+
|
|
226
|
+
Clear all terminal output.
|
|
227
|
+
|
|
228
|
+
```javascript
|
|
229
|
+
terminal.clear();
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Output Options
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
interface OutputOptions {
|
|
236
|
+
color?: string; // Text color (CSS color)
|
|
237
|
+
backgroundColor?: string; // Background color
|
|
238
|
+
bold?: boolean; // Bold text
|
|
239
|
+
italic?: boolean; // Italic text
|
|
240
|
+
underline?: boolean; // Underlined text
|
|
241
|
+
className?: string; // Custom CSS class
|
|
242
|
+
html?: boolean; // Parse as HTML
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Examples:**
|
|
247
|
+
|
|
248
|
+
```javascript
|
|
249
|
+
// Colored text
|
|
250
|
+
terminal.writeln('Error!', { color: '#ff5555' });
|
|
251
|
+
terminal.writeln('Success!', { color: 'rgb(80, 250, 123)' });
|
|
252
|
+
|
|
253
|
+
// Styled text
|
|
254
|
+
terminal.writeln('Important', { bold: true });
|
|
255
|
+
terminal.writeln('Emphasis', { italic: true });
|
|
256
|
+
terminal.writeln('Link', { underline: true, color: '#8be9fd' });
|
|
257
|
+
|
|
258
|
+
// Combined styles
|
|
259
|
+
terminal.writeln('Critical Error', {
|
|
260
|
+
color: '#ff5555',
|
|
261
|
+
bold: true,
|
|
262
|
+
backgroundColor: '#1a1a1a'
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// HTML content
|
|
266
|
+
terminal.writeln('<strong>Bold</strong> and <em>italic</em>', { html: true });
|
|
267
|
+
terminal.writeln('<span style="color: red">Red text</span>', { html: true });
|
|
268
|
+
|
|
269
|
+
// Custom class
|
|
270
|
+
terminal.writeln('Custom styled', { className: 'my-custom-class' });
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
### Command Registration
|
|
276
|
+
|
|
277
|
+
#### `addCommand(name, handler, description?)`
|
|
278
|
+
|
|
279
|
+
Simple command registration.
|
|
280
|
+
|
|
281
|
+
```javascript
|
|
282
|
+
terminal.addCommand('time', () => {
|
|
283
|
+
return new Date().toLocaleTimeString();
|
|
284
|
+
}, 'Display current time');
|
|
285
|
+
|
|
286
|
+
terminal.addCommand('add', ({ args }) => {
|
|
287
|
+
const sum = args.reduce((a, b) => a + parseFloat(b), 0);
|
|
288
|
+
return `Sum: ${sum}`;
|
|
289
|
+
}, 'Add numbers together');
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
#### `registerCommand(definition)`
|
|
293
|
+
|
|
294
|
+
Advanced command registration.
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
interface CommandDefinition {
|
|
298
|
+
name: string; // Command name
|
|
299
|
+
handler: CommandHandler; // Handler function
|
|
300
|
+
description?: string; // Help description
|
|
301
|
+
usage?: string; // Usage example
|
|
302
|
+
aliases?: string[]; // Alternative names
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
```javascript
|
|
307
|
+
terminal.registerCommand({
|
|
308
|
+
name: 'fetch',
|
|
309
|
+
description: 'Fetch data from a URL',
|
|
310
|
+
usage: 'fetch <url> [--json]',
|
|
311
|
+
aliases: ['get', 'request'],
|
|
312
|
+
handler: async ({ args, flags, terminal }) => {
|
|
313
|
+
const url = args[0];
|
|
314
|
+
if (!url) {
|
|
315
|
+
terminal.writeError('Usage: fetch <url>');
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
try {
|
|
320
|
+
terminal.writeln(`Fetching ${url}...`);
|
|
321
|
+
const response = await fetch(url);
|
|
322
|
+
const data = flags.json
|
|
323
|
+
? await response.json()
|
|
324
|
+
: await response.text();
|
|
325
|
+
|
|
326
|
+
return typeof data === 'object'
|
|
327
|
+
? JSON.stringify(data, null, 2)
|
|
328
|
+
: data;
|
|
329
|
+
} catch (error) {
|
|
330
|
+
terminal.writeError(`Failed: ${error.message}`);
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
});
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
#### `registerCommands(definitions[])`
|
|
337
|
+
|
|
338
|
+
Register multiple commands at once.
|
|
339
|
+
|
|
340
|
+
```javascript
|
|
341
|
+
terminal.registerCommands([
|
|
342
|
+
{
|
|
343
|
+
name: 'start',
|
|
344
|
+
handler: () => 'Starting...',
|
|
345
|
+
description: 'Start the application',
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
name: 'stop',
|
|
349
|
+
handler: () => 'Stopping...',
|
|
350
|
+
description: 'Stop the application',
|
|
351
|
+
},
|
|
352
|
+
]);
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
#### `removeCommand(name)`
|
|
356
|
+
|
|
357
|
+
Remove a registered command.
|
|
358
|
+
|
|
359
|
+
```javascript
|
|
360
|
+
terminal.removeCommand('hello');
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
#### `hasCommand(name)`
|
|
364
|
+
|
|
365
|
+
Check if command exists.
|
|
366
|
+
|
|
367
|
+
```javascript
|
|
368
|
+
if (terminal.hasCommand('deploy')) {
|
|
369
|
+
terminal.exec('deploy');
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
#### `getCommands()`
|
|
374
|
+
|
|
375
|
+
Get all registered commands.
|
|
376
|
+
|
|
377
|
+
```javascript
|
|
378
|
+
const commands = terminal.getCommands();
|
|
379
|
+
commands.forEach(cmd => {
|
|
380
|
+
console.log(cmd.name, cmd.description);
|
|
381
|
+
});
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Command Handler Context
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
interface CommandContext {
|
|
388
|
+
terminal: TerminalInterface; // Terminal instance
|
|
389
|
+
args: string[]; // Positional arguments
|
|
390
|
+
flags: Record<string, string | boolean>; // Parsed flags
|
|
391
|
+
rawInput: string; // Original input string
|
|
392
|
+
}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
**Example:**
|
|
396
|
+
|
|
397
|
+
```javascript
|
|
398
|
+
terminal.addCommand('example', (context) => {
|
|
399
|
+
const { terminal, args, flags, rawInput } = context;
|
|
400
|
+
|
|
401
|
+
console.log('Raw input:', rawInput);
|
|
402
|
+
console.log('Arguments:', args);
|
|
403
|
+
console.log('Flags:', flags);
|
|
404
|
+
|
|
405
|
+
// Use terminal methods
|
|
406
|
+
terminal.writeln('Processing...');
|
|
407
|
+
|
|
408
|
+
if (flags.verbose) {
|
|
409
|
+
terminal.writeln('Verbose mode enabled');
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
return `Processed ${args.length} arguments`;
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
// Usage: example arg1 arg2 --verbose --output=file.txt
|
|
416
|
+
// args: ['arg1', 'arg2']
|
|
417
|
+
// flags: { verbose: true, output: 'file.txt' }
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
### Control Methods
|
|
423
|
+
|
|
424
|
+
#### `focus()`
|
|
425
|
+
|
|
426
|
+
Focus the terminal input.
|
|
427
|
+
|
|
428
|
+
```javascript
|
|
429
|
+
terminal.focus();
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
#### `blur()`
|
|
433
|
+
|
|
434
|
+
Remove focus from terminal.
|
|
435
|
+
|
|
436
|
+
```javascript
|
|
437
|
+
terminal.blur();
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
#### `disable()`
|
|
441
|
+
|
|
442
|
+
Disable terminal input.
|
|
443
|
+
|
|
444
|
+
```javascript
|
|
445
|
+
terminal.disable();
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
#### `enable()`
|
|
449
|
+
|
|
450
|
+
Enable terminal input.
|
|
451
|
+
|
|
452
|
+
```javascript
|
|
453
|
+
terminal.enable();
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
#### `setPrompt(prompt)`
|
|
457
|
+
|
|
458
|
+
Change the command prompt.
|
|
459
|
+
|
|
460
|
+
```javascript
|
|
461
|
+
terminal.setPrompt('>>> ');
|
|
462
|
+
terminal.setPrompt('user@host:~$ ');
|
|
463
|
+
terminal.setPrompt('🚀 ');
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
#### `getPrompt()`
|
|
467
|
+
|
|
468
|
+
Get current prompt string.
|
|
469
|
+
|
|
470
|
+
```javascript
|
|
471
|
+
const prompt = terminal.getPrompt(); // '$ '
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
#### `setValue(value)`
|
|
475
|
+
|
|
476
|
+
Set the input field value.
|
|
477
|
+
|
|
478
|
+
```javascript
|
|
479
|
+
terminal.setValue('echo hello');
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
#### `getValue()`
|
|
483
|
+
|
|
484
|
+
Get current input value.
|
|
485
|
+
|
|
486
|
+
```javascript
|
|
487
|
+
const input = terminal.getValue();
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
#### `exec(command)`
|
|
491
|
+
|
|
492
|
+
Execute a command programmatically.
|
|
493
|
+
|
|
494
|
+
```javascript
|
|
495
|
+
await terminal.exec('help');
|
|
496
|
+
await terminal.exec('clear');
|
|
497
|
+
await terminal.exec('echo Hello World');
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
#### `destroy()`
|
|
501
|
+
|
|
502
|
+
Clean up and remove terminal.
|
|
503
|
+
|
|
504
|
+
```javascript
|
|
505
|
+
terminal.destroy();
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
### Theme Methods
|
|
511
|
+
|
|
512
|
+
#### `setTheme(theme)`
|
|
513
|
+
|
|
514
|
+
Change terminal theme.
|
|
515
|
+
|
|
516
|
+
```javascript
|
|
517
|
+
// Use built-in theme
|
|
518
|
+
terminal.setTheme('dracula');
|
|
519
|
+
terminal.setTheme('matrix');
|
|
520
|
+
|
|
521
|
+
// Use custom theme
|
|
522
|
+
terminal.setTheme({
|
|
523
|
+
background: '#1a1a2e',
|
|
524
|
+
foreground: '#eaeaea',
|
|
525
|
+
cursor: '#00ff88',
|
|
526
|
+
selection: 'rgba(0, 255, 136, 0.3)',
|
|
527
|
+
black: '#000000',
|
|
528
|
+
red: '#ff5555',
|
|
529
|
+
green: '#00ff88',
|
|
530
|
+
yellow: '#ffff55',
|
|
531
|
+
blue: '#5555ff',
|
|
532
|
+
magenta: '#ff55ff',
|
|
533
|
+
cyan: '#55ffff',
|
|
534
|
+
white: '#ffffff',
|
|
535
|
+
});
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
#### `getTheme()`
|
|
539
|
+
|
|
540
|
+
Get current theme object.
|
|
541
|
+
|
|
542
|
+
```javascript
|
|
543
|
+
const theme = terminal.getTheme();
|
|
544
|
+
console.log(theme.background); // '#282a36'
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### Available Themes
|
|
548
|
+
|
|
549
|
+
| Theme | Description |
|
|
550
|
+
|-------|-------------|
|
|
551
|
+
| `default` | Default dark theme |
|
|
552
|
+
| `dark` | GitHub dark inspired |
|
|
553
|
+
| `light` | Light theme |
|
|
554
|
+
| `matrix` | Matrix green on black |
|
|
555
|
+
| `ubuntu` | Ubuntu terminal colors |
|
|
556
|
+
| `monokai` | Monokai color scheme |
|
|
557
|
+
| `dracula` | Dracula theme |
|
|
558
|
+
| `solarized-dark` | Solarized dark |
|
|
559
|
+
| `solarized-light` | Solarized light |
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
### History Methods
|
|
564
|
+
|
|
565
|
+
#### `getHistory()`
|
|
566
|
+
|
|
567
|
+
Get command history array.
|
|
568
|
+
|
|
569
|
+
```javascript
|
|
570
|
+
const history = terminal.getHistory();
|
|
571
|
+
// ['ls', 'cd documents', 'cat file.txt']
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
#### `clearHistory()`
|
|
575
|
+
|
|
576
|
+
Clear command history.
|
|
577
|
+
|
|
578
|
+
```javascript
|
|
579
|
+
terminal.clearHistory();
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
#### `setHistory(history)`
|
|
583
|
+
|
|
584
|
+
Set command history (for persistence).
|
|
585
|
+
|
|
586
|
+
```javascript
|
|
587
|
+
// Restore from localStorage
|
|
588
|
+
const saved = localStorage.getItem('terminal-history');
|
|
589
|
+
if (saved) {
|
|
590
|
+
terminal.setHistory(JSON.parse(saved));
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// Save on command
|
|
594
|
+
terminal.on('command', () => {
|
|
595
|
+
localStorage.setItem('terminal-history',
|
|
596
|
+
JSON.stringify(terminal.getHistory())
|
|
597
|
+
);
|
|
598
|
+
});
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
---
|
|
602
|
+
|
|
603
|
+
### Events
|
|
604
|
+
|
|
605
|
+
#### `on(event, callback)`
|
|
606
|
+
|
|
607
|
+
Subscribe to terminal events.
|
|
608
|
+
|
|
609
|
+
```javascript
|
|
610
|
+
terminal.on('command', (command, args) => {
|
|
611
|
+
console.log('Executed:', command, args);
|
|
612
|
+
analytics.track('command', { command, args });
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
terminal.on('input', (value) => {
|
|
616
|
+
console.log('Input changed:', value);
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
terminal.on('clear', () => {
|
|
620
|
+
console.log('Terminal cleared');
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
terminal.on('ready', () => {
|
|
624
|
+
console.log('Terminal initialized');
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
terminal.on('key', (event) => {
|
|
628
|
+
if (event.key === 'Escape') {
|
|
629
|
+
terminal.blur();
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
#### `off(event, callback)`
|
|
635
|
+
|
|
636
|
+
Unsubscribe from events.
|
|
637
|
+
|
|
638
|
+
```javascript
|
|
639
|
+
const handler = (cmd) => console.log(cmd);
|
|
640
|
+
terminal.on('command', handler);
|
|
641
|
+
terminal.off('command', handler);
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
### Event Types
|
|
645
|
+
|
|
646
|
+
| Event | Callback Signature | Description |
|
|
647
|
+
|-------|-------------------|-------------|
|
|
648
|
+
| `command` | `(command: string, args: string[]) => void` | Command executed |
|
|
649
|
+
| `input` | `(value: string) => void` | Input value changed |
|
|
650
|
+
| `clear` | `() => void` | Terminal cleared |
|
|
651
|
+
| `ready` | `() => void` | Terminal initialized |
|
|
652
|
+
| `key` | `(event: KeyboardEvent) => void` | Key pressed |
|
|
653
|
+
|
|
654
|
+
---
|
|
655
|
+
|
|
656
|
+
### Built-in Commands
|
|
657
|
+
|
|
658
|
+
| Command | Description |
|
|
659
|
+
|---------|-------------|
|
|
660
|
+
| `help` | Show all available commands |
|
|
661
|
+
| `help <command>` | Show help for specific command |
|
|
662
|
+
| `clear` | Clear terminal screen |
|
|
663
|
+
| `history` | Show command history |
|
|
664
|
+
| `echo <text>` | Print text to terminal |
|
|
665
|
+
|
|
666
|
+
---
|
|
667
|
+
|
|
668
|
+
### Keyboard Shortcuts
|
|
669
|
+
|
|
670
|
+
| Shortcut | Action |
|
|
671
|
+
|----------|--------|
|
|
672
|
+
| `↑` Arrow Up | Previous command in history |
|
|
673
|
+
| `↓` Arrow Down | Next command in history |
|
|
674
|
+
| `Tab` | Auto-complete command name |
|
|
675
|
+
| `Ctrl + C` | Cancel current input |
|
|
676
|
+
| `Ctrl + L` | Clear terminal |
|
|
677
|
+
| `Ctrl + U` | Clear current line |
|
|
678
|
+
| `Enter` | Execute command |
|
|
679
|
+
|
|
680
|
+
---
|
|
681
|
+
|
|
682
|
+
## 🎨 Theming
|
|
683
|
+
|
|
684
|
+
### Custom Theme Object
|
|
685
|
+
|
|
686
|
+
```typescript
|
|
687
|
+
interface TerminalTheme {
|
|
688
|
+
background: string; // Background color
|
|
689
|
+
foreground: string; // Default text color
|
|
690
|
+
cursor: string; // Cursor color
|
|
691
|
+
cursorAccent?: string; // Cursor text color
|
|
692
|
+
selection?: string; // Selection background
|
|
693
|
+
|
|
694
|
+
// ANSI Colors
|
|
695
|
+
black?: string;
|
|
696
|
+
red?: string;
|
|
697
|
+
green?: string;
|
|
698
|
+
yellow?: string;
|
|
699
|
+
blue?: string;
|
|
700
|
+
magenta?: string;
|
|
701
|
+
cyan?: string;
|
|
702
|
+
white?: string;
|
|
703
|
+
|
|
704
|
+
// Bright ANSI Colors
|
|
705
|
+
brightBlack?: string;
|
|
706
|
+
brightRed?: string;
|
|
707
|
+
brightGreen?: string;
|
|
708
|
+
brightYellow?: string;
|
|
709
|
+
brightBlue?: string;
|
|
710
|
+
brightMagenta?: string;
|
|
711
|
+
brightCyan?: string;
|
|
712
|
+
brightWhite?: string;
|
|
713
|
+
}
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
### Theme Examples
|
|
717
|
+
|
|
718
|
+
```javascript
|
|
719
|
+
// Cyberpunk theme
|
|
720
|
+
terminal.setTheme({
|
|
721
|
+
background: '#0a0a0f',
|
|
722
|
+
foreground: '#0ff',
|
|
723
|
+
cursor: '#f0f',
|
|
724
|
+
green: '#0f0',
|
|
725
|
+
red: '#f00',
|
|
726
|
+
yellow: '#ff0',
|
|
727
|
+
blue: '#00f',
|
|
728
|
+
magenta: '#f0f',
|
|
729
|
+
cyan: '#0ff',
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
// Nord theme
|
|
733
|
+
terminal.setTheme({
|
|
734
|
+
background: '#2e3440',
|
|
735
|
+
foreground: '#d8dee9',
|
|
736
|
+
cursor: '#d8dee9',
|
|
737
|
+
black: '#3b4252',
|
|
738
|
+
red: '#bf616a',
|
|
739
|
+
green: '#a3be8c',
|
|
740
|
+
yellow: '#ebcb8b',
|
|
741
|
+
blue: '#81a1c1',
|
|
742
|
+
magenta: '#b48ead',
|
|
743
|
+
cyan: '#88c0d0',
|
|
744
|
+
white: '#e5e9f0',
|
|
745
|
+
});
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
---
|
|
749
|
+
|
|
750
|
+
## 💡 Examples
|
|
751
|
+
|
|
752
|
+
### File System Simulation
|
|
753
|
+
|
|
754
|
+
```javascript
|
|
755
|
+
const fs = {
|
|
756
|
+
'/': { type: 'dir', children: ['home', 'usr', 'var'] },
|
|
757
|
+
'/home': { type: 'dir', children: ['user'] },
|
|
758
|
+
'/home/user': { type: 'dir', children: ['documents', 'readme.txt'] },
|
|
759
|
+
'/home/user/readme.txt': { type: 'file', content: 'Hello World!' },
|
|
760
|
+
};
|
|
761
|
+
|
|
762
|
+
let cwd = '/home/user';
|
|
763
|
+
|
|
764
|
+
terminal.addCommand('pwd', () => cwd);
|
|
765
|
+
|
|
766
|
+
terminal.addCommand('ls', ({ args }) => {
|
|
767
|
+
const path = args[0] ? resolvePath(args[0]) : cwd;
|
|
768
|
+
const node = fs[path];
|
|
769
|
+
if (!node) return `ls: ${path}: No such file or directory`;
|
|
770
|
+
if (node.type === 'file') return path.split('/').pop();
|
|
771
|
+
return node.children.join(' ');
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
terminal.addCommand('cd', ({ args }) => {
|
|
775
|
+
const path = args[0] ? resolvePath(args[0]) : '/home/user';
|
|
776
|
+
if (!fs[path] || fs[path].type !== 'dir') {
|
|
777
|
+
return `cd: ${args[0]}: Not a directory`;
|
|
778
|
+
}
|
|
779
|
+
cwd = path;
|
|
780
|
+
terminal.setPrompt(`${cwd} $ `);
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
terminal.addCommand('cat', ({ args }) => {
|
|
784
|
+
const path = resolvePath(args[0]);
|
|
785
|
+
const node = fs[path];
|
|
786
|
+
if (!node) return `cat: ${args[0]}: No such file`;
|
|
787
|
+
if (node.type !== 'file') return `cat: ${args[0]}: Is a directory`;
|
|
788
|
+
return node.content;
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
function resolvePath(path) {
|
|
792
|
+
if (path.startsWith('/')) return path;
|
|
793
|
+
if (path === '..') return cwd.split('/').slice(0, -1).join('/') || '/';
|
|
794
|
+
return `${cwd}/${path}`.replace(/\/+/g, '/');
|
|
795
|
+
}
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
### Interactive Game
|
|
799
|
+
|
|
800
|
+
```javascript
|
|
801
|
+
let gameState = {
|
|
802
|
+
score: 0,
|
|
803
|
+
level: 1,
|
|
804
|
+
target: randomTarget(),
|
|
805
|
+
};
|
|
806
|
+
|
|
807
|
+
function randomTarget() {
|
|
808
|
+
return Math.floor(Math.random() * 100) + 1;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
terminal.registerCommand({
|
|
812
|
+
name: 'play',
|
|
813
|
+
description: 'Start the number guessing game',
|
|
814
|
+
handler: ({ terminal }) => {
|
|
815
|
+
gameState = { score: 0, level: 1, target: randomTarget() };
|
|
816
|
+
terminal.writeln('🎮 Number Guessing Game Started!');
|
|
817
|
+
terminal.writeln('Guess a number between 1-100');
|
|
818
|
+
terminal.writeln('Use: guess <number>');
|
|
819
|
+
},
|
|
820
|
+
});
|
|
821
|
+
|
|
822
|
+
terminal.registerCommand({
|
|
823
|
+
name: 'guess',
|
|
824
|
+
description: 'Guess the number',
|
|
825
|
+
usage: 'guess <number>',
|
|
826
|
+
handler: ({ args, terminal }) => {
|
|
827
|
+
const num = parseInt(args[0]);
|
|
828
|
+
|
|
829
|
+
if (isNaN(num)) {
|
|
830
|
+
return 'Please enter a valid number';
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
if (num === gameState.target) {
|
|
834
|
+
gameState.score += gameState.level * 10;
|
|
835
|
+
gameState.level++;
|
|
836
|
+
gameState.target = randomTarget();
|
|
837
|
+
|
|
838
|
+
terminal.writeSuccess(`🎉 Correct! Score: ${gameState.score}`);
|
|
839
|
+
terminal.writeln(`Level ${gameState.level} - New number generated`);
|
|
840
|
+
} else if (num < gameState.target) {
|
|
841
|
+
terminal.writeWarning('📈 Go higher!');
|
|
842
|
+
} else {
|
|
843
|
+
terminal.writeWarning('📉 Go lower!');
|
|
844
|
+
}
|
|
845
|
+
},
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
terminal.addCommand('score', () => {
|
|
849
|
+
return `Score: ${gameState.score} | Level: ${gameState.level}`;
|
|
850
|
+
});
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
### API Client
|
|
854
|
+
|
|
855
|
+
```javascript
|
|
856
|
+
const API_BASE = 'https://jsonplaceholder.typicode.com';
|
|
857
|
+
|
|
858
|
+
terminal.registerCommand({
|
|
859
|
+
name: 'api',
|
|
860
|
+
description: 'Make API requests',
|
|
861
|
+
usage: 'api <endpoint> [--method=GET] [--body={}]',
|
|
862
|
+
handler: async ({ args, flags, terminal }) => {
|
|
863
|
+
const endpoint = args[0];
|
|
864
|
+
if (!endpoint) {
|
|
865
|
+
terminal.writeError('Usage: api <endpoint>');
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
const method = flags.method || 'GET';
|
|
870
|
+
const url = `${API_BASE}${endpoint}`;
|
|
871
|
+
|
|
872
|
+
terminal.writeln(`${method} ${url}`, { color: '#8be9fd' });
|
|
873
|
+
|
|
874
|
+
try {
|
|
875
|
+
const options = { method };
|
|
876
|
+
if (flags.body) {
|
|
877
|
+
options.body = flags.body;
|
|
878
|
+
options.headers = { 'Content-Type': 'application/json' };
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
const response = await fetch(url, options);
|
|
882
|
+
const data = await response.json();
|
|
883
|
+
|
|
884
|
+
terminal.writeSuccess(`Status: ${response.status}`);
|
|
885
|
+
terminal.writeln(JSON.stringify(data, null, 2));
|
|
886
|
+
} catch (error) {
|
|
887
|
+
terminal.writeError(`Error: ${error.message}`);
|
|
888
|
+
}
|
|
889
|
+
},
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
// Usage:
|
|
893
|
+
// api /posts/1
|
|
894
|
+
// api /posts --method=POST --body={"title":"Hello"}
|
|
895
|
+
```
|
|
896
|
+
|
|
897
|
+
### Task Manager
|
|
898
|
+
|
|
899
|
+
```javascript
|
|
900
|
+
const tasks = [];
|
|
901
|
+
let taskId = 1;
|
|
902
|
+
|
|
903
|
+
terminal.addCommand('add', ({ args }) => {
|
|
904
|
+
const text = args.join(' ');
|
|
905
|
+
if (!text) return 'Usage: add <task description>';
|
|
906
|
+
|
|
907
|
+
tasks.push({ id: taskId++, text, done: false });
|
|
908
|
+
return `✅ Added task #${taskId - 1}`;
|
|
909
|
+
});
|
|
910
|
+
|
|
911
|
+
terminal.addCommand('list', ({ terminal }) => {
|
|
912
|
+
if (tasks.length === 0) {
|
|
913
|
+
return '📭 No tasks';
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
tasks.forEach(task => {
|
|
917
|
+
const status = task.done ? '✅' : '⬜';
|
|
918
|
+
const style = task.done ? { color: '#6b7280' } : {};
|
|
919
|
+
terminal.writeln(`${status} #${task.id}: ${task.text}`, style);
|
|
920
|
+
});
|
|
921
|
+
});
|
|
922
|
+
|
|
923
|
+
terminal.addCommand('done', ({ args }) => {
|
|
924
|
+
const id = parseInt(args[0]);
|
|
925
|
+
const task = tasks.find(t => t.id === id);
|
|
926
|
+
|
|
927
|
+
if (!task) return `Task #${id} not found`;
|
|
928
|
+
|
|
929
|
+
task.done = true;
|
|
930
|
+
return `✅ Completed: ${task.text}`;
|
|
931
|
+
});
|
|
932
|
+
|
|
933
|
+
terminal.addCommand('remove', ({ args }) => {
|
|
934
|
+
const id = parseInt(args[0]);
|
|
935
|
+
const index = tasks.findIndex(t => t.id === id);
|
|
936
|
+
|
|
937
|
+
if (index === -1) return `Task #${id} not found`;
|
|
938
|
+
|
|
939
|
+
const [task] = tasks.splice(index, 1);
|
|
940
|
+
return `🗑️ Removed: ${task.text}`;
|
|
941
|
+
});
|
|
942
|
+
```
|
|
943
|
+
|
|
944
|
+
### Progress Animation
|
|
945
|
+
|
|
946
|
+
```javascript
|
|
947
|
+
terminal.registerCommand({
|
|
948
|
+
name: 'download',
|
|
949
|
+
description: 'Simulate file download with progress',
|
|
950
|
+
handler: async ({ args, terminal }) => {
|
|
951
|
+
const filename = args[0] || 'file.zip';
|
|
952
|
+
const size = parseInt(args[1]) || 100;
|
|
953
|
+
|
|
954
|
+
terminal.writeln(`Downloading ${filename}...`);
|
|
955
|
+
|
|
956
|
+
for (let i = 0; i <= 100; i += 5) {
|
|
957
|
+
const filled = Math.floor(i / 5);
|
|
958
|
+
const empty = 20 - filled;
|
|
959
|
+
const bar = '█'.repeat(filled) + '░'.repeat(empty);
|
|
960
|
+
const mb = ((i / 100) * size).toFixed(1);
|
|
961
|
+
|
|
962
|
+
// Create/update progress line
|
|
963
|
+
process.stdout.write(`\r[${bar}] ${i}% (${mb}/${size} MB)`);
|
|
964
|
+
|
|
965
|
+
await new Promise(r => setTimeout(r, 100));
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
terminal.writeln('');
|
|
969
|
+
terminal.writeSuccess(`✅ Downloaded ${filename}`);
|
|
970
|
+
},
|
|
971
|
+
});
|
|
972
|
+
```
|
|
973
|
+
|
|
974
|
+
---
|
|
975
|
+
|
|
976
|
+
## 🌐 Browser Support
|
|
977
|
+
|
|
978
|
+
| Browser | Version |
|
|
979
|
+
|---------|---------|
|
|
980
|
+
| Chrome | 60+ |
|
|
981
|
+
| Firefox | 55+ |
|
|
982
|
+
| Safari | 12+ |
|
|
983
|
+
| Edge | 79+ |
|
|
984
|
+
| Opera | 47+ |
|
|
985
|
+
|
|
986
|
+
---
|
|
987
|
+
|
|
988
|
+
## 📄 TypeScript
|
|
989
|
+
|
|
990
|
+
Full TypeScript support with exported types:
|
|
991
|
+
|
|
992
|
+
```typescript
|
|
993
|
+
import {
|
|
994
|
+
Terminal,
|
|
995
|
+
TerminalOptions,
|
|
996
|
+
TerminalTheme,
|
|
997
|
+
CommandDefinition,
|
|
998
|
+
CommandHandler,
|
|
999
|
+
CommandContext,
|
|
1000
|
+
OutputOptions,
|
|
1001
|
+
ThemeName,
|
|
1002
|
+
} from 'browser-terminal-cli';
|
|
1003
|
+
|
|
1004
|
+
const options: TerminalOptions = {
|
|
1005
|
+
container: '#terminal',
|
|
1006
|
+
theme: 'dracula',
|
|
1007
|
+
};
|
|
1008
|
+
|
|
1009
|
+
const terminal = new Terminal(options);
|
|
1010
|
+
|
|
1011
|
+
const myCommand: CommandDefinition = {
|
|
1012
|
+
name: 'test',
|
|
1013
|
+
description: 'A test command',
|
|
1014
|
+
handler: (ctx: CommandContext): string => {
|
|
1015
|
+
return `Args: ${ctx.args.join(', ')}`;
|
|
1016
|
+
},
|
|
1017
|
+
};
|
|
1018
|
+
|
|
1019
|
+
terminal.registerCommand(myCommand);
|
|
1020
|
+
```
|
|
1021
|
+
|
|
1022
|
+
---
|
|
1023
|
+
|
|
1024
|
+
## 🔧 Advanced Usage
|
|
1025
|
+
|
|
1026
|
+
### Persisting History
|
|
1027
|
+
|
|
1028
|
+
```javascript
|
|
1029
|
+
const HISTORY_KEY = 'terminal-history';
|
|
1030
|
+
|
|
1031
|
+
// Load history on init
|
|
1032
|
+
const terminal = new Terminal({
|
|
1033
|
+
container: '#terminal',
|
|
1034
|
+
});
|
|
1035
|
+
|
|
1036
|
+
const savedHistory = localStorage.getItem(HISTORY_KEY);
|
|
1037
|
+
if (savedHistory) {
|
|
1038
|
+
terminal.setHistory(JSON.parse(savedHistory));
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
// Save history on each command
|
|
1042
|
+
terminal.on('command', () => {
|
|
1043
|
+
localStorage.setItem(HISTORY_KEY, JSON.stringify(terminal.getHistory()));
|
|
1044
|
+
});
|
|
1045
|
+
```
|
|
1046
|
+
|
|
1047
|
+
### Custom Autocomplete
|
|
1048
|
+
|
|
1049
|
+
```javascript
|
|
1050
|
+
terminal.on('key', (e) => {
|
|
1051
|
+
if (e.key === 'Tab') {
|
|
1052
|
+
e.preventDefault();
|
|
1053
|
+
|
|
1054
|
+
const input = terminal.getValue();
|
|
1055
|
+
const suggestions = getAutocompleteSuggestions(input);
|
|
1056
|
+
|
|
1057
|
+
if (suggestions.length === 1) {
|
|
1058
|
+
terminal.setValue(suggestions[0] + ' ');
|
|
1059
|
+
} else if (suggestions.length > 1) {
|
|
1060
|
+
terminal.writeln('');
|
|
1061
|
+
terminal.writeln(suggestions.join(' '));
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1065
|
+
|
|
1066
|
+
function getAutocompleteSuggestions(input) {
|
|
1067
|
+
const files = ['readme.md', 'package.json', 'index.js'];
|
|
1068
|
+
return files.filter(f => f.startsWith(input.split(' ').pop()));
|
|
1069
|
+
}
|
|
1070
|
+
```
|
|
1071
|
+
|
|
1072
|
+
### Multiple Terminals
|
|
1073
|
+
|
|
1074
|
+
```javascript
|
|
1075
|
+
const term1 = new Terminal({
|
|
1076
|
+
container: '#terminal-1',
|
|
1077
|
+
prompt: 'server1$ ',
|
|
1078
|
+
theme: 'dracula',
|
|
1079
|
+
});
|
|
1080
|
+
|
|
1081
|
+
const term2 = new Terminal({
|
|
1082
|
+
container: '#terminal-2',
|
|
1083
|
+
prompt: 'server2$ ',
|
|
1084
|
+
theme: 'monokai',
|
|
1085
|
+
});
|
|
1086
|
+
|
|
1087
|
+
// Sync commands between terminals
|
|
1088
|
+
term1.on('command', (cmd) => {
|
|
1089
|
+
term2.writeln(`[server1]: ${cmd}`, { color: '#888' });
|
|
1090
|
+
});
|
|
1091
|
+
```
|
|
1092
|
+
|
|
1093
|
+
---
|
|
1094
|
+
|
|
1095
|
+
## 📝 License
|
|
1096
|
+
|
|
1097
|
+
MIT © [Adhi](https://github.com/liladhiee-web)
|
|
1098
|
+
|
|
1099
|
+
---
|
|
1100
|
+
|
|
1101
|
+
## 🤝 Contributing
|
|
1102
|
+
|
|
1103
|
+
Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
1104
|
+
|
|
1105
|
+
1. Fork the repository
|
|
1106
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
1107
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
1108
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
1109
|
+
5. Open a Pull Request
|
|
1110
|
+
|
|
1111
|
+
---
|
|
1112
|
+
|
|
1113
|
+
## 🙏 Acknowledgments
|
|
1114
|
+
|
|
1115
|
+
- Inspired by [Xterm.js](https://xtermjs.org/)
|
|
1116
|
+
- Themes inspired by popular color schemes
|
|
1117
|
+
- Built with TypeScript and Rollup
|
|
1118
|
+
|
|
1119
|
+
---
|
|
1120
|
+
|
|
1121
|
+
## 📬 Support
|
|
1122
|
+
|
|
1123
|
+
- 📫 [Open an issue](https://github.com/liladhiee-web/browser-terminal-cli/issues)
|
|
1124
|
+
- 💬 [Discussions](https://github.com/liladhiee-web/browser-terminal-cli/discussions)
|
|
1125
|
+
|
|
1126
|
+
---
|
|
1127
|
+
|
|
1128
|
+
<p align="center">
|
|
1129
|
+
Made with ❤️ for the web developer community
|
|
1130
|
+
</p>
|