From ecf71ff3c817196fbbda637abda3e7fd53d3283a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Ram=C3=B3n?= Date: Fri, 16 May 2025 12:47:31 -0500 Subject: [PATCH 1/7] bubbletea/tablemodel: adds bubbletea table --- bubbletea/tablemodel.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/bubbletea/tablemodel.go b/bubbletea/tablemodel.go index d0634cb..5ed8c14 100644 --- a/bubbletea/tablemodel.go +++ b/bubbletea/tablemodel.go @@ -8,12 +8,12 @@ import ( // `TableModel` represents the component that implements the `Model` interface. type TableModel struct { + // baseStyle is the base styling for the `table` model. + baseStyle lipgloss.Style + // table is the `bubbletea` table model. // TODO(@chris-ramon): Wire to the `TableModel` component. table table.Model - - // baseStyle is the base styling for the `table` model. - baseStyle lipgloss.Style } // `Init` is the `TableModel` method required for implementing the `Model` interface. @@ -84,7 +84,18 @@ type TableModelParams struct { // `NewTableModel` returns a pointer to a `TableModel`. func NewTableModel(p *TableModelParams) *TableModel { + columns := []table.Column{} + rows := []table.Row{} + + t := table.New( + table.WithColumns(columns), + table.WithRows(rows), + table.WithFocused(true), + table.WithHeight(7), + ) + return &TableModel{ baseStyle: p.BaseStyle, + table: t, } } From 68430ff07ed069851113c2268f94461f7ad9616b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Ram=C3=B3n?= Date: Mon, 19 May 2025 07:19:24 -0500 Subject: [PATCH 2/7] bubbletea: handles current model update method upstream --- bubbletea/bubbletea.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bubbletea/bubbletea.go b/bubbletea/bubbletea.go index 84d67c9..af646b1 100644 --- a/bubbletea/bubbletea.go +++ b/bubbletea/bubbletea.go @@ -35,12 +35,13 @@ func (b BubbleTea) Init() tea.Cmd { // Update is the `BubbleTea` method required for implementing the `Model` interface. func (b BubbleTea) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - return b.currentModel.Update(msg) + _, cmd := b.currentModel.Update(msg) + return b, cmd } // View is the `BubbleTea` method required for implementing the `Model` interface. func (b BubbleTea) View() string { - return b.baseStyle.Render(b.currentModel.View()) + "\n" + return b.currentModel.View() } // Run runs the `BubbleTea` component and returns its result. From b4b8caab78228a7921c24cb388c99ce7ffddbb96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Ram=C3=B3n?= Date: Mon, 19 May 2025 09:35:34 -0500 Subject: [PATCH 3/7] bubbletea: removes unused ChoicesModel.table field --- bubbletea/choicesmodel.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/bubbletea/choicesmodel.go b/bubbletea/choicesmodel.go index 2c4746f..2b1b6c8 100644 --- a/bubbletea/choicesmodel.go +++ b/bubbletea/choicesmodel.go @@ -3,7 +3,6 @@ package bubbletea import ( "strings" - "github.com/charmbracelet/bubbles/table" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" ) @@ -22,10 +21,6 @@ type ChoicesModel struct { // ui is the UI of the CLI. ui ChoicesModelUI - // table is the bubbletea table model. - // TODO(@chris-ramon): Make it available through multiple model support. - table table.Model //nolint:golint,unused - // baseStyle is the base styling of the BubbleTea component. baseStyle lipgloss.Style } From be81b82242b3d917f540b967eedeae11f3c48e75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Ram=C3=B3n?= Date: Mon, 19 May 2025 09:35:57 -0500 Subject: [PATCH 4/7] bubbletea: syncs unit tests --- bubbletea/bubbletea_view_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bubbletea/bubbletea_view_test.go b/bubbletea/bubbletea_view_test.go index 0c8d127..b690b20 100644 --- a/bubbletea/bubbletea_view_test.go +++ b/bubbletea/bubbletea_view_test.go @@ -24,7 +24,7 @@ func TestBubbleTeaView(t *testing.T) { }), BaseStyle: NewBaseStyle(), }), - expectedView: "┌────────────────────────────────────────────────────────────────────────────────┐\n│ │\n│ ┌──────────────────────────────────────────────────────────────────────────────│\n│ ──┐ │\n│ │ │\n│ │ │\n│ │ test-header: │\n│ │ │\n│ │ (•) test-choice-0 │\n│ │ │\n│ │ │\n│ │ │\n│ │ (press q to quit) │\n│ │ │\n│ │ │\n│ │ │\n│ └──────────────────────────────────────────────────────────────────────────────│\n│ ──┘ │\n│ │\n└────────────────────────────────────────────────────────────────────────────────┘\n", + expectedView: "┌────────────────────────────────────────────────────────────────────────────────┐\n│ │\n│ test-header: │\n│ (•) test-choice-0 │\n│ │\n│ (press q to quit) │\n│ │\n└────────────────────────────────────────────────────────────────────────────────┘\n", }, { subTestName: "Handles success view result with multiple choices", @@ -37,7 +37,7 @@ func TestBubbleTeaView(t *testing.T) { }), BaseStyle: NewBaseStyle(), }), - expectedView: "┌────────────────────────────────────────────────────────────────────────────────┐\n│ │\n│ ┌──────────────────────────────────────────────────────────────────────────────│\n│ ──┐ │\n│ │ │\n│ │ │\n│ │ test-header: │\n│ │ │\n│ │ (•) test-choice-0 │\n│ │ │\n│ │ ( ) test-choice-1 │\n│ │ │\n│ │ │\n│ │ │\n│ │ (press q to quit) │\n│ │ │\n│ │ │\n│ │ │\n│ └──────────────────────────────────────────────────────────────────────────────│\n│ ──┘ │\n│ │\n└────────────────────────────────────────────────────────────────────────────────┘\n", + expectedView: "┌────────────────────────────────────────────────────────────────────────────────┐\n│ │\n│ test-header: │\n│ (•) test-choice-0 │\n│ ( ) test-choice-1 │\n│ │\n│ (press q to quit) │\n│ │\n└────────────────────────────────────────────────────────────────────────────────┘\n", }, } From b27f0d1f9010bbab4ee67740ec2aac3f053b4c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Ram=C3=B3n?= Date: Mon, 19 May 2025 13:07:07 -0500 Subject: [PATCH 5/7] bubbletea: adds Model updates and improves Bubbletea.Update method --- bubbletea/bubbletea.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/bubbletea/bubbletea.go b/bubbletea/bubbletea.go index af646b1..ec7a22c 100644 --- a/bubbletea/bubbletea.go +++ b/bubbletea/bubbletea.go @@ -9,8 +9,14 @@ import ( // Model represents the component that wraps the `bubbletea` Model interface. type Model interface { - // tea.Model is the base interface. - tea.Model + // Init initializes the model and returns the next tea command. + Init() tea.Cmd + + // Update updates the model and returns the same model and the next tea command. + Update(msg tea.Msg) (Model, tea.Cmd) + + // View returns the model view representation. + View() string // Run runs and returns its result. Run(modelResult any) (any, error) @@ -35,7 +41,8 @@ func (b BubbleTea) Init() tea.Cmd { // Update is the `BubbleTea` method required for implementing the `Model` interface. func (b BubbleTea) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - _, cmd := b.currentModel.Update(msg) + model, cmd := b.currentModel.Update(msg) + b.currentModel = model return b, cmd } From c0179866e29f28a39a23f9389424a2270ae30304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Ram=C3=B3n?= Date: Mon, 19 May 2025 13:07:24 -0500 Subject: [PATCH 6/7] bubbletea: syncs ChoicesModel.Update method --- bubbletea/choicesmodel.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bubbletea/choicesmodel.go b/bubbletea/choicesmodel.go index 2b1b6c8..78ccb44 100644 --- a/bubbletea/choicesmodel.go +++ b/bubbletea/choicesmodel.go @@ -37,7 +37,7 @@ func (b ChoicesModel) Init() tea.Cmd { } // Update is the `BubbleTea` method required for implementing the `Model` interface. -func (b ChoicesModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { //nolint:golint,ireturn +func (b *ChoicesModel) Update(msg tea.Msg) (Model, tea.Cmd) { //nolint:golint,ireturn keyMsg, ok := msg.(tea.KeyMsg) if !ok { return b, nil From 2e5695b05b3ad8e1e101db8a91d59021ada561a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Ram=C3=B3n?= Date: Mon, 19 May 2025 13:07:41 -0500 Subject: [PATCH 7/7] bubbletea: syncs unit tests --- bubbletea/bubbletea_update_test.go | 51 +++++++++++++++++++----------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/bubbletea/bubbletea_update_test.go b/bubbletea/bubbletea_update_test.go index 2bad46b..b2d2635 100644 --- a/bubbletea/bubbletea_update_test.go +++ b/bubbletea/bubbletea_update_test.go @@ -14,7 +14,7 @@ func TestBubbleTeaUpdate(t *testing.T) { subTestName string initialBubbletea tea.Model updateParams tea.Msg - expectedModel *ChoicesModel + expectedModel *BubbleTea expectedCmd tea.Cmd }{ { @@ -24,7 +24,8 @@ func TestBubbleTeaUpdate(t *testing.T) { BaseStyle: NewBaseStyle(), }), updateParams: nil, - expectedModel: NewChoicesModel(&ChoicesModelParams{ + expectedModel: New(&Params{ + Model: NewChoicesModel(&ChoicesModelParams{}), BaseStyle: NewBaseStyle(), }), expectedCmd: (tea.Cmd)(nil), @@ -38,7 +39,8 @@ func TestBubbleTeaUpdate(t *testing.T) { updateParams: tea.KeyMsg{ Type: tea.KeyCtrlC, }, - expectedModel: NewChoicesModel(&ChoicesModelParams{ + expectedModel: New(&Params{ + Model: NewChoicesModel(&ChoicesModelParams{}), BaseStyle: NewBaseStyle(), }), expectedCmd: tea.Quit, @@ -54,10 +56,13 @@ func TestBubbleTeaUpdate(t *testing.T) { updateParams: tea.KeyMsg{ Type: tea.KeyEnter, }, - expectedModel: NewChoicesModel(&ChoicesModelParams{ - Cursor: 0, - Choices: []string{"test-choice-0"}, - Choice: "test-choice-0", + expectedModel: New(&Params{ + Model: NewChoicesModel(&ChoicesModelParams{ + Cursor: 0, + Choices: []string{"test-choice-0"}, + Choice: "test-choice-0", + BaseStyle: NewBaseStyle(), + }), BaseStyle: NewBaseStyle(), }), expectedCmd: tea.Quit, @@ -74,9 +79,11 @@ func TestBubbleTeaUpdate(t *testing.T) { Type: tea.KeyRunes, Runes: []rune("j"), }, - expectedModel: NewChoicesModel(&ChoicesModelParams{ - Cursor: 1, - Choices: []string{"test-choice-0", "test-choice-1"}, + expectedModel: New(&Params{ + Model: NewChoicesModel(&ChoicesModelParams{ + Cursor: 1, + Choices: []string{"test-choice-0", "test-choice-1"}, + }), BaseStyle: NewBaseStyle(), }), expectedCmd: nil, @@ -94,9 +101,11 @@ func TestBubbleTeaUpdate(t *testing.T) { Type: tea.KeyRunes, Runes: []rune("j"), }, - expectedModel: NewChoicesModel(&ChoicesModelParams{ - Cursor: 0, - Choices: []string{"test-choice-0", "test-choice-1"}, + expectedModel: New(&Params{ + Model: NewChoicesModel(&ChoicesModelParams{ + Cursor: 0, + Choices: []string{"test-choice-0", "test-choice-1"}, + }), BaseStyle: NewBaseStyle(), }), expectedCmd: nil, @@ -114,9 +123,11 @@ func TestBubbleTeaUpdate(t *testing.T) { Type: tea.KeyRunes, Runes: []rune("k"), }, - expectedModel: NewChoicesModel(&ChoicesModelParams{ - Cursor: 0, - Choices: []string{"test-choice-0", "test-choice-1"}, + expectedModel: New(&Params{ + Model: NewChoicesModel(&ChoicesModelParams{ + Cursor: 0, + Choices: []string{"test-choice-0", "test-choice-1"}, + }), BaseStyle: NewBaseStyle(), }), expectedCmd: nil, @@ -134,9 +145,11 @@ func TestBubbleTeaUpdate(t *testing.T) { Type: tea.KeyRunes, Runes: []rune("k"), }, - expectedModel: NewChoicesModel(&ChoicesModelParams{ - Cursor: 0, - Choices: []string{"test-choice-0"}, + expectedModel: New(&Params{ + Model: NewChoicesModel(&ChoicesModelParams{ + Cursor: 0, + Choices: []string{"test-choice-0"}, + }), BaseStyle: NewBaseStyle(), }), expectedCmd: nil,