diff --git a/PLAN.md b/PLAN.md new file mode 100644 index 0000000..30f775d --- /dev/null +++ b/PLAN.md @@ -0,0 +1,66 @@ +# Implementation Plan: BEL Control Code Event Emission + +## Summary + +Wire up BEL (0x07) handling in the Terminal class (`src/terminal.js`) to emit a callback event, and add a default visual bell handler in the Renderer (`src/renderer.js`). This is a small, well-scoped feature that touches 4 files. + +## Architecture Analysis + +The codebase has two layers relevant to this task: + +1. **Terminal engine** (`src/terminal.js`) — Pure state machine. Parser callbacks (`onPrint`, `onExecute`, `onCsiDispatch`, etc.) drive state changes. The `_execute()` method already has a `case 0x07: // BEL` stub that does nothing. + +2. **Renderer** (`src/renderer.js`) — DOM renderer that reads terminal state and renders it. Currently has no event subscription — it just reads `terminal.getState()`. + +The codebase uses a simple **callback property** pattern for events (e.g., `parser.onPrint`, `parser.onExecute`). Following this pattern, the Terminal class should expose an `onBell` callback property. + +## Research + +xterm.js added `onBell` in v4.12.0 ([Issue #3014](https://github.com/xtermjs/xterm.js/issues/3014)). Their approach: the terminal emits a bell event, and the UI layer subscribes to it independently. The bell event carries no data (it's a `void` callback). This matches our acceptance criteria for full decoupling. + +## Changes + +### 1. `src/terminal.js` — Add `onBell` callback + +- Add `this.onBell = null;` in the constructor (following the pattern of other state like `this.title`). +- In `_execute()`, change `case 0x07` from a bare `break` to `this.onBell?.(); break;`. The optional chaining (`?.`) ensures no error if no handler is registered (AC #5). +- In `reset()`, set `this.onBell` back to `null` is NOT needed — the callback is external configuration, not terminal state. The `title` callback pattern shows that external registrations persist across resets. + +### 2. `src/renderer.js` — Add visual bell handler + +- Add a `_setupBellHandler()` method called from the constructor that subscribes to `terminal.onBell`. +- The handler adds a CSS class (`mogterm-visual-bell`) to the container for a brief flash, then removes it after the animation completes. +- The flash uses a CSS animation (opacity pulse or border flash) defined inline or via a `