Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Key maps #12

Merged
merged 2 commits into from
Feb 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@ updates:

.PHONY: test
test:
@go test ./table
@go test -race -cover ./table

.PHONY: test-coverage
test-coverage: coverage.out
@go tool cover -html=coverage.out

coverage.out: table/*.go go.*
@go test -coverprofile=coverage.out ./table

.PHONY: fmt
fmt:
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ Displays a table with a header, rows, and borders.

Border shape is customizable with a basic thick square default.

Rows can be individually styled.
Row text can be individually styled.

Can be focused to highlight a row and navigate with up/down (and j/k).
Can be focused to highlight a row and navigate with up/down (and j/k). These
keys can be customized with a KeyMap.

Can make rows selectable, and fetch the current selections.

Expand Down
8 changes: 7 additions & 1 deletion examples/features/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,19 @@ func NewModel() Model {
}),
}

// Start with the default key map and change it slightly, just for demoing
keys := table.DefaultKeyMap()
keys.RowDown.SetKeys("j", "down", "s")
keys.RowUp.SetKeys("j", "down", "w")

return Model{
tableModel: table.New(columns).
WithRows(rows).
HeaderStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("10")).Bold(true)).
SelectableRows(true).
Focused(true).
Border(customBorder),
Border(customBorder).
WithKeyMap(keys),
}
}

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/evertras/bubble-table
go 1.17

require (
github.com/charmbracelet/bubbles v0.10.3
github.com/charmbracelet/bubbletea v0.19.3
github.com/charmbracelet/lipgloss v0.4.0
github.com/stretchr/testify v1.7.0
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/charmbracelet/bubbles v0.10.3 h1:fKarbRaObLn/DCsZO4Y3vKCwRUzynQD9L+gGev1E/ho=
github.com/charmbracelet/bubbles v0.10.3/go.mod h1:jOA+DUF1rjZm7gZHcNyIVW+YrBPALKfpGVdJu8UiJsA=
github.com/charmbracelet/bubbletea v0.19.3 h1:OKeO/Y13rQQqt4snX+lePB0QrnW80UdrMNolnCcmoAw=
github.com/charmbracelet/bubbletea v0.19.3/go.mod h1:VuXF2pToRxDUHcBUcPmCRUHRvFATM4Ckb/ql1rBl3KA=
github.com/charmbracelet/harmonica v0.1.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
github.com/charmbracelet/lipgloss v0.4.0 h1:768h64EFkGUr8V5yAKV7/Ta0NiVceiPaV+PphaW1K9g=
github.com/charmbracelet/lipgloss v0.4.0/go.mod h1:vmdkHvce7UzX6xkyf4cca8WlwdQ5RQr8fzta+xl7BOM=
github.com/containerd/console v1.0.2 h1:Pi6D+aZXM+oUw1czuKgH5IJ+y0jhYcwBJfx5/Ghn9dE=
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
Expand All @@ -28,6 +33,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
Expand Down
26 changes: 26 additions & 0 deletions table/keys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package table

import "github.com/charmbracelet/bubbles/key"

// KeyMap defines the keybindings for the table when it's focused
type KeyMap struct {
RowDown key.Binding
RowUp key.Binding

RowSelectToggle key.Binding
}

// DefaultKeyMap returns a set of sensible defaults for controlling a focused table
func DefaultKeyMap() KeyMap {
return KeyMap{
RowDown: key.NewBinding(
key.WithKeys("down", "j"),
),
RowUp: key.NewBinding(
key.WithKeys("up", "k"),
),
RowSelectToggle: key.NewBinding(
key.WithKeys(" ", "enter"),
),
}
}
55 changes: 55 additions & 0 deletions table/model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package table

import (
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)

const (
columnKeySelect = "___select___"
)

var (
defaultHighlightStyle = lipgloss.NewStyle().Background(lipgloss.Color("#334"))
)

// Model is the main table model. Create using New()
type Model struct {
keyMap KeyMap
columns []Column
headerStyle lipgloss.Style

rows []Row

selectableRows bool

rowCursorIndex int

focused bool

highlightStyle lipgloss.Style

selectedRows []Row

border Border
}

// New creates a new table ready for further modifications
func New(columns []Column) Model {
m := Model{
columns: make([]Column, len(columns)),
highlightStyle: defaultHighlightStyle.Copy(),
border: borderDefault,
keyMap: DefaultKeyMap(),
}

// Do a full deep copy to avoid unexpected edits
copy(m.columns, columns)

return m
}

// Init initializes the table per the Bubble Tea architecture
func (m Model) Init() tea.Cmd {
return nil
}
75 changes: 75 additions & 0 deletions table/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package table

import "github.com/charmbracelet/lipgloss"

// HeaderStyle sets the style to apply to the header text, such as color or bold
func (m Model) HeaderStyle(style lipgloss.Style) Model {
m.headerStyle = style.Copy()
return m
}

// WithRows sets the rows to show as data in the table
func (m Model) WithRows(rows []Row) Model {
m.rows = rows
return m
}

// WithKeyMap sets the key map to use for controls when focused
func (m Model) WithKeyMap(keyMap KeyMap) Model {
m.keyMap = keyMap
return m
}

// KeyMap returns a copy of the current key map in use
func (m Model) KeyMap() KeyMap {
return m.keyMap
}

// SelectableRows sets whether or not rows are selectable. If set, adds a column
// in the front that acts as a checkbox and responds to controls if Focused
func (m Model) SelectableRows(selectable bool) Model {
m.selectableRows = selectable

hasSelectColumn := m.columns[0].Key == columnKeySelect

if hasSelectColumn != selectable {
if selectable {
m.columns = append([]Column{
NewColumn(columnKeySelect, "[x]", 3),
}, m.columns...)
} else {
m.columns = m.columns[1:]
}
}

return m
}

// HighlightedRow returns the full Row that's currently highlighted by the user
func (m Model) HighlightedRow() Row {
if len(m.rows) > 0 {
return m.rows[m.rowCursorIndex]
}

// TODO: Better way to do this without pointers/nil? Or should it be nil?
return Row{}
}

// SelectedRows returns all rows that have been set as selected by the user
func (m Model) SelectedRows() []Row {
return m.selectedRows
}

// HighlightStyle sets a custom style to use when the row is being highlighted
// by the cursor
func (m Model) HighlightStyle(style lipgloss.Style) Model {
m.highlightStyle = style
return m
}

// Focused allows the table to show highlighted rows and take in controls of
// up/down/space/etc to let the user navigate the table and interact with it
func (m Model) Focused(focused bool) Model {
m.focused = focused
return m
}
Loading