chore: backlog tasks from v1.1/v1.2 review (TASK-002 fixed; 003-005 follow-ups)
7ef737941aecd6e0d5a11e912ca996501db479f7
Kevin Kortum <kevinkortum@me.com> · 2026-06-28 11:38
parent 2347d8e8
4 files changed
- → Editor-inserts-double-space-per-spacebar-press.md +25 −0
@@ -0,0 +1,25 @@
+---
+id: TASK-002
+title: Editor inserts double space per spacebar press
+status: "\U0001F3C1 Done"
+assignee: []
+created_date: '2026-06-28 18:21'
+updated_date: '2026-06-28 18:22'
+labels:
+ - bug
+dependencies: []
+priority: high
+ordinal: 2000
+---
+
+## Description
+
+<!-- SECTION:DESCRIPTION:BEGIN -->
+HandleKey case 'tea.KeyRunes, tea.KeySpace' loops over k.Runes inserting each rune, THEN an 'if k.Type == tea.KeySpace { InsertRune(" ") }' inserts another. In real bubbletea (v1.3.6 key.go) a space keypress is Key{Type:KeySpace, Runes:[' ']}, so both fire → two spaces. v1 test TestHandleKeySpaceInsertsSingleSpace missed it by sending KeySpace with empty Runes (unrealistic). Fix: drop the redundant if-block; make the test send Runes:[' '].
+<!-- SECTION:DESCRIPTION:END -->
+
+## Acceptance Criteria
+<!-- AC:BEGIN -->
+- [ ] #1 single space inserted per spacebar press in the real terminal
+- [ ] #2 test sends a realistic KeySpace msg (Runes: [' '])
+<!-- AC:END -->
- → Wrapped-line-vertical-move-can-skip-a-row-at-a-trailing-space-boundary.md +24 −0
@@ -0,0 +1,24 @@
+---
+id: TASK-003
+title: Wrapped-line vertical move can skip a row at a trailing-space boundary
+status: "\U0001F7E6 Backlog"
+assignee: []
+created_date: '2026-06-28 18:38'
+labels:
+ - bug
+dependencies: []
+priority: low
+ordinal: 3000
+---
+
+## Description
+
+<!-- SECTION:DESCRIPTION:BEGIN -->
+MoveUp/MoveDown via applyGoal: when goalCol clamps to min(goalCol, target.runes) and the target is a non-last wrap segment ending in a trailing space (e.g. 'aaaa ' runes=5), landing at col=start+5 == start of the NEXT segment, so cursorVIndex maps to the row after the intended one — arrow visibly skips a row. No buffer/state corruption; logical position is sensible. Fix: clamp non-last segments to runes-1 at a soft-wrap boundary, or special-case the trailing-space column. Add a regression test pinning intended behavior.
+<!-- SECTION:DESCRIPTION:END -->
+
+## Acceptance Criteria
+<!-- AC:BEGIN -->
+- [ ] #1 vertical move lands on the visually-adjacent row at wrap boundaries
+- [ ] #2 regression test added
+<!-- AC:END -->
- → Editor-rebuilds-full-visual-model-twice-per-keystroke-Odocument.md +23 −0
@@ -0,0 +1,23 @@
+---
+id: TASK-004
+title: Editor rebuilds full visual model twice per keystroke (O(document))
+status: "\U0001F7E6 Backlog"
+assignee: []
+created_date: '2026-06-28 18:38'
+labels:
+ - perf
+dependencies: []
+priority: low
+ordinal: 4000
+---
+
+## Description
+
+<!-- SECTION:DESCRIPTION:BEGIN -->
+Every InsertRune→followCursor→buildVisual rescans+rewraps all lines; MoveUp/MoveDown call buildVisual then followCursor calls it again (2 full scans/vertical keystroke). Fine for notes, costly for long docs in the writing canvas. Fix: thread one []vrow through move→followCursorWith(rows); longer term cache the visual model, invalidate on edit/resize.
+<!-- SECTION:DESCRIPTION:END -->
+
+## Acceptance Criteria
+<!-- AC:BEGIN -->
+- [ ] #1 at most one buildVisual per keystroke
+<!-- AC:END -->
- → Canvas-measures-tabs-CJK-emoji-as-rune-count-not-display-cells.md +23 −0
@@ -0,0 +1,23 @@
+---
+id: TASK-005
+title: 'Canvas measures tabs/CJK/emoji as rune count, not display cells'
+status: "\U0001F7E6 Backlog"
+assignee: []
+created_date: '2026-06-28 18:38'
+labels:
+ - bug
+dependencies: []
+priority: low
+ordinal: 5000
+---
+
+## Description
+
+<!-- SECTION:DESCRIPTION:BEGIN -->
+wrapLine and visualColOf measure in runes, not terminal display width. A \t (KeyTab) or wide rune (CJK/emoji) wraps and positions the cursor cell by the wrong column. Pre-existing approach, now load-bearing for the canvas layout. Will surface on tab-indented code blocks or CJK text. Use a display-width (e.g. go-runewidth / uniseg) measure for wrapping + cursor placement.
+<!-- SECTION:DESCRIPTION:END -->
+
+## Acceptance Criteria
+<!-- AC:BEGIN -->
+- [ ] #1 wrapping and cursor placement use display-cell width
+<!-- AC:END -->