chore: go mod tidy / vendor / make deps
This commit is contained in:
252
vendor/github.com/evertras/bubble-table/table/row.go
generated
vendored
Normal file
252
vendor/github.com/evertras/bubble-table/table/row.go
generated
vendored
Normal file
@ -0,0 +1,252 @@
|
||||
package table
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/muesli/reflow/wordwrap"
|
||||
)
|
||||
|
||||
// RowData is a map of string column keys to arbitrary data. Data with a key
|
||||
// that matches a column key will be displayed. Data with a key that does not
|
||||
// match a column key will not be displayed, but will remain attached to the Row.
|
||||
// This can be useful for attaching hidden metadata for future reference when
|
||||
// retrieving rows.
|
||||
type RowData map[string]any
|
||||
|
||||
// Row represents a row in the table with some data keyed to the table columns>
|
||||
// Can have a style applied to it such as color/bold. Create using NewRow().
|
||||
type Row struct {
|
||||
Style lipgloss.Style
|
||||
Data RowData
|
||||
|
||||
selected bool
|
||||
|
||||
// id is an internal unique ID to match rows after they're copied
|
||||
id uint32
|
||||
}
|
||||
|
||||
var lastRowID uint32 = 1
|
||||
|
||||
// NewRow creates a new row and copies the given row data.
|
||||
func NewRow(data RowData) Row {
|
||||
row := Row{
|
||||
Data: make(map[string]any),
|
||||
id: lastRowID,
|
||||
}
|
||||
|
||||
atomic.AddUint32(&lastRowID, 1)
|
||||
|
||||
for key, val := range data {
|
||||
// Doesn't deep copy val, but close enough for now...
|
||||
row.Data[key] = val
|
||||
}
|
||||
|
||||
return row
|
||||
}
|
||||
|
||||
// WithStyle uses the given style for the text in the row.
|
||||
func (r Row) WithStyle(style lipgloss.Style) Row {
|
||||
r.Style = style.Copy()
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
//nolint:cyclop,funlen // Breaking this up will be more complicated than it's worth for now
|
||||
func (m Model) renderRowColumnData(row Row, column Column, rowStyle lipgloss.Style, borderStyle lipgloss.Style) string {
|
||||
cellStyle := rowStyle.Copy().Inherit(column.style).Inherit(m.baseStyle)
|
||||
|
||||
var str string
|
||||
|
||||
switch column.key {
|
||||
case columnKeySelect:
|
||||
if row.selected {
|
||||
str = m.selectedText
|
||||
} else {
|
||||
str = m.unselectedText
|
||||
}
|
||||
case columnKeyOverflowRight:
|
||||
cellStyle = cellStyle.Align(lipgloss.Right)
|
||||
str = ">"
|
||||
case columnKeyOverflowLeft:
|
||||
str = "<"
|
||||
default:
|
||||
fmtString := "%v"
|
||||
|
||||
var data any
|
||||
|
||||
if entry, exists := row.Data[column.key]; exists {
|
||||
data = entry
|
||||
|
||||
if column.fmtString != "" {
|
||||
fmtString = column.fmtString
|
||||
}
|
||||
} else if m.missingDataIndicator != nil {
|
||||
data = m.missingDataIndicator
|
||||
} else {
|
||||
data = ""
|
||||
}
|
||||
|
||||
switch entry := data.(type) {
|
||||
case StyledCell:
|
||||
str = fmt.Sprintf(fmtString, entry.Data)
|
||||
|
||||
if entry.StyleFunc != nil {
|
||||
cellStyle = entry.StyleFunc(StyledCellFuncInput{
|
||||
Column: column,
|
||||
Data: entry.Data,
|
||||
Row: row,
|
||||
GlobalMetadata: m.metadata,
|
||||
}).Copy().Inherit(cellStyle)
|
||||
} else {
|
||||
cellStyle = entry.Style.Copy().Inherit(cellStyle)
|
||||
}
|
||||
default:
|
||||
str = fmt.Sprintf(fmtString, entry)
|
||||
}
|
||||
}
|
||||
|
||||
if m.multiline {
|
||||
str = wordwrap.String(str, column.width)
|
||||
cellStyle = cellStyle.Align(lipgloss.Top)
|
||||
} else {
|
||||
str = limitStr(str, column.width)
|
||||
}
|
||||
|
||||
cellStyle = cellStyle.Inherit(borderStyle)
|
||||
cellStr := cellStyle.Render(str)
|
||||
|
||||
return cellStr
|
||||
}
|
||||
|
||||
func (m Model) renderRow(rowIndex int, last bool) string {
|
||||
row := m.GetVisibleRows()[rowIndex]
|
||||
highlighted := rowIndex == m.rowCursorIndex
|
||||
|
||||
rowStyle := row.Style.Copy()
|
||||
|
||||
if m.rowStyleFunc != nil {
|
||||
styleResult := m.rowStyleFunc(RowStyleFuncInput{
|
||||
Index: rowIndex,
|
||||
Row: row,
|
||||
IsHighlighted: m.focused && highlighted,
|
||||
})
|
||||
|
||||
rowStyle = rowStyle.Inherit(styleResult)
|
||||
} else if m.focused && highlighted {
|
||||
rowStyle = rowStyle.Inherit(m.highlightStyle)
|
||||
}
|
||||
|
||||
return m.renderRowData(row, rowStyle, last)
|
||||
}
|
||||
|
||||
func (m Model) renderBlankRow(last bool) string {
|
||||
return m.renderRowData(NewRow(nil), lipgloss.NewStyle(), last)
|
||||
}
|
||||
|
||||
// This is long and could use some refactoring in the future, but not quite sure
|
||||
// how to pick it apart yet.
|
||||
//
|
||||
//nolint:funlen, cyclop
|
||||
func (m Model) renderRowData(row Row, rowStyle lipgloss.Style, last bool) string {
|
||||
numColumns := len(m.columns)
|
||||
|
||||
columnStrings := []string{}
|
||||
totalRenderedWidth := 0
|
||||
|
||||
stylesInner, stylesLast := m.styleRows()
|
||||
|
||||
maxCellHeight := 1
|
||||
if m.multiline {
|
||||
for _, column := range m.columns {
|
||||
cellStr := m.renderRowColumnData(row, column, rowStyle, lipgloss.NewStyle())
|
||||
maxCellHeight = max(maxCellHeight, lipgloss.Height(cellStr))
|
||||
}
|
||||
}
|
||||
|
||||
for columnIndex, column := range m.columns {
|
||||
var borderStyle lipgloss.Style
|
||||
var rowStyles borderStyleRow
|
||||
|
||||
if !last {
|
||||
rowStyles = stylesInner
|
||||
} else {
|
||||
rowStyles = stylesLast
|
||||
}
|
||||
rowStyle = rowStyle.Copy().Height(maxCellHeight)
|
||||
|
||||
if m.horizontalScrollOffsetCol > 0 && columnIndex == m.horizontalScrollFreezeColumnsCount {
|
||||
var borderStyle lipgloss.Style
|
||||
|
||||
if columnIndex == 0 {
|
||||
borderStyle = rowStyles.left.Copy()
|
||||
} else {
|
||||
borderStyle = rowStyles.inner.Copy()
|
||||
}
|
||||
|
||||
rendered := m.renderRowColumnData(row, genOverflowColumnLeft(1), rowStyle, borderStyle)
|
||||
|
||||
totalRenderedWidth += lipgloss.Width(rendered)
|
||||
|
||||
columnStrings = append(columnStrings, rendered)
|
||||
}
|
||||
|
||||
if columnIndex >= m.horizontalScrollFreezeColumnsCount &&
|
||||
columnIndex < m.horizontalScrollOffsetCol+m.horizontalScrollFreezeColumnsCount {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(columnStrings) == 0 {
|
||||
borderStyle = rowStyles.left
|
||||
} else if columnIndex < numColumns-1 {
|
||||
borderStyle = rowStyles.inner
|
||||
} else {
|
||||
borderStyle = rowStyles.right
|
||||
}
|
||||
|
||||
cellStr := m.renderRowColumnData(row, column, rowStyle, borderStyle)
|
||||
|
||||
if m.maxTotalWidth != 0 {
|
||||
renderedWidth := lipgloss.Width(cellStr)
|
||||
|
||||
const (
|
||||
borderAdjustment = 1
|
||||
overflowColWidth = 2
|
||||
)
|
||||
|
||||
targetWidth := m.maxTotalWidth - overflowColWidth
|
||||
|
||||
if columnIndex == len(m.columns)-1 {
|
||||
// If this is the last header, we don't need to account for the
|
||||
// overflow arrow column
|
||||
targetWidth = m.maxTotalWidth
|
||||
}
|
||||
|
||||
if totalRenderedWidth+renderedWidth > targetWidth {
|
||||
overflowWidth := m.maxTotalWidth - totalRenderedWidth - borderAdjustment
|
||||
overflowStyle := genOverflowStyle(rowStyles.right, overflowWidth)
|
||||
overflowColumn := genOverflowColumnRight(overflowWidth)
|
||||
overflowStr := m.renderRowColumnData(row, overflowColumn, rowStyle, overflowStyle)
|
||||
|
||||
columnStrings = append(columnStrings, overflowStr)
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
totalRenderedWidth += renderedWidth
|
||||
}
|
||||
|
||||
columnStrings = append(columnStrings, cellStr)
|
||||
}
|
||||
|
||||
return lipgloss.JoinHorizontal(lipgloss.Bottom, columnStrings...)
|
||||
}
|
||||
|
||||
// Selected returns a copy of the row that's set to be selected or deselected.
|
||||
// The old row is not changed in-place.
|
||||
func (r Row) Selected(selected bool) Row {
|
||||
r.selected = selected
|
||||
|
||||
return r
|
||||
}
|
Reference in New Issue
Block a user