Skip to content

Commit a2fa441

Browse files
engalarako
authored andcommitted
feat(tui): lazygit-style UI with compare view, search, and BSON/MDL integration
Major TUI overhaul replacing the command bar with lazygit-style direct shortcuts and adding side-by-side compare view for BSON/MDL debugging. New components: - ScrollList: unified scrollable list with smooth scrolling, visual scrollbar, mouse support, and fzf-style fuzzy filter - Breadcrumb: navigation path display with click-to-navigate - ContentView: vim-style content viewer with line numbers, scrollbar, search (/n/N), and mouse scroll - CompareView: side-by-side panes (NDSL|NDSL, NDSL|MDL, MDL|MDL) with fuzzy object picker, sync scroll, and mode switching - Overlay: fullscreen modal reusing ContentView - Highlight: chroma-based syntax highlighting for MDL/SQL/NDSL Key interactions: - b: BSON dump, m: MDL describe, c: compare view, z: zen mode - /: search in content views with live matching and n/N navigation - Tab: switch panels/panes, Enter: drill in or open detail - Progressive 2-panel expansion, mouse click and scroll everywhere - Filter mode passes all keys to input (no shortcut conflicts)
1 parent e02c73c commit a2fa441

19 files changed

Lines changed: 3008 additions & 626 deletions
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
# TUI Enhancement Design
2+
3+
**Date**: 2026-03-22
4+
**Status**: Draft
5+
6+
## Context
7+
8+
The current TUI (`mxcli tui`) uses bubbles `list.Model` for panels with page-based scrolling, fixed 3-panel layout, no mouse support, no syntax highlighting, and no BSON/NDSL integration. This design overhauls the TUI for a more fluid, interactive experience.
9+
10+
## Requirements
11+
12+
1. **Unified ScrollList** — Replace `list.Model` with custom component using picker-style smooth scrolling + visual scrollbar
13+
2. **Breadcrumb navigation** — Top of each panel shows navigation path, clickable
14+
3. **Z mode** — Press `z` to zoom current panel to fullscreen
15+
4. **Progressive expansion** — Start with 1 panel, expand as user drills in
16+
5. **Panel 3 summary mode** — Show metadata summary, Enter opens fullscreen overlay
17+
6. **Mouse support** — Click selection, scroll wheel, breadcrumb click
18+
7. **MDL/SQL/NDSL syntax highlighting** — Using alecthomas/chroma
19+
8. **BSON/NDSL commands** — Cmdbar verbs with multi-level completion
20+
21+
## Architecture
22+
23+
### New Files
24+
25+
| File | Lines | Responsibility |
26+
|------|-------|----------------|
27+
| `tui/panels/scrolllist.go` | ~350 | Reusable scrollable list: cursor, scrollOffset, scrollbar, filter, mouse |
28+
| `tui/panels/breadcrumb.go` | ~80 | Breadcrumb path display and click-to-navigate |
29+
| `tui/highlight.go` | ~120 | Chroma-based syntax highlighting (MDL/SQL/NDSL) |
30+
| `tui/overlay.go` | ~150 | Fullscreen overlay with scrollable viewport |
31+
32+
### Modified Files
33+
34+
| File | Changes |
35+
|------|---------|
36+
| `tui/panels/modules.go` | Replace `list.Model``ScrollList`, add breadcrumb + nav stack |
37+
| `tui/panels/elements.go` | Same refactor as modules |
38+
| `tui/layout.go` | Dynamic panel widths, `PanelRect` geometry for mouse hit testing |
39+
| `tui/model.go` | Visibility state, zen mode, mouse routing, overlay integration, BSON dispatch |
40+
| `tui/styles.go` | Remove duplicate `typeIconMap`, add scrollbar/overlay styles |
41+
| `tui/cmdbar.go` | Multi-level completion tree, qualified name completion |
42+
43+
### New Dependency
44+
45+
- `github.com/alecthomas/chroma/v2`
46+
47+
## Phase 1: ScrollList + Breadcrumb (Foundation)
48+
49+
### ScrollList (`tui/panels/scrolllist.go`)
50+
51+
```go
52+
type ScrollListItem interface {
53+
Label() string
54+
Icon() string
55+
Description() string
56+
FilterValue() string
57+
}
58+
59+
type ScrollList struct {
60+
items []ScrollListItem
61+
filteredItems []int // indices into items (nil = no filter)
62+
cursor int
63+
scrollOffset int
64+
filterInput textinput.Model
65+
filterActive bool
66+
width, height int
67+
focused bool
68+
headerHeight int // reserved for breadcrumb
69+
}
70+
```
71+
72+
**Scrolling**: `scrollOffset + maxVisible` window. Cursor moves smoothly, scrollOffset follows.
73+
74+
**Scrollbar**: Right-side vertical track (``) with thumb (``). Position = `scrollOffset / (total - maxVisible) * trackHeight`.
75+
76+
**Mouse**: `MouseWheelUp/Down` adjusts scrollOffset. `MouseActionPress` computes `clickedIndex = scrollOffset + (Y - topOffset)`.
77+
78+
**Filter**: `/` activates textinput, real-time substring filter on `FilterValue()`. Esc exits.
79+
80+
### Breadcrumb (`tui/panels/breadcrumb.go`)
81+
82+
```go
83+
type BreadcrumbSegment struct {
84+
Label string
85+
}
86+
87+
type Breadcrumb struct {
88+
segments []BreadcrumbSegment
89+
width int
90+
}
91+
```
92+
93+
Methods: `Push()`, `PopTo(level)`, `Depth()`, `View()` (renders `A > B > C`), `ClickedSegment(x int) int`.
94+
95+
### Panel Refactor
96+
97+
Each panel (modules, elements) maintains:
98+
- `ScrollList` instead of `list.Model`
99+
- `Breadcrumb` for navigation path
100+
- `navigationStack [][]*TreeNode` for drill-in/back
101+
102+
## Phase 2: Progressive Expansion + Z Mode
103+
104+
### Dynamic Layout (`tui/layout.go`)
105+
106+
```go
107+
type PanelVisibility int
108+
const (
109+
ShowOnePanel PanelVisibility = iota // modules only, 100%
110+
ShowTwoPanels // modules 35% + elements 65%
111+
ShowThreePanels // 20% + 30% + 50%
112+
ShowZoomed // zoomed panel 100%
113+
)
114+
115+
type PanelRect struct {
116+
X, Y, Width, Height int
117+
Visible bool
118+
}
119+
```
120+
121+
### Visibility State Machine
122+
123+
- Start: `ShowOnePanel`
124+
- Select module + right/enter → `ShowTwoPanels`
125+
- Select element → `ShowThreePanels`
126+
- Left from elements (empty stack) → `ShowOnePanel`
127+
- Left from preview → `ShowTwoPanels`
128+
129+
### Z Mode
130+
131+
- `z` toggles between `ShowZoomed` and previous visibility
132+
- Remembers `zenPrevFocus` and `zenPrevVisibility` for restore
133+
- `Esc` also exits zen mode
134+
135+
## Phase 3: Mouse Support
136+
137+
Root model translates `tea.MouseMsg` coordinates using `PanelRect`:
138+
139+
```go
140+
case tea.MouseMsg:
141+
for i, rect := range m.panelLayout {
142+
if rect.contains(msg.X, msg.Y) {
143+
localMsg := translateMouse(msg, rect)
144+
m.focus = Focus(i)
145+
// forward to panel
146+
}
147+
}
148+
```
149+
150+
ScrollList handles translated coordinates internally. Breadcrumb click detected by checking `localMsg.Y < headerHeight`.
151+
152+
## Phase 4: Summary + Overlay + Highlighting
153+
154+
### Preview Summary Mode
155+
156+
Panel 3 shows compact metadata card:
157+
```
158+
Type: Entity
159+
Module: MyModule
160+
Name: Customer
161+
Attrs: 5 Assocs: 2
162+
[Enter] view details
163+
```
164+
165+
`SetContent()` stores both `summaryContent` (panel) and `fullContent` (overlay).
166+
167+
### Fullscreen Overlay (`tui/overlay.go`)
168+
169+
- Reuses `viewport.Model` for scrollable content
170+
- `lipgloss.Place` for centering
171+
- Title bar + content + bottom hints
172+
- Serves: detail view, BSON dump, NDSL output
173+
174+
### Syntax Highlighting (`tui/highlight.go`)
175+
176+
- `alecthomas/chroma/v2` with `terminal256` formatter + `monokai` style
177+
- SQL lexer as MDL base
178+
- Custom NDSL lexer (regex: field paths, type annotations, values)
179+
- Functions: `HighlightMDL()`, `HighlightSQL()`, `HighlightNDSL()`, `DetectAndHighlight()`
180+
181+
## Phase 5: BSON/NDSL Commands
182+
183+
### Multi-level Cmdbar
184+
185+
```go
186+
type cmdDef struct {
187+
name string
188+
children []cmdDef
189+
}
190+
```
191+
192+
Commands: `bson dump <name>`, `bson compare <name>`, `ndsl <name>`
193+
194+
Completion levels:
195+
1. Command name (bson, ndsl, callers, ...)
196+
2. Subcommand (dump, compare)
197+
3. Qualified name (from flattened tree nodes)
198+
199+
Results → `HighlightNDSL()``OpenOverlayMsg` → fullscreen overlay
200+
201+
## Phase Dependency
202+
203+
```
204+
Phase 1 (ScrollList + Breadcrumb)
205+
├──→ Phase 2 (Layout + Z Mode)
206+
│ └──→ Phase 3 (Mouse)
207+
└──→ Phase 4 (Summary + Overlay + Highlighting)
208+
└──→ Phase 5 (BSON/NDSL Commands)
209+
```
210+
211+
Phases 2 and 4 can proceed in parallel after Phase 1.
212+
213+
## Verification
214+
215+
After each phase:
216+
1. `make build` — compiles cleanly
217+
2. `./bin/mxcli tui -p /mnt/data_sdd/gh/mxproj-GenAIDemo/App.mpr` — manual testing
218+
3. Verify scrolling, mouse, breadcrumb, overlay, highlighting visually
219+
4. Run `make test` for any unit tests added

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ require (
2424
)
2525

2626
require (
27+
github.com/alecthomas/chroma/v2 v2.23.1 // indirect
2728
github.com/atotto/clipboard v0.1.4 // indirect
2829
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
2930
github.com/charmbracelet/colorprofile v0.4.1 // indirect
@@ -33,6 +34,7 @@ require (
3334
github.com/clipperhouse/displaywidth v0.9.0 // indirect
3435
github.com/clipperhouse/stringish v0.1.1 // indirect
3536
github.com/clipperhouse/uax29/v2 v2.5.0 // indirect
37+
github.com/dlclark/regexp2 v1.11.5 // indirect
3638
github.com/dustin/go-humanize v1.0.1 // indirect
3739
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
3840
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 h1:nCYfg
1010
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0/go.mod h1:ucUjca2JtSZboY8IoUqyQyuuXvwbMBVwFOm0vdQPNhA=
1111
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs=
1212
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk=
13+
github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY=
14+
github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o=
1315
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
1416
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
1517
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
@@ -53,6 +55,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
5355
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5456
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
5557
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
58+
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
59+
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
5660
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
5761
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
5862
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=

0 commit comments

Comments
 (0)