From 9709e6aed1ddc4a38db8dc764789220e437ecedb Mon Sep 17 00:00:00 2001 From: Leon Mika Date: Mon, 28 Mar 2022 21:36:47 +1100 Subject: [PATCH] table-select: cleanup --- cmd/dynamo-browse/main.go | 116 +------ internal/common/ui/commandctrl/commandctrl.go | 54 ++-- internal/common/ui/commandctrl/types.go | 11 + .../dynamo-browse/controllers/tableread.go | 9 - internal/dynamo-browse/ui/iface.go | 7 - internal/dynamo-browse/ui/model.go | 7 +- internal/dynamo-browse/ui/modelold.go | 303 ------------------ internal/dynamo-browse/ui/sizewaitmodel.go | 48 --- internal/dynamo-browse/ui/tableselectmodel.go | 95 ------ .../ui/teamodels/dynamotableview/model.go | 15 +- .../dynamo-browse/ui/teamodels/modalevents.go | 9 - .../dynamo-browse/ui/teamodels/testmodel.go | 33 -- 12 files changed, 68 insertions(+), 639 deletions(-) create mode 100644 internal/common/ui/commandctrl/types.go delete mode 100644 internal/dynamo-browse/ui/iface.go delete mode 100644 internal/dynamo-browse/ui/modelold.go delete mode 100644 internal/dynamo-browse/ui/sizewaitmodel.go delete mode 100644 internal/dynamo-browse/ui/tableselectmodel.go delete mode 100644 internal/dynamo-browse/ui/teamodels/modalevents.go delete mode 100644 internal/dynamo-browse/ui/teamodels/testmodel.go diff --git a/cmd/dynamo-browse/main.go b/cmd/dynamo-browse/main.go index 7347638..4f5312f 100644 --- a/cmd/dynamo-browse/main.go +++ b/cmd/dynamo-browse/main.go @@ -4,25 +4,18 @@ import ( "context" "flag" "fmt" - "log" - "os" - "time" - "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/dynamodb" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/lmika/awstools/internal/common/ui/commandctrl" - "github.com/lmika/awstools/internal/common/ui/dispatcher" - "github.com/lmika/awstools/internal/common/ui/uimodels" "github.com/lmika/awstools/internal/dynamo-browse/controllers" "github.com/lmika/awstools/internal/dynamo-browse/providers/dynamo" "github.com/lmika/awstools/internal/dynamo-browse/services/tables" "github.com/lmika/awstools/internal/dynamo-browse/ui" - "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels" - "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/modal" - "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/tableselect" "github.com/lmika/gopkgs/cli" + "log" + "os" ) func main() { @@ -32,10 +25,7 @@ func main() { ctx := context.Background() - // TEMP cfg, err := config.LoadDefaultConfig(ctx) - - // END TEMP if err != nil { cli.Fatalf("cannot load AWS config: %v", err) } @@ -52,70 +42,22 @@ func main() { tableService := tables.NewService(dynamoProvider) - loopback := &msgLoopback{} - uiDispatcher := dispatcher.NewDispatcher(loopback) - tableReadController := controllers.NewTableReadController(tableService, *flagTable) tableWriteController := controllers.NewTableWriteController(tableService, tableReadController, *flagTable) + _ = tableWriteController - commandController := commandctrl.NewCommandController(map[string]uimodels.Operation{ - // "scan": tableReadController.Scan(), - "rw": tableWriteController.ToggleReadWrite(), - "dup": tableWriteController.Duplicate(), + commandController := commandctrl.NewCommandController(map[string]commandctrl.Command{ + "q": commandctrl.NoArgCommand(tea.Quit), + //"rw": tableWriteController.ToggleReadWrite(), + //"dup": tableWriteController.Duplicate(), }) - _ = uiDispatcher - _ = commandController - - // uiModel := ui.NewModel(uiDispatcher, commandController, tableReadController, tableWriteController) - - // TEMP - // _ = uiModel - // END TEMP - - /* - var model tea.Model = statusandprompt.New( - layout.NewVBox( - layout.LastChildFixedAt(11), - dynamotableview.New(tableReadController), - dynamoitemview.New(), - ), - "Hello world", - ) - model = layout.FullScreen(tableselect.New(model)) - */ - model := ui.NewModel(tableReadController) + model := ui.NewModel(tableReadController, commandController) // Pre-determine if layout has dark background. This prevents calls for creating a list to hang. lipgloss.HasDarkBackground() - //frameSet := frameset.New([]frameset.Frame{ - // { - // Header: "Frame 1", - // Model: newTestModel("this is model 1"), - // }, - // { - // Header: "Frame 2", - // Model: newTestModel("this is model 2"), - // }, - //}) - // - //modal := modal.New(frameSet) - p := tea.NewProgram(model, tea.WithAltScreen()) - //loopback.program = p - - // TEMP -- profiling - //cf, err := os.Create("trace.out") - //if err != nil { - // log.Fatal("could not create CPU profile: ", err) - //} - //defer cf.Close() // error handling omitted for example - //if err := trace.Start(cf); err != nil { - // log.Fatal("could not start CPU profile: ", err) - //} - //defer trace.Stop() - // END TEMP f, err := tea.LogToFile("debug.log", "debug") if err != nil { @@ -131,37 +73,11 @@ func main() { } } -type msgLoopback struct { - program *tea.Program -} - -func (m *msgLoopback) Send(msg tea.Msg) { - m.program.Send(msg) -} - -func newTestModel(descr string) tea.Model { - return teamodels.TestModel{ - Message: descr, - OnKeyPressed: func(k string) tea.Cmd { - log.Println("got key press: " + k) - if k == "enter" { - return tea.Batch( - tableselect.IndicateLoadingTables(), - tea.Sequentially( - func() tea.Msg { - <-time.After(2 * time.Second) - return nil - }, - tableselect.ShowTableSelect(func(n string) tea.Cmd { - // return statusandprompt.SetStatus("New table = " + n) - return nil - }), - ), - ) - } else if k == "k" { - return modal.PopMode - } - return nil - }, - } -} +// +//type msgLoopback struct { +// program *tea.Program +//} +// +//func (m *msgLoopback) Send(msg tea.Msg) { +// m.program.Send(msg) +//} diff --git a/internal/common/ui/commandctrl/commandctrl.go b/internal/common/ui/commandctrl/commandctrl.go index 298e88c..92a384a 100644 --- a/internal/common/ui/commandctrl/commandctrl.go +++ b/internal/common/ui/commandctrl/commandctrl.go @@ -1,49 +1,45 @@ package commandctrl import ( - "context" + tea "github.com/charmbracelet/bubbletea" "strings" "github.com/lmika/awstools/internal/common/ui/events" - "github.com/lmika/awstools/internal/common/ui/uimodels" "github.com/lmika/shellwords" - "github.com/pkg/errors" ) type CommandController struct { - commands map[string]uimodels.Operation + commands map[string]Command } -func NewCommandController(commands map[string]uimodels.Operation) *CommandController { +func NewCommandController(commands map[string]Command) *CommandController { return &CommandController{ commands: commands, } } -func (c *CommandController) Prompt() uimodels.Operation { - return uimodels.OperationFn(func(ctx context.Context) error { - uiCtx := uimodels.Ctx(ctx) - uiCtx.Send(events.PromptForInputMsg{ +func (c *CommandController) Prompt() tea.Cmd { + return func() tea.Msg { + return events.PromptForInputMsg{ Prompt: ":", - // OnDone: c.Execute(), - }) + OnDone: func(value string) tea.Cmd { + return c.Execute(value) + }, + } + } +} + +func (c *CommandController) Execute(commandInput string) tea.Cmd { + input := strings.TrimSpace(commandInput) + if input == "" { return nil - }) -} - -func (c *CommandController) Execute() uimodels.Operation { - return uimodels.OperationFn(func(ctx context.Context) error { - input := strings.TrimSpace(uimodels.PromptValue(ctx)) - if input == "" { - return nil - } - - tokens := shellwords.Split(input) - command, ok := c.commands[tokens[0]] - if !ok { - return errors.New("no such command: " + tokens[0]) - } - - return command.Execute(WithCommandArgs(ctx, tokens[1:])) - }) + } + + tokens := shellwords.Split(input) + command, ok := c.commands[tokens[0]] + if !ok { + return events.SetStatus("no such command: " + tokens[0]) + } + + return command(tokens) } diff --git a/internal/common/ui/commandctrl/types.go b/internal/common/ui/commandctrl/types.go new file mode 100644 index 0000000..ca6d9ca --- /dev/null +++ b/internal/common/ui/commandctrl/types.go @@ -0,0 +1,11 @@ +package commandctrl + +import tea "github.com/charmbracelet/bubbletea" + +type Command func(args []string) tea.Cmd + +func NoArgCommand(cmd tea.Cmd) Command { + return func(args []string) tea.Cmd { + return cmd + } +} diff --git a/internal/dynamo-browse/controllers/tableread.go b/internal/dynamo-browse/controllers/tableread.go index 670c4f1..90b7d00 100644 --- a/internal/dynamo-browse/controllers/tableread.go +++ b/internal/dynamo-browse/controllers/tableread.go @@ -2,8 +2,6 @@ package controllers import ( "context" - "log" - tea "github.com/charmbracelet/bubbletea" "github.com/lmika/awstools/internal/common/ui/events" "github.com/lmika/awstools/internal/dynamo-browse/models" @@ -52,20 +50,16 @@ func (c *TableReadController) scanTable(name string) tea.Cmd { return func() tea.Msg { ctx := context.Background() - log.Println("Fetching table info") tableInfo, err := c.tableService.Describe(ctx, name) if err != nil { return events.Error(errors.Wrapf(err, "cannot describe %v", c.tableName)) } - log.Println("Scanning") resultSet, err := c.tableService.Scan(ctx, tableInfo) if err != nil { - log.Println("error: ", err) return events.Error(err) } - log.Println("Scan done") return NewResultSet{resultSet} } } @@ -74,14 +68,11 @@ func (c *TableReadController) Rescan(resultSet *models.ResultSet) tea.Cmd { return func() tea.Msg { ctx := context.Background() - log.Println("Scanning") resultSet, err := c.tableService.Scan(ctx, resultSet.TableInfo) if err != nil { - log.Println("error: ", err) return events.Error(err) } - log.Println("Scan done") return NewResultSet{resultSet} } } diff --git a/internal/dynamo-browse/ui/iface.go b/internal/dynamo-browse/ui/iface.go deleted file mode 100644 index ade311a..0000000 --- a/internal/dynamo-browse/ui/iface.go +++ /dev/null @@ -1,7 +0,0 @@ -package ui - -import tea "github.com/charmbracelet/bubbletea" - -type MessagePublisher interface { - Send(msg tea.Msg) -} diff --git a/internal/dynamo-browse/ui/model.go b/internal/dynamo-browse/ui/model.go index 2215d7f..e2b8362 100644 --- a/internal/dynamo-browse/ui/model.go +++ b/internal/dynamo-browse/ui/model.go @@ -2,6 +2,7 @@ package ui import ( tea "github.com/charmbracelet/bubbletea" + "github.com/lmika/awstools/internal/common/ui/commandctrl" "github.com/lmika/awstools/internal/dynamo-browse/controllers" "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/dynamoitemview" "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/dynamotableview" @@ -12,12 +13,13 @@ import ( type Model struct { tableReadController *controllers.TableReadController + commandController *commandctrl.CommandController root tea.Model } -func NewModel(rc *controllers.TableReadController) Model { - dtv := dynamotableview.New(rc) +func NewModel(rc *controllers.TableReadController, cc *commandctrl.CommandController) Model { + dtv := dynamotableview.New(rc, cc) div := dynamoitemview.New() m := statusandprompt.New( @@ -28,6 +30,7 @@ func NewModel(rc *controllers.TableReadController) Model { return Model{ tableReadController: rc, + commandController: cc, root: root, } } diff --git a/internal/dynamo-browse/ui/modelold.go b/internal/dynamo-browse/ui/modelold.go deleted file mode 100644 index f24fedc..0000000 --- a/internal/dynamo-browse/ui/modelold.go +++ /dev/null @@ -1,303 +0,0 @@ -package ui - -import ( - "context" - "strings" - - table "github.com/calyptia/go-bubble-table" - "github.com/charmbracelet/bubbles/textinput" - "github.com/charmbracelet/bubbles/viewport" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" - "github.com/lmika/awstools/internal/common/ui/commandctrl" - "github.com/lmika/awstools/internal/common/ui/dispatcher" - "github.com/lmika/awstools/internal/common/ui/uimodels" - "github.com/lmika/awstools/internal/dynamo-browse/controllers" -) - -var ( - activeHeaderStyle = lipgloss.NewStyle(). - Bold(true). - Foreground(lipgloss.Color("#ffffff")). - Background(lipgloss.Color("#4479ff")) - - inactiveHeaderStyle = lipgloss.NewStyle(). - Foreground(lipgloss.Color("#000000")). - Background(lipgloss.Color("#d1d1d1")) -) - -type uiModel struct { - table table.Model - viewport viewport.Model - - // TEMP - tableSelect tea.Model - - tableWidth, tableHeight int - - ready bool - state controllers.State - message string - - // pendingInput *events.PromptForInput - textInput textinput.Model - - dispatcher *dispatcher.Dispatcher - commandController *commandctrl.CommandController - tableReadController *controllers.TableReadController - tableWriteController *controllers.TableWriteController -} - -func NewModelOld(dispatcher *dispatcher.Dispatcher, commandController *commandctrl.CommandController, tableReadController *controllers.TableReadController, tableWriteController *controllers.TableWriteController) tea.Model { - tbl := table.New([]string{"pk", "sk"}, 100, 20) - rows := make([]table.Row, 0) - tbl.SetRows(rows) - - textInput := textinput.New() - - model := uiModel{ - table: tbl, - message: "Press s to scan", - textInput: textInput, - - // TEMP - tableSelect: newSizeWaitModel(func(w, h int) tea.Model { - return newTableSelectModel(w, h) - }), - - dispatcher: dispatcher, - commandController: commandController, - tableReadController: tableReadController, - tableWriteController: tableWriteController, - } - - return model -} - -func (m uiModel) Init() tea.Cmd { - //m.invokeOperation(context.Background(), m.tableReadController.Scan()) - return nil -} - -/* -func (m *uiModel) updateTable() { - if !m.ready { - return - } - - resultSet := m.state.ResultSet - newTbl := table.New(resultSet.Columns, m.tableWidth, m.tableHeight) - newRows := make([]table.Row, len(resultSet.Items)) - for i, r := range resultSet.Items { - newRows[i] = itemTableRow{resultSet, r} - } - newTbl.SetRows(newRows) - - m.table = newTbl -} - - - -func (m *uiModel) selectedItem() (itemTableRow, bool) { - resultSet := m.state.ResultSet - if m.ready && resultSet != nil && len(resultSet.Items) > 0 { - selectedItem, ok := m.table.SelectedRow().(itemTableRow) - if ok { - return selectedItem, true - } - } - - return itemTableRow{}, false -} - -func (m *uiModel) updateViewportToSelectedMessage() { - selectedItem, ok := m.selectedItem() - if !ok { - m.viewport.SetContent("(no row selected)") - return - } - - viewportContent := &strings.Builder{} - tabWriter := tabwriter.NewWriter(viewportContent, 0, 1, 1, ' ', 0) - for _, colName := range selectedItem.resultSet.Columns { - switch colVal := selectedItem.item[colName].(type) { - case nil: - break - case *types.AttributeValueMemberS: - fmt.Fprintf(tabWriter, "%v\tS\t%s\n", colName, colVal.Value) - case *types.AttributeValueMemberN: - fmt.Fprintf(tabWriter, "%v\tN\t%s\n", colName, colVal.Value) - default: - fmt.Fprintf(tabWriter, "%v\t?\t%s\n", colName, "(other)") - } - } - - tabWriter.Flush() - m.viewport.SetContent(viewportContent.String()) -} -*/ - -func (m uiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - var textInputCommands tea.Cmd - - switch msg := msg.(type) { - - // Local events - case controllers.NewResultSet: - m.state.ResultSet = msg.ResultSet - // m.updateTable() - // m.updateViewportToSelectedMessage() - case controllers.SetReadWrite: - m.state.InReadWriteMode = msg.NewValue - - // Shared events - // case events.Error: - // m.message = "Error: " + msg.Error() - // case events.Message: - // m.message = string(msg) - // case events.PromptForInput: - // m.textInput.Prompt = msg.Prompt - // m.textInput.Focus() - // m.textInput.SetValue("") - // m.pendingInput = &msg - - // Tea events - case tea.WindowSizeMsg: - fixedViewsHeight := lipgloss.Height(m.headerView()) + lipgloss.Height(m.splitterView()) + lipgloss.Height(m.footerView()) - viewportHeight := msg.Height / 2 // TODO: make this dynamic - if viewportHeight > 15 { - viewportHeight = 15 - } - tableHeight := msg.Height - fixedViewsHeight - viewportHeight - - if !m.ready { - m.viewport = viewport.New(msg.Width, viewportHeight) - m.viewport.SetContent("(no message selected)") - m.ready = true - } else { - m.viewport.Width = msg.Width - m.viewport.Height = msg.Height - tableHeight - fixedViewsHeight - } - - m.tableWidth, m.tableHeight = msg.Width, tableHeight - m.table.SetSize(m.tableWidth, m.tableHeight) - - case tea.KeyMsg: - - // If text input in focus, allow that to accept input messages - // if m.pendingInput != nil { - // switch msg.String() { - // case "ctrl+c", "esc": - // m.pendingInput = nil - // case "enter": - // m.invokeOperation(uimodels.WithPromptValue(context.Background(), m.textInput.Value()), m.pendingInput.OnDone) - // m.pendingInput = nil - // default: - // m.textInput, textInputCommands = m.textInput.Update(msg) - // } - // break - // } - - switch msg.String() { - case "ctrl+c", "q": - return m, tea.Quit - case "up", "i": - m.table.GoUp() - // m.updateViewportToSelectedMessage() - case "down", "k": - m.table.GoDown() - // m.updateViewportToSelectedMessage() - - // TODO: these should be moved somewhere else - case ":": - m.invokeOperation(context.Background(), m.commandController.Prompt()) - // case "s": - // m.invokeOperation(context.Background(), m.tableReadController.Scan()) - case "D": - m.invokeOperation(context.Background(), m.tableWriteController.Delete()) - } - default: - m.textInput, textInputCommands = m.textInput.Update(msg) - } - - updatedTable, tableMsgs := m.table.Update(msg) - updatedViewport, viewportMsgs := m.viewport.Update(msg) - updatedTableSelectModel, tableSelectMsgs := m.tableSelect.Update(msg) - - m.table = updatedTable - m.viewport = updatedViewport - m.tableSelect = updatedTableSelectModel - - return m, tea.Batch(textInputCommands, tableMsgs, viewportMsgs, tableSelectMsgs) -} - -func (m uiModel) invokeOperation(ctx context.Context, op uimodels.Operation) { - state := m.state - // if selectedItem, ok := m.selectedItem(); ok { - // state.SelectedItem = selectedItem.item - // } - - ctx = controllers.ContextWithState(ctx, state) - m.dispatcher.Start(ctx, op) -} - -func (m uiModel) View() string { - // TEMP - return m.tableSelect.View() - - /* - if !m.ready { - return "Initializing" - } - - if m.pendingInput != nil { - return lipgloss.JoinVertical(lipgloss.Top, - m.headerView(), - m.table.View(), - m.splitterView(), - m.viewport.View(), - m.textInput.View(), - ) - } - - return lipgloss.JoinVertical(lipgloss.Top, - m.headerView(), - m.table.View(), - m.splitterView(), - m.viewport.View(), - m.footerView(), - ) - */ -} - -func (m uiModel) headerView() string { - var titleText string - if m.state.ResultSet != nil { - titleText = "Table: " + m.state.ResultSet.TableInfo.Name - } else { - titleText = "No table" - } - - title := activeHeaderStyle.Render(titleText) - line := activeHeaderStyle.Render(strings.Repeat(" ", max(0, m.viewport.Width-lipgloss.Width(title)))) - return lipgloss.JoinHorizontal(lipgloss.Left, title, line) -} - -func (m uiModel) splitterView() string { - title := inactiveHeaderStyle.Render("Item") - line := inactiveHeaderStyle.Render(strings.Repeat(" ", max(0, m.viewport.Width-lipgloss.Width(title)))) - return lipgloss.JoinHorizontal(lipgloss.Left, title, line) -} - -func (m uiModel) footerView() string { - title := m.message - line := strings.Repeat(" ", max(0, m.viewport.Width-lipgloss.Width(title))) - return lipgloss.JoinHorizontal(lipgloss.Left, title, line) -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} diff --git a/internal/dynamo-browse/ui/sizewaitmodel.go b/internal/dynamo-browse/ui/sizewaitmodel.go deleted file mode 100644 index db57486..0000000 --- a/internal/dynamo-browse/ui/sizewaitmodel.go +++ /dev/null @@ -1,48 +0,0 @@ -package ui - -import ( - tea "github.com/charmbracelet/bubbletea" - "log" -) - -// sizeWaitModel is a model which waits until the first screen size message comes through. It then creates the -// submodel and delegates calls to that model -type sizeWaitModel struct { - constr func(width, height int) tea.Model - model tea.Model -} - -func newSizeWaitModel(constr func(width, height int) tea.Model) tea.Model { - return sizeWaitModel{constr: constr} -} - -func (s sizeWaitModel) Init() tea.Cmd { - return nil -} - -func (s sizeWaitModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch m := msg.(type) { - case tea.WindowSizeMsg: - log.Println("got window size message") - if s.model == nil { - log.Println("creating model") - s.model = s.constr(m.Width, m.Height) - s.model.Init() - } - } - - var submodelCmds tea.Cmd - if s.model != nil { - log.Println("starting update") - s.model, submodelCmds = s.model.Update(msg) - log.Println("ending update") - } - return s, submodelCmds -} - -func (s sizeWaitModel) View() string { - if s.model == nil { - return "" - } - return s.model.View() -} diff --git a/internal/dynamo-browse/ui/tableselectmodel.go b/internal/dynamo-browse/ui/tableselectmodel.go deleted file mode 100644 index c9d2c6b..0000000 --- a/internal/dynamo-browse/ui/tableselectmodel.go +++ /dev/null @@ -1,95 +0,0 @@ -package ui - -import ( - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" -) - -var ( - titleStyle = lipgloss.NewStyle().MarginLeft(2) - itemStyle = lipgloss.NewStyle().PaddingLeft(4) - selectedItemStyle = lipgloss.NewStyle().PaddingLeft(2).Foreground(lipgloss.Color("170")) - paginationStyle = list.DefaultStyles().PaginationStyle.PaddingLeft(4) - helpStyle = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1) - quitTextStyle = lipgloss.NewStyle().Margin(1, 0, 2, 4) -) - -type tableSelectModel struct { - list list.Model -} - -func (t tableSelectModel) Init() tea.Cmd { - return nil -} - -func (t tableSelectModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.WindowSizeMsg: - t.list.SetHeight(msg.Height) - t.list.SetWidth(msg.Width) - return t, nil - - case tea.KeyMsg: - switch keypress := msg.String(); keypress { - case "ctrl+c": - return t, tea.Quit - - case "enter": - //i, ok := m.list.SelectedItem().(item) - //if ok { - // m.choice = string(i) - //} - return t, tea.Quit - } - } - - var cmd tea.Cmd - t.list, cmd = t.list.Update(msg) - return t, cmd -} - -func (t tableSelectModel) View() string { - return t.list.View() -} - -func newTableSelectModel(w, h int) tableSelectModel { - tableItems := []tableItem{ - {name: "alpha"}, - {name: "beta"}, - {name: "gamma"}, - } - - items := toListItems(tableItems) - - delegate := list.NewDefaultDelegate() - delegate.ShowDescription = false - - return tableSelectModel{ - list: list.New(items, delegate, w, h), - } -} - -type tableItem struct { - name string -} - -func (ti tableItem) FilterValue() string { - return "" -} - -func (ti tableItem) Title() string { - return ti.name -} - -func (ti tableItem) Description() string { - return "abc" -} - -func toListItems[T list.Item](xs []T) []list.Item { - ls := make([]list.Item, len(xs)) - for i, x := range xs { - ls[i] = x - } - return ls -} diff --git a/internal/dynamo-browse/ui/teamodels/dynamotableview/model.go b/internal/dynamo-browse/ui/teamodels/dynamotableview/model.go index bcc6c13..6245be4 100644 --- a/internal/dynamo-browse/ui/teamodels/dynamotableview/model.go +++ b/internal/dynamo-browse/ui/teamodels/dynamotableview/model.go @@ -4,6 +4,7 @@ import ( table "github.com/calyptia/go-bubble-table" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" + "github.com/lmika/awstools/internal/common/ui/commandctrl" "github.com/lmika/awstools/internal/dynamo-browse/controllers" "github.com/lmika/awstools/internal/dynamo-browse/models" "github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/dynamoitemview" @@ -13,15 +14,17 @@ import ( type Model struct { tableReadControllers *controllers.TableReadController - frameTitle frame.FrameTitle - table table.Model - w, h int + commandCtrl *commandctrl.CommandController + + frameTitle frame.FrameTitle + table table.Model + w, h int // model state resultSet *models.ResultSet } -func New(tableReadControllers *controllers.TableReadController) Model { +func New(tableReadControllers *controllers.TableReadController, commandCtrl *commandctrl.CommandController) Model { tbl := table.New([]string{"pk", "sk"}, 100, 100) rows := make([]table.Row, 0) tbl.SetRows(rows) @@ -30,6 +33,7 @@ func New(tableReadControllers *controllers.TableReadController) Model { return Model{ tableReadControllers: tableReadControllers, + commandCtrl: commandCtrl, frameTitle: frameTitle, table: tbl, } @@ -58,6 +62,9 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { // TEMP case "s": return m, m.tableReadControllers.Rescan(m.resultSet) + case ":": + return m, m.commandCtrl.Prompt() + // END TEMP case "ctrl+c", "esc": return m, tea.Quit } diff --git a/internal/dynamo-browse/ui/teamodels/modalevents.go b/internal/dynamo-browse/ui/teamodels/modalevents.go deleted file mode 100644 index 3a2c293..0000000 --- a/internal/dynamo-browse/ui/teamodels/modalevents.go +++ /dev/null @@ -1,9 +0,0 @@ -package teamodels - -import tea "github.com/charmbracelet/bubbletea" - -// NewModePushed pushes a new mode on the modal stack -type NewModePushed tea.Model - -// ModePopped pops a mode from the modal stack -type ModePopped struct{} diff --git a/internal/dynamo-browse/ui/teamodels/testmodel.go b/internal/dynamo-browse/ui/teamodels/testmodel.go deleted file mode 100644 index 5400aae..0000000 --- a/internal/dynamo-browse/ui/teamodels/testmodel.go +++ /dev/null @@ -1,33 +0,0 @@ -package teamodels - -import ( - tea "github.com/charmbracelet/bubbletea" -) - -// TestModel is a model used for testing -type TestModel struct { - Message string - OnKeyPressed func(k string) tea.Cmd -} - -func (t TestModel) Init() tea.Cmd { - return nil -} - -func (t TestModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return t, tea.Quit - default: - return t, t.OnKeyPressed(msg.String()) - } - } - - return t, nil -} - -func (t TestModel) View() string { - return t.Message -}