Skip to content

Commit 05b8fb1

Browse files
committed
added help menu
1 parent eb1fa71 commit 05b8fb1

9 files changed

Lines changed: 158 additions & 23 deletions

File tree

internal/tui/app/model.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ package app
33
import (
44
"strings"
55

6+
"github.com/charmbracelet/bubbles/help"
7+
"github.com/charmbracelet/bubbles/key"
68
tea "github.com/charmbracelet/bubbletea"
79
"github.com/charmbracelet/lipgloss"
10+
"github.com/maniac-en/req/internal/tui/keybinds"
811
"github.com/maniac-en/req/internal/tui/styles"
912
"github.com/maniac-en/req/internal/tui/views"
1013
)
@@ -21,6 +24,7 @@ type AppModel struct {
2124
height int
2225
Views map[ViewName]views.ViewInterface
2326
focusedView ViewName
27+
help help.Model
2428
}
2529

2630
func (a AppModel) Init() tea.Cmd {
@@ -38,8 +42,8 @@ func (a AppModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
3842
cmds = append(cmds, cmd)
3943
return a, tea.Batch(cmds...)
4044
case tea.KeyMsg:
41-
switch msg.String() {
42-
case "ctrl+c":
45+
switch {
46+
case key.Matches(msg, keybinds.Keys.Quit):
4347
return a, tea.Quit
4448
}
4549
}
@@ -54,13 +58,20 @@ func (a AppModel) View() string {
5458
footer := a.Footer()
5559
header := a.Header()
5660
view := a.Views[a.focusedView].View()
57-
return lipgloss.JoinVertical(lipgloss.Top, header, view, footer)
61+
help := a.Help()
62+
return lipgloss.JoinVertical(lipgloss.Top, header, view, help, footer)
63+
}
64+
65+
func (a AppModel) Help() string {
66+
appHelp := styles.AppHelpStyle.Render(" • " + a.help.View(keybinds.Keys))
67+
return lipgloss.JoinHorizontal(lipgloss.Left, a.Views[a.focusedView].Help(), appHelp)
5868
}
5969

6070
func (a *AppModel) AvailableHeight() int {
6171
footer := a.Footer()
6272
header := a.Header()
63-
return a.height - lipgloss.Height(header) - lipgloss.Height(footer)
73+
help := a.Views[a.focusedView].Help()
74+
return a.height - lipgloss.Height(header) - lipgloss.Height(footer) - lipgloss.Height(help)
6475
}
6576

6677
func (a AppModel) Header() string {
@@ -88,6 +99,7 @@ func NewAppModel(ctx *Context) AppModel {
8899
model := AppModel{
89100
focusedView: Collections,
90101
ctx: ctx,
102+
help: help.New(),
91103
}
92104
model.Views = map[ViewName]views.ViewInterface{
93105
Collections: views.NewCollectionsView(model.ctx.Collections),

internal/tui/components/OptionsProvider/component.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type OptionsProvider[T, U any] struct {
2424
list list.Model
2525
input input.OptionsInput
2626
onSelectAction tea.Msg
27+
keys *keybinds.ListKeyMap
2728
width int
2829
height int
2930
focused focusedComp
@@ -59,14 +60,14 @@ func (o OptionsProvider[T, U]) Update(msg tea.Msg) (OptionsProvider[T, U], tea.C
5960
case listComponent:
6061
if !o.IsFiltering() {
6162
switch {
62-
case key.Matches(msg, keybinds.Keys.InsertItem):
63+
case key.Matches(msg, o.keys.AddItem):
6364
o.list.SetSize(o.list.Width(), o.height-lipgloss.Height(o.input.View()))
6465
o.input.OnFocus()
6566
o.focused = textComponent
6667
return o, tea.Batch(cmds...)
67-
case key.Matches(msg, keybinds.Keys.Remove):
68+
case key.Matches(msg, o.keys.DeleteItem):
6869
return o, func() tea.Msg { return messages.DeleteItem{ItemID: int64(o.GetSelected().ID)} }
69-
case key.Matches(msg, keybinds.Keys.EditItem):
70+
case key.Matches(msg, o.keys.EditItem):
7071
o.list.SetSize(o.list.Width(), o.height-lipgloss.Height(o.input.View()))
7172
o.input.SetInput(o.GetSelected().Name)
7273
o.input.OnFocus(o.GetSelected().ID)
@@ -144,8 +145,7 @@ func initList[T, U any](config *ListConfig[T, U]) list.Model {
144145
list.SetShowPagination(config.ShowPagination)
145146
list.SetShowHelp(config.ShowHelp)
146147
list.SetShowTitle(config.ShowTitle)
147-
148-
// list.KeyMap = config.KeyMap
148+
list.KeyMap = config.KeyMap
149149

150150
return list
151151
}
@@ -165,6 +165,7 @@ func NewOptionsProvider[T, U any](config *ListConfig[T, U]) OptionsProvider[T, U
165165
input: input.NewOptionsInput(&inputConfig),
166166
getItems: config.GetItemsFunc,
167167
itemMapper: config.ItemMapper,
168+
keys: config.AdditionalKeymaps,
168169
// onSelectAction: config.OnSelectAction,
169170
}
170171
}

internal/tui/components/OptionsProvider/config.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/charmbracelet/bubbles/list"
77
tea "github.com/charmbracelet/bubbletea"
8+
"github.com/maniac-en/req/internal/tui/keybinds"
89
)
910

1011
type ListConfig[T, U any] struct {
@@ -18,8 +19,9 @@ type ListConfig[T, U any] struct {
1819

1920
FilteringEnabled bool
2021

21-
Delegate list.ItemDelegate
22-
KeyMap list.KeyMap
22+
Delegate list.ItemDelegate
23+
KeyMap list.KeyMap
24+
AdditionalKeymaps *keybinds.ListKeyMap
2325

2426
ItemMapper func([]T) []list.Item
2527

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package keybinds
2+
3+
import "github.com/charmbracelet/bubbles/key"
4+
5+
type ListKeyMap struct {
6+
CursorUp key.Binding
7+
CursorDown key.Binding
8+
NextPage key.Binding
9+
PrevPage key.Binding
10+
Filter key.Binding
11+
ClearFilter key.Binding
12+
CancelWhileFiltering key.Binding
13+
AcceptWhileFiltering key.Binding
14+
AddItem key.Binding
15+
EditItem key.Binding
16+
DeleteItem key.Binding
17+
}
18+
19+
func (c ListKeyMap) ShortHelp() []key.Binding {
20+
return []key.Binding{c.CursorUp, c.CursorDown, c.NextPage, c.PrevPage, c.AddItem, c.EditItem, c.DeleteItem}
21+
}
22+
23+
func (c ListKeyMap) FullHelp() [][]key.Binding {
24+
return [][]key.Binding{
25+
{c.CursorUp, c.CursorDown, c.NextPage, c.PrevPage},
26+
}
27+
}
28+
29+
func NewListKeyMap() *ListKeyMap {
30+
return &ListKeyMap{
31+
CursorUp: Keys.Up,
32+
CursorDown: Keys.Down,
33+
NextPage: Keys.NextPage,
34+
PrevPage: Keys.PrevPage,
35+
Filter: Keys.Filter,
36+
ClearFilter: Keys.ClearFilter,
37+
CancelWhileFiltering: Keys.CancelWhileFiltering,
38+
AcceptWhileFiltering: Keys.AcceptWhileFiltering,
39+
AddItem: Keys.InsertItem,
40+
DeleteItem: Keys.Remove,
41+
EditItem: Keys.EditItem,
42+
}
43+
}

internal/tui/keybinds/keys.go

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,70 @@ import (
55
)
66

77
type Keymaps struct {
8-
InsertItem key.Binding
9-
DeleteItem key.Binding
10-
EditItem key.Binding
11-
Choose key.Binding
12-
Remove key.Binding
13-
Back key.Binding
8+
InsertItem key.Binding
9+
DeleteItem key.Binding
10+
EditItem key.Binding
11+
Choose key.Binding
12+
Remove key.Binding
13+
Back key.Binding
14+
Up key.Binding
15+
Down key.Binding
16+
NextPage key.Binding
17+
PrevPage key.Binding
18+
Filter key.Binding
19+
ClearFilter key.Binding
20+
CancelWhileFiltering key.Binding
21+
AcceptWhileFiltering key.Binding
22+
Quit key.Binding
23+
}
24+
25+
func (k Keymaps) ShortHelp() []key.Binding {
26+
return []key.Binding{
27+
k.Quit,
28+
}
29+
}
30+
31+
func (k Keymaps) FullHelp() [][]key.Binding {
32+
return [][]key.Binding{}
1433
}
1534

1635
var Keys = Keymaps{
1736
Back: key.NewBinding(
1837
key.WithKeys("esc"),
1938
key.WithHelp("esc", "back"),
2039
),
40+
Up: key.NewBinding(
41+
key.WithKeys("up", "k"),
42+
key.WithHelp("↑/k", "back"),
43+
),
44+
Down: key.NewBinding(
45+
key.WithKeys("down", "j"),
46+
key.WithHelp("↓/j", "down"),
47+
),
48+
PrevPage: key.NewBinding(
49+
key.WithKeys("left", "h", "pgup"),
50+
key.WithHelp("←/h/pgup", "prev page"),
51+
),
52+
NextPage: key.NewBinding(
53+
key.WithKeys("right", "l", "pgdown"),
54+
key.WithHelp("→/l/pgdn", "next page"),
55+
),
56+
Filter: key.NewBinding(
57+
key.WithKeys("/"),
58+
key.WithHelp("/", "filter"),
59+
),
60+
ClearFilter: key.NewBinding(
61+
key.WithKeys("esc"),
62+
key.WithHelp("esc", "clear filter"),
63+
),
64+
CancelWhileFiltering: key.NewBinding(
65+
key.WithKeys("esc"),
66+
key.WithHelp("esc", "cancel"),
67+
),
68+
AcceptWhileFiltering: key.NewBinding(
69+
key.WithKeys("enter", "tab", "shift+tab", "ctrl+k", "up", "ctrl+j", "down"),
70+
key.WithHelp("enter", "apply filter"),
71+
),
2172
InsertItem: key.NewBinding(
2273
key.WithKeys("a"),
2374
key.WithHelp("a", "add item"),
@@ -34,4 +85,8 @@ var Keys = Keymaps{
3485
key.WithKeys("x", "backspace"),
3586
key.WithHelp("x", "delete"),
3687
),
88+
Quit: key.NewBinding(
89+
key.WithKeys("ctrl+c"),
90+
key.WithHelp("ctrl+c", "quit"),
91+
),
3792
}

internal/tui/styles/app-styles.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,6 @@ var (
1111
FooterVersionStyle = lipgloss.NewStyle().Background(footerSegmentBG).AlignHorizontal(lipgloss.Right).PaddingRight(2).Foreground(footerSegmentFG)
1212
TabHeadingInactive = lipgloss.NewStyle().Width(25).AlignHorizontal(lipgloss.Center).Border(lipgloss.NormalBorder(), false, false, false, true)
1313
TabHeadingActive = lipgloss.NewStyle().Background(accent).Foreground(headingForeground).Width(25).AlignHorizontal(lipgloss.Center).Border(lipgloss.NormalBorder(), false, false, false, true)
14+
HelpStyle = lipgloss.NewStyle().Padding(1, 0, 1, 2)
15+
AppHelpStyle = lipgloss.NewStyle().Padding(1, 0).Foreground(helpFG)
1416
)

internal/tui/styles/colors.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ var (
1010
headingForeground = lipgloss.Color("#000000")
1111
footerSegmentBG = lipgloss.Color("#262626")
1212
footerSegmentFG = lipgloss.Color("#656565")
13+
helpFG = lipgloss.Color("#3C3C3C")
1314
)

internal/tui/views/collections-view-helper.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package views
33
import (
44
"github.com/charmbracelet/bubbles/list"
55
optionsProvider "github.com/maniac-en/req/internal/tui/components/OptionsProvider"
6+
"github.com/maniac-en/req/internal/tui/keybinds"
67
"github.com/maniac-en/req/internal/tui/styles"
78
)
89

@@ -15,15 +16,24 @@ func createDelegate() list.DefaultDelegate {
1516
return d
1617
}
1718

18-
func defaultListConfig[T, U any]() *optionsProvider.ListConfig[T, U] {
19+
func defaultListConfig[T, U any](binds *keybinds.ListKeyMap) *optionsProvider.ListConfig[T, U] {
1920
config := optionsProvider.ListConfig[T, U]{
20-
ShowPagination: false,
21+
ShowPagination: true,
2122
ShowStatusBar: false,
2223
ShowHelp: false,
2324
ShowTitle: false,
2425
FilteringEnabled: true,
25-
26-
Delegate: createDelegate(),
26+
Delegate: createDelegate(),
27+
KeyMap: list.KeyMap{
28+
CursorUp: binds.CursorUp,
29+
CursorDown: binds.CursorDown,
30+
NextPage: binds.NextPage,
31+
PrevPage: binds.PrevPage,
32+
Filter: binds.Filter,
33+
ClearFilter: binds.ClearFilter,
34+
CancelWhileFiltering: binds.CancelWhileFiltering,
35+
AcceptWhileFiltering: binds.AcceptWhileFiltering,
36+
},
2737
}
2838
return &config
2939
}

internal/tui/views/collections-view.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,23 @@ import (
44
"context"
55
"fmt"
66

7+
"github.com/charmbracelet/bubbles/help"
78
"github.com/charmbracelet/bubbles/list"
89
tea "github.com/charmbracelet/bubbletea"
910
"github.com/maniac-en/req/internal/backend/collections"
1011
optionsProvider "github.com/maniac-en/req/internal/tui/components/OptionsProvider"
12+
"github.com/maniac-en/req/internal/tui/keybinds"
1113
"github.com/maniac-en/req/internal/tui/messages"
14+
"github.com/maniac-en/req/internal/tui/styles"
1215
)
1316

1417
type CollectionsView struct {
1518
width int
1619
height int
1720
list optionsProvider.OptionsProvider[collections.CollectionEntity, string]
1821
manager *collections.CollectionsManager
22+
help help.Model
23+
keys *keybinds.ListKeyMap
1924
}
2025

2126
func (c CollectionsView) Init() tea.Cmd {
@@ -27,7 +32,7 @@ func (c CollectionsView) Name() string {
2732
}
2833

2934
func (c CollectionsView) Help() string {
30-
return ""
35+
return styles.HelpStyle.Render(c.help.View(c.keys))
3136
}
3237

3338
func (c CollectionsView) GetFooterSegment() string {
@@ -84,13 +89,17 @@ func itemMapper(items []collections.CollectionEntity) []list.Item {
8489
}
8590

8691
func NewCollectionsView(collManager *collections.CollectionsManager) *CollectionsView {
87-
config := defaultListConfig[collections.CollectionEntity, string]()
92+
keybinds := keybinds.NewListKeyMap()
93+
config := defaultListConfig[collections.CollectionEntity, string](keybinds)
8894

8995
config.GetItemsFunc = collManager.List
9096
config.ItemMapper = itemMapper
97+
config.AdditionalKeymaps = keybinds
9198

9299
return &CollectionsView{
93100
list: optionsProvider.NewOptionsProvider(config),
94101
manager: collManager,
102+
help: help.New(),
103+
keys: keybinds,
95104
}
96105
}

0 commit comments

Comments
 (0)