okami.mom/albedo

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

dawnadd charm tui skillf7fcae1

main
2.2 KiB82 linesraw
1// Package contracts is a dependency-free teaching fixture, not a UI framework.
2// Its state is owned by one event loop; it is deliberately not thread-safe.
3package contracts
4
5type phase uint8
6
7const (
8	idle phase = iota
9	debouncing
10	loading
11	ready
12	failed
13	stopped
14)
15
16type searchState struct {
17	generation uint64
18	query      string
19	phase      phase
20	rows       []string
21	err        error
22}
23
24// change records new intent now, before the debounce timer fires. This fixture
25// clears rows; an application may instead retain them with an explicit stale tag.
26// The real application must also cancel its superseded backend context.
27func (s *searchState) change(query string) uint64 {
28	s.generation++
29	s.query = query
30	s.phase = debouncing
31	s.rows = nil
32	s.err = nil
33	return s.generation
34}
35
36// begin admits one request for the current intent, rejecting stale or duplicate
37// debounce messages. A same-query retry must first create new intent with change.
38func (s *searchState) begin(generation uint64) bool {
39	if generation != s.generation || s.phase != debouncing {
40		return false
41	}
42	s.phase = loading
43	return true
44}
45
46// finish transfers an immutable result to this state only while its request is
47// active. The producer must not mutate rows concurrently, even during this copy.
48func (s *searchState) finish(generation uint64, rows []string, err error) bool {
49	if generation != s.generation || s.phase != loading {
50		return false
51	}
52	if err != nil {
53		s.phase = failed
54		s.rows = nil
55		s.err = err
56		return true
57	}
58	s.phase = ready
59	s.rows = append([]string(nil), rows...)
60	s.err = nil
61	return true
62}
63
64// stop invalidates pending completions. It does not stop real I/O; the caller
65// must cancel and clean up the application's owned resources as well.
66func (s *searchState) stop() {
67	s.generation++
68	s.phase = stopped
69}
70
71// bodyRows handles nonnegative row allocation. compact is true when the caller
72// must use a different layout because the chrome does not fit. It does not
73// measure text or model Lip Gloss's box behavior.
74func bodyRows(total, header, footer int) (rows int, compact bool) {
75	total = max(0, total)
76	header = max(0, header)
77	footer = max(0, footer)
78	if header > total || footer > total-header {
79		return 0, true
80	}
81	return total - header - footer, false
82}