Skip to content

Tell every editor which key copies, since y there types a y - #680

Merged
hahwul merged 1 commit into
mainfrom
hahwul/repeater-selection-copy
Aug 13, 2026
Merged

Tell every editor which key copies, since y there types a y#680
hahwul merged 1 commit into
mainfrom
hahwul/repeater-selection-copy

Conversation

@hahwul

@hahwul hahwul commented Aug 13, 2026

Copy link
Copy Markdown
Owner

^Y became Copy in every text box in #677. The footers only half followed: five INS strips named it, five did not.

The Fuzzer template editor was the pure case — it told you a ⇧arrow band could be built and then named no key that copies one. The bare y its READ strip advertises is, in that mode, a literal character that replaces the band you just built. One keystroke, no toast, selection gone. That is the bug report ^Y exists to answer, and the footer is where it lands.

The strips

The axis is a strip describing a mode it is not in.

Surface Before After
Fuzzer template INS type · ⇧arrows select · ^Z undo · … … select · **^Y copy** · ^Z undo · …
Repeater gRPC INS type head/metadata · esc read · ↹ pane … · **⇧arrows select · ^Y copy** · … · ↹ text
Rewriter preview INPUT type sample HTTP · ↑ list · … … · **⇧arrows select · ^Y copy** · …
JWT INPUT INS type a JWT · esc read · … … · **⇧arrows select · ^Y copy** · …
JWT HEADER / PAYLOAD type JSON · … · space cmds · … … · **⇧arrows select · ^Y copy** · …
JWT SECRET type secret · … · space cmds · … … · **^Y copy** · … (no band — single-line field)
Intercept held bytes type to edit · ^R forward · … … · **⇧arrows select · ^Y copy** · …

The Intercept editor named neither token, which is how it kept a registered ^Y that nothing on screen mentioned for its whole life.

On the JWT ENCODE panes and the Rewriter sample there is no READ mode at all, so ^Y is not the convenient copy — it is the only one. Those same strips advertised space cmds, which edit_json/edit_secret insert as a literal space; the menu that never opened was spending the one token with room to say which key copies.

Shown in INS throughout rather than only while a band is live — matching the five strips that already did, and #677's own decision not to gate the key on a selection. ^Y copy sits right after the select token so it survives an 80-column truncation.

What the footers promised, made true

A strip that names a band the copy ignores is worse than one that names nothing.

  • jwt_copy consulted a band on one of its four editors. INPUT-in-INS copied the whole token while jwt_selection_active? reported the band as live — the split RepeaterView#pane_selection? documents in its own comment. HEADER/PAYLOAD were never asked. The four sibling tabs already agreed; JWT was the outlier.
  • jwt_clear_selection cleared the READ model in a mode whose band lives on the editor, so the verb was a no-op exactly where this change makes bands copy-relevant.
  • edit_json was the one printable arm of nine missing report_replaced — typing over a band on the pane this change teaches you to build one on lost text with no toast and no pointer at ^Z.
  • rewriter_copy returned without a status on an empty pane — a dead key on a pane whose ^Y is its only copy.

↹ pane↹ text on three Repeater INSERT arms

editor_captures_tab? is request_text_editing?, which has no gRPC or sub-pane exclusion, so Tab splices a TAB into a header value. The plain-HTTP arm has said ↹ text since it grew its own INSERT branch; gRPC, split-decode and WS shared one string across both modes and kept the READ token.

Also retags ~24 comments and it descriptions still teaching ^Y for the chain editor, which moved to ^Q in #677 — now actively misleading, since ^Y is live.

Guard

spec/tui/editor_footer_copy_key_spec.cr, three source-grep rules:

  1. a strip that advertises a band names a copy key;
  2. a type … strip does not offer space cmds;
  3. every tab whose Copy verb carries ^Y names it in a strip of its own.

Rule 3 is anchored to the keymap rather than a hand-kept list, and is the one that sees a strip saying neither token — the Intercept shape rule 1 is structurally blind to. All three were control-run against the pre-fix strings. Rule 3 passed on its first draft because a controller's own explanatory comment contains the token, so it now reads code lines only.

These are hand-written prose strings with no compiler behind them, and the pair drifted across ten strips.

Verification

  • crystal spec — 8513 examples, 0 failures (the 8 capture_status/project_registry failures on this machine are a gori already holding :8070, identical before and after)
  • crystal build --no-codegen clean; crystal tool format src spec clean; no new ameba findings
  • Live in the TUI under tmux: Rewriter copied 3b on a 3-char band; JWT HEADER copied (6b) on a 6-char band where it would previously have said 15b; Fuzzer/JWT/Rewriter strips read as intended on screen

#677 made `^Y` Copy in every text box. The FOOTERS only half followed: five INS
strips named it, five did not, and the Fuzzer template was the pure case — it told
you a ⇧arrow band could be built and then named no key that copies one, while the
bare `y` the READ strip advertises is, in that mode, a literal character that
REPLACES the band you just built. One keystroke, no toast, selection gone.

The axis is a strip describing a mode it is not in. Six now name `⇧arrows select ·
^Y copy`: Fuzzer template, Repeater gRPC, Rewriter preview INPUT, JWT INPUT-in-INS,
JWT HEADER/PAYLOAD, JWT SECRET (no band — single-line field — but `^Y` still copies
it). The Intercept held-bytes editor named NEITHER token, which is how it kept a
registered `^Y` that nothing on screen mentioned for its whole life.

On the JWT ENCODE panes and the Rewriter sample there is no READ mode at all, so
`^Y` is not the convenient copy — it is the ONLY one. Those same strips advertised
`space cmds`, which `edit_json`/`edit_secret` insert as a literal space; the menu
that never opened was spending the one token with room to say which key copies.

WHAT THE FOOTERS PROMISED, MADE TRUE. `JwtController#jwt_copy` consulted a band on
one of its four editors: INPUT-in-INS copied the whole token while
`jwt_selection_active?` reported the band as live (the split
`RepeaterView#pane_selection?` documents), and HEADER/PAYLOAD were never asked.
`jwt_clear_selection` cleared the READ model in a mode whose band lives on the
editor, so the verb was a no-op exactly there. `edit_json` was the one printable
arm of nine missing `report_replaced`, so typing over a band on the pane this
change teaches you to build one on lost text silently. `rewriter_copy` returned
without a status on an empty pane — a dead key on a pane whose `^Y` is its only copy.

`↹ pane` → `↹ text` on the three Repeater INSERT arms (gRPC, split-decode, WS):
`editor_captures_tab?` is `request_text_editing?`, which has no gRPC or sub-pane
exclusion, so Tab splices a TAB into a header value. The plain-HTTP arm has said
`↹ text` since it grew its own INSERT branch; these three shared one string across
both modes and kept the READ token.

Also retags ~24 comments and `it` descriptions still teaching `^Y` for the chain
editor, which moved to `^Q` in #677 — now actively misleading, since `^Y` is live.

GUARD: `spec/tui/editor_footer_copy_key_spec.cr`, three source-grep rules — a strip
that advertises a band names a copy key; a `type …` strip does not offer `space
cmds`; and every tab whose Copy verb carries `^Y` names it in a strip of its own
(the file-level rule, anchored to the keymap, is the one that sees a strip saying
NEITHER token — the Intercept shape a per-string rule is blind to). All three were
control-run against the pre-fix strings. The third passed on its first draft
because a controller's own explanatory comment contains the token, so it reads code
lines only.
@hahwul
hahwul merged commit 193e585 into main Aug 13, 2026
6 checks passed
@hahwul
hahwul deleted the hahwul/repeater-selection-copy branch August 13, 2026 15:25
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