Commit Graph

268 Commits

Author SHA1 Message Date
xu0o0
bd2c3ab67e feat(tui): treat paste markers as atomic segments in editor (#2111)
* feat(tui): treat paste markers as atomic segments in editor

Paste markers like `[paste #1 +123 lines]` are now treated as single
atomic units for cursor movement, word navigation, deletion, and
wrapping. Only markers with valid paste IDs (present in the editor's
pastes Map) are treated atomically.

* fix(tui): word-wrap oversized atomic segments in editor
2026-03-13 17:42:59 +01:00
xu0o0
adce496f63 fix(tui): handle narrow terminal width in editor scroll indicator (#2103) 2026-03-13 17:41:14 +01:00
xu0o0
b6b7fafddb fix(tui): normalize tabs in editor setText and input paths (#2027) 2026-03-12 23:48:15 +00:00
xu0o0
48e4bd94ef fix(tui): wordWrapLine overflow with wide chars at wrap boundary (#2082) 2026-03-12 23:46:37 +00:00
Lucas Rangel Cezimbra
baeccade54 fix(tui): restore shift+tab in xterm modifyOtherKeys mode (#2081) 2026-03-12 23:36:45 +00:00
Fero
15e0957b04 fix(tui): stop wide input slice overflow closes #1982 (#2006) 2026-03-09 23:19:26 +01:00
Mario Zechner
aaeb2d8208 fix(tui): handle wide unicode input scrolling closes #1982 2026-03-09 17:51:38 +01:00
xu0o0
78bf0262e5 fix(tui): normalize tab characters in Input paste to spaces (#1975) 2026-03-09 13:30:53 +01:00
Mario Zechner
deb5fb3b88 feat(tui): support digit keybindings closes #1905 2026-03-08 00:36:04 +01:00
Mario Zechner
d48843ea55 Pr 1724 (#1939)
* feat(coding-agent): add fold/unfold to tree branch navigation

Remap left/right arrow keys in the session tree to jump between branch
segment starts (first child of each branching point). Left on a foldable
node (root or segment start) folds it, hiding its descendants. Right on
a folded node unfolds it. Nested fold state is preserved. Search and
filter changes reset all folds.

Folded branches show ⊞ in the connector (├⊞/└⊞) or as a prefix for
roots. Active path marker • appears after the fold indicator.

Add Page Up/Down support for paging through the tree list, consistent
with session selector and config selector.

* feat(coding-agent): improve tree branch folding closes #1724

---------

Co-authored-by: Sviatoslav Abakumov <dust.harvesting@gmail.com>
2026-03-08 00:15:47 +01:00
Benjamin Rapaport
6937d2129e fix(tui): chain slash arg autocomplete after Tab completion
fixes #1437
2026-03-07 23:19:26 +01:00
Mario Zechner
9a8bc61300 fix(tui,coding-agent): handle tmux xterm extended keys and warn on tmux setup fixes #1872 2026-03-07 23:01:48 +01:00
Aliou Diallo
e3decbcdd6 fix(tui): autocomplete highlight follows first prefix match as user types (#1931) 2026-03-07 19:03:42 +01:00
Nico Bailon
841c95ac9c feat(tui): add non-capturing overlays with focus control (#1916) 2026-03-07 14:19:16 +01:00
Mario Zechner
bdf482cefc fix(tui): add modifyOtherKeys fallback for modified enter keys in tmux
When Kitty keyboard protocol is not available (e.g. inside tmux), fall
back to xterm modifyOtherKeys mode 2 so that Shift+Enter, Ctrl+Enter,
and other modified keys are distinguishable from plain Enter.

tmux users need to add to ~/.tmux.conf:
  set -g extended-keys on
  set -g extended-keys-format csi-u

closes #1872
2026-03-06 16:02:17 +01:00
Mario Zechner
9bcf06c056 fix(tui): add Kitty CSI-u printable decoding to Input component, closes #1857 2026-03-06 00:33:58 +01:00
Mario Zechner
dabcda0db3 fix(tui): full redraw on terminal width/height resize\n\ncloses #1844 2026-03-05 20:27:37 +01:00
Mario Zechner
f430dce00a fix(tui): isolate blockquote rendering from default text style 2026-03-04 21:30:54 +01:00
Mario Zechner
9673f52919 fix(tui): render blockquote list content correctly
closes #1787
2026-03-04 20:25:55 +01:00
Mario Zechner
4cb1a56b53 fix(tui,coding-agent): add OSC 133 user message markers support closes #1805 2026-03-04 18:33:22 +01:00
Mario Zechner
689e7b4ac2 fix(tui): make single-line paste atomic to avoid @ autocomplete lag
closes #1812
2026-03-04 18:25:37 +01:00
Mario Zechner
49749407fa fix(tui): ignore unsupported Kitty CSI-u modifiers closes #1807 2026-03-04 18:14:29 +01:00
Zhou Rui
85d06052fb fix(tui): stabilize regional indicator width to prevent streaming render drift (#1783) 2026-03-03 21:59:56 +01:00
herr kaste
f129ac93c5 fix(tui): load koffi via createRequire in ESM (#1627)
The previous lazy-loading change switched to require("koffi") inside
enableWindowsVTInput(). In ESM, require is undefined, so the call
threw and VT input mode was silently not enabled on Windows.

Use createRequire(import.meta.url) at module scope and
cjsRequire("koffi") at the call site. This keeps koffi externalized
for Bun binaries while restoring Windows VT input behavior, including
multiline paste handling.
2026-02-25 12:05:27 +01:00
Mario Zechner
8386a807ff fix(tui): externalize koffi from bun binary builds
Changed koffi import from top-level to dynamic require in
enableWindowsVTInput() and added --external koffi to bun build.
This prevents embedding all 18 platform .node files (~74MB) into
every compiled binary. For Windows builds, only the win32_x64
koffi.node is shipped alongside the binary.

Binary size reduction: darwin-arm64 142MB -> 67MB, archive 43MB -> 28MB.
2026-02-22 14:29:21 +01:00
Duncan Ogilvie
9e22d3913a fix(tui): enable VT input mode on Windows (#1495)
This fixes Shift+Tab not being recognized correctly
2026-02-14 01:45:11 +01:00
Mario Zechner
31f765ff1b fix(tui): scope @ fuzzy search to path prefixes\n\ncloses #1423 2026-02-12 21:26:47 +01:00
Sam Fold
30fd99bd82 feat: add terminal input hook for extensions 2026-02-12 20:45:33 +01:00
Kao Félix
6a3d6fe944 feat(tui, coding-agent): add pasteToEditor to ExtensionUIContext (#1351)
Add pasteToEditor(text) method that pastes text into the editor via
bracketed paste sequences, triggering paste handling (including collapse
for large content). Unlike setEditorText which directly replaces content,
pasteToEditor routes through handleInput on the active editor component.

- Add pasteToEditor to ExtensionUIContext interface
- Add handleInput to EditorComponent interface (was missing, all
  concrete implementations already had it)
- Implement in interactive mode via bracketed paste sequence
- Add fallback in RPC mode (delegates to setEditorText)
- Document in extensions.md
2026-02-07 15:55:08 +01:00
Sviatoslav Abakumov
4c2d78f6cb Add the kill ring and undo features to the Input component (#1373)
* feat(tui): extract KillRing and UndoStack, add to Input

Extract kill ring and undo logic from Editor into reusable classes:

- KillRing: ring buffer with accumulation for consecutive kills
- UndoStack<S>: generic stack with clone-on-push semantics

Refactor Editor to use both classes. Add kill ring (kill/yank/
yank-pop), undo with coalescing, and deleteWordForward to Input.

* feat(tui): extract handleBackspace() and handleForwardDelete()
2026-02-07 15:47:27 +01:00
Aliou Diallo
9920d899b5 fix(tui): allow slash command menu on first line with existing text 2026-02-04 14:02:38 +01:00
haoqixu
ed4168bff4 fix(coding-agent): avoid crash of /settings with small width 2026-02-04 15:27:33 +08:00
haoqixu
99c78b91cb fix(tui): avoid split of emojis when scrolling input 2026-02-04 02:06:07 +08:00
Mario Zechner
20d704fee1 fix(tui): restore legacy newline handling 2026-02-03 01:36:46 +01:00
Mario Zechner
ba5eb05f44 fix(tui): include hidden paths in @ autocomplete 2026-02-03 01:36:46 +01:00
Mario Zechner
c64e228b76 fix(tui): honor keybindings for submit fallback 2026-02-03 01:10:06 +01:00
Mario Zechner
8c38de0495 fix(tui): drain stdin on exit to avoid Kitty release leak
Drain stdin for up to 1s after disabling Kitty protocol so in-flight key
release events are consumed before the shell regains control.

Fixes #1204
2026-02-03 00:07:35 +01:00
Mario Zechner
9a4d043b28 fix(tui): drain Kitty key release events before exit to prevent SSH leak
Adds Terminal.prepareForExit() to disable Kitty protocol and wait for
in-flight release events before fully stopping. This prevents escape
sequences from leaking to the parent shell over slow SSH connections.

Fixes #1204
2026-02-03 00:01:39 +01:00
Mario Zechner
f431f62609 fix(tui): pause stdin before restoring raw mode to prevent SSH session close
Fixes #1185
2026-02-02 19:24:55 +01:00
xu0o0
fe534b2200 fix(tui): handle emojis in input cursor (#1183) 2026-02-02 18:03:57 +01:00
Mario Zechner
0d934091f4 feat(tui): add PI_DEBUG_REDRAW=1 env var for debugging full redraws
Logs redraw triggers to ~/.pi/agent/pi-debug.log when enabled.
2026-02-02 08:39:57 +01:00
Mario Zechner
0925fafe3b fix(tui): reduce unnecessary full redraws for better performance
- Remove height change detection (only width changes trigger full redraw)
- Change clearOnShrink default to false (use PI_CLEAR_ON_SHRINK=1 to enable)
- Fix viewport check to use previousLines.length instead of maxLinesRendered
  (prevents false positive redraws when appending lines after content shrunk)
- Add clearOnShrink setting to /settings in coding-agent
- Remove line truncation in custom message component (always show full content)
2026-02-02 08:10:08 +01:00
Ryota
5bb3700717 fix(tui): prevent Kitty protocol base layout key from causing false shortcut matches
With the Kitty keyboard protocol (flag 4), terminals report both the
logical key codepoint and the physical base layout key (PC-101 QWERTY
position). The key matching logic in matchesKittySequence matched
against both unconditionally, which caused a single keypress to match
multiple shortcuts on remapped keyboard layouts.

For example, on a Dvorak layout with xremap, pressing Ctrl+K sends
CSI 107::118;5u (codepoint=107 'k', base layout=118 'v'). The
unconditional base layout match made this also match Ctrl+V, which is
bound to pasteImage. Since CustomEditor checks app-level keybindings
(pasteImage) before editor keybindings (deleteToLineEnd), Ctrl+K was
silently intercepted by the paste image handler instead of deleting
to end of line. The same issue affects symbol keys, as Dvorak also
remaps symbols to different physical positions (e.g., '/' sits where
'[' is on QWERTY).

The fix restricts base layout key matching to cases where the codepoint
is not a recognized Latin letter (a-z) or symbol (/, -, [, ;, etc.).
When the codepoint is already a recognized key, it is authoritative and
the base layout key is ignored. This preserves non-Latin layout support
(Ctrl+К on a Russian layout still matches Ctrl+K via base layout key
107) while preventing false matches from differing physical key
positions on remapped layouts.

Both matchesKittySequence and parseKey are updated with the same logic.
2026-02-01 01:25:00 +01:00
Sviatoslav Abakumov
d075291b08 feat(tui): add sticky column for vertical cursor navigation (#1120)
When moving up/down through lines of varying lengths, the editor now
remembers the original column position and restores it when reaching a
line long enough to accommodate it.

Example: cursor at column 10, move up to a shorter line (cursor clamps
to end), move up again to a longer line - cursor returns to column 10.

Implementation:

- Add preferredVisualCol instance property (nullable)
- Set it when moving to a shorter line during vertical navigation
- Clear it when arriving at a line that fits the preferred column
- Clear it on any horizontal movement or editing via setCursorCol()
- Detect line rewrap by checking if cursor is in middle of line
- When pressing right at end of prompt, set preferredVisualCol so
  subsequent up/down navigation uses that column position
2026-01-31 22:52:47 +01:00
Marc Krenn
39c898d7c9 fix(tui): auto-clear empty rows when content shrinks (#1095)
- Add height change detection (analogous to existing width detection)
- Auto-detect when content shrinks below maxLinesRendered and trigger
  full re-render to clear leftover empty rows
- Only triggers when no overlays are active (overlays need padding)

Fixes empty rows appearing below footer when:
- Closing /tree or other selectors
- Clearing multi-line editor content
- Any component shrinking

Also adds regression tests for resize handling and content shrinkage.
2026-01-30 20:45:34 +01:00
Mario Zechner
836e852af1 Fixes #1099 2026-01-30 18:19:16 +01:00
Mario Zechner
abd0c47b03 perf(tui): use startsWith short-circuit in isImageLine 2026-01-30 17:07:43 +01:00
Dave dV
2339d7b5ac fix(tui): isImageLine should detect image escape sequences anywhere in line
Changed isImageLine() from using startsWith() to includes() to detect
Kitty and iTerm2 image escape sequences anywhere in a line, not just
at the start. This prevents TUI width checks from failing on lines
containing image data, which could cause crashes when rendering tool
results with images (e.g., when reading image files).

Also added comprehensive test coverage for isImageLine() including:
- Both iTerm2 and Kitty protocols
- Regression tests for long lines and terminals without image support
- Negative cases to ensure no false positives

Fixes crash: 'Rendered line exceeds terminal width' when image
escape sequences appear in output.
2026-01-30 10:07:22 +00:00
Fero
20ca6836b0 fix(tui): blockquote multiline rendering and wrapping (#1073)
* fix(tui): blockquote multiline rendering and wrapping

Fix two bugs in blockquote rendering:

1. ANSI codes split incorrectly on newlines - when text tokens contain
   newlines, applyDefaultStyle() wrapped the entire string including the
   newline in ANSI codes. Any caller splitting by \n would break the codes.
   Fixed by splitting text by newlines before styling in renderInlineTokens().

2. Wrapped blockquote lines lost the │ border - long blockquote lines
   that wrapped to multiple lines only had the border on the first line.
   Fixed by wrapping within the blockquote case and adding border to each line.

* test(tui): add test for inline formatting inside blockquotes
2026-01-30 03:02:38 +01:00
4h9fbZ
ab37d661af feat(tui): jump to line start/end when pressing up/down at boundaries (#1050)
When cursor is on the first visual line and up is pressed, jump to
start of line instead of doing nothing. When cursor is on the last
visual line and down is pressed, jump to end of line instead of doing
nothing. This matches standard behavior in most native text inputs.
2026-01-30 02:42:24 +01:00