Skip to content

feat(tui): implement ADR-0049 bracketed paste support in settings overlay - #72

Merged
justinwilkin merged 3 commits into
feat/tui-upliftfrom
feat/tui-uplift-paste
Feb 27, 2026
Merged

feat(tui): implement ADR-0049 bracketed paste support in settings overlay#72
justinwilkin merged 3 commits into
feat/tui-upliftfrom
feat/tui-uplift-paste

Conversation

@justinwilkin

Copy link
Copy Markdown
Member

Summary

Implements ADR-0049 — bracketed paste support for the TUI settings dialog fields.

Problem

The settings overlay only accepted single-character key events. Multi-character paste events (from the terminal's bracketed paste mode) were silently discarded, making it impossible to paste API keys, base URLs, or other long strings into dialog fields.

Solution

Bubble Tea v1.3.10 delivers bracketed paste as a tea.KeyMsg with Paste: true and Type: KeyRunes — the pasted content is in keyMsg.Runes. Bracketed paste is enabled by default in v1.3.10; no program option changes were needed.

Changes

pkg/executor/tui/overlay/settings.go

  • Added keyMsg.Paste branch in handleDialogInput — routes paste events to the new handleDialogPaste before they hit the key-switch
  • Replaced len(keyMsg.String()) == 1 guard in handleDialogCharInput with isPrintableInput() — correctly rejects control sequences while accepting multi-rune characters
  • New handleDialogPaste(text string) — strips \n, \r, \t (password managers append trailing newlines), respects maxLength via rune-aware slicing, clears errorMsg on success
  • New isPrintableInput(s string) bool — uses unicode.IsPrint to gate single-char input

pkg/executor/tui/overlay/settings_test.go

  • 22 new tests: 12 for isPrintableInput, 9 for bracketed paste scenarios (basic paste, append, newline/tab stripping, maxLength, password fields, error clearing)

Test Results

ok  github.com/entrhq/forge/pkg/executor/tui          1.967s
ok  github.com/entrhq/forge/pkg/executor/tui/overlay  2.449s

All 22 new tests pass. Full suite green, no regressions.

Known Limitations

Ctrl+V on terminals without bracketed paste support still delivers a raw key event and will not trigger paste behaviour. Supported terminals: iTerm2, Alacritty, kitty, Windows Terminal, GNOME Terminal, tmux ≥ 2.6.

entr-agent and others added 2 commits February 27, 2026 17:11
Co-authored-by: Justin Wilkin <justin@entr.net.au>
…ution

Co-authored-by: Justin Wilkin <justin@entr.net.au>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Implements ADR-0049 by adding bracketed paste handling to the TUI settings overlay so users can paste multi-character values (API keys, base URLs, etc.) into dialog fields.

Changes:

  • Route tea.KeyMsg{Paste: true} events to a new paste handler for dialog fields.
  • Replace the single-character guard with isPrintableInput() and add helpers for paste sanitization and printable input detection.
  • Add unit tests covering isPrintableInput and bracketed paste behaviors.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
pkg/executor/tui/overlay/settings.go Adds paste routing + paste insertion helper + printable-input gating for dialog input.
pkg/executor/tui/overlay/settings_test.go Adds new tests for printable input gating and bracketed paste scenarios.
docs/adr/0049-tui-bracketed-paste-support.md Updates ADR status/decision details to reflect the implemented approach for Bubble Tea v1.3.10.
Comments suppressed due to low confidence (1)

docs/adr/0049-tui-bracketed-paste-support.md:277

  • ADR note says unicode is already imported in settings.go and no new imports are needed, but this PR explicitly adds the unicode import. Consider updating this line to avoid contradicting the implementation/diff (or remove the import-related note entirely).
In Bubble Tea v1.3.10, there is no exported `tea.PasteMsg` type. The `keyMsg.Paste` check in `handleDialogInput` must appear **before** the key-switch so pasted content is never dispatched to the normal key handlers.

`strings` and `unicode` packages are already imported in `settings.go` — no new imports needed.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pkg/executor/tui/overlay/settings.go Outdated
Comment thread pkg/executor/tui/overlay/settings_test.go Outdated
Comment thread pkg/executor/tui/overlay/settings.go
Comment thread pkg/executor/tui/overlay/settings.go Outdated
Comment thread pkg/executor/tui/overlay/settings.go Outdated
…mentation

- Replace isPrintableInput() guard in handleDialogCharInput with
  keyMsg.Type == tea.KeyRunes check; avoids inserting Bubble Tea
  control-key strings (ctrl+v, ctrl+c, alt+x) as literal text
- Use keyMsg.Runes directly for character insertion (avoids keyMsg.String()
  which formats multi-key events as 'ctrl+x' etc.)
- Replace handleDialogPaste whitelist (\n\r\t) with unicode.IsPrint filter
  so escape sequences and other control chars are also stripped
- Fix maxLength enforcement in both handleDialogCharInput and
  handleDialogPaste to use rune counts (len([]rune(...))) not byte counts
- Remove isPrintableInput() helper (no longer needed)
- Replace TestIsPrintableInput with TestInputDialog_CharInput (5 subtests)
- Add TestInputDialog_BracketedPaste: escape-sequence stripping and
  rune-based maxLength subtests (11 subtests total, all pass)
@justinwilkin
justinwilkin merged commit 95dc861 into feat/tui-uplift Feb 27, 2026
@justinwilkin
justinwilkin deleted the feat/tui-uplift-paste branch February 27, 2026 06:42
justinwilkin added a commit that referenced this pull request Mar 2, 2026
…rlay (#72)

* fix(tui/overlay): handle bracketed paste input in settings dialog

Co-authored-by: Justin Wilkin <justin@entr.net.au>

* docs(adr): update ADR-0049 to reflect implemented bracketed paste solution

Co-authored-by: Justin Wilkin <justin@entr.net.au>

* fix(tui/overlay): address PR review comments on bracketed paste implementation

- Replace isPrintableInput() guard in handleDialogCharInput with
  keyMsg.Type == tea.KeyRunes check; avoids inserting Bubble Tea
  control-key strings (ctrl+v, ctrl+c, alt+x) as literal text
- Use keyMsg.Runes directly for character insertion (avoids keyMsg.String()
  which formats multi-key events as 'ctrl+x' etc.)
- Replace handleDialogPaste whitelist (\n\r\t) with unicode.IsPrint filter
  so escape sequences and other control chars are also stripped
- Fix maxLength enforcement in both handleDialogCharInput and
  handleDialogPaste to use rune counts (len([]rune(...))) not byte counts
- Remove isPrintableInput() helper (no longer needed)
- Replace TestIsPrintableInput with TestInputDialog_CharInput (5 subtests)
- Add TestInputDialog_BracketedPaste: escape-sequence stripping and
  rune-based maxLength subtests (11 subtests total, all pass)

---------

Co-authored-by: anvxl <anvxl@entr.net.au>
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.

3 participants