Skip to content

Unify TUI input editing in Tui::InputField - #134

Closed
tobi wants to merge 2 commits into
spinel-aot-lintfrom
tui-input-field
Closed

Unify TUI input editing in Tui::InputField#134
tobi wants to merge 2 commits into
spinel-aot-lintfrom
tui-input-field

Conversation

@tobi

@tobitobi commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Stacked on #133.

Steal from tobi/try-cli: one real input widget instead of four copy-pasted editors. try-cli's tui_push/tui_pop is an ANSI style stack, not a view stack; Ruby's Screen/Section/Line layout is already better, so this only ports the input/terminal layer.

  • Tui::InputField#handle_key used by search, rename, graduate, and the YES prompt
  • Left/Right move the cursor; Ctrl-U kill-to-start; Delete-forward; Ctrl-H backspace
  • Reverse-video cursor #to_s unchanged (existing screenshots still match)
  • TryEntry#method_missing replaced with explicit accessors
  • at_exit restores alt-screen / cooked / cursor if we crash in raw mode
  • Drain leftover stdin on TUI exit; consume unknown CSI/mouse so trackpad junk doesn't land in the filter

MRI and native: 399/399 (original 397 plus two keyboard tests). runner_and_compare.sh 13/13.

Not in this PR: C style stack, C fuzzy scoring, ghost-placeholder rename UX, collapsing dialogs into a single-loop mode enum.

Demo

Same key story on both runtimes (cursor into spin, insert x, Ctrl-A/E, Ctrl-U, rename):

MRI

try MRI

Native / Spinel

try native

Playable: MRI asciinema · native asciinema

Benchmark (hyperfine)

MRI ruby try.rb vs native dist/try, 2026-08-13 16:04 EDT. hyperfine 1.19.0, --shell=none -w 3 -r 20. Ruby 3.3.8, Spinel 79b1aba8bdef (PR 3906). Native at measurement was ~1.0 MiB unstripped; current dist/try after -Os+strip is 705 KB. Native won every case.

CaseMRInativeSpeedup
--help69.4 ± 4.8 ms0.956 ± 0.096 ms72.6×
--version70.8 ± 6.3 ms0.959 ± 0.125 ms73.8×
no args (exit 2)68.7 ± 4.3 ms0.982 ± 0.068 ms69.9×
init96.5 ± 9.4 ms21.2 ± 1.3 ms4.5×
TUI empty74.0 ± 8.4 ms1.28 ± 0.14 ms57.8×
TUI 5 dirs72.0 ± 6.0 ms1.38 ± 0.08 ms52.1×
TUI --and-keys=beta72.4 ± 5.9 ms2.70 ± 0.35 ms26.8×
TUI exec beta74.6 ± 8.1 ms1.49 ± 0.16 ms50.2×
clone script70.3 ± 6.2 ms0.959 ± 0.103 ms73.3×
worktree script72.9 ± 8.6 ms1.01 ± 0.09 ms71.9×
scan 1000 dirs80.3 ± 7.3 ms8.57 ± 0.69 ms9.4×
filter 1000 dirs93.9 ± 5.5 ms40.9 ± 4.8 ms2.3×

init still forks ps to detect fish vs bash (~20 ms on native). The 1000-entry filter is whole-process (scan + four keystrokes + re-renders), not an isolated matcher.

tobi added 2 commits August 13, 2026 20:53
Steal try-cli's editor keys (arrows, Ctrl-U, Delete) into one Spinel-safe widget used by search, rename, graduate, and delete prompts, with emergency terminal restore on crash.
Short asciinema captures of the InputField editor (cursor motion, insert-in-middle, Ctrl-U) on both ruby try.rb and dist/try.
@tobi

tobi commented Aug 13, 2026

Copy link
Copy Markdown
OwnerAuthor

TUI demos

Same key story on MRI and the Spinel native binary: type spin, Left into the word, insert xsxpin, Ctrl-A/E, Backspace, Ctrl-U, filter tui, open rename, Esc.

MRI (ruby try.rb)

try MRI

Native / Spinel (dist/try)

try native

Playable asciinema (unclaimed uploads expire in 7 days):

.cast files are in demo/ (asciinema play demo/try-mri.cast).

@tobi

tobi commented Aug 13, 2026

Copy link
Copy Markdown
OwnerAuthor

Benchmark (hyperfine, MRI vs native)

Measured 2026-08-13 16:04 EDT on this box. hyperfine 1.19.0, --shell=none -w 3 -r 20 (native is <5 ms; a shell would swamp it). Ruby 3.3.8, Spinel 79b1aba8bdef (PR 3906). Native at measurement was the unstripped ~1.0 MiB binary; current dist/try after -Os+strip is 705 KB.

Speedup is MRI mean / native mean. Native won every case.

| Case | MRI mean ± σ | native mean ± σ | Speedup |
|------|----------------|-------------------|
| --help | 69.4 ± 4.8 ms | 0.956 ± 0.096 ms | 72.6× |
| --version | 70.8 ± 6.3 ms | 0.959 ± 0.125 ms | 73.8× |
| no args (exit 2) | 68.7 ± 4.3 ms | 0.982 ± 0.068 ms | 69.9× |
| init | 96.5 ± 9.4 ms | 21.2 ± 1.3 ms | 4.5× |
| TUI empty + --and-exit | 74.0 ± 8.4 ms | 1.28 ± 0.14 ms | 57.8× |
| TUI 5 dirs | 72.0 ± 6.0 ms | 1.38 ± 0.08 ms | 52.1× |
| TUI filter --and-keys=beta | 72.4 ± 5.9 ms | 2.70 ± 0.35 ms | 26.8× |
| TUI exec beta | 74.6 ± 8.1 ms | 1.49 ± 0.16 ms | 50.2× |
| clone script only | 70.3 ± 6.2 ms | 0.959 ± 0.103 ms | 73.3× |
| worktree script only | 72.9 ± 8.6 ms | 1.01 ± 0.09 ms | 71.9× |
| TUI scan 1000 dirs | 80.3 ± 7.3 ms | 8.57 ± 0.69 ms | 9.4× |
| TUI filter 1000 dirs | 93.9 ± 5.5 ms | 40.9 ± 4.8 ms | 2.3× |

init is the outlier because native still forks ps to detect fish vs bash (~20 ms). The 1000-entry filter is whole-process (scan + four keystrokes + re-renders), not an isolated matcher microbench.

@tobi

tobi commented Aug 13, 2026

Copy link
Copy Markdown
OwnerAuthor

Moved off the Spinel stack. The TUI InputField work now lives on main as #135 (no TryCompat, 399/399 MRI).

This stacked PR mixed Spinel + TUI + native demos; closing so #130#131#133 stays Spinel-only.

@tobitobi closed this Aug 13, 2026
Sign up for freeto 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

@tobi