Skip to content

terminal: xterm addons (unicode11, web-links, search) and a find bar (#131) - #134

Merged
Lexus2016 merged 1 commit into
mainfrom
feat/terminal-addons-131
Nov 9, 2026
Merged

Lexus2016 merged 1 commit into
mainfrom
feat/terminal-addons-131

Conversation

@Lexus2016

Copy link
Copy Markdown
Owner

Second slice of #131: the pane gets the three addons it was missing, and a way to search
the scrollback.

What landed

public/vendor now holds the addon bundles next to xterm.js, the same way
xterm-addon-fit.js already did. All four come from the 5.3.0 release, which is the
version of the vendored xterm.js — public/vendor/xterm.js is byte-identical to
xterm@5.3.0/lib/xterm.js, so the addons are the matching builds and not a newer API on
an older core.

file package what it does
xterm-addon-unicode11.js @xterm/addon-unicode11@0.7.0 Unicode 11 width tables — wide characters and emoji keep their columns
xterm-addon-web-links.js @xterm/addon-web-links@0.10.0 a URL in the output is clickable
xterm-addon-search.js @xterm/addon-search@0.14.0 search the scrollback

The files are the package's own UMD bundles (lib/addon-*.js), copied unchanged —
sha256 of each equals the extracted npm tarball. electron-builder.yml already ships
**/*, so nothing else is needed for the desktop build.

_createTerminal loads them through termAddonPlan(), which takes the bundle globals and
returns only the ones that exist: a checkout (or a packaged build) that lost one vendor
file keeps the pane it has instead of throwing before xterm.open().

unicode11 is activated, not just loaded — term.unicode.activeVersion = '11'. The
addon registers its width tables and does nothing until they are the active version; that
one line is the whole fix for the misaligned TUI the issue reported.

web-links gets our own handler. The default opens the URL with window.open, which in
the desktop build is already routed to the system browser by applyWindowOpenPolicy, but
the handler now also refuses anything that is not http(s), so a future provider cannot
make the pane open file:// or javascript:.

The find bar

Ctrl+Shift+F (or Cmd+F on macOS) inside the pane, and a Find… item in the pane's
right-click menu, open a row above the terminal:

  • typing searches incrementally, so the view stays on the match it already found;
  • Enter steps forward, Shift+Enter back, both non-incremental;
  • the count reads 3 of 12, 1000 of 1000+ at the addon's highlight cap, and No matches
    otherwise;
  • Esc closes the bar, clears the decorations and hands the keyboard back to the pane;
  • the bar belongs to the pane it was opened on: switching tabs closes it, and a result
    count from a hidden pane can no longer write into it;
  • opening and closing refits the pty, so the TUI does not keep drawing to the old height
    and leave a band of blank rows.

Plain Ctrl+F is deliberately not the pane's: it is readline's forward-char for
whatever is running inside, and the chat's own Ctrl+F search is bound where focus is
outside the pane. Seven new strings in all five dictionaries.

Verification

Real Chromium, against the vendored files (headless shell, the page's own
_createTerminal and find block, the real keyboard path):

  • term.unicode.activeVersion is 11, versions is ['6', '11'];
  • Ctrl+Shift+F pressed inside the pane opens the bar and focuses the field;
  • typing needle over 40 matching lines reports 1 of 40, Enter gives 2 of 40, a query
    with no match reads No matches;
  • Esc closes it, clears the field, and two resize frames went out (open and close);
  • a click on a URL in the output calls the handler with https://example.com/x;
  • no console or page errors.

Unit — test/terminal-addons.test.js (new, 21 checks): the three vendored bundles are
evaluated as the <script> tag evaluates them and must expose their constructors; the plan
drops a missing bundle; only http(s) leaves through the link handler; the chords, the
count label, the incremental/step/clear calls, Esc, the per-session result filter and the
"no addon, no bar" path are all run against a fake xterm. test/terminal-clipboard.test.js
gained the menu's Find item and now evaluates the new block, since _createTerminal calls
into it.

Still open in #131

  • clipboard and webgl: both change rendering and need a wider check on the embedded
    Electron build;
  • the mobile proposals from the second comment (typing field, touch scrolling, long-press
    selection, pinch-to-zoom, 80-column floor, prompt buttons on input_needed).

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-09T00:23:36.163360Z 1d7eaa5 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Unicode 11 width tables, clickable URLs and search, vendored from the same
xterm 5.3.0 release as public/vendor/xterm.js. The find bar opens with
Ctrl+Shift+F (Cmd+F on macOS) or from the pane menu, searches incrementally,
steps on Enter / Shift+Enter and closes on Esc. Loading unicode11 alone does
nothing, so the pane also activates it.
@Lexus2016
Lexus2016 force-pushed the feat/terminal-addons-131 branch from 1d7eaa5 to 18cb887 Compare November 9, 2026 00:23
@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

https://github.com/Lexus2016/claude-code-studio/blob/1d7eaa5ba515892934f6c189b1f24511abbe8f4c/public/index.html#L19734
P2 Badge Dismiss the terminal menu only on outside mouse presses

When a user clicks any menu item, its mousedown bubbles to this document listener and removes the menu before mouseup and click can reach the button. Since the actions are attached to click, Copy, Paste, Select All, Find, and the copy-on-select toggle never execute through normal mouse interaction. Ignore presses inside the menu, or dismiss after the item's click handler has run.


https://github.com/Lexus2016/claude-code-studio/blob/1d7eaa5ba515892934f6c189b1f24511abbe8f4c/public/index.html#L19936-L19937
P2 Badge Prevent the native paste when handling the paste shortcut

On macOS, Cmd+V now calls _pasteFromClipboard() without preventing the keyboard event's default action. In the vendored public/vendor/xterm.js, returning false from the custom handler only exits _keyDown; it does not cancel the DOM event, and xterm separately handles native paste events. Consequently, when clipboard access succeeds, Cmd+V pastes once through xterm's native handler and again through pasteToTerminal, duplicating the clipboard contents in the running application. Call ev.preventDefault() when consuming this shortcut, or retain the native paste path instead of adding a second one.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Lexus2016
Lexus2016 merged commit 2d95fe4 into main Nov 9, 2026
3 checks passed
@Lexus2016
Lexus2016 deleted the feat/terminal-addons-131 branch November 9, 2026 00:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant