turbo-editors/turbo-gopublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-go.git
git clone ssh://git@rickub.com/turbo-editors/turbo-go.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

📦 Turbo Go 3d7798b · on main · k33g · 9h ago
2026-08-31-terminal-windows.md · 40 lines · 4.4 KBmarkdown
Blame HistoryOpen raw

Handoff — 2026-08-31 — terminal windows

State

Terminal windows are done and green. F8, or Window ▸ New terminal, opens a window running a real shell in a real pseudo-terminal. Ticket 0007.

  • New package internal/terminal: Session (pty + process), Parser + Screen (VT/ANSI emulation, scrollback, alternate screen), Encode (keys → terminal bytes), View (the ui widget). Coverage 95.7 %.
  • Wired into app via terminals.go; app coverage went from ~71 % to 82.8 %.
  • Two theme keys added, terminal.text and terminal.cursor, set in all three shipped themes. The theme suite fails if a shipped theme misses one, so that is enforced rather than remembered.
  • Whole suite green under -race across eight consecutive full runs.
  • Quality gate PASS: 0 errors, 0 warnings, 0 smells, complexity 1023.
  • Docs complete in EN and FR — three new pages each, six existing pages updated each. docs/diagrams/packages.drawio was regenerated and then checked against go list programmatically: it matches the real import graph edge for edge.
  • Ticket 0015 created for the Windows/ConPTY port.

Nothing has been committed. The working tree carries the whole feature, the docs, the memory update and the new ticket.

In flight

Nothing. The feature is finished through Phase 8 of methodical-dev.

Next steps

  1. Commit. Suggested message and file list are in the session's final summary; git status shows .tickets/, .vscode/ and kits/ as untracked from before this work — decide what belongs in the repository before staging everything.
  2. Try a terminal window on a real terminal. Everything here was verified against a real pty, but nobody has yet opened one inside a running turbo-go on a physical terminal emulator and run vim or htop. That is the check most likely to find something.
  3. Decide about ticket 0007. It is the terminal-window ticket and is still state: open; closing it was left to the user.

Open questions / blockers

  • Should F1F12 be reachable inside a terminal? They are currently reserved by the editor, so htop's function-key menu cannot be used. The reasoning is written up in docs/*/explanation/terminal-windows.md; if the user disagrees, the change is one predicate — editorOwnedKey in internal/app/app.go.
  • internal/terminal/pty_darwin.go has never been run. It compiles and passes go vet, and uses the documented TIOCPTYGRANT / TIOCPTYUNLK / TIOCPTYGNAME ioctls, but this sandbox is Linux. The first Mac run is the test.
  • The tickets' tasks: schema is unknown. Every existing ticket has tasks: [], so 0015's checklist went into the body rather than into an invented task shape. If IssueSpec defines one, move it.

Watch out for

  • A pseudo-terminal echoes the command line. A test that types echo red and waits for red on screen passes before the shell has run anything — it matched the echo. Wait for something only the output can produce: a colour, or a string the typed line spells differently (echo turbo''-go-works produces turbo-go-works). This is the same class of mistake as the gopls-answers-from-disk trap from 2026-08-30.
  • Never assert on a screen cell while a live shell is writing to it. A drawing test doing that passed by luck and was hiding a real fault: the cell it sampled, (0,0), is where the cursor is drawn on a fresh screen, not the text. newOfflineView in view_test.go builds a View with no session behind it — Draw needs none — and is the deterministic way to test drawing.
  • tcell.KeyCtrlC is 67, not 3. tcell reports a control byte as KeyCtrlSpace + b, and KeyCtrlSpace is 64. Code testing key < 0x20 for a control key matches nothing, silently, and every Ctrl-key would send no bytes at all.
  • The routing order in App.keyLayers() is load-bearing. A focused terminal deliberately sits above the global shortcuts. Move it below and Ctrl-W closes the window instead of deleting a word — there is a test for exactly that, TestAFocusedTerminalKeepsTheKeysAShellNeeds.
  • terminal.* theme keys do not fall back to editor.*. Dotted fallback runs along the dots and stops at default. A new theme must set both groups.
  • internal/app/README.md's file table was stale — it listed an actions.go that has not existed for some time. It is corrected now; the lesson is that a table of files rots silently.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# Handoff — 2026-08-31 — terminal windows

## State

**Terminal windows are done and green.** `F8`, or **Window ▸ New terminal**, opens a window running a real shell in a real pseudo-terminal. Ticket 0007.

- New package `internal/terminal`: `Session` (pty + process), `Parser` + `Screen` (VT/ANSI emulation, scrollback, alternate screen), `Encode` (keys → terminal bytes), `View` (the `ui` widget). Coverage 95.7 %.
- Wired into `app` via `terminals.go`; `app` coverage went from ~71 % to 82.8 %.
- Two theme keys added, `terminal.text` and `terminal.cursor`, set in all three shipped themes. The theme suite fails if a shipped theme misses one, so that is enforced rather than remembered.
- Whole suite green under `-race` across eight consecutive full runs.
- Quality gate **PASS**: 0 errors, 0 warnings, 0 smells, complexity 1023.
- Docs complete in EN and FR — three new pages each, six existing pages updated each. `docs/diagrams/packages.drawio` was regenerated and then **checked against `go list` programmatically**: it matches the real import graph edge for edge.
- Ticket `0015` created for the Windows/ConPTY port.

**Nothing has been committed.** The working tree carries the whole feature, the docs, the memory update and the new ticket.

## In flight

Nothing. The feature is finished through Phase 8 of `methodical-dev`.

## Next steps

1. **Commit.** Suggested message and file list are in the session's final summary; `git status` shows `.tickets/`, `.vscode/` and `kits/` as untracked from before this work — decide what belongs in the repository before staging everything.
2. **Try a terminal window on a real terminal.** Everything here was verified against a real pty, but nobody has yet opened one inside a running `turbo-go` on a physical terminal emulator and run `vim` or `htop`. That is the check most likely to find something.
3. **Decide about ticket 0007.** It is the terminal-window ticket and is still `state: open`; closing it was left to the user.

## Open questions / blockers

- **Should `F1``F12` be reachable inside a terminal?** They are currently reserved by the editor, so `htop`'s function-key menu cannot be used. The reasoning is written up in `docs/*/explanation/terminal-windows.md`; if the user disagrees, the change is one predicate — `editorOwnedKey` in `internal/app/app.go`.
- **`internal/terminal/pty_darwin.go` has never been run.** It compiles and passes `go vet`, and uses the documented `TIOCPTYGRANT` / `TIOCPTYUNLK` / `TIOCPTYGNAME` ioctls, but this sandbox is Linux. The first Mac run is the test.
- **The tickets' `tasks:` schema is unknown.** Every existing ticket has `tasks: []`, so `0015`'s checklist went into the `body` rather than into an invented task shape. If IssueSpec defines one, move it.

## Watch out for

- **A pseudo-terminal echoes the command line.** A test that types `echo red` and waits for `red` on screen passes *before* the shell has run anything — it matched the echo. Wait for something only the output can produce: a colour, or a string the typed line spells differently (`echo turbo''-go-works` produces `turbo-go-works`). This is the same class of mistake as the gopls-answers-from-disk trap from 2026-08-30.
- **Never assert on a screen cell while a live shell is writing to it.** A drawing test doing that passed by luck and was hiding a real fault: the cell it sampled, (0,0), is where the *cursor* is drawn on a fresh screen, not the text. `newOfflineView` in `view_test.go` builds a `View` with no session behind it — `Draw` needs none — and is the deterministic way to test drawing.
- **`tcell.KeyCtrlC` is 67, not 3.** tcell reports a control byte as `KeyCtrlSpace + b`, and `KeyCtrlSpace` is 64. Code testing `key < 0x20` for a control key matches nothing, silently, and every Ctrl-key would send no bytes at all.
- **The routing order in `App.keyLayers()` is load-bearing.** A focused terminal deliberately sits *above* the global shortcuts. Move it below and `Ctrl-W` closes the window instead of deleting a word — there is a test for exactly that, `TestAFocusedTerminalKeepsTheKeysAShellNeeds`.
- **`terminal.*` theme keys do not fall back to `editor.*`.** Dotted fallback runs along the dots and stops at `default`. A new theme must set both groups.
- **`internal/app/README.md`'s file table was stale** — it listed an `actions.go` that has not existed for some time. It is corrected now; the lesson is that a table of files rots silently.