v0.11.2 619aabb

view_bench_test.go RawHistoryFolder

1package tui
2
3import (
4	"fmt"
5	"strconv"
6	"strings"
7	"testing"
8
9	"github.com/bnema/zut/packages/provider"
10)
11
12func BenchmarkViewBuildWithAnchorsToolStorm(b *testing.B) {
13	for _, width := range []int{48, 80, 160} {
14		for _, expanded := range []bool{false, true} {
15			for _, temperature := range []string{"cold", "warm"} {
16				name := fmt.Sprintf("width=%d/expanded=%t/%s", width, expanded, temperature)
17				b.Run(name, func(b *testing.B) {
18					base := benchmarkToolStormView(expanded)
19					if temperature == "warm" {
20						base.BuildWithAnchors(width)
21					}
22					b.ReportAllocs()
23					b.ResetTimer()
24					for n := 0; n < b.N; n++ {
25						view := base
26						if temperature == "cold" {
27							view.InvalidateRenderCache()
28						}
29						lines, anchors := view.BuildWithAnchors(width)
30						if len(lines) == 0 || len(anchors) == 0 {
31							b.Fatal("tool storm produced no rows or anchors")
32						}
33					}
34				})
35			}
36		}
37	}
38}
39
40func BenchmarkViewBuildWithAnchorsLiveToolStorm(b *testing.B) {
41	for _, width := range []int{48, 80, 160} {
42		for _, expanded := range []bool{false, true} {
43			name := "width=" + strconv.Itoa(width) + "/expanded=" + strconv.FormatBool(expanded)
44			b.Run(name, func(b *testing.B) {
45				view := &View{
46					Theme:            Dark,
47					ExpandAll:        expanded,
48					Messages:         benchmarkToolStormMessages(24, 8),
49					MessagesRevision: 1,
50					ToolCalls:        benchmarkLiveTools(8, 96),
51				}
52				liveResults := make([]string, len(view.ToolCalls))
53				for i := range liveResults {
54					liveResults[i] = benchmarkResult(96, i)
55				}
56				b.ReportAllocs()
57				b.ResetTimer()
58				for n := 0; n < b.N; n++ {
59					call := &view.ToolCalls[n%len(view.ToolCalls)]
60					call.Revision++
61					call.Result = liveResults[n%len(liveResults)]
62					lines, anchors := view.BuildWithAnchors(width)
63					if len(lines) == 0 || len(anchors) == 0 {
64						b.Fatal("live tool storm produced no rows or anchors")
65					}
66				}
67			})
68		}
69	}
70}
71
72func benchmarkToolStormView(expanded bool) *View {
73	return &View{
74		Theme:            Dark,
75		ExpandAll:        expanded,
76		Messages:         benchmarkToolStormMessages(48, 96),
77		MessagesRevision: 1,
78	}
79}
80
81func benchmarkToolStormMessages(tools, resultLines int) []provider.Message {
82	messages := make([]provider.Message, 0, tools*3)
83	for i := 0; i < tools; i++ {
84		id := fmt.Sprintf("call-%d", i)
85		messages = append(messages,
86			provider.Message{
87				Role: provider.RoleUser,
88				Content: []provider.Content{provider.TextBlock{
89					Text: fmt.Sprintf("inspect result %d", i),
90				}},
91			},
92			provider.Message{
93				Role: provider.RoleAssistant,
94				Content: []provider.Content{provider.ToolCallBlock{
95					ID:        id,
96					Name:      "bash",
97					Arguments: []byte(`{"command":"printf storm"}`),
98				}},
99			},
100			provider.Message{
101				Role: provider.RoleTool,
102				Content: []provider.Content{provider.ToolResultBlock{
103					CallID:  id,
104					Content: []provider.Content{provider.TextBlock{Text: benchmarkResult(resultLines, i)}},
105				}},
106			},
107		)
108	}
109	return messages
110}
111
112func benchmarkLiveTools(tools, resultLines int) []ToolCallView {
113	out := make([]ToolCallView, 0, tools)
114	for i := 0; i < tools; i++ {
115		out = append(out, ToolCallView{
116			ID:       fmt.Sprintf("live-%d", i),
117			Name:     "bash",
118			Revision: 1,
119			Args:     "printf storm",
120			Result:   benchmarkResult(resultLines, i),
121			Done:     true,
122		})
123	}
124	return out
125}
126
127func benchmarkResult(lines, tool int) string {
128	var b strings.Builder
129	for line := 0; line < lines; line++ {
130		fmt.Fprintf(&b, "tool=%d line=%03d output payload for highlighting and wrapping\n", tool, line)
131	}
132	return b.String()
133}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 476

↑↓ moveenter openesc close