architecture.md lists the new packages, each host and its size, and what stays in package ui and why; extending.md's pattern 2 says how a component gets its host and when it moves out, and the gap narrows to the overlays that still keep the model.
- commit
- fd19d9117fd0553d288da4850531d2b4d2387da6
- parent
- b4931c8dae918e1d4991a2f8ebc12e8c643ddc67
- author
- Dami <dami.etoile@gmail.com>
| M | docs/ | 71 | +++++++++++++++++++++++------- |
| M | docs/ | 22 | ++++++++- |
| M | internal/ | 8 | ++-- |
@@ -22,6 +22,14 @@ internal/ui the Bubble Tea model: modes, menus, overlays, rendering
2222 theme style roles, color schemes and the widgets drawn with them (frames, key chips)2323 rowtext laying out a row of cell text across the columns on screen2424 formula reading the formula being typed (F4, the word and call at the caret)25+ overlay the contract of what takes over input: Overlay, boxes, mouse events, lists26+ lineedit the one-line editor every text field shares27+ picker the searchable list behind the palette and every picker28+ cmdline the : command line and its completions29+ findbar find and replace, a bar on the context line30+ themepicker File > Settings > Theme, previewing as it moves31+ tabstrip the sheet tabs' layout and where each sheet was left32+ transfer imports running in the background and their progress2533 e2e/ end-to-end tests through libghostty (separate module, cgo)2634 oracle/ differential tests against excelize's calculation (separate module)2735 ```@@ -168,23 +176,50 @@ draw. The components:
168176 | Component | Type | Owns |169177 |---|---|---|170178 | grid (embedded) | `grid` | the sheet shown, active cell, scroll, window size, selection; mapping rows and columns to the screen, frozen panes, moving and selecting (`grid.go`, `panes.go`, `selection.go`) |171-| edit line | `lineEdit` | the one-line editor shared by cell entries, prompts and search fields (`line.go`) |179+| edit line | `lineedit.Line` | the one-line editor shared by cell entries, prompts and search fields (package `lineedit`) |172180 | cell entry | `entry`, `assist` | typing into a cell, pointing at references, other sheets while pointing, formula suggestions and signatures (`entry.go`, `assist.go`) |173181 | prompt | `prompt` | a question on the context line, typed or pointed at (`prompt.go`) |174-| overlays | `overlay` | whatever has taken over input: menus (`menuoverlay.go`), the palette and pickers (`palette.go`, `names.go`), the filter picker, the find, sort and choice bars, the chart editor and selection, the pivot editor (`pivoteditor.go`, `pivotactions.go`), the shortcuts |175-| sheet tabs | `tabStrip` | where each sheet was left, the tab strip's scroll, layout and clicks (`tabstrip.go`) |182+| overlays | `overlay.Overlay` | whatever has taken over input: menus (`menuoverlay.go`), the palette and pickers (package `picker`, with `palette.go`, `names.go`), the command line (package `cmdline`), the theme picker (package `themepicker`), the find bar (package `findbar`), the filter picker, the sort and choice bars, the chart editor and selection, the pivot editor (`pivoteditor.go`, `pivotactions.go`), the shortcuts |183+| sheet tabs | `tabstrip.Strip` | where each sheet was left, the tab strip's scroll and layout (package `tabstrip`); what clicks on it do (`tabstrip.go`) |176184 | mouse | `mouseState` | drags, hover, double clicks, the fill handle (`mouse.go`, `fill.go`) |177-| import | `transfer` | the import in progress, its progress display and cancelling (`transfer.go`) |185+| import | `transfer.Transfer` | the import in progress, its progress display and cancelling (package `transfer`); choosing and placing imports (`transfer.go`, `importplace.go`) |178186 | macros | `recorder`, `macroState` | a recording in progress (`macrorec.go`); a macro running, trust in the file's macros (`macrorun.go`); what scripts act on (`macrohost.go`, `macrohostnav.go`); Data > Macros and the manager (`macro.go`, `macromanage.go`) |179187 | others | `clipboard`, `trace`, `chartState`, `jevRunner`, `terminal` | what Ctrl+V pastes, a trace being shown, chart commands' target, JEV questions in flight, what the terminal supports and the chart images sent to it |180188 181-Overlays implement the `overlay` interface (`overlay.go`): an indicator182-for the mode, `key` and `mouse` handlers, a `layout` of boxes to draw, and183-the status line while open; bars on the context line add a184-`contextLine`, and those with a text field a `cursor`. Like `assist` and185-`prompt`, they are handed the model when they handle input, since acting186-on it is their job. A new overlay is a new type; `Model` needs no new187-fields, only a way to open it (usually a command).189+Overlays implement `overlay.Overlay` (package `overlay`): an indicator for190+the mode, `Key` and `Mouse` handlers, a `Layout` of boxes to draw, and191+the status line while open; bars on the context line add `ContextLine`192+(`overlay.Liner`), and those with a text field `Cursor` and `Changed`193+(`overlay.Text`). The model routes to them without handing itself over:194+each overlay is built with the host it acts on and keeps it. A new195+overlay is a new type; `Model` needs no new fields, only a way to open it196+(usually a command).197+198+**Hosts.** A component names what it needs of the model in a small199+interface, its host, and is tested against a fake of it. Components in200+packages of their own declare an exported `Host`, which the model201+implements through `host` (`hosts.go`), an adapter that keeps those202+methods off `ui.Model`'s exported API:203+204+| Package | Host | Methods |205+|---|---|---|206+| `picker` | `picker.Host` | theme, size, the edit line, close, record the answer to a command's question (5) |207+| `cmdline` | `cmdline.Host` | theme, size, the edit line, close, the commands to complete, run a line, fail (7) |208+| `themepicker` | `themepicker.Host` | a picker's host, and the current theme, the themes directory, preview, keep (9) |209+| `findbar` | `findbar.Host` | theme, size, the edit line, the workbook, the sheet and cell shown, show a cell, note, mark modified, leave keeping the search, pass a click to the grid (10) |210+| `tabstrip`, `transfer` | none | they're handed a view or messages and draw what they're given |211+212+Components that stay in package `ui` declare an unexported host the model213+implements itself: `menuHost` for menus (9 methods; their items are the214+command registry and the menu bar's definitions), `macrosHost` for the215+macro manager (9; it's a few keys over a picker, and what they do is the216+macro machinery), and `pivotHost` for the pivot editor and its field217+picker (14; it opens the model's pickers, filter values and range prompt218+and comes back from them). The rest (the filter picker, the sort and219+choice bars, the chart editor and selection, the shortcuts, the named220+ranges picker) still keep the model itself. Commands still run in one221+place: a host's way to run one (`runFromOverlay`, `cmdline.Host.Run`)222+goes through `runCommand`, so macros record them and pivots guard them.188223 189224 **Drawing.** `View` (`panel.go`) stacks the control panel, the header,190225 the grid rows and the status line, then composites the floating layers@@ -196,11 +231,15 @@ of roles with dark and light variants on the terminal's 16 ANSI colors,
196231 so the user's palette applies; its widgets (framed boxes, key chips, key197232 hints) are what every overlay is drawn with.198233 199-**Packages.** `theme`, `rowtext` and `formula` depend on nothing in200-`ui`, so they can be tested and measured alone. The components stay in201-package `ui` because they act on the model; moving them out would mean202-exporting most of it. New leaf packages are split off the same way when203-a part needs only the sheet or the theme.234+**Packages.** `theme`, `rowtext`, `formula`, `overlay` and `lineedit`235+depend on nothing in `ui`, so they can be tested and measured alone. The236+components in `picker`, `cmdline`, `themepicker`, `findbar`, `tabstrip`237+and `transfer` build on them and reach the model only through their238+hosts, with unit tests of their own. A component moves out of package239+`ui` when its host stays small (about ten methods or fewer); one that240+needs more keeps a narrow interface inside `ui` instead, since moving it241+would mean exporting half of the model. New leaf packages are split off242+the same way when a part needs only the sheet or the theme.204243 205244 ## Files206245 @@ -34,10 +34,23 @@ be kept in sync by hand, turn it into a registry.
3434 UI features that take over input (menus, palette, find bar, pickers, chart3535 editor, sheet tabs, import flow) are components: a type with its own state,3636 key and mouse handling, layout and status line, owned by `Model` and driven37-through the `overlay` interface or its siblings. `Model` routes messages and37+through `overlay.Overlay` or its siblings. `Model` routes messages and3838 composes the screen; it doesn't hold a component's fields. Overlays are3939 composited over the finished grid, so a new one never shifts the layout.4040 41+A component is built with a host: the small interface of what it needs42+of the model (reading the sheet or the selection, running a command,43+opening or closing an overlay, a note, the theme), which the model44+implements, so it can be tested against a fake. When the host stays45+small, about ten methods or fewer, the component lives in a package of46+its own under `internal/ui` (`picker`, `cmdline`, `findbar`,47+`themepicker`), declares `Host`, and the model implements it through the48+`host` adapter in `hosts.go`; parts that need no host at all take plain49+values (`tabstrip`, `transfer`). A component that needs more keeps an50+unexported host inside package `ui` (`menuHost`, `pivotHost`,51+`macrosHost`) rather than exporting half of `Model`. Either way, running a52+command goes through `runCommand` (pattern 3).53+4154 ### 3. Actions go through commands4255 4356 Every user action is a registered command, whatever reaches it (key, menu,@@ -156,8 +169,11 @@ a golden screen reviewed in the gallery for anything visible (see
156169 157170 Where the code doesn't follow the patterns yet:158171 159-- Components in `internal/ui` are handed the whole `*Model` rather than a160- narrower interface, so they stay in package `ui` (pattern 2).172+- Some overlays still keep the whole `*Model` as their host rather than a173+ narrower interface: the filter picker, the sort and choice bars, the174+ chart editor and selection, the shortcuts and the named ranges picker175+ (pattern 2). The cell entry, its suggestions and prompts are handed the176+ model too.161177 - Movement keys, typing, F4 in formulas, Alt+letter menus and direct mouse162178 manipulation act without a registered command (pattern 3). The macro163179 recorder covers what matters for replay without them (entries, the@@ -88,18 +88,18 @@ type Model struct {
8888 8989 // Components. Each owns its state and the handling of the input it9090 // takes; Model routes messages to them and composes what they draw.91- line lineedit.Line // the edit line of entries, prompts and search fields: line.go91+ line lineedit.Line // the edit line of entries, prompts and search fields: package lineedit9292 entry entry // typing into a cell: entry.go9393 point pointer // the cell or range pointed at in POINT mode and range prompts9494 prompt *prompt // a question on the context line: prompt.go9595 overlay overlay.Overlay // the open menu, picker or bar, if any (modeMenu): overlay.go9696 mouse mouseState // drags, hover and double clicks: mouse.go97- tabs tabstrip.Strip // the sheet tabs and where each sheet was left: tabstrip.go98- find *findbar.Bar // the last search, reopened by Ctrl+F: find.go97+ tabs tabstrip.Strip // the sheet tabs and where each sheet was left: package tabstrip98+ find *findbar.Bar // the last search, reopened by Ctrl+F: package findbar9999 charts chartState // chart commands' target: charts.go100100 copied clipboard // what Ctrl+V pastes: clipboard.go101101 trace *trace // precedents or dependents being shown: trace.go102- xfer transfer.Transfer // imports and downloads: transfer.go102+ xfer transfer.Transfer // the import running and the file imported: package transfer103103 jev *jevRunner // answers JEV functions; nil without an API key: jev.go104104 term terminal // what the terminal supports: graphics.go105105 prefs prefs // the settings in effect and the theme chosen: prefs.go