|
| 1 | +# Terminal |
| 2 | + |
| 3 | +The `terminal` module exposes Acode’s xterm.js-based terminal. Require it with `acode.require('terminal')` to create terminals, manage sessions, and add themes. |
| 4 | + |
| 5 | +## Import |
| 6 | + |
| 7 | +```js |
| 8 | +const terminal = acode.require('terminal'); |
| 9 | +``` |
| 10 | + |
| 11 | +## API Overview |
| 12 | + |
| 13 | +The module exposes these methods: |
| 14 | + |
| 15 | +- `create(options)`: Creates a new terminal tab. Returns an instance object. |
| 16 | +- `createLocal(options)`: Creates a local-only terminal (no backend). |
| 17 | +- `createServer(options)`: Creates a server-connected terminal when available(By default it will connect to Alpine). |
| 18 | +- `get(id)`: Returns a terminal instance by id or null. |
| 19 | +- `getAll()`: Returns a Map-like collection of all terminals. |
| 20 | +- `write(id, data)`: Writes text to a terminal (ANSI supported). This only write input into the terminal, **it does not automatically submit/execute shell commands**. To execute a command, include a line ending (carriage return/newline) such as `\r` or `\r\n`. |
| 21 | +- `clear(id)`: Clears a terminal screen. |
| 22 | +- `close(id)`: Closes and disposes a terminal. |
| 23 | +- `themes.register(name, theme, pluginId)`: Adds a custom theme. |
| 24 | +- `themes.unregister(name, pluginId)`: Removes a theme registered by your plugin. |
| 25 | +- `themes.get(name)`: Returns a theme by name. |
| 26 | +- `themes.getAll()`: Returns an object map of all themes. |
| 27 | +- `themes.getNames()`: Returns an array of available theme names. |
| 28 | +- `themes.createVariant(baseName, overrides)`: Clones a theme with overrides. |
| 29 | + |
| 30 | +## Create |
| 31 | + |
| 32 | +```js |
| 33 | +// Generic create (chooses mode from options) |
| 34 | +const term = await terminal.create({ |
| 35 | + name: 'My Terminal', |
| 36 | + theme: 'dark', // Any installed theme |
| 37 | +}); |
| 38 | + |
| 39 | +// Local terminal (no backend), It is like a empty terminal instance where you can write stuff , it doesn't opens any shell |
| 40 | +const local = await terminal.createLocal({ name: 'Plugin Output' }); |
| 41 | + |
| 42 | +// Server terminal (connects to backend if available) |
| 43 | +const server = await terminal.createServer({ name: 'Server Shell' }); |
| 44 | + |
| 45 | +// Or via command |
| 46 | +acode.exec('new-terminal'); |
| 47 | +``` |
| 48 | + |
| 49 | +### TerminalOptions |
| 50 | + |
| 51 | +Common options accepted by create functions: |
| 52 | + |
| 53 | +- `name`: Display name for the terminal tab. |
| 54 | +- `serverMode`: Boolean to force server connection (default true) or local mode (false). |
| 55 | +- `port`: Useful in server mode to connect to specific `axs` port. Backend HTTP/WS port (default 8767). |
| 56 | +- `theme`: Theme name to apply (see Themes). |
| 57 | +- `rows, cols`: Preferred initial size hints. |
| 58 | +- `renderer`: Preferred xterm.js renderer. Accepts `'auto'` (default; prefers `webgl`), `'webgl'`, or `'canvas'`. Use `webgl` for best performance; `canvas` is a fallback and may be slower. |
| 59 | +- `fontSize`: Initial font size. |
| 60 | +- And other xtermjs terminal options such as: allowProposedApi,scrollOnUserInput,fontFamily,fontWeight,cursorBlink,cursorStyle,cursorInactiveStyle,scrollback,letterSpacing, etc |
| 61 | + |
| 62 | +### Return Value |
| 63 | + |
| 64 | +The create methods resolve to an instance object: |
| 65 | + |
| 66 | +- id: Unique id (PID when available; fallback to generated id). |
| 67 | +- name: Terminal name. |
| 68 | +- component: [TerminalComponent instance](https://github.com/Acode-Foundation/Acode/blob/a38f019444cac4c155aff5f18df52d8685fb171d/src/components/terminal/terminal.js#L24). |
| 69 | +- file: EditorFile tab representing the terminal. |
| 70 | +- container: The DOM element hosting the terminal. |
| 71 | + |
| 72 | +## Manage |
| 73 | + |
| 74 | +```js |
| 75 | +// Get a terminal by id |
| 76 | +const t = terminal.get('terminal_1'); |
| 77 | + |
| 78 | +// Iterate all terminals |
| 79 | +for (const [id, inst] of terminal.getAll()) { |
| 80 | + console.log(id, inst.name); |
| 81 | +} |
| 82 | + |
| 83 | +// Write text (ANSI supported) |
| 84 | +terminal.write('terminal_1', 'Hello World!\r\n'); |
| 85 | + |
| 86 | +// Clear and close |
| 87 | +terminal.clear('terminal_1'); |
| 88 | +terminal.close('terminal_1'); |
| 89 | +``` |
| 90 | + |
| 91 | +> [!Note] |
| 92 | +> write uses a secured path internally to prevent unintended escape sequences from breaking state. |
| 93 | +
|
| 94 | +## Themes |
| 95 | + |
| 96 | +Register custom themes or derive variants from existing ones. You can also query available themes. |
| 97 | + |
| 98 | +```js |
| 99 | +// Register |
| 100 | +terminal.themes.register('myTheme', { |
| 101 | + background: '#1a1a1a', foreground: '#ffffff', cursor: '#ffffff', cursorAccent: '#1a1a1a', selection: '#ffffff40', |
| 102 | + black: '#000000', red: '#ff5555', green: '#50fa7b', yellow: '#f1fa8c', blue: '#bd93f9', magenta: '#ff79c6', cyan: '#8be9fd', white: '#f8f8f2', |
| 103 | + brightBlack: '#44475a', brightRed: '#ff6e6e', brightGreen: '#69ff94', brightYellow: '#ffffa5', brightBlue: '#d6acff', brightMagenta: '#ff92df', brightCyan: '#a4ffff', brightWhite: '#ffffff', |
| 104 | +}, 'my-plugin-id'); |
| 105 | + |
| 106 | +// Variants |
| 107 | +const darkVariant = terminal.themes.createVariant('dark', { background: '#000', red: '#ff3030', green: '#30ff30' }); |
| 108 | +terminal.themes.register('darkCustom', darkVariant, 'my-plugin-id'); |
| 109 | + |
| 110 | +// Query |
| 111 | +const theme = terminal.themes.get('dark'); |
| 112 | +const all = terminal.themes.getAll(); |
| 113 | +const names = terminal.themes.getNames(); |
| 114 | + |
| 115 | +// Unregister |
| 116 | +terminal.themes.unregister('myTheme', 'my-plugin-id'); |
| 117 | +terminal.themes.unregister('darkCustom', 'my-plugin-id'); |
| 118 | +``` |
| 119 | + |
| 120 | +### Required Theme Keys |
| 121 | + |
| 122 | +- background, foreground, cursor, cursorAccent, selection |
| 123 | +- black, red, green, yellow, blue, magenta, cyan, white |
| 124 | +- brightBlack, brightRed, brightGreen, brightYellow, brightBlue, brightMagenta, brightCyan, brightWhite |
| 125 | + |
| 126 | +## Behavior & Lifecycle |
| 127 | + |
| 128 | +- Installation flow: When serverMode is true (default), terminal checks if the backend is installed and supported. If missing, an installation terminal opens and streams progress. Creation proceeds only if install succeeds. |
| 129 | +- IDs: If the backend provides a PID, it becomes the terminal id; otherwise a generated id like `terminal_1` is used. |
| 130 | +- Tab: Each terminal is an EditorFile tab with an icon and custom title (PID or generated id). On process exit, the tab closes and a toast shows the exit status. |
| 131 | + |
| 132 | +## Background Execution (No Terminal) |
| 133 | + |
| 134 | +Use the globally available `Executor` when you need to run a one‑off shell command without opening a visual terminal session. |
| 135 | + |
| 136 | +> [!Warning] |
| 137 | +> Prefer visible terminals for transparency. Avoid hiding work in the background and do not start long‑running processes via `Executor.execute`. For interactive or long‑lived tasks, use a terminal session instead. |
| 138 | +
|
| 139 | +### `Executor.execute(command, alpine?)` |
| 140 | + |
| 141 | +- Purpose: Runs a single shell command and waits for it to finish. Output is returned after the process exits (no live streaming of output). |
| 142 | +- Parameters: |
| 143 | + - `command` (string): The command to run. |
| 144 | + - `alpine` (boolean, optional): Run inside the Alpine sandbox when `true`; run in the Android environment when `false`. |
| 145 | +- Returns: `Promise<string>` that resolves with stdout on success, or rejects with an error/stderr on failure. |
| 146 | + |
| 147 | +#### Example |
| 148 | + |
| 149 | +```js |
| 150 | +// Quick directory listing without opening a terminal UI |
| 151 | +Executor.execute('ls -l') |
| 152 | + .then(console.log) |
| 153 | + .catch(console.error); |
| 154 | +``` |
| 155 | + |
| 156 | +## Example: Themed Output Terminal |
| 157 | + |
| 158 | +```js |
| 159 | +const terminal = acode.require('terminal'); |
| 160 | + |
| 161 | +// Ensure your theme exists (or use a built-in one) |
| 162 | +terminal.themes.register('cyberpunk', { /* colors */ }, 'my-plugin'); |
| 163 | + |
| 164 | +// Create a local output terminal and log |
| 165 | +const out = await terminal.createLocal({ name: 'Plugin Output', theme: 'cyberpunk' }); |
| 166 | +// Or |
| 167 | +const out = await terminal.create({ name: 'Plugin Output', serverMode: false, theme: 'cyberpunk' }); |
| 168 | +terminal.write(out.id, '\u001b[36mPlugin initialized\u001b[0m\r\n'); |
| 169 | +``` |
0 commit comments