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.

2026-08-31-go-tools.md · 59 lines · 6.6 KBmarkdown Blame HistoryRaw
📦 Turbo Go 3d7798b k33g 11h ago1# Handoff — 2026-08-31 — the Go menu, and a data race it exposed
2
3## State
4
5**Ticket 0017 is partly done and green**, on branch `feature/go-format-lint`, **uncommitted**.
6
7`Alt-G` opens a **Go** menu built from `.turbo-go/tools.toml`. Each entry says where its output goes — `popup` (the default), `terminal`, or `editor` — and files the command rewrote that have no unsaved changes are re-read afterwards. **Go ▸ Create tools file** writes a starter file holding the five Go commands, four `popup` and `Run` `terminal`.
8
9```
10 … Window Snippets Go Help
11 ┌───────────────┐ ┌──────── go vet ./... — exit 1 ────────┐
12 │ Format │ │ main.go:6:2: unreachable code │
13 │ Lint │ │ │
14 │ Build │ │ [ Close ] │
15 │ Test │ └───────────────────────────────────────┘
16 │ Run │
17 ├───────────────┤
18 │ Create tools… │
19 └───────────────┘
20```
21
22- New `internal/tools` (95.0 %, both the file and the running of a command) and `internal/projectfile` (75.0 %).
23- `terminal.Options.Args`, `terminal.ViewOptions`, `View.Exited()`; `Buffer.Reload` with `ErrModified`; `NewOutputDialog`; `App.tick`.
24- Whole suite green under `-race`, five consecutive runs of the two most affected packages. Quality gate **PASS**: 0/0/0, complexity **down** from 1528 to 1513.
25- Docs complete in EN and FR — three new pages each, six existing pages updated each. Diagram re-checked against `go list` (39 edges each side).
26- **Verified in a real terminal**: `go build ./... — ok` with `(no output)`, `go vet ./... — exit 1` with its diagnostic, `gofmt -l -w . — ok` listing the file it rewrote, and the buffer reloading afterwards.
27
28Earlier the same day, PR #6 merged the snippets work.
29
30## In flight
31
32Nothing. Finished through Phase 8.
33
34## Next steps
35
361. **Commit and open the PR.** `feature/go-format-lint` is the branch.
372. **Finish ticket 0017.** It also asked for `go mod init` + `touch main.go` — creating a project from nothing, which is a different shape from running a command in an existing one (it needs a name, and there is no project yet). Not done, and the ticket should stay open for it.
383. **Tickets.** 0002, 0003, 0006, 0007, 0009, 0013, 0014 are implemented and open; 0017 is partly implemented.
39
40## Open questions / blockers
41
42- **A modal popup holds the whole editor while a command runs.** That was chosen knowingly and is documented, with `output = "terminal"` as the way out for any command it annoys you on. If it turns out to annoy generally, a non-modal output window is the alternative — and it is a different feature, not a tweak.
43- **`output = "editor"` shows a popup first, then a window.** The popup is how you watch it and how you stop it; the window arrives when you close the popup. It reads oddly written down and is fine in use, but it is worth a second look with real output.
44
45- **`go mod init` is not in the menu**, and does not fit the current shape: every other tool runs in the project that already exists, whereas this one creates it and needs a module path typed. It wants a prompt dialog and probably its own item rather than a `tools.toml` entry.
46- **Nothing jumps to a compile error.** `go build` prints `internal/app/app.go:42:3: …` in the terminal window and you have to open the file yourself. Parsing that output and jumping would be a real win and is a feature of its own — it needs a per-language error format, and the output lives in a terminal emulator rather than in a captured buffer.
47- **A menu panel still does not scroll** (carried over from the snippets handoff). A `tools.toml` with twenty entries draws a panel taller than the terminal and the bottom is clipped.
48
49## Watch out for
50
51- **Verify a new test by breaking the code it covers.** Two tests in this session passed while proving nothing, both because the test drove the step under test: `waitForLoopTurn` called `reloadAfterTools` itself (so the test passed with that step deleted from the loop — hence `App.tick`), and the process-group test killed the shell before it had forked (so it passed without the fix — it now waits for the child to print). Neither was visible by reading.
52- **Stopping a command must take the process group.** Killing only the shell leaves a grandchild holding the output pipe, and the reading goroutine blocks until *it* ends — 20 seconds in the test suite, and for `go test ./...` it would be every test binary. `processGroup()` and `killGroup()` are build-tagged; `cmd.WaitDelay` is the backstop for anything that escapes.
53
54- **A constructor that starts a goroutine must take its callbacks as parameters.** `terminal.NewView` started the reader and callers assigned `OnChange`/`OnExit` afterwards — a data race present since the terminal feature that `-race` never caught, because a shell takes longer to produce its first output than an assignment takes to run. `sh -c "echo x"` finished immediately and the detector fired at once. `ViewOptions` fixes it structurally; do not add an assignable callback back.
55- **A finished terminal must not swallow keys.** It used to write every key to the dead shell, where the write failed silently and the key was consumed anyway, so `Ctrl-W` could never close the window. `View.HandleKey` returns false after `Exited()`, except for the scrolling keys. `TestAFinishedTerminalStopsTakingKeys` covers it.
56- **`Buffer.Reload` must refuse over unsaved work.** That restriction is the whole safety of it. `TestReloadRefusesToThrowAwayUnsavedWork` pins it, and `TestAToolLeavesAModifiedBufferAlone` pins the app end of it.
57- **`internal/buffer`'s atomic write was deliberately left out of `projectfile`.** It preserves the mode of the file it replaces, because it is saving over something the user already had; `projectfile` creates a file with a fixed `0644`. They look alike and are not the same operation — merging them would mean parameterising the mode and losing the different error text.
58- **`projectfile.Write` already does `MkdirAll`.** The three `Create` functions used to do it themselves; do not add it back.
59- **The app tests for tools drive the event loop by hand.** `Run` is not running, so `waitForLoopTurn` calls `a.reloadAfterTools()` itself. A test that waits for a reload without calling it will hang until its deadline.