Skip to content

Commit e32c664

Browse files
author
Dolev Hadar
committed
feat: help
1 parent 941897a commit e32c664

File tree

1 file changed

+105
-13
lines changed

1 file changed

+105
-13
lines changed

tree/tree.go

Lines changed: 105 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import (
66
tea "github.com/charmbracelet/bubbletea"
77
"github.com/charmbracelet/lipgloss"
88
ltree "github.com/charmbracelet/lipgloss/tree"
9+
"github.com/charmbracelet/x/ansi"
910

11+
"github.com/charmbracelet/bubbles/help"
1012
"github.com/charmbracelet/bubbles/key"
1113
)
1214

@@ -16,6 +18,7 @@ type Styles struct {
1618
SelectedNode lipgloss.Style
1719
ItemStyle lipgloss.Style
1820
SelectionCursor lipgloss.Style
21+
HelpStyle lipgloss.Style
1922
}
2023

2124
// DefaultStyles returns a set of default style definitions for this tree
@@ -27,6 +30,7 @@ func DefaultStyles() (s Styles) {
2730
Bold(true)
2831
s.SelectionCursor = lipgloss.NewStyle().Foreground(lipgloss.Color("9"))
2932
s.ItemStyle = lipgloss.NewStyle()
33+
s.HelpStyle = lipgloss.NewStyle().Padding(1, 0, 0, 2)
3034

3135
return s
3236
}
@@ -36,32 +40,68 @@ type KeyMap struct {
3640
Down key.Binding
3741
Up key.Binding
3842
Toggle key.Binding
39-
Quit key.Binding
43+
44+
// Help toggle keybindings.
45+
ShowFullHelp key.Binding
46+
CloseFullHelp key.Binding
47+
48+
Quit key.Binding
4049
}
4150

4251
// DefaultKeyMap is the default set of key bindings for navigating and acting
4352
// upon the tree.
4453
var DefaultKeyMap = KeyMap{
45-
Down: key.NewBinding(key.WithKeys("down", "j", "ctrl+n"), key.WithHelp("down", "next line")),
46-
Up: key.NewBinding(key.WithKeys("up", "k", "ctrl+p"), key.WithHelp("up", "previous line")),
47-
Toggle: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "toggle")),
48-
Quit: key.NewBinding(key.WithKeys("q", "ctrl+c"), key.WithHelp("q", "quit")),
54+
Down: key.NewBinding(
55+
key.WithKeys("down", "j", "ctrl+n"),
56+
key.WithHelp("down", "next line"),
57+
),
58+
Up: key.NewBinding(
59+
key.WithKeys("up", "k", "ctrl+p"),
60+
key.WithHelp("up", "previous line"),
61+
),
62+
Toggle: key.NewBinding(
63+
key.WithKeys("enter"),
64+
key.WithHelp("enter", "toggle"),
65+
),
66+
67+
// Toggle help.
68+
ShowFullHelp: key.NewBinding(
69+
key.WithKeys("?"),
70+
key.WithHelp("?", "more"),
71+
),
72+
CloseFullHelp: key.NewBinding(
73+
key.WithKeys("?"),
74+
key.WithHelp("?", "close help"),
75+
),
76+
77+
Quit: key.NewBinding(
78+
key.WithKeys("q", "ctrl+c"),
79+
key.WithHelp("q", "quit"),
80+
),
4981
}
5082

5183
// Model is the Bubble Tea model for this tree element.
5284
type Model struct {
53-
root *Item
85+
showHelp bool
86+
// OpenCharacter is the character used to represent an open node.
87+
OpenCharacter string
88+
// ClosedCharacter is the character used to represent a closed node.
89+
ClosedCharacter string
5490
// KeyMap encodes the keybindings recognized by the widget.
5591
KeyMap KeyMap
56-
5792
// Styles sets the styling for the tree
5893
Styles Styles
94+
Help help.Model
5995

60-
// OpenCharacter is the character used to represent an open node.
61-
OpenCharacter string
96+
// Additional key mappings for the short and full help views. This allows
97+
// you to add additional key mappings to the help menu without
98+
// re-implementing the help component. Of course, you can also disable the
99+
// list's help component and implement a new one if you need more
100+
// flexibility.
101+
AdditionalShortHelpKeys func() []key.Binding
102+
AdditionalFullHelpKeys func() []key.Binding
62103

63-
// ClosedCharacter is the character used to represent a closed node.
64-
ClosedCharacter string
104+
root *Item
65105

66106
// yOffset is the vertical offset of the selected node.
67107
yOffset int
@@ -210,10 +250,12 @@ func Root(root any) *Item {
210250
func New(t *Item) Model {
211251
m := Model{
212252
root: t,
253+
showHelp: true,
213254
KeyMap: DefaultKeyMap,
214255
Styles: DefaultStyles(),
215256
OpenCharacter: "▼",
216257
ClosedCharacter: "▶",
258+
Help: help.New(),
217259
}
218260
m.setAttributes()
219261
m.updateStyles()
@@ -246,6 +288,10 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
246288
m.yOffset = node.yOffset
247289
case key.Matches(msg, m.KeyMap.Quit):
248290
return m, tea.Quit
291+
case key.Matches(msg, m.KeyMap.ShowFullHelp):
292+
fallthrough
293+
case key.Matches(msg, m.KeyMap.CloseFullHelp):
294+
m.Help.ShowAll = !m.Help.ShowAll
249295
}
250296
}
251297

@@ -256,7 +302,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
256302

257303
// View renders the component.
258304
func (m Model) View() string {
259-
s := fmt.Sprintf("y=%d\n", m.yOffset)
305+
s := fmt.Sprintf("y=%2d current=%s\n", m.yOffset, ansi.Strip(m.ItemAtCurrentOffset().Value()))
260306

261307
// TODO: remove
262308
debug := printDebugInfo(m.root)
@@ -277,7 +323,53 @@ func (m Model) View() string {
277323
cursor,
278324
m.root.String(),
279325
)
280-
return lipgloss.JoinVertical(lipgloss.Left, s, t)
326+
327+
var help string
328+
if m.showHelp {
329+
help = m.helpView()
330+
}
331+
332+
return lipgloss.JoinVertical(lipgloss.Left, s, t, help)
333+
}
334+
335+
// ShortHelp returns bindings to show in the abbreviated help view. It's part
336+
// of the help.KeyMap interface.
337+
func (m Model) ShortHelp() []key.Binding {
338+
kb := []key.Binding{
339+
m.KeyMap.Up,
340+
m.KeyMap.Down,
341+
m.KeyMap.Toggle,
342+
m.KeyMap.Quit,
343+
}
344+
345+
if m.AdditionalShortHelpKeys != nil {
346+
kb = append(kb, m.AdditionalShortHelpKeys()...)
347+
}
348+
349+
return kb
350+
}
351+
352+
// FullHelp returns bindings to show the full help view. It's part of the
353+
// help.KeyMap interface.
354+
func (m Model) FullHelp() [][]key.Binding {
355+
kb := [][]key.Binding{
356+
{
357+
m.KeyMap.Up,
358+
m.KeyMap.Down,
359+
m.KeyMap.Toggle,
360+
m.KeyMap.Quit,
361+
},
362+
}
363+
364+
if m.AdditionalFullHelpKeys != nil {
365+
kb = append(kb, m.AdditionalFullHelpKeys())
366+
}
367+
368+
return kb
369+
}
370+
371+
func (m Model) helpView() string {
372+
return m.Styles.HelpStyle.Render(m.Help.View(m))
281373
}
282374

283375
// FlatItems returns all items in the tree as a flat list.

0 commit comments

Comments
 (0)