res-sheets: embed core/lib/edit for formula editing (scroll, undo, syntax highlight) #16

Open
opened 2026-07-27 19:43:41 +00:00 by agent · 0 comments
Member

Problem

The formula entry bar in res-sheets renders the full buffer with no horizontal scrolling. When a cell contains a long formula (e.g. the prime-factorization lambda in extra/test-eval.txt), the text overflows the terminal width — the cursor becomes invisible and the formula is unreadable.

Additionally, the edit mode has no undo/redo, no copy/paste within the buffer, and no syntax highlighting. The hand-rolled key handling duplicates logic that core/lib/edit already solves.

Current behavior (extra/lib/sheets/tui/view.go:142-154): renderEditBuffer() concatenates before + cursor + after with no viewport clamping.

Solution

Embed core/lib/edit.Editor into the res-sheets TUI for formula editing, following the pattern established by res-code (extra/internal/code/).

core/lib/edit.Editor is a tea.Model that already handles horizontal/vertical scrolling, cursor visibility, undo/redo, and syntax highlighting. The res-code embedding recipe demonstrates: hide status bar, size each frame, forward key events, render via View().

Phased approach

Phase 1 — Quick win: horizontal scroll for existing entry bar

Add a scroll offset to renderEditBuffer() so the cursor stays visible. Minimal change, immediate fix.

  • Add editScroll int field to Model
  • Slice editBuf[editScroll:] in renderEditBuffer() and clamp to terminal width
  • Adjust editScroll in updateEdit() when cursor moves
  • Reset on enterEdit()

Phase 2 — Full editor embedding

Replace editBuf/editPos with an embedded *edit.Editor:

  • enterEdit(): create editor, SetContent(raw), hide status bar
  • updateEdit(): forward keys via e.Update(msg), commit on Enter, cancel on Esc
  • renderEditBuffer(): e.SetSize(width, 1); return e.View()
  • Import core/lib/edit (already used by extra/ via res-code)

Gives: horizontal scrolling, undo/redo (Ctrl+Z/Ctrl+Y), syntax highlighting, cursor visibility.

Files to modify

File Phase Change
extra/lib/sheets/tui/model.go 1, 2 Add editScroll (phase 1); replace editBuf/editPos with formulaEditor *edit.Editor (phase 2)
extra/lib/sheets/tui/view.go 1, 2 Fix renderEditBuffer() with scroll offset (phase 1); delegate to formulaEditor.View() (phase 2)
extra/lib/sheets/tui/model_test.go 2 Update tests referencing editBuf/editPos

Verification

  1. Open test-eval.sheet.csv, navigate to B1, press Enter. Cursor should scroll horizontally and stay visible.
  2. Ctrl+Z/Ctrl+Y undo/redo within formula edit (phase 2).
  3. go test ./... in extra/ — no regressions.

Design reference

  • core/lib/edit/ — the editor library (SetContent, Content, SetSize, Update, View)
  • extra/internal/code/tabs.go — Tab wrapping pattern
  • extra/internal/code/render.go:55-63 — editor sizing and rendering
  • extra/internal/code/keys.go:129-139 — key forwarding with type assertion
  • extra/test-eval.txt — the formula that exposed the scrolling bug
  • Forgejo issue #14 — formula engine gap (LET/LAMBDA/etc.)
## Problem The formula entry bar in res-sheets renders the full buffer with no horizontal scrolling. When a cell contains a long formula (e.g. the prime-factorization lambda in `extra/test-eval.txt`), the text overflows the terminal width — the cursor becomes invisible and the formula is unreadable. Additionally, the edit mode has no undo/redo, no copy/paste within the buffer, and no syntax highlighting. The hand-rolled key handling duplicates logic that `core/lib/edit` already solves. **Current behavior** (`extra/lib/sheets/tui/view.go:142-154`): `renderEditBuffer()` concatenates `before + cursor + after` with no viewport clamping. ## Solution Embed `core/lib/edit.Editor` into the res-sheets TUI for formula editing, following the pattern established by `res-code` (`extra/internal/code/`). `core/lib/edit.Editor` is a `tea.Model` that already handles horizontal/vertical scrolling, cursor visibility, undo/redo, and syntax highlighting. The `res-code` embedding recipe demonstrates: hide status bar, size each frame, forward key events, render via `View()`. ## Phased approach ### Phase 1 — Quick win: horizontal scroll for existing entry bar Add a scroll offset to `renderEditBuffer()` so the cursor stays visible. Minimal change, immediate fix. - Add `editScroll int` field to `Model` - Slice `editBuf[editScroll:]` in `renderEditBuffer()` and clamp to terminal width - Adjust `editScroll` in `updateEdit()` when cursor moves - Reset on `enterEdit()` ### Phase 2 — Full editor embedding Replace `editBuf`/`editPos` with an embedded `*edit.Editor`: - `enterEdit()`: create editor, `SetContent(raw)`, hide status bar - `updateEdit()`: forward keys via `e.Update(msg)`, commit on Enter, cancel on Esc - `renderEditBuffer()`: `e.SetSize(width, 1); return e.View()` - Import `core/lib/edit` (already used by `extra/` via `res-code`) Gives: horizontal scrolling, undo/redo (`Ctrl+Z`/`Ctrl+Y`), syntax highlighting, cursor visibility. ## Files to modify | File | Phase | Change | |------|-------|--------| | `extra/lib/sheets/tui/model.go` | 1, 2 | Add `editScroll` (phase 1); replace `editBuf`/`editPos` with `formulaEditor *edit.Editor` (phase 2) | | `extra/lib/sheets/tui/view.go` | 1, 2 | Fix `renderEditBuffer()` with scroll offset (phase 1); delegate to `formulaEditor.View()` (phase 2) | | `extra/lib/sheets/tui/model_test.go` | 2 | Update tests referencing `editBuf`/`editPos` | ## Verification 1. Open `test-eval.sheet.csv`, navigate to B1, press Enter. Cursor should scroll horizontally and stay visible. 2. `Ctrl+Z`/`Ctrl+Y` undo/redo within formula edit (phase 2). 3. `go test ./...` in `extra/` — no regressions. ## Design reference - `core/lib/edit/` — the editor library (SetContent, Content, SetSize, Update, View) - `extra/internal/code/tabs.go` — Tab wrapping pattern - `extra/internal/code/render.go:55-63` — editor sizing and rendering - `extra/internal/code/keys.go:129-139` — key forwarding with type assertion ## Related - `extra/test-eval.txt` — the formula that exposed the scrolling bug - Forgejo issue #14 — formula engine gap (LET/LAMBDA/etc.)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
residual/.agent#16
No description provided.