zot/internal
patriceckhart cb8526c061 fix(tui): up/down arrows move the cursor through visual rows, not history
Two related changes to how the input handles the arrow keys.

1) History recall is gone.

   The editor used to maintain a 200-entry ring of previously
   submitted prompts and swap the current draft for a history
   entry when up/down hit the top/bottom edge of the buffer.
   In practice this mis-fired more than it helped: pressing up
   on a single-line draft silently replaced it with an older
   prompt. Users expect history recall (when they want it) on
   a dedicated key, not as a side effect of cursor navigation.

   Dropped: Editor.History, histIdx, savedDraft; PushHistory,
   historyPrev, historyNext, findInHistory; every e.histIdx
   assignment sprinkled across the mutating methods; the
   PushHistory call sites in interactive.go (submit handler
   and the slash-selector enter path). Clear() already wiped
   the visible buffer, it now also doesn't touch history
   because there's no history to wipe.

2) Up/Down navigate VISUAL rows, not logical buffer lines.

   The TUI wraps a long single-line input across several
   visual rows. Before this patch, up/down only moved between
   entries in e.Lines, so when the cursor was on the second
   visual row of a wrapped single line, up did nothing
   (CursorR was already 0). Users saw their cursor stuck at
   the bottom of a wrapped draft with no way to move up
   except arrow-left until they wrapped around.

   Added moveCursorVisual(dir int) which rebuilds the same
   wrapped layout Render produces, records which visual row
   the cursor currently occupies, computes the target visual
   row = current + dir, then maps the current visual column
   onto the rune index inside the target row's slice of its
   logical line. Subsumes the multi-line logical-line case:
   if a wrapped row straddles a logical-line boundary, the
   mapping naturally advances CursorR.

   The editor now records the latest width passed to Render so
   moveCursorVisual can walk the same layout. Fallback
   moveCursorLogical covers the edge case where Render hasn't
   run yet (shouldn't happen in practice; kept for safety).

Tests: existing TestEditorCursorAfterMultilinePaste and
TestEditorCursorAfterLongPasteWithWrap still pass because they
test Editor.Insert followed by Render, not up/down traversal;
the new navigation leaves Render's cursor-position math
unchanged.
2026-04-21 09:22:54 +02:00
..
agent fix(tui): up/down arrows move the cursor through visual rows, not history 2026-04-21 09:22:54 +02:00
assets assets: refresh zot logo to cleaner pixel-art Z 2026-04-20 12:01:43 +02:00
auth feat(auth,tui): dark login pages + /logout picker 2026-04-19 20:14:22 +02:00
core feat(session): /session fork + /session tree 2026-04-20 11:10:56 +02:00
extproto feat(ext): phase 4 - full-event interception, arg rewrites, /reload-ext 2026-04-19 17:02:04 +02:00
provider perf(anthropic): fix cost double-count, tighten caching, correct catalog 2026-04-19 18:57:18 +02:00
skills perf(prompt): cut system prompt to the bone (410 -> 54 tokens) 2026-04-19 17:39:38 +02:00
tui fix(tui): up/down arrows move the cursor through visual rows, not history 2026-04-21 09:22:54 +02:00