diff --git a/cmd/sqv-tea/main.go b/cmd/sqv-tea/main.go index 61d7908..5c63088 100644 --- a/cmd/sqv-tea/main.go +++ b/cmd/sqv-tea/main.go @@ -7,26 +7,29 @@ import ( engine "git.pablu.de/pablu/sqv-engine" "github.com/charmbracelet/bubbles/list" - "github.com/charmbracelet/bubbles/table" "github.com/charmbracelet/bubbles/textarea" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/lipgloss/table" "github.com/charmbracelet/log" ) +type Focused int + +const ( + EDITOR Focused = iota + TABLE + PICKER +) + type mainModel struct { width, height int - pickerFocused bool manager *engine.Manager - lastFocused int + lastFocused, focused Focused - viewStyle lipgloss.Style - editorStyle lipgloss.Style - pickerStyle lipgloss.Style - - table table.Model + table *table.Table editor textarea.Model picker list.Model @@ -39,9 +42,6 @@ var ( BorderStyle(lipgloss.NormalBorder()) focusedStyle = defaultStyle.BorderForeground(lipgloss.Color("202")) - - baseTableStyle = lipgloss.NewStyle(). - BorderStyle(lipgloss.NormalBorder()) ) type item struct { @@ -57,54 +57,17 @@ func newMainModerl(manager *engine.Manager) mainModel { ed.Placeholder = "Try \"SELECT * FROM ?;\"" ed.ShowLineNumbers = false - ed.Focus() - columns := []table.Column{ - {Title: "id", Width: 4}, - {Title: "name", Width: 4}, - {Title: "family_name", Width: 4}, - } + ta := table.New().Border(lipgloss.NormalBorder()) - rows := []table.Row{ - {"0", "Conrad", "Adenauer"}, - {"1", "Anna", "Aachen"}, - {"2", "Karli", "Columbus"}, - {"3", "Max", "Mustermann"}, - {"4", "Bernd", "Brot"}, - } - - ta := table.New( - table.WithColumns(columns), - table.WithRows(rows), - ) - - items := []list.Item{ - item{ - title: "user", - // desc: "users table", - }, - item{ - title: "job", - // desc: "jobs table", - }, - item{ - title: "user_has_job", - // desc: "user has a job", - }, - } - - li := list.New(items, list.NewDefaultDelegate(), 0, 0) + li := list.New(nil, list.NewDefaultDelegate(), 0, 0) li.Title = "Table Picker" return mainModel{ - pickerFocused: false, - viewStyle: baseTableStyle, - editorStyle: defaultStyle, - pickerStyle: defaultStyle.BorderStyle(lipgloss.RoundedBorder()).BorderForeground(lipgloss.Color("67")), - editor: ed, - table: ta, - picker: li, - manager: manager, + editor: ed, + table: ta, + picker: li, + manager: manager, } } @@ -146,38 +109,16 @@ func (m mainModel) GetTable(name string) tea.Cmd { m.manager.LoadTable(&t) msg := tableMsg{ - Columns: make([]table.Column, len(t.Columns)), - Rows: make([]table.Row, len(t.Rows)), + Columns: make([]string, len(t.Columns)), + Rows: make([][]string, len(t.Rows)), } - lRow := make([]int, len(t.Columns)) - lRowC := 0 for i, r := range t.Rows { - msg.Rows[i] = r.Values - - // Pure stupid estemation of how long each row should be - if i == 0 { - for j, v := range r.Values { - vLen := len(v) - vLen = max(vLen, len(t.Columns[j].Name)) - - lRow[j] = vLen - lRowC += vLen - } - } } - h, _ := m.viewStyle.GetFrameSize() - width := m.viewStyle.GetWidth() - h - width -= (len(t.Columns) + 1) * 2 for i, c := range t.Columns { - columnWidth := float64(width) * (float64(lRow[i]) / float64(lRowC)) - - msg.Columns[i] = table.Column{ - Title: c.Name, - Width: int(columnWidth), - } + msg.Columns[i] = c.Name } return msg @@ -185,8 +126,8 @@ func (m mainModel) GetTable(name string) tea.Cmd { } type tableMsg struct { - Columns []table.Column - Rows []table.Row + Columns []string + Rows [][]string } func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { @@ -204,43 +145,35 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case "ctrl+c": return m, tea.Quit case "tab": - if m.table.Focused() { - m.table.Blur() - m.editor.Focus() - m.lastFocused = 0 - } else { + if m.focused == EDITOR { + m.focused = TABLE m.editor.Blur() - m.table.Focus() - m.lastFocused = 1 + } else { + m.focused = EDITOR } + case "j": + m.table.Offset(50) case "ctrl+e": - m.pickerFocused = !m.pickerFocused - - // Picker is now focused - if m.pickerFocused { - m.table.Blur() - m.editor.Blur() + if m.focused == PICKER { + m.focused = m.lastFocused } else { - if m.lastFocused == 0 { - m.editor.Focus() - } else { - m.table.Focus() - } + // Maybe blur is not even needed + m.editor.Blur() + m.lastFocused = m.focused + m.focused = PICKER } case "enter": log.Debug("Enter was pressed") - if m.pickerFocused { + if m.focused == PICKER { i, ok := m.picker.SelectedItem().(item) if ok { log.Debug("Selected item okay and batched") cmds = tea.Batch(cmds, m.GetTable(i.title)) } - m.pickerFocused = !m.pickerFocused - if m.lastFocused == 0 { + m.focused = m.lastFocused + if m.focused == EDITOR { m.editor.Focus() - } else { - m.table.Focus() } } } @@ -249,26 +182,20 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { cmds = tea.Batch(cmds, m.GetFirstTable) case tableMsg: - // log.Debug("Setting new table view", "columns", msg.Columns, "rows", msg.Rows) - - m.table = table.New( - table.WithColumns(msg.Columns), - table.WithRows(msg.Rows), - ) - - m.table.SetWidth(m.viewStyle.GetWidth() - 2) - m.table.SetHeight(m.viewStyle.GetHeight() - 2) - - // m.table.SetColumns(msg.Columns) - // m.table.SetRows(msg.Rows) + m.table.Offset(0) + m.table.ClearRows() + m.table.Headers(msg.Columns...) + m.table.Rows(msg.Rows...) case tableDefinitionsMsg: pickerCmd = m.picker.SetItems(msg.Tables) } - m.editor, edCmd = m.editor.Update(msg) - m.table, taCmd = m.table.Update(msg) - if m.pickerFocused { + switch m.focused { + case EDITOR: + m.editor.Focus() + m.editor, edCmd = m.editor.Update(msg) + case PICKER: m.picker, liCmd = m.picker.Update(msg) } @@ -276,60 +203,54 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } func (m mainModel) updateStyles(width, height int) mainModel { - h, v := defaultStyle.GetFrameSize() - bh, bv := baseTableStyle.GetFrameSize() - - log.Debug("Update styles", "bh", bh, "bv", bv, "h", h, "v", v) - - topHeight := (height * 3 / 4) - bh - editorHeight := (height * 1 / 4) - h - - m.editorStyle = defaultStyle. - Width(width - v). - Height(editorHeight) - - m.viewStyle = baseTableStyle. - Width(width - bv). - Height(topHeight) - - m.editor.SetWidth(m.editorStyle.GetWidth()) - m.editor.SetHeight(m.editorStyle.GetHeight()) - - m.table.SetWidth(m.viewStyle.GetWidth()) - m.table.SetHeight(m.viewStyle.GetHeight()) - - columns := m.table.Columns() - colLen := len(columns) - colWidth := m.table.Width() / colLen - for i := range columns { - columns[i].Width = colWidth - } - m.table.SetColumns(columns) - - m.pickerStyle = m.pickerStyle. - Width((width * 7 / 10) - v). - Height((height * 7 / 10) - h) - m.picker.SetSize(m.pickerStyle.GetWidth(), m.pickerStyle.GetHeight()) - m.width = width m.height = height + + h, v := defaultStyle.GetFrameSize() + topHeight := (m.height * 3 / 4) - h + editorHeight := (m.height * 1 / 4) - h + + m.editor.SetWidth(m.width - v) + m.editor.SetHeight(editorHeight) + + m.table.Width(m.width - v) + m.table.Height(topHeight - h) + + m.picker.SetSize(m.width*7/10, m.height*7/10) + return m } func (m mainModel) View() string { - view := m.viewStyle. - Render(m.table.View()) + var ( + view, editor string + ) - editor := m.editorStyle. - Render(m.editor.View()) + switch m.focused { + case EDITOR: + view = defaultStyle. + Render(m.table.Render()) + editor = focusedStyle. + Render(m.editor.View()) + case TABLE: + view = focusedStyle. + Render(m.table.Render()) + editor = defaultStyle. + Render(m.editor.View()) + case PICKER: + view = defaultStyle. + Render(m.table.Render()) + editor = defaultStyle. + Render(m.editor.View()) + } main := lipgloss.JoinVertical(lipgloss.Top, view, editor) - if m.pickerFocused { + if m.focused == PICKER { x := (m.width / 2) - m.picker.Width()/2 y := (m.height / 2) - m.picker.Height()/2 - return PlaceOverlay(x, y, m.pickerStyle.Render(m.picker.View()), main, false) + return PlaceOverlay(x, y, focusedStyle.Render(m.picker.View()), main, false) } return main @@ -358,6 +279,8 @@ func main() { os.Exit(1) } + table.New() + p := tea.NewProgram(newMainModerl(m), tea.WithAltScreen()) if _, err := p.Run(); err != nil { fmt.Println("fatal:", err)