Fixed various bugs and papercuts (#37)

- Enabled CGO for release builds so that copy to clipboard does not panic.
- Added a prompt to confirm quitting when pressing Esc or Ctrl+C
- Fixed the table prompt to not quit app on Esc when invoked with the table command.
This commit is contained in:
Leon Mika 2022-11-01 21:59:46 +11:00 committed by GitHub
parent 5e24f0e9d7
commit 7d2817812c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 38 additions and 27 deletions

View file

@ -5,6 +5,8 @@ builds:
- linux_amd64 - linux_amd64
- darwin_amd64 - darwin_amd64
- darwin_arm64 - darwin_arm64
env:
- CGO_ENABLED=1
main: ./cmd/dynamo-browse/. main: ./cmd/dynamo-browse/.
binary: dynamo-browse binary: dynamo-browse
archives: archives:

View file

@ -83,13 +83,13 @@ func (c *TableReadController) Init() tea.Msg {
} }
if c.tableName == "" { if c.tableName == "" {
return c.ListTables() return c.ListTables(true)
} else { } else {
return c.ScanTable(c.tableName) return c.ScanTable(c.tableName)
} }
} }
func (c *TableReadController) ListTables() tea.Msg { func (c *TableReadController) ListTables(quitIfNoTable bool) tea.Msg {
return NewJob(c.jobController, "Listing tables…", func(ctx context.Context) (any, error) { return NewJob(c.jobController, "Listing tables…", func(ctx context.Context) (any, error) {
tables, err := c.tableService.ListTables(context.Background()) tables, err := c.tableService.ListTables(context.Background())
if err != nil { if err != nil {
@ -101,6 +101,9 @@ func (c *TableReadController) ListTables() tea.Msg {
Tables: res.([]string), Tables: res.([]string),
OnSelected: func(tableName string) tea.Msg { OnSelected: func(tableName string) tea.Msg {
if tableName == "" { if tableName == "" {
if quitIfNoTable {
return tea.Quit()
}
return events.StatusMsg("No table selected") return events.StatusMsg("No table selected")
} }

View file

@ -34,7 +34,7 @@ func TestTableReadController_ListTables(t *testing.T) {
t.Run("returns a list of tables", func(t *testing.T) { t.Run("returns a list of tables", func(t *testing.T) {
srv := newService(t, serviceConfig{}) srv := newService(t, serviceConfig{})
event := srv.readController.ListTables().(controllers.PromptForTableMsg) event := srv.readController.ListTables(false).(controllers.PromptForTableMsg)
assert.Equal(t, []string{"alpha-table", "bravo-table"}, event.Tables) assert.Equal(t, []string{"alpha-table", "bravo-table"}, event.Tables)

View file

@ -87,7 +87,7 @@ func NewModel(
"quit": commandctrl.NoArgCommand(tea.Quit), "quit": commandctrl.NoArgCommand(tea.Quit),
"table": func(ctx commandctrl.ExecContext, args []string) tea.Msg { "table": func(ctx commandctrl.ExecContext, args []string) tea.Msg {
if len(args) == 0 { if len(args) == 0 {
return rc.ListTables() return rc.ListTables(false)
} else { } else {
return rc.ScanTable(args[0]) return rc.ScanTable(args[0])
} }
@ -255,13 +255,11 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case key.Matches(msg, m.keyMap.PromptForCommand): case key.Matches(msg, m.keyMap.PromptForCommand):
return m, m.commandController.Prompt return m, m.commandController.Prompt
case key.Matches(msg, m.keyMap.PromptForTable): case key.Matches(msg, m.keyMap.PromptForTable):
return m, events.SetTeaMessage(m.tableReadController.ListTables()) return m, events.SetTeaMessage(m.tableReadController.ListTables(false))
case key.Matches(msg, m.keyMap.CancelRunningJob): case key.Matches(msg, m.keyMap.CancelRunningJob):
return m, events.SetTeaMessage(m.jobController.CancelRunningJob(func() tea.Msg { return m, events.SetTeaMessage(m.jobController.CancelRunningJob(m.promptToQuit))
return tea.Quit()
}))
case key.Matches(msg, m.keyMap.Quit): case key.Matches(msg, m.keyMap.Quit):
return m, tea.Quit return m, m.promptToQuit
} }
} }
} }
@ -312,3 +310,12 @@ func (m *Model) setMainViewIndex(viewIndex int) tea.Cmd {
m.itemEdit.SetSubmodel(m.mainView) m.itemEdit.SetSubmodel(m.mainView)
return m.tableView.Refresh() return m.tableView.Refresh()
} }
func (m *Model) promptToQuit() tea.Msg {
return events.Confirm("Quit dynamo-browse? ", func(yes bool) tea.Msg {
if yes {
return tea.Quit()
}
return nil
})
}

View file

@ -2,19 +2,6 @@ package tableselect
import tea "github.com/charmbracelet/bubbletea" import tea "github.com/charmbracelet/bubbletea"
func IndicateLoadingTables() tea.Cmd {
return func() tea.Msg {
return indicateLoadingTablesMsg{}
}
}
func ShowTableSelect(onSelected func(n string) tea.Cmd) tea.Cmd {
return func() tea.Msg {
return showTableSelectMsg{
onSelected: onSelected,
}
}
}
type indicateLoadingTablesMsg struct{} type indicateLoadingTablesMsg struct{}
type showTableSelectMsg struct { type showTableSelectMsg struct {

View file

@ -50,6 +50,7 @@ func newListController(tableNames []string, w, h int) listController {
key.WithHelp("→/l/pgdn", "next page"), key.WithHelp("→/l/pgdn", "next page"),
) )
list.SetShowTitle(false) list.SetShowTitle(false)
list.DisableQuitKeybindings()
return listController{list: list} return listController{list: list}
} }

View file

@ -1,6 +1,7 @@
package tableselect package tableselect
import ( import (
"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/list" "github.com/charmbracelet/bubbles/list"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
@ -17,6 +18,9 @@ var (
Bold(true). Bold(true).
Foreground(lipgloss.Color("#ffffff")). Foreground(lipgloss.Color("#ffffff")).
Background(lipgloss.Color("#4479ff")) Background(lipgloss.Color("#4479ff"))
chooseSelectedTableBinding = key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "select table"))
exitTableSelectionBinding = key.NewBinding(key.WithKeys("ctrl+c", "esc"), key.WithHelp("esc", "close selection"))
) )
type Model struct { type Model struct {
@ -50,8 +54,8 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, nil return m, nil
case tea.KeyMsg: case tea.KeyMsg:
if m.pendingSelection != nil { if m.pendingSelection != nil {
switch msg.String() { switch {
case "enter": case key.Matches(msg, chooseSelectedTableBinding):
if m.listController.list.FilterState() != list.Filtering { if m.listController.list.FilterState() != list.Filtering {
var sel controllers.PromptForTableMsg var sel controllers.PromptForTableMsg
sel, m.pendingSelection = *m.pendingSelection, nil sel, m.pendingSelection = *m.pendingSelection, nil
@ -59,6 +63,13 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if selTableItem, isTableItem := m.listController.list.SelectedItem().(tableItem); isTableItem { if selTableItem, isTableItem := m.listController.list.SelectedItem().(tableItem); isTableItem {
return m, events.SetTeaMessage(sel.OnSelected(selTableItem.name)) return m, events.SetTeaMessage(sel.OnSelected(selTableItem.name))
} }
return m, events.SetTeaMessage(sel.OnSelected(""))
}
case key.Matches(msg, exitTableSelectionBinding):
if m.listController.list.FilterState() != list.Filtering && m.listController.list.FilterState() != list.FilterApplied {
var sel controllers.PromptForTableMsg
sel, m.pendingSelection = *m.pendingSelection, nil
return m, events.SetTeaMessage(sel.OnSelected("")) return m, events.SetTeaMessage(sel.OnSelected(""))
} }
} }