okami.mom/albedo

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

dawntui: listView, confirm and one fuzzy matcher for list screens to share8101869

main
1.7 KiB55 linesraw
1package tui
2
3import (
4	"strings"
5
6	tea "charm.land/bubbletea/v2"
7	"github.com/charmbracelet/x/ansi"
8)
9
10// confirm is the one way a screen asks before something far-reaching:
11// enter does it, esc leaves it, and every other key is ignored, so a stray
12// press while you read the question changes nothing.
13type confirm struct {
14	prompt string // what will happen, and the question
15	verb   string // what enter does, in the hint
16	what   string // which action this asks about; the screen dispatches on it
17	target string // what the action applies to
18	failed bool   // the last attempt failed, so enter retries
19}
20
21func (c confirm) asking() bool { return c.prompt != "" }
22
23func (c *confirm) ask(what, target, verb, prompt string) {
24	*c = confirm{prompt: prompt, verb: verb, what: what, target: target}
25}
26
27func (c *confirm) dismiss() { *c = confirm{} }
28
29// key settles a key press while asking: yes on enter, dismissed on esc,
30// and ignored otherwise. It reports whether the key was for the question.
31func (c *confirm) key(msg tea.KeyPressMsg) (yes bool) {
32	switch msg.String() {
33	case "enter":
34		return true
35	case "esc", "ctrl+c":
36		c.dismiss()
37	}
38	return false
39}
40
41// footer is the question, the last failure if there was one, and the keys.
42func (c confirm) footer(width int, failure string) string {
43	var rows []string
44	for line := range strings.SplitSeq(ansi.Wrap(c.prompt, max(1, width-1), " "), "\n") {
45		rows = append(rows, " "+DefaultStyles.Warning.Render(line))
46	}
47	if failure != "" {
48		rows = append(rows, " "+DefaultStyles.Error.Render(ansi.Truncate(failure, max(1, width-1), "…")))
49	}
50	verb := c.verb
51	if c.failed || failure != "" {
52		verb = "retry"
53	}
54	return strings.Join(append(rows, " "+keyHints(hint{"enter", verb}, hint{"esc", "cancel"})), "\n")
55}