diff --git a/table/command.go b/table/command.go index 2e6f8fa22..af1c96dab 100644 --- a/table/command.go +++ b/table/command.go @@ -5,6 +5,7 @@ import ( "fmt" "os" + "github.com/charmbracelet/bubbles/help" "github.com/charmbracelet/bubbles/table" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/gum/internal/stdin" @@ -117,8 +118,14 @@ func (o Options) Run() error { ctx, cancel := timeout.Context(o.Timeout) defer cancel() + m := model{ + table: table, + showHelp: o.ShowHelp, + help: help.New(), + keymap: defaultKeymap(), + } tm, err := tea.NewProgram( - model{table: table}, + m, tea.WithOutput(os.Stderr), tea.WithContext(ctx), ).Run() @@ -130,8 +137,7 @@ func (o Options) Run() error { return fmt.Errorf("failed to get selection") } - m := tm.(model) - + m = tm.(model) if o.ReturnColumn > 0 && o.ReturnColumn <= len(m.selected) { if err = writer.Write([]string{m.selected[o.ReturnColumn-1]}); err != nil { return fmt.Errorf("failed to write col %d of selected row: %w", o.ReturnColumn, err) diff --git a/table/options.go b/table/options.go index 853a8de7c..1b1844a95 100644 --- a/table/options.go +++ b/table/options.go @@ -15,6 +15,7 @@ type Options struct { Print bool `short:"p" help:"static print" default:"false"` File string `short:"f" help:"file path" default:""` Border string `short:"b" help:"border style" default:"rounded" enum:"rounded,thick,normal,hidden,double,none"` + ShowHelp bool `help:"Show help keybinds" default:"true" negatable:"" env:"GUM_TABLE_SHOW_HELP"` BorderStyle style.Styles `embed:"" prefix:"border." envprefix:"GUM_TABLE_BORDER_"` CellStyle style.Styles `embed:"" prefix:"cell." envprefix:"GUM_TABLE_CELL_"` diff --git a/table/table.go b/table/table.go index 7e2b03531..31356a32c 100644 --- a/table/table.go +++ b/table/table.go @@ -15,14 +15,59 @@ package table import ( + "github.com/charmbracelet/bubbles/help" + "github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/table" tea "github.com/charmbracelet/bubbletea" ) +type keymap struct { + Navigate, + Select, + Quit, + Abort key.Binding +} + +// FullHelp implements help.KeyMap. +func (k keymap) FullHelp() [][]key.Binding { return nil } + +// ShortHelp implements help.KeyMap. +func (k keymap) ShortHelp() []key.Binding { + return []key.Binding{ + k.Navigate, + k.Select, + k.Quit, + } +} + +func defaultKeymap() keymap { + return keymap{ + Navigate: key.NewBinding( + key.WithKeys("up", "down"), + key.WithHelp("↑↓", "navigate"), + ), + Select: key.NewBinding( + key.WithKeys("enter"), + key.WithHelp("enter", "select"), + ), + Quit: key.NewBinding( + key.WithKeys("esc", "ctrl+q", "q"), + key.WithHelp("esc", "quit"), + ), + Abort: key.NewBinding( + key.WithKeys("ctrl+c"), + key.WithHelp("ctrl+c", "abort"), + ), + } +} + type model struct { table table.Model selected table.Row quitting bool + showHelp bool + help help.Model + keymap keymap } func (m model) Init() tea.Cmd { return nil } @@ -32,15 +77,16 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.KeyMsg: - switch msg.String() { - case "enter": + km := m.keymap + switch { + case key.Matches(msg, km.Select): m.selected = m.table.SelectedRow() m.quitting = true return m, tea.Quit - case "q", "esc": + case key.Matches(msg, km.Quit): m.quitting = true return m, tea.Quit - case "ctrl+c": + case key.Matches(msg, km.Abort): m.quitting = true return m, tea.Interrupt } @@ -54,5 +100,9 @@ func (m model) View() string { if m.quitting { return "" } - return m.table.View() + s := m.table.View() + if m.showHelp { + s += "\n" + m.help.View(m.keymap) + } + return s }