Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@gdamore
Copy link
Owner

@gdamore gdamore commented Dec 11, 2025

The logic to force behavior for WezTerm was wrong, and was the result of an incorrect escape sequence for the win32-input-mode. Fixing that lets us eliminate the WezTerm specific logic.

This significantly fixes the win32-input-mode, particularly the nesting so that only the sequences requiring the extra parsing pass receive it.

A few other minor bugs are resolved as well.

Summary by CodeRabbit

  • Refactor

    • Streamlined terminal keyboard/input-mode initialization and removed special-casing for a specific terminal emulator for more consistent cross-platform behavior.
  • New Features

    • Added Ctrl‑Q as a quit shortcut and updated on-screen instructions accordingly.
  • Bug Fixes

    • Improved parsing and handling of various terminal key sequences to reduce ambiguity and make key/mouse input more reliable.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 11, 2025

Walkthrough

Reworks terminal input and CSI handling across three areas: tscreen.go removes TERM_PROGRAM/WezTerm special-casing and the t.enableCsiU == "" guard and consolidates CSI-U init/disable sequences; input.go restructures Win32 ASCII handling, relaxes hasLT/CSI restrictions, refines CSI parameter parsing and mouse/key dispatch; _demos/mouse.go adds Ctrl‑Q quit handling and updates on-screen instructions.

Changes

Cohort / File(s) Summary
CSI U Mode Initialization
tscreen.go
Rewrote prepareExtendedOSC() CSI U initialization: removed the t.enableCsiU == "" guard, eliminated TERM_PROGRAM/WezTerm branches, simplified Windows handling to depend only on empty TERM, and unified non-Windows path to emit a fixed set of enable/disable CSI sequences.
Input parsing and CSI/Win32 keys
input.go
Reworked Win32 ASCII handling to use a nested inputParser for ASCII subsequences and reset escaped flags; CSI parsing now appends explicit 0 for empty params, handles hasLT mouse events early, treats CSI‑u/kitty sequences more broadly, relaxes tilde handling and removes hasLT restrictions when mapping CSI sequences via csiAllKeys, and swallows unknown intermediates.
Demo key handling / UI text
_demos/mouse.go
Changed on-screen instruction text and added Ctrl‑Q handling to gracefully call s.Fini() and exit(0); Ctrl‑Q branch added alongside existing Ctrl‑L/Ctrl‑Z handling.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Review input.go carefully — dense parsing logic, many conditional paths changed (Win32 nested parser, CSI parameter handling, mapping lookups).
  • Verify tscreen.go CSI enable/disable sequences — ensure correct ordering and no duplicate or missing sequences across OS/TERM combos.
  • Check _demos/mouse.go for correct teardown on Ctrl‑Q (resource cleanup / exit semantics).
  • Run terminal-based integration tests or manual scenarios (WezTerm, Windows console, xterm, kitty) to confirm behavior.

Possibly related PRs

Poem

🐰 I hopped through bytes and CSI queues,
Sniffed escapes, untangled cues.
A Ctrl‑Q nibble, a cleaner start,
Fewer branches, steadier heart.
Code carrots munched — a tidy chart. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: fix terminal key protocol handling' is directly related to the main changes in the PR, which involve reworking terminal key protocol initialization and handling across multiple files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch gdamore/wezterm-win-input-mode-fix

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tscreen.go (1)

304-304: Clarify the comment to match actual behavior.

The comment states "if we don't have a TERM" but the code doesn't check the TERM environment variable. On Windows, win32-input-mode is used unconditionally. Consider updating the comment to accurately reflect this behavior.

Apply this diff to clarify the comment:

-		// on Windows, if we don't have a TERM, use only win32-input-mode
+		// on Windows, use only win32-input-mode
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c5ba8a0 and df2ae0e.

📒 Files selected for processing (1)
  • tscreen.go (1 hunks)
🔇 Additional comments (1)
tscreen.go (1)

303-314: Good simplification of the CSI U mode initialization logic.

The OS-based branching provides a cleaner approach than the previous WezTerm-specific handling. The separation between Windows (win32-input-mode only) and non-Windows (three-protocol composite) is clear and maintainable.

The logic to force behavior for WezTerm was wrong, and was the
result of an incorrect escape sequence for the win32-input-mode.
Fixing that lets us eliminate the WezTerm specific logic.
@gdamore gdamore force-pushed the gdamore/wezterm-win-input-mode-fix branch from df2ae0e to 393ed0b Compare December 11, 2025 03:39
This seems to fix things quite nicely for WezTerm regardless of
running remotely or locally on Windows, or on macOS.  The goofy
nesting level only needs to be done when dealing with nesting, and
we can be reasonably sure that all content requiring the extra
parse pass comes together and is complete (and is generally only
required for non-keyboard data.)
@gdamore gdamore changed the title fix: fix terminal key protocol selection logic fix: fix terminal key protocol handling Dec 11, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
_demos/mouse.go (1)

18-21: File comment is inconsistent with updated UI text.

The file-level comment at lines 18-20 and the inline comment at line 87-88 still reference "Press ESC twice to exit", but the on-screen instruction now says "Press Ctrl-Q to Quit". Consider updating the comments to mention both options (ESC twice still works, but Ctrl-Q is now the primary method).

input.go (1)

738-749: Redundant check and consider using constructor for nested parser.

Two minor observations:

  1. The check at line 746 if P[2] > 0 is redundant since line 738 already ensures P[2] > 0 && P[2] < 0x80.

  2. The nested parser is created manually, missing the pre-allocated buffer from newInputParser(). Consider using the constructor for consistency:

 if P[0] == 0 && P[1] == 0 && P[2] > 0 && P[2] < 0x80 { // only ASCII in win32-input-mode
     if ip.nested == nil {
-        ip.nested = &inputParser{
-            evch: ip.evch,
-            rows: ip.rows,
-            cols: ip.cols,
-        }
+        ip.nested = newInputParser(ip.evch)
+        ip.nested.rows = ip.rows
+        ip.nested.cols = ip.cols
     }
-    if P[2] > 0 {
-        ip.nested.ScanUTF8([]byte{byte(P[2])})
-    }
+    ip.nested.ScanUTF8([]byte{byte(P[2])})
     return
 }

Regarding the static analysis hint about integer conversion at line 747: this is a false positive since the bounds check at line 738 (P[2] > 0 && P[2] < 0x80) guarantees the value fits safely in a uint8.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 393ed0b and 8940a91.

📒 Files selected for processing (2)
  • _demos/mouse.go (2 hunks)
  • input.go (6 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
_demos/mouse.go (1)
key.go (2)
  • Key (332-332)
  • KeyCtrlQ (459-459)
🪛 GitHub Check: CodeQL
input.go

[failure] 747-747: Incorrect conversion between integer types
Incorrect conversion of a signed 32-bit integer from strconv.ParseInt to a lower bit size type uint8 without an upper bound check.

🔇 Additional comments (6)
_demos/mouse.go (1)

199-201: LGTM!

The Ctrl-Q quit handling follows the established pattern and correctly uses s.Fini() before os.Exit(0), consistent with the ESC twice exit behavior.

input.go (5)

821-823: LGTM!

Appending explicit 0 for empty CSI parameters ensures proper handling of protocols that distinguish between omitted parameters and zero-valued parameters.


831-836: LGTM!

Early return after handling mouse events with the < prefix prevents incorrect fall-through to other CSI handlers.


851-867: LGTM!

The CSI-u (Kitty keyboard protocol) handling is correctly structured. Removing the hasLT dependency allows proper handling of unambiguous Kitty protocol sequences.


884-898: LGTM!

The relaxed hasLT requirement for CSI ~ handling with proper modifier extraction looks correct. The special case for P0 == 27 (xterm modifyOtherKeys) correctly handles both control characters and printable runes.


901-910: LGTM!

The general CSI key dispatch correctly applies modifiers when present and preserves the aixterm compatibility hack for the P key conflict.

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