Files
terminal-lab/xterminal/docs/guide/events.md
douboer@gmail.com 3b7c1d558a first commit
2026-03-03 13:23:14 +08:00

180 lines
5.1 KiB
Markdown

# Events
The [XTerminal](../api/index.md#xterminal) class, from which we create an instance, extends an internal [EventEmitter](../api/index.md#xeventemitter) class.
This implies that we can handle events the same way the browser does to provide interaction through events like:
click, keydown, and so on.
The underlying [EventEmitter](../api/index.md#xeventemitter) exposes, the `on`, `off`, `once`, and `emit` methods.
- `on` is used to add an event listener that's executed when the event is triggered
- `off` is used to remove an event listener from an event
- `once` is used to add a one-time event listener, it is triggered only once and then removed using `off`
- `emit` is used to trigger an event
## Custom Events
Create a `start` event, and as a matter of providing an example, the reaction to the event is a simply outputting to the terminal.
```js
term.on('start', () => {
term.writeln('started...');
});
```
When we run the `emit` method passing the `start` event,
```js
term.emit('start');
```
the event handler function is triggered, and we get the terminal log.
### Arguments
You can pass multiple arguments to the event handler by passing them as additional arguments to `term.emit()`.
```js
term.on('start', (id) => {
term.writeln('started...', id);
});
term.emit('start', 5173);
```
Example with multiple arguments:
```js
term.on('start', (start, end) => {
term.writeln(`started from ${start} to ${end}`);
});
term.emit('start', 1, 10);
```
### One-Time Event
In some cases, it might be necessary to only run an operation once and only once.
Any event listener added using the `term.once()` method is executed once and deleted thereafter when the event is triggered.
```js
term.once('load', () => {
term.writeln('loaded...');
});
term.emit('load');
term.emit('load');
```
The `load` event is triggered and will output to the terminal for the first `term.emit('load')`.
The second event trigger does nothing since there is no event listener for the `load` event anymore.
### Symbols
Apart from strings, JavaScript symbols can as well be used to create events too.
```js
const START_EVENT = Symbol('start');
term.on(START_EVENT, () => {
term.writeln('started with a symbol...');
});
term.emit(START_EVENT);
```
## Default Events
Every terminal instance has existing events that are used internally and can be used in your application lifecycle.
They include:
- `data` event - triggered when user inputs data and presses the _Enter_ key
- `clear` event - triggered on [term.clear()](../api/index.md#term-clear)
- `keypress` event - triggered on every key press except _Tab, Enter, ArrowUp_ and _ArrowDown_
- `pause` event - triggered on [term.pause()](./prompt.md#pause-resume), when the terminal input is _deactivated_ or _paused_
- `resume` event - triggered on [term.resume()](./prompt.md#pause-resume), when the terminal input is _activated_ or _resumed_
### Example
In this example, you are going to capture the user's input and simply write it to the terminal.
First, add an event listener for the `data` event to capture data, output it and then ask for more input thereafter. Clear the terminal on recieving the input matching to `clear` and as a result, everything is erased from the terminal including the prompt style. Additionally, add a `keypress` event to clear the terminal.
:::details Code
```js
term.on('data', (input) => {
if (input == 'clear') {
// clear the terminal
term.clear();
} else {
// do something
term.writeln('Data: ' + input);
}
// write the prompt again
term.write("$ ");
});
term.on('clear', () => {
term.writeln('You cleared the terminal');
});
term.on('keypress', (ev) => {
/**
* Checkout the event object
*/
console.log(ev);
// on CTRL+L - clear
if (ev.key.toLowerCase() == 'l' && ev.ctrlKey) {
// prevent default behaviour
ev.cancel();
// clear and trigger `clear` event
term.clear();
}
});
```
:::
The terminal will be cleared incase the user inputs `clear` or presses the shortcut `CTRL+L` which triggers the `clear` event that logs `You cleared the terminal` on the screen.
## Limitations
Multiple events can exist on the same terminal instance which is an advantage. However you should keep caution on when every event is triggered.
:::warning Nested Emits
When an event is triggered, it is added on top of the emitting stack and then the listeners attached to the event are invoked synchronously.
If you emit the same event within one of the listeners, it will not work.
:::
**Example:**
The code sample below will not work as expected.
```js
term.on('run', () => {
console.log('running...');
// ...
term.emit('run');
});
```
Triggering the event `run` will log in the console: `running...`, do stuff, and attempt to trigger itself again (possible deadlock).
**Workaround**
Trigger the same event in the next event loop.
```js{4}
term.on('run', () => {
console.log('running...');
// ...
setTimeout(() => term.emit('run'), 0);
});
```
## Next Step
You'll learn to everything about the prompt including activation, styling, blur and focus.