From 93d6978d974e617ca2afc2f98ecd978b1bb16516 Mon Sep 17 00:00:00 2001 From: "Jager,Petar" Date: Fri, 24 Feb 2023 13:22:19 +0100 Subject: [PATCH 1/2] wip: customizable table cells/rows --- cmd/scom/scom.go | 14 +++-- .../model/tabs/clustertab/clustertabtable.go | 25 +++++++++ internal/styles/styles.go | 17 +++--- internal/table/table.go | 56 +++++++++++++++++-- 4 files changed, 93 insertions(+), 19 deletions(-) diff --git a/cmd/scom/scom.go b/cmd/scom/scom.go index 37ce8ec..c416917 100644 --- a/cmd/scom/scom.go +++ b/cmd/scom/scom.go @@ -8,8 +8,8 @@ import ( "github.com/charmbracelet/bubbles/help" "github.com/charmbracelet/bubbles/textinput" "github.com/charmbracelet/bubbles/viewport" - "github.com/charmbracelet/lipgloss" tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" "github.com/CLIP-HPC/SlurmCommander/internal/cmdline" "github.com/CLIP-HPC/SlurmCommander/internal/command" @@ -30,7 +30,7 @@ func main() { var ( debugSet bool = false - args *cmdline.CmdArgs + args *cmdline.CmdArgs ) fmt.Printf("Welcome to Slurm Commander!\n\n") @@ -103,11 +103,11 @@ func main() { }, JobTab: jobtab.JobTab{ SqueueTable: table.New(table.WithColumns(jobtab.SqueueTabCols), table.WithRows(jobtab.TableRows{}), table.WithStyles(s)), - Filter: ti, + Filter: ti, }, JobHistTab: jobhisttab.JobHistTab{ SacctTable: table.New(table.WithColumns(jobhisttab.SacctTabCols), table.WithRows(jobtab.TableRows{}), table.WithStyles(s)), - Filter: ti, + Filter: ti, UserInputs: jobhisttab.NewUserInputs(cc.JobHist.Timeout, cc.JobHist.Starttime, cc.JobHist.Endtime), HistFetched: false, HistFetchFail: false, @@ -130,10 +130,14 @@ func main() { }, ClusterTab: clustertab.ClusterTab{ SinfoTable: table.New(table.WithColumns(clustertab.SinfoTabCols), table.WithRows(jobtab.TableRows{}), table.WithStyles(s)), - Filter: ti, + Filter: ti, }, } + m.ClusterTab.SinfoTable.CustomCellStyle = new(clustertab.CellStyle) + m.ClusterTab.SinfoTable.CustomRowStyle = new(clustertab.RowStyle) + m.ClusterTab.SinfoTable.CustomSelectedStyle = new(clustertab.SelectedStyle) + // OLD: bubbletea@v0.22.1 //p := tea.NewProgram(tea.Model(m), tea.WithAltScreen()) //if err := p.Start(); err != nil { diff --git a/internal/model/tabs/clustertab/clustertabtable.go b/internal/model/tabs/clustertab/clustertabtable.go index 6f09425..8bde228 100644 --- a/internal/model/tabs/clustertab/clustertabtable.go +++ b/internal/model/tabs/clustertab/clustertabtable.go @@ -8,7 +8,9 @@ import ( "github.com/CLIP-HPC/SlurmCommander/internal/command" "github.com/CLIP-HPC/SlurmCommander/internal/slurm" + "github.com/CLIP-HPC/SlurmCommander/internal/styles" "github.com/CLIP-HPC/SlurmCommander/internal/table" + "github.com/charmbracelet/lipgloss" ) const ( @@ -64,6 +66,29 @@ var SinfoTabCols = []table.Column{ type SinfoJSON slurm.SinfoJSON type TableRows []table.Row +type CellStyle struct{} +type RowStyle struct{} +type SelectedStyle struct{} + +func (h CellStyle) Style(i int, r table.Row) lipgloss.Style { + switch r[i] { + case "down": + return styles.TextRed + case "mixed": + return styles.TextOrange + default: + return lipgloss.NewStyle() + } +} + +func (h RowStyle) Style(i int, r table.Row) lipgloss.Style { + return lipgloss.NewStyle() +} + +func (h SelectedStyle) Style(i int, r table.Row) lipgloss.Style { + return styles.SelectedRow +} + func (siJson *SinfoJSON) FilterSinfoTable(f string, l *log.Logger) (*TableRows, *SinfoJSON, *command.ErrorMsg) { var ( siTabRows = TableRows{} diff --git a/internal/styles/styles.go b/internal/styles/styles.go index 3af6922..c093379 100644 --- a/internal/styles/styles.go +++ b/internal/styles/styles.go @@ -5,15 +5,11 @@ import ( ) var ( - // Blue - Blue = lipgloss.Color("#0057b7") - // Yellow + Blue = lipgloss.Color("#0057b7") Yellow = lipgloss.Color("#ffd700") - // Red - Red = lipgloss.Color("#cc0000") - //red = lipgloss.Color("#b30000") - //Green = lipgloss.Color("#009900") - Green = lipgloss.Color("#00b300") + Red = lipgloss.Color("#cc0000") + Green = lipgloss.Color("#00b300") + Orange = lipgloss.Color("#FFA500") Bluegrey = lipgloss.Color("#c2d1f0") @@ -22,9 +18,14 @@ var ( TextYellow = lipgloss.NewStyle().Foreground(Yellow) TextGreen = lipgloss.NewStyle().Foreground(Green) TextBlue = lipgloss.NewStyle().Foreground(Blue) + TextOrange = lipgloss.NewStyle().Foreground(Orange) TextBlueGrey = lipgloss.NewStyle().Foreground(Bluegrey) TextYellowOnBlue = lipgloss.NewStyle().Foreground(Yellow).Background(Blue).Underline(true) + // Table styles + //SelectedRow = lipgloss.NewStyle().Background(Blue).Foreground(Yellow).Bold(false) + SelectedRow = lipgloss.NewStyle().Background(Blue).Foreground(Yellow) + // ErrorHelp Box //ErrorHelp = lipgloss.NewStyle().Foreground(red).Border(lipgloss.RoundedBorder()).BorderForeground(red) ErrorHelp = lipgloss.NewStyle().Foreground(Red) diff --git a/internal/table/table.go b/internal/table/table.go index 2324f9a..7913c82 100644 --- a/internal/table/table.go +++ b/internal/table/table.go @@ -19,11 +19,22 @@ type Model struct { cursor int focus bool styles Styles + CustomStyles viewport viewport.Model renderedLines } +type CustomStyles struct { + CustomCellStyle CustomStyle + CustomRowStyle CustomStyle + CustomSelectedStyle CustomStyle +} + +type CustomStyle interface { + Style(int, Row) lipgloss.Style +} + type renderedLines struct { start, end int } @@ -393,19 +404,52 @@ func (m Model) headersView() string { } func (m *Model) renderRow(rowID int) string { - var s = make([]string, 0, len(m.cols)) + var ( + selStyle lipgloss.Style + rowStyle lipgloss.Style + cellStyles = make([]lipgloss.Style, len(m.cols)) + s = make([]string, 0, len(m.cols)) + ) + + // Prepare RowStyle + if m.CustomRowStyle != nil { + rowStyle = m.CustomRowStyle.Style(rowID, m.rows[rowID]) + } else { + // We don't have rowstyle separately, what now? + // do an empty one? or m.Styles.Cell ??? + rowStyle = lipgloss.NewStyle() + } + // If row is selected, prepare selStyle + if rowID == m.cursor { + if m.CustomSelectedStyle != nil { + selStyle = m.CustomSelectedStyle.Style(rowID, m.rows[rowID]) + } else { + selStyle = m.styles.Selected + } + } else { + selStyle = lipgloss.NewStyle() + } + // For each cell in a row get its style and save it + for i := range m.rows[rowID] { + if m.CustomCellStyle != nil { + cellStyles[i] = m.CustomCellStyle.Style(i, m.rows[rowID]) + } else { + cellStyles[i] = m.styles.Cell + } + } + // Loop through the cells again Render() with overlayed styles for i, value := range m.rows[rowID] { 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, "…"))) + overlayedStyle := cellStyles[i].Inherit(rowStyle) + overlayedStyle = overlayedStyle.Copy().Inherit(selStyle) + //renderedCell := cellStyles[i].Inherit(rowStyle).Render(style.Render(runewidth.Truncate(value, m.cols[i].Width, "…"))) + renderedCell := overlayedStyle.Render(style.Render(runewidth.Truncate(value, m.cols[i].Width, "…"))) + s = append(s, renderedCell) } row := lipgloss.JoinHorizontal(lipgloss.Left, s...) - if rowID == m.cursor { - return m.styles.Selected.Render(row) - } - return row } From fffabb0eb6954d48102d44b9eb1a2aa2813f1294 Mon Sep 17 00:00:00 2001 From: "Jager,Petar" Date: Fri, 24 Feb 2023 18:42:11 +0100 Subject: [PATCH 2/2] fix: padding bug, add: more colors --- internal/model/tabs/clustertab/clustertabtable.go | 14 +++++++++++--- internal/styles/styles.go | 14 +++++++++----- internal/table/table.go | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/internal/model/tabs/clustertab/clustertabtable.go b/internal/model/tabs/clustertab/clustertabtable.go index 8bde228..ff48136 100644 --- a/internal/model/tabs/clustertab/clustertabtable.go +++ b/internal/model/tabs/clustertab/clustertabtable.go @@ -71,11 +71,19 @@ type RowStyle struct{} type SelectedStyle struct{} func (h CellStyle) Style(i int, r table.Row) lipgloss.Style { - switch r[i] { - case "down": + switch { + case r[2] == "down": + return styles.TextDarkRed + case strings.Contains(r[9], "NOT_RESPONDING"): + return styles.TextDarkRed + case i == 2 && r[i] == "allocated": return styles.TextRed - case "mixed": + case i == 2 && r[i] == "idle": + return styles.TextGreenIdle + case i == 2 && r[i] == "mixed": return styles.TextOrange + case i == 9 && strings.Contains(r[i], "POWERED_DOWN"): + return styles.TextDarkRed default: return lipgloss.NewStyle() } diff --git a/internal/styles/styles.go b/internal/styles/styles.go index c093379..6bf8c5c 100644 --- a/internal/styles/styles.go +++ b/internal/styles/styles.go @@ -5,18 +5,22 @@ import ( ) var ( - Blue = lipgloss.Color("#0057b7") - Yellow = lipgloss.Color("#ffd700") - Red = lipgloss.Color("#cc0000") - Green = lipgloss.Color("#00b300") - Orange = lipgloss.Color("#FFA500") + Blue = lipgloss.Color("#0057b7") + Yellow = lipgloss.Color("#ffd700") + Red = lipgloss.Color("#cc0000") + DarkRed = lipgloss.Color("#990000") + Green = lipgloss.Color("#00b300") + GreenIdle = lipgloss.Color("#00cc66") + Orange = lipgloss.Color("#FF8000") Bluegrey = lipgloss.Color("#c2d1f0") // Generic text color styles TextRed = lipgloss.NewStyle().Foreground(Red) + TextDarkRed = lipgloss.NewStyle().Foreground(DarkRed) TextYellow = lipgloss.NewStyle().Foreground(Yellow) TextGreen = lipgloss.NewStyle().Foreground(Green) + TextGreenIdle = lipgloss.NewStyle().Foreground(GreenIdle) TextBlue = lipgloss.NewStyle().Foreground(Blue) TextOrange = lipgloss.NewStyle().Foreground(Orange) TextBlueGrey = lipgloss.NewStyle().Foreground(Bluegrey) diff --git a/internal/table/table.go b/internal/table/table.go index 7913c82..503a1c4 100644 --- a/internal/table/table.go +++ b/internal/table/table.go @@ -441,7 +441,7 @@ func (m *Model) renderRow(rowID int) string { for i, value := range m.rows[rowID] { style := lipgloss.NewStyle().Width(m.cols[i].Width).MaxWidth(m.cols[i].Width).Inline(true) overlayedStyle := cellStyles[i].Inherit(rowStyle) - overlayedStyle = overlayedStyle.Copy().Inherit(selStyle) + overlayedStyle = overlayedStyle.Copy().Inherit(selStyle).Padding(0, 1) //renderedCell := cellStyles[i].Inherit(rowStyle).Render(style.Render(runewidth.Truncate(value, m.cols[i].Width, "…"))) renderedCell := overlayedStyle.Render(style.Render(runewidth.Truncate(value, m.cols[i].Width, "…")))