Merge branch 'master' into term/input

This commit is contained in:
Ayman Bagabas
2024-05-13 13:15:22 -04:00
7 changed files with 97 additions and 12 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
- uses: actions/checkout@v4
- name: golangci-lint
uses: golangci/golangci-lint-action@v4
uses: golangci/golangci-lint-action@v5
with:
# Optional: golangci-lint command line arguments.
args: --config .golangci-soft.yml --issues-exit-code=0
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
- uses: actions/checkout@v4
- name: golangci-lint
uses: golangci/golangci-lint-action@v4
uses: golangci/golangci-lint-action@v5
with:
# Optional: golangci-lint command line arguments.
#args:
-1
View File
@@ -23,7 +23,6 @@ linters:
- gomnd
- gomoddirectives
- goprintffuncname
- ifshort
# - lll
- misspell
- nakedret
+2
View File
@@ -217,6 +217,8 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
* [mritd/bubbles](https://github.com/mritd/bubbles): Some general-purpose
bubbles. Inputs with validation, menu selection, a modified progressbar, and
so on.
* [kevm/bubbleo](https://github.com/KevM/bubbleo): A set of bubbles with a
focus on navigation: navigation stacks, breakcrumbs, menus and so on.
* [treilik/bubbleboxer](https://github.com/treilik/bubbleboxer): Layout
multiple bubbles side-by-side in a layout-tree.
* [treilik/bubblelister](https://github.com/treilik/bubblelister): An alternate
+30 -9
View File
@@ -14,11 +14,12 @@ import (
type Model struct {
KeyMap KeyMap
cols []Column
rows []Row
cursor int
focus bool
styles Styles
cols []Column
rows []Row
cursor int
focus bool
styles Styles
styleFunc StyleFunc
viewport viewport.Model
start int
@@ -188,6 +189,13 @@ func WithStyles(s Styles) Option {
}
}
// WithStyleFunc sets the table style func which can determine a cell style per column, row, and selected state.
func WithStyleFunc(f StyleFunc) Option {
return func(m *Model) {
m.styleFunc = f
}
}
// WithKeyMap sets the key map.
func WithKeyMap(km KeyMap) Option {
return func(m *Model) {
@@ -397,6 +405,9 @@ func (m *Model) FromValues(value, separator string) {
m.SetRows(rows)
}
// StyleFunc is a function that can be used to customize the style of a table cell based on the row and column index.
type StyleFunc func(row, col int, value string) lipgloss.Style
func (m Model) headersView() string {
var s = make([]string, 0, len(m.cols))
for _, col := range m.cols {
@@ -410,20 +421,30 @@ func (m Model) headersView() string {
return lipgloss.JoinHorizontal(lipgloss.Left, s...)
}
func (m *Model) renderRow(rowID int) string {
func (m *Model) renderRow(r int) string {
var s = make([]string, 0, len(m.cols))
for i, value := range m.rows[rowID] {
for i, value := range m.rows[r] {
if m.cols[i].Width <= 0 {
continue
}
var cellStyle lipgloss.Style
if m.styleFunc != nil {
cellStyle = m.styleFunc(r, i, value)
if r == m.cursor {
cellStyle.Inherit(m.styles.Selected)
}
} else {
cellStyle = m.styles.Cell
}
style := lipgloss.NewStyle().Width(m.cols[i].Width).MaxWidth(m.cols[i].Width).Inline(true)
renderedCell := m.styles.Cell.Render(style.Render(runewidth.Truncate(value, m.cols[i].Width, "…")))
renderedCell := cellStyle.Render(style.Render(runewidth.Truncate(value, m.cols[i].Width, "…")))
s = append(s, renderedCell)
}
row := lipgloss.JoinHorizontal(lipgloss.Left, s...)
if rowID == m.cursor {
if r == m.cursor {
return m.styles.Selected.Render(row)
}
+31
View File
@@ -1,6 +1,7 @@
package table
import (
"strings"
"testing"
"github.com/charmbracelet/lipgloss"
@@ -108,3 +109,33 @@ func TestRenderRow(t *testing.T) {
})
}
}
func TestRenderRowStyleFunc(t *testing.T) {
tests := []struct {
name string
table *Model
expected string
}{
{
name: "simple row",
table: &Model{
rows: []Row{{"Foooooo", "Baaaaar", "Baaaaaz"}},
cols: cols,
styleFunc: func(row, col int, value string) lipgloss.Style {
if strings.HasSuffix(value, "z") {
return lipgloss.NewStyle().Transform(strings.ToLower)
}
return lipgloss.NewStyle().Transform(strings.ToUpper)
},
},
expected: "FOOOOOO BAAAAAR baaaaaz ",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
row := tc.table.renderRow(0)
if row != tc.expected {
t.Fatalf("\n\nWant: \n%s\n\nGot: \n%s\n", tc.expected, row)
}
})
}
}
+32
View File
@@ -0,0 +1,32 @@
package textinput
import (
"testing"
)
func Test_CurrentSuggestion(t *testing.T) {
textinput := New()
textinput.ShowSuggestions = true
suggestion := textinput.CurrentSuggestion()
expected := ""
if suggestion != expected {
t.Fatalf("Error: expected no current suggestion but was %s", suggestion)
}
textinput.SetSuggestions([]string{"test1", "test2", "test3"})
suggestion = textinput.CurrentSuggestion()
expected = ""
if suggestion != expected {
t.Fatalf("Error: expected no current suggestion but was %s", suggestion)
}
textinput.SetValue("test")
textinput.updateSuggestions()
textinput.nextSuggestion()
suggestion = textinput.CurrentSuggestion()
expected = "test2"
if suggestion != expected {
t.Fatalf("Error: expected first suggestion but was %s", suggestion)
}
}