-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbubblehelp.go
More file actions
227 lines (178 loc) · 5.52 KB
/
bubblehelp.go
File metadata and controls
227 lines (178 loc) · 5.52 KB
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
// Package bubblehelp is a manager to help render, contextualize and manage keybinds for bubbletea.
package bubblehelp
import (
"log"
"math"
"strings"
"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/lipgloss"
)
var (
// CurrentContext holds the current context identifier.
CurrentContext KeymapContext
// Contexts map of single every registered contexts.
Contexts map[KeymapContext]*Keymap
// ShowAll is the flag to define whether it's the full or short help that will be rendered.
ShowAll bool
// previousContext allows to reset the previous context.
previousContext KeymapContext
// defaultStyle is used by defautl by all keymaps.
defaultStyle Style
)
// Init is the first function that needs to be called in the start of the app.
func Init() {
Contexts = make(map[KeymapContext]*Keymap)
defaultStyle = Style{
EssentialKey: lipgloss.NewStyle().
Bold(true),
EssentialKeyDescription: lipgloss.NewStyle().
Italic(true),
EssentialKeySeparator: lipgloss.NewStyle().
Italic(true),
EssentialKeySeparatorValue: " - ",
EssentialColSeparator: lipgloss.NewStyle().
Bold(true),
EssentialColSeparatorValue: " • ",
FullKey: lipgloss.NewStyle().
Bold(true),
FullKeyDescription: lipgloss.NewStyle().
Italic(true),
FullKeySeparator: lipgloss.NewStyle().
Italic(true),
FullKeySeparatorValue: " - ",
FullColSeparator: lipgloss.NewStyle().
Italic(true),
FullColSeparatorValue: " ",
}
}
// RegisterContext allows to register a new Keymap context and link it with the given identifier.
func RegisterContext(context KeymapContext, keymap *Keymap) {
Contexts[context] = keymap
}
// GetCurrentContextKeymap returns a pointer on the current Keymap context.
func GetCurrentContextKeymap() *Keymap {
ctx, ok := Contexts[CurrentContext]
if !ok {
return nil
}
return ctx
}
// SwitchContext take care of properly changing context. Resets the current context before switching.
func SwitchContext(context KeymapContext) {
_, ok := Contexts[context]
if !ok {
log.Println("bubblehelp: context not found")
}
keymap := GetCurrentContextKeymap()
if keymap != nil {
keymap.Reset()
}
previousContext = CurrentContext
CurrentContext = context
ShowAll = false
}
func SwitchToPreviousContext() {
SwitchContext(previousContext)
}
// UpdateKeybindHelpDesc allows to temporary change the help description for a keybind in the current Keymap context.
func UpdateKeybindHelpDesc(keybind key.Binding, desc string) {
keymap := GetCurrentContextKeymap()
if keymap == nil {
return
}
keymap.updateHelpDesc(keybind, desc)
}
// SetKeybindVisible allows to set keybinds visibility in the current Keymap context.
func SetKeybindVisible(keybind key.Binding, visible bool) {
keymap := GetCurrentContextKeymap()
if keymap == nil {
return
}
keymap.setVisible(keybind, visible)
}
// IsKeybindVisible returns the current visibility of a Keybind.
// If the Keybind do not exist in the current context, returns false.
func IsKeybindVisible(keybind key.Binding) bool {
keymap := GetCurrentContextKeymap()
if keymap == nil {
return false
}
return keymap.isVisible(keybind)
}
// View is the main render function of bubblehelp.
// Take the ShowAll flag into account to render full or short help.
func View(width int) string {
keymap := GetCurrentContextKeymap()
if keymap == nil {
return "ERROR : UNKNOWN KEYMAP CONTEXT"
}
if ShowAll {
return ViewAll(keymap, width)
} else {
return ViewEssential(keymap, width)
}
}
// ViewAll is the full help render function, can be called directly.
func ViewAll(keymap *Keymap, width int) string {
var keys []Key
var columns []string
var keyStr, sepStr, descStr strings.Builder
keys = keymap.AllBindings()
colCount := keymap.ShowAllColumnCount
rowCount := int(math.Ceil(float64(len(keys)) / float64(colCount)))
columns = make([]string, 0)
for i, key := range keys {
remainingCount := len(keys) - i
notLastCol := len(columns)+1 < colCount
if i%rowCount > 0 || (remainingCount == 1 && notLastCol) {
keyStr.WriteString("\n")
sepStr.WriteString("\n")
descStr.WriteString("\n")
}
keyStr.WriteString(keymap.Style.FullKey.
Render(key.Binding.Help().Key))
sepStr.WriteString(keymap.Style.FullKeySeparator.
Render(keymap.Style.FullKeySeparatorValue))
descStr.WriteString(keymap.Style.FullKeyDescription.
Render(key.GetHelpDesc()))
if ((i+1)%rowCount == 0 && i != 0 && notLastCol) || (remainingCount == 1) {
columns = append(columns, lipgloss.
JoinHorizontal(lipgloss.Center,
keyStr.String(),
sepStr.String(),
descStr.String()))
if i < len(keys)-1 {
columns = append(columns, keymap.Style.FullColSeparatorValue)
colCount++
}
keyStr.Reset()
sepStr.Reset()
descStr.Reset()
}
}
return lipgloss.JoinHorizontal(lipgloss.Top, columns...)
}
// ViewEssential is the short help render function, can be called directly
func ViewEssential(keymap *Keymap, width int) string {
var b strings.Builder
var keys []Key
keys = keymap.EssentialBindings()
for i, key := range keys {
if i > 0 {
b.WriteString(keymap.Style.EssentialColSeparator.
Render(keymap.Style.EssentialColSeparatorValue))
}
b.WriteString(keymap.Style.EssentialKey.
Render(key.Binding.Help().Key))
b.WriteString(keymap.Style.EssentialKeySeparator.
Render(keymap.Style.EssentialKeySeparatorValue))
b.WriteString(keymap.Style.EssentialKeyDescription.
Render(key.GetHelpDesc()))
}
return lipgloss.NewStyle().
AlignHorizontal(lipgloss.Center).
Width(width).Render(b.String())
}
func SetDefaultStyle(style Style) {
defaultStyle = style
}