-
Notifications
You must be signed in to change notification settings - Fork 0
/
select.go
122 lines (101 loc) · 2.71 KB
/
select.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package prompts
import (
"fmt"
"strings"
tea "github.com/charmbracelet/bubbletea"
)
type selectModel struct {
choices []string
cursor int
label string
selected map[int]struct{}
}
type SelectOptions struct {
Choices []string
Label string
}
// prompt user to select between choices , and return the selected indexes
//
// example :
//
// prompts.SelectBox("you are intersted at ", []string{"gaming", "coding"})
func SelectBox(label string, choices []string) ([]int, error) {
res := tea.NewProgram(selectModel{
choices: choices,
label: label,
selected: map[int]struct{}{},
})
selected, err := res.Run()
s := selected.(selectModel)
return s.getSelected(), err
}
func (s selectModel) Init() tea.Cmd {
return nil
}
func (s selectModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c", "q":
return s, tea.Quit
case "up", "k", "left":
if s.cursor > 0 {
s.cursor--
} else {
s.cursor = len(s.choices) - 1
}
case "down", "j", "right":
if s.cursor < len(s.choices)-1 {
s.cursor++
} else {
s.cursor = 0
}
case "enter", " ":
_, ok := s.selected[s.cursor]
if ok {
delete(s.selected, s.cursor)
} else {
s.selected[s.cursor] = struct{}{}
}
}
}
return s, nil
}
func (s selectModel) View() string {
m := "\n"
m += style().Margin(0, 0, 0, 1).Foreground(color("#495867")).Render("┌─")
m += style().Margin(0, 1, 0, 1).Foreground(color("#07beb8")).Render(s.label)
m += style().Foreground(color("#495867")).Render(strings.Repeat("─", getTrmW()-charWidth(s.label)-7))
m += style().Foreground(color("#495867")).Render("┐")
m += "\n"
for i, choice := range s.choices {
cursor := style().Foreground(color("#495867")).Render(" │")
if s.cursor == i {
cursor += style().Foreground(color("#07beb8")).Render("➧")
} else {
cursor += " "
}
checked := style().Foreground(color("#495867")).Render("☐ ")
if _, ok := s.selected[i]; ok {
checked = style().Foreground(color("#07beb8")).Render("☑ ")
}
m += fmt.Sprintf("%s %s %s", cursor, checked, choice)
m += strings.Repeat(" ", getTrmW()-9-len(choice))
m += style().Foreground(color("#495867")).Render("│")
m += "\n"
}
m += style().Foreground(color("#495867")).Render(" └")
m += style().Foreground(color("#495867")).Render(strings.Repeat("─", getTrmW()-4))
m += style().Foreground(color("#495867")).Render("┘")
m += "\n"
m += style().Foreground(color("#444")).Render(" q quit ⬩ ↵ select.")
m += "\n\n"
return m
}
func (s selectModel) getSelected() []int {
selected := make([]int, 0, len(s.selected))
for i := range s.selected {
selected = append(selected, i)
}
return selected
}