okami.mom/ultraviolet

git clone https://git.nkp.pet/okami.mom/ultraviolet

Ayman Bagabasfix(examples): remove unused code in splits example0322041

main
5.3 KiB276 linesraw
1package main
2
3import (
4	"fmt"
5	"log"
6	"slices"
7	"strconv"
8	"strings"
9	"time"
10
11	uv "github.com/charmbracelet/ultraviolet"
12	"github.com/charmbracelet/ultraviolet/layout"
13	"github.com/charmbracelet/ultraviolet/screen"
14	"github.com/charmbracelet/x/ansi"
15)
16
17func main() {
18	t := uv.DefaultTerminal()
19	scr := t.Screen()
20	scr.EnterAltScreen()
21
22	if err := t.Start(); err != nil {
23		log.Fatalln("failed to start terminal:", err)
24	}
25
26	defer t.Stop()
27
28	var area uv.Rectangle
29
30	ticker := time.NewTicker(time.Second / 60)
31	defer ticker.Stop()
32
33	for {
34		select {
35		case <-ticker.C:
36			render(scr, area)
37
38			scr.Render()
39			scr.Flush()
40
41		case ev := <-t.Events():
42			switch ev := ev.(type) {
43			case uv.WindowSizeEvent:
44				area = ev.Bounds()
45				scr.Resize(area.Dx(), area.Dy())
46				screen.Clear(scr)
47
48			case uv.KeyPressEvent:
49				switch {
50				case ev.MatchString("ctrl+c", "q"):
51					return
52				}
53			}
54		}
55	}
56}
57
58func render(sc uv.Screen, area uv.Rectangle) {
59	var textArea uv.Rectangle
60
61	layout.Vertical(layout.Len(7), layout.Min(0)).Split(area).Assign(&textArea, &area)
62
63	lines := `Horizontal Layout Example. Press q to quit
64Each line has 2 constraints, plus Min(0) to fill the remaining space.
65E.g. the second line of the Len/Min box is [Len(2), Min(2), Min(0)]
66Note: constraint labels that don't fit are truncated`
67	screen.NewContext(sc).DrawStringWrapped(lines, textArea.Min.X, textArea.Min.Y)
68
69	rows := layout.Vertical(
70		layout.Len(9),
71		layout.Len(9),
72		layout.Len(9),
73		layout.Len(9),
74		layout.Len(9),
75		layout.Min(0), // fills remaining space
76	).Split(area)
77
78	var areas []uv.Rectangle
79
80	for _, r := range rows {
81		cols := layout.Horizontal(
82			layout.Len(14),
83			layout.Len(14),
84			layout.Len(14),
85			layout.Len(14),
86			layout.Len(14),
87			layout.Min(0),
88		).Split(r)
89
90		areas = append(areas, cols[:5]...) // ignore Min(0)
91	}
92
93	type Named struct {
94		Name        string
95		Constraints []layout.Constraint
96	}
97
98	examples := []Named{
99		{
100			"Len",
101			[]layout.Constraint{
102				layout.Len(0),
103				layout.Len(2),
104				layout.Len(3),
105				layout.Len(6),
106				layout.Len(10),
107				layout.Len(15),
108			},
109		},
110		{
111			"Min",
112			[]layout.Constraint{
113				layout.Min(0),
114				layout.Min(2),
115				layout.Min(3),
116				layout.Min(6),
117				layout.Min(10),
118				layout.Min(15),
119			},
120		},
121		{
122			"Max",
123			[]layout.Constraint{
124				layout.Max(0),
125				layout.Max(2),
126				layout.Max(3),
127				layout.Max(6),
128				layout.Max(10),
129				layout.Max(15),
130			},
131		},
132		{
133			"Perc",
134			[]layout.Constraint{
135				layout.Percent(0),
136				layout.Percent(25),
137				layout.Percent(50),
138				layout.Percent(75),
139				layout.Percent(100),
140				layout.Percent(150),
141			},
142		},
143		{
144			"Ratio",
145			[]layout.Constraint{
146				layout.Ratio{0, 4},
147				layout.Ratio{1, 4},
148				layout.Ratio{2, 4},
149				layout.Ratio{3, 4},
150				layout.Ratio{4, 4},
151				layout.Ratio{6, 4},
152			},
153		},
154	}
155
156	for i, e := range cartesianProduct(examples, examples) {
157		renderExampleCombinations(
158			sc,
159			areas[i],
160			fmt.Sprintf("%s | %s", e.Left.Name, e.Right.Name),
161			zip(e.Left.Constraints, e.Right.Constraints),
162		)
163	}
164}
165
166func renderExampleCombinations(
167	sc uv.Screen,
168	area uv.Rectangle,
169	title string,
170	constraints []Pair[layout.Constraint, layout.Constraint],
171) {
172	rows := layout.Vertical(
173		slices.Repeat(
174			[]layout.Constraint{layout.Len(1)},
175			len(constraints)+1,
176		)...,
177	).
178		WithPadding(layout.Pad(1)).
179		Split(area)
180
181	screen.NewContext(sc).DrawString(title, rows[0].Min.X, rows[0].Min.Y-1)
182
183	for _, p := range zip(constraints, rows) {
184		renderExample(sc, p.Right, p.Left.Left, p.Left.Right, layout.Min(0))
185	}
186
187	nums := "123456789012"
188	row := rows[len(rows)-1]
189
190	screen.NewContext(sc).DrawString(
191		nums[:min(len(nums), row.Dx())],
192		row.Min.X,
193		row.Min.Y,
194	)
195}
196
197func renderExample(sc uv.Screen, area uv.Rectangle, constraints ...layout.Constraint) {
198	var r, g, b uv.Rectangle
199
200	layout.Horizontal(constraints...).Split(area).Assign(&r, &b, &g)
201
202	screen.FillArea(sc, cell(ansi.Red), r)
203	screen.FillArea(sc, cell(ansi.Green), g)
204	screen.FillArea(sc, cell(ansi.Blue), b)
205
206	draw := func(bg ansi.Color, s string, r uv.Rectangle) {
207		ctx := screen.NewContext(sc).WithStyle(uv.Style{Bg: bg})
208
209		ctx.DrawString(s[:min(len(s), r.Dx())], r.Min.X, r.Min.Y)
210	}
211
212	draw(ansi.Red, constraintLabel(constraints[0]), r)
213	draw(ansi.Green, strings.Repeat(".", g.Dx()), g)
214	draw(ansi.Blue, constraintLabel(constraints[1]), b)
215}
216
217func constraintLabel(c layout.Constraint) string {
218	switch c := c.(type) {
219	case layout.Fill:
220		return strconv.Itoa(int(c))
221
222	case layout.Len:
223		return strconv.Itoa(int(c))
224
225	case layout.Max:
226		return strconv.Itoa(int(c))
227
228	case layout.Min:
229		return strconv.Itoa(int(c))
230
231	case layout.Percent:
232		return strconv.Itoa(int(c))
233
234	case layout.Ratio:
235
236		return fmt.Sprintf("%d/%d", c.Num, c.Den)
237	default:
238		return ""
239	}
240}
241
242func cell(bg ansi.Color) *uv.Cell {
243	return &uv.Cell{
244		Content: " ",
245		Width:   1,
246		Style: uv.Style{
247			Bg: bg,
248		},
249	}
250}
251
252type Pair[T, U any] struct {
253	Left  T
254	Right U
255}
256
257func zip[T, U any](a []T, b []U) []Pair[T, U] {
258	zipped := make([]Pair[T, U], 0, min(len(a), len(b)))
259
260	for i := range min(len(a), len(b)) {
261		zipped = append(zipped, Pair[T, U]{Left: a[i], Right: b[i]})
262	}
263
264	return zipped
265}
266
267func cartesianProduct[T, U any](as []T, bs []U) []Pair[T, U] {
268	product := make([]Pair[T, U], 0, len(as)*len(bs))
269
270	for _, a := range as {
271		for _, b := range bs {
272			product = append(product, Pair[T, U]{Left: a, Right: b})
273		}
274	}
275	return product
276}