# Handoff — 2026-08-31 — snippets, and submenus in the menu bar ## State **Ticket 0006 is done and green**, on branch `feature/snippets`, **uncommitted**. `Alt-N` opens a **Snippets** menu built from `.turbo-go/snippets.toml` and the user's own file, grouped into submenus and filtered by the language of the front window. Choosing one inserts it at the cursor, re-indented to the line it landed on, as one undo step. **Snippets ▸ Create snippets file** writes a commented starter file and opens it. ``` File Edit Search Run Options Window Snippets Help ┌───────────────┐┌──────────────────────┐ │ if err != nil ││ Go ▶ │ │ table test ││ General ▶ │ └───────────────┘├──────────────────────┤ │ Create snippets file │ └──────────────────────┘ ``` - `ui` gained **one level of submenus** (`MenuItem.Items`) and `Menu.OnOpen`. `menu.go` was split four ways: `menu.go` (types and state), `menu_draw.go`, `menu_events.go`, `submenu.go`. - New `internal/snippets` (83.8 %), `editor.InsertSnippet` (editor 96.2 %), `internal/app/snippets.go`. - Whole suite green under `-race`. Quality gate **PASS**: 0/0/0, complexity 1480. - Docs complete in EN and FR — three new pages each, five existing pages updated each. `docs/diagrams/packages.drawio` gained `snippets` and three edges, re-checked against `go list` (34 edges each side). - **Verified in a real terminal** through the project's own VT emulator: the menu, the submenu (which flipped left for want of room), the file creation, and a four-line snippet inserted with correct indentation. Earlier the same day, PR #5 merged the Markdown/JavaScript/HTML/shell colouring. ## In flight Nothing. Finished through Phase 8. ## Next steps 1. **Commit and open the PR.** `feature/snippets` is the branch. 2. **Try it with thirty snippets.** The submenu geometry was verified with two groups of two. A group with twenty items is taller than the terminal, and nothing scrolls a menu panel — see the blockers below. 3. **Tickets.** 0002, 0003, 0006, 0007, 0009, 0013 and 0014 are all implemented and all still `state: open`. ## Open questions / blockers - **A menu panel does not scroll.** `dropdownBounds` and `submenuBounds` are `len(items)+2` tall with no cap, so a group of thirty snippets draws a panel taller than the terminal and the bottom is simply clipped by the painter. This existed before — the Window menu has never been long enough to hit it — and snippets are the first thing that can. It wants either a scrolling panel or a "…" overflow item, and it is a `ui` feature to decide on rather than something to slip in. - **Placeholders and tab stops are absent** (`${1:name}`, moving between them). Deliberate: a second feature with state to maintain across edits. The `body` is inserted verbatim apart from indentation. - **Nothing rebuilds the menu bar itself.** `OnOpen` refills a menu's items, but the *set of menus* is fixed at start-up. That is fine today; a feature wanting to add or remove a whole menu at runtime would need more. ## Watch out for - **Two menus sharing a hot key silently make one unreachable.** `handleClosedKey` returns on the first match, so `~S~nippets` beside `~S~earch` meant `Alt-S` never reached Snippets — and every test passed. It was found by driving the real binary. `TestNoTwoMenusShareAHotKey` covers it now; keep it, and check it when adding a menu. - **Flipping a submenu left does not fit a panel wider than the terminal.** The width is capped to the screen as well, and long labels are clipped by the painter. `TestASubmenuFlipsLeftWhenThereIsNoRoomOnTheRight` failed exactly on this before the cap. - **`MenuItem.enabled()` must treat a submenu as choosable.** It used to return false for an item with no `Action`, which made every branch disabled and every submenu unreachable. `TestAnItemWithNoActionButASubmenuCanStillBeChosen` pins it. - **`SetText` marks a buffer modified**, so `Modified()` cannot show that an editor operation did nothing. Use `Revision()` — `TestInsertingAnEmptySnippetChangesNothing` was wrong until it did. - **The snippets tests must set `TURBO_GO_SNIPPET_DIR`.** Without it they read the snippets of whoever is running them, and pass or fail by accident. Every test in `internal/snippets` and `internal/app` that touches snippets sets it to an empty temp directory. - **The template's bodies contain the two characters `\` and `t`, not a tab.** TOML interprets the escape on read. `TestTheCreatedFilesTabsSurviveTOML` checks the tab comes back out; a "helpful" replacement with a real tab would leave the template at the mercy of whatever a reader's editor does with tabs.