Skip to content

feat(dialogs): add a text input dialog - #41

Merged
fx merged 4 commits into
mainfrom
feat/0017-dialog-text-input
Aug 29, 2026
Merged

feat(dialogs): add a text input dialog#41
fx merged 4 commits into
mainfrom
feat/0017-dialog-text-input

Conversation

@fx

@fx fx commented Aug 29, 2026

Copy link
Copy Markdown
Owner

Adds a standalone text input dialog to the bundled dialogs provider. This is Task A of change 0017; composition is deliberately deferred.

What input does

input({ message, initialValue? }) resolves Promise<string | undefined>.

  • Renders the message and the current value, starting from initialValue when supplied and empty otherwise.
  • Printable characters append in typed order. Input arriving as one multi-character chunk, as a paste does, appends whole, minus any control characters it carries.
  • Backspace drops the last character, counted by code point so a non-BMP character leaves whole, and does nothing when the value is empty.
  • Any other input leaves the value unchanged: arrow keys, Tab, Ctrl and Alt combinations, and unresolved CSI control sequences append nothing.
  • Enter resolves the value exactly as entered, including the empty string. Escape and Ctrl-C resolve undefined without terminating the process, so an intentional empty value stays distinguishable from cancellation.
  • Never trims, validates, or transforms the value, and never writes it to standard output.
  • Rejects before rendering when the injected stdin or stderr is not a TTY, renders only on injected stderr, and finishes terminal restoration and renderer unmount before settling — the same finite-retry cleanup contract select already had.

Shared render session

select's render, race, and cleanup skeleton is now runDialog, which both dialogs use. Adding a second consumer of that ~90-line block was the alternative to duplicating it; extraction was clearly the smaller change. select's observable behavior is unchanged, including its Select renderer exited before the dialog completed rejection, which runDialog reproduces verbatim via a label parameter.

Deferred to Task B

Composition — user-provided select options, the fields property on SelectOption, and the SelectResult { value, values } envelope — is a separate later PR. select still returns Promise<T | undefined> here. Change 0017's status stays draft and Task B's checkboxes stay unticked; that PR flips them.

Known limit, recorded in REVIEW.md

Ink strips the leading escape before useInput runs and exposes no flag saying it did, and the same handler must append multi-character pastes, so an unresolved control sequence can only be recognized by shape. The filter covers the CSI form; consequently a paste that is exactly a CSI body — [25~ on its own — enters nothing, and an unrecognized SS3 sequence still appends its payload. Both directions are documented in the manual and in REVIEW.md so the trade-off is not re-litigated.

Verification

HOME=$(mktemp -d) XDG_DATA_HOME=$(mktemp -d) bun run check exits 0: 453 tests pass, 100% statement/function/line coverage on every production source. The env isolation is needed on a developer machine because the test run otherwise pulls the real ~/.local/share/tx/marketplaces plugins into the coverage report; CI is unaffected.

Copilot AI lite review requested due to automatic review settings August 29, 2026 16:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

The dialogs specs doc still states input behavior is not implemented yet, which is now incorrect and should be updated to avoid misleading documentation.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds a standalone input text-entry dialog to the bundled dialogs provider and factors the shared Ink render/cleanup lifecycle into a reusable runDialog helper so both select and input share the same session/cleanup semantics.

Changes:

  • Added Dialogs.input({ message, initialValue? }) implementation with paste/control filtering, code-point backspace, submit/cancel semantics, and non-interactive stream rejection.
  • Extracted the shared render/race/cleanup skeleton from select into runDialog, and rewired select to use it without changing select’s externally observed behavior.
  • Added comprehensive Bun tests for the new input dialog behavior and updated plugin manual + change doc task checklists.
File summaries
File Description
plugins/dialogs/index.ts Adds input dialog and extracts shared runDialog render/cleanup session used by both dialogs.
test/dialogs-plugin.test.ts Adds input-dialog test harness and a broad test suite covering rendering, editing, cancellation/submission, failures, and cleanup.
docs/manual/plugins.md Documents the input dialog contract and clarifies shared dialog session/cleanup behavior.
docs/changes/0017-add-dialog-text-input-and-composition.md Checks off Task A items for change 0017 now that standalone input is implemented and tested.
REVIEW.md Records the intentional “unresolved control sequence recognized by shape (CSI only)” limitation as a review constraint.
Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/manual/plugins.md
@fx
fx requested a lite review from Copilot August 29, 2026 16:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

The implementation matches the stated dialog semantics, preserves select behavior via a shared runDialog, and is backed by thorough tests and aligned documentation updates.

Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@fx
fx merged commit cd2110d into main Aug 29, 2026
2 checks passed
@fx
fx deleted the feat/0017-dialog-text-input branch August 29, 2026 16:08
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.

2 participants