diff --git a/app/app.go b/app/app.go index dd8cb30..7e853b9 100644 --- a/app/app.go +++ b/app/app.go @@ -9,6 +9,8 @@ import ( "github.com/gdamore/tcell/v2" "github.com/rivo/tview" + + "github.com/jorgerojas26/lazysql/models" ) var ( @@ -19,6 +21,7 @@ var ( type Application struct { *tview.Application + config *Config context context.Context cancelFn context.CancelFunc waitGroup sync.WaitGroup @@ -35,6 +38,7 @@ func init() { App = &Application{ Application: tview.NewApplication(), + config: defaultConfig(), context: ctx, cancelFn: cancel, } @@ -68,6 +72,21 @@ func (a *Application) Context() context.Context { return a.context } +// Config returns the application configuration. +func (a *Application) Config() *models.AppConfig { + return a.config.AppConfig +} + +// Connections returns the database connections. +func (a *Application) Connections() []models.Connection { + return a.config.Connections +} + +// SaveConnections saves the database connections. +func (a *Application) SaveConnections(connections []models.Connection) error { + return a.config.SaveConnections(connections) +} + // Register adds a task to the wait group and returns a // function that decrements the task count when called. // diff --git a/helpers/config.go b/app/config.go similarity index 53% rename from helpers/config.go rename to app/config.go index 27a2c2a..681fdac 100644 --- a/helpers/config.go +++ b/app/config.go @@ -1,4 +1,4 @@ -package helpers +package app import ( "os" @@ -10,38 +10,33 @@ import ( ) type Config struct { + AppConfig *models.AppConfig `toml:"application"` Connections []models.Connection `toml:"database"` } -func LoadConfig() (config Config, err error) { - file, err := os.ReadFile(filepath.Join(os.Getenv("HOME"), ".config", "lazysql", "config.toml")) - if err != nil { - return +func defaultConfig() *Config { + return &Config{ + AppConfig: &models.AppConfig{ + DefaultPageSize: 300, + }, } - - err = toml.Unmarshal(file, &config) - - return } -func LoadConnections() (connections []models.Connection, err error) { - config, err := LoadConfig() +func LoadConfig() error { + file, err := os.ReadFile(filepath.Join(os.Getenv("HOME"), ".config", "lazysql", "config.toml")) if err != nil { - return + return err } - - connections = config.Connections - - return + return toml.Unmarshal(file, App.config) } -func SaveConnectionConfig(connections []models.Connection) (err error) { - config := Config{Connections: connections} +func (c *Config) SaveConnections(connections []models.Connection) error { + c.Connections = connections directoriesPath := filepath.Join(os.Getenv("HOME"), ".config", "lazysql") configFilePath := filepath.Join(directoriesPath, "config.toml") - err = os.MkdirAll(directoriesPath, 0755) + err := os.MkdirAll(directoriesPath, 0o755) if err != nil { return err } @@ -50,10 +45,7 @@ func SaveConnectionConfig(connections []models.Connection) (err error) { if err != nil { return err } - defer file.Close() - err = toml.NewEncoder(file).Encode(config) - - return err + return toml.NewEncoder(file).Encode(c) } diff --git a/components/arg_connection.go b/components/arg_connection.go index cf9351e..fd4df77 100644 --- a/components/arg_connection.go +++ b/components/arg_connection.go @@ -41,7 +41,7 @@ func InitFromArg(connectionString string) error { if err != nil { return fmt.Errorf("Could not connect to database %s: %s", connectionString, err) } - MainPages.AddAndSwitchToPage(connection.URL, NewHomePage(connection, newDBDriver).Flex, true) + mainPages.AddAndSwitchToPage(connection.URL, NewHomePage(connection, newDBDriver).Flex, true) return nil } diff --git a/components/connection_form.go b/components/connection_form.go index 0047661..64a7991 100644 --- a/components/connection_form.go +++ b/components/connection_form.go @@ -95,7 +95,7 @@ func (form *ConnectionForm) inputCapture(connectionPages *models.ConnectionPages return event } - databases, _ := helpers.LoadConnections() + databases := app.App.Connections() newDatabases := make([]models.Connection, len(databases)) DBName := strings.Split(parsed.Normalize(",", "NULL", 0), ",")[3] @@ -115,7 +115,7 @@ func (form *ConnectionForm) inputCapture(connectionPages *models.ConnectionPages case actionNewConnection: newDatabases = append(databases, parsedDatabaseData) - err := helpers.SaveConnectionConfig(newDatabases) + err := app.App.SaveConnections(newDatabases) if err != nil { form.StatusText.SetText(err.Error()).SetTextStyle(tcell.StyleDefault.Foreground(tcell.ColorRed)) return event @@ -123,7 +123,7 @@ func (form *ConnectionForm) inputCapture(connectionPages *models.ConnectionPages case actionEditConnection: newDatabases = make([]models.Connection, len(databases)) - row, _ := ConnectionListTable.GetSelection() + row, _ := connectionsTable.GetSelection() for i, database := range databases { if i == row { @@ -143,7 +143,7 @@ func (form *ConnectionForm) inputCapture(connectionPages *models.ConnectionPages } } - err := helpers.SaveConnectionConfig(newDatabases) + err := app.App.SaveConnections(newDatabases) if err != nil { form.StatusText.SetText(err.Error()).SetTextStyle(tcell.StyleDefault.Foreground(tcell.ColorRed)) return event @@ -151,7 +151,7 @@ func (form *ConnectionForm) inputCapture(connectionPages *models.ConnectionPages } } - ConnectionListTable.SetConnections(newDatabases) + connectionsTable.SetConnections(newDatabases) connectionPages.SwitchToPage(pageNameConnectionSelection) } else if event.Key() == tcell.KeyF2 { diff --git a/components/connection_selection.go b/components/connection_selection.go index 00657fe..8673e0d 100644 --- a/components/connection_selection.go +++ b/components/connection_selection.go @@ -19,8 +19,6 @@ type ConnectionSelection struct { StatusText *tview.TextView } -var ConnectionListTable = NewConnectionsTable() - func NewConnectionSelection(connectionForm *ConnectionForm, connectionPages *models.ConnectionPages) *ConnectionSelection { wrapper := tview.NewFlex() @@ -66,7 +64,7 @@ func NewConnectionSelection(connectionForm *ConnectionForm, connectionPages *mod statusText := tview.NewTextView() statusText.SetBorderPadding(1, 1, 0, 0) - wrapper.AddItem(ConnectionListTable, 0, 1, true) + wrapper.AddItem(NewConnectionsTable(), 0, 1, true) wrapper.AddItem(statusText, 4, 0, false) wrapper.AddItem(buttonsWrapper, 3, 0, false) @@ -76,12 +74,12 @@ func NewConnectionSelection(connectionForm *ConnectionForm, connectionPages *mod } wrapper.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { - connections := ConnectionListTable.GetConnections() + connections := connectionsTable.GetConnections() command := app.Keymaps.Group(app.ConnectionGroup).Resolve(event) if len(connections) != 0 { - row, _ := ConnectionListTable.GetSelection() + row, _ := connectionsTable.GetSelection() selectedConnection := connections[row] switch command { @@ -99,23 +97,23 @@ func NewConnectionSelection(connectionForm *ConnectionForm, connectionPages *mod confirmationModal := NewConfirmationModal("") confirmationModal.SetDoneFunc(func(_ int, buttonLabel string) { - MainPages.RemovePage(pageNameConfirmation) + mainPages.RemovePage(pageNameConfirmation) confirmationModal = nil if buttonLabel == "Yes" { newConnections := append(connections[:row], connections[row+1:]...) - err := helpers.SaveConnectionConfig(newConnections) + err := app.App.SaveConnections(newConnections) if err != nil { - ConnectionListTable.SetError(err) + connectionsTable.SetError(err) } else { - ConnectionListTable.SetConnections(newConnections) + connectionsTable.SetConnections(newConnections) } } }) - MainPages.AddPage(pageNameConfirmation, confirmationModal, true, true) + mainPages.AddPage(pageNameConfirmation, confirmationModal, true, true) return nil } @@ -141,8 +139,8 @@ func NewConnectionSelection(connectionForm *ConnectionForm, connectionPages *mod } func (cs *ConnectionSelection) Connect(connection models.Connection) *tview.Application { - if MainPages.HasPage(connection.Name) { - MainPages.SwitchToPage(connection.Name) + if mainPages.HasPage(connection.Name) { + mainPages.SwitchToPage(connection.Name) return App.Draw() } @@ -202,8 +200,8 @@ func (cs *ConnectionSelection) Connect(connection models.Connection) *tview.Appl return App.Draw() } - selectedRow, selectedCol := ConnectionListTable.GetSelection() - cell := ConnectionListTable.GetCell(selectedRow, selectedCol) + selectedRow, selectedCol := connectionsTable.GetSelection() + cell := connectionsTable.GetCell(selectedRow, selectedCol) cell.SetText(fmt.Sprintf("[green]* %s", cell.Text)) cs.StatusText.SetText("") @@ -211,7 +209,7 @@ func (cs *ConnectionSelection) Connect(connection models.Connection) *tview.Appl newHome.Tree.SetCurrentNode(newHome.Tree.GetRoot()) newHome.Tree.Wrapper.SetTitle(connection.Name) - MainPages.AddAndSwitchToPage(connection.Name, newHome, true) + mainPages.AddAndSwitchToPage(connection.Name, newHome, true) App.SetFocus(newHome.Tree) return App.Draw() diff --git a/components/connections_table.go b/components/connections_table.go index 8211a00..8d2ec83 100644 --- a/components/connections_table.go +++ b/components/connections_table.go @@ -5,7 +5,6 @@ import ( "github.com/rivo/tview" "github.com/jorgerojas26/lazysql/app" - "github.com/jorgerojas26/lazysql/helpers" "github.com/jorgerojas26/lazysql/models" ) @@ -17,6 +16,8 @@ type ConnectionsTable struct { connections []models.Connection } +var connectionsTable *ConnectionsTable + func NewConnectionsTable() *ConnectionsTable { wrapper := tview.NewFlex() @@ -33,23 +34,16 @@ func NewConnectionsTable() *ConnectionsTable { table.SetSelectedStyle(tcell.StyleDefault.Foreground(app.Styles.SecondaryTextColor).Background(tview.Styles.PrimitiveBackgroundColor)) wrapper.AddItem(table, 0, 1, true) + table.SetConnections(app.App.Connections()) - connections, err := helpers.LoadConnections() - - if err != nil { - table.SetError(err) - } else { - table.SetConnections(connections) - } + connectionsTable = table - return table + return connectionsTable } func (ct *ConnectionsTable) AddConnection(connection models.Connection) { rowCount := ct.GetRowCount() - ct.SetCellSimple(rowCount, 0, connection.Name) - ct.connections = append(ct.connections, connection) } diff --git a/components/help_modal.go b/components/help_modal.go index 85331ca..bf0b38f 100644 --- a/components/help_modal.go +++ b/components/help_modal.go @@ -75,7 +75,7 @@ func NewHelpModal() *HelpModal { table.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { command := app.Keymaps.Group(app.HomeGroup).Resolve(event) if command == commands.Quit || command == commands.HelpPopup || event.Key() == tcell.KeyEsc { - MainPages.RemovePage(pageNameHelp) + mainPages.RemovePage(pageNameHelp) } return event }) diff --git a/components/home.go b/components/home.go index 5c6c1ce..2c4993b 100644 --- a/components/home.go +++ b/components/home.go @@ -74,7 +74,7 @@ func NewHomePage(connection models.Connection, dbdriver drivers.Driver) *Home { } }) - MainPages.AddPage(connection.URL, home, true, false) + mainPages.AddPage(connection.URL, home, true, false) return home } @@ -109,7 +109,9 @@ func (home *Home) subscribeToTreeChanges() { home.focusLeftWrapper() }) - if len(results) > 1 && !table.GetShowSidebar() { // 1 because the row 0 is the column names + // Show sidebar if there is more then 1 row (row 0 are + // the column names) and the sidebar is not disabled. + if !App.Config().DisableSidebar && len(results) > 1 && !table.GetShowSidebar() { table.ShowSidebar(true) } @@ -296,7 +298,7 @@ func (home *Home) homeInputCapture(event *tcell.EventKey) *tcell.EventKey { App.ForceDraw() case commands.SwitchToConnectionsView: if (table != nil && !table.GetIsEditing() && !table.GetIsFiltering() && !table.GetIsLoading()) || table == nil { - MainPages.SwitchToPage(pageNameConnections) + mainPages.SwitchToPage(pageNameConnections) } case commands.Quit: if tab == nil || (!table.GetIsEditing() && !table.GetIsFiltering()) { @@ -307,7 +309,7 @@ func (home *Home) homeInputCapture(event *tcell.EventKey) *tcell.EventKey { confirmationModal := NewConfirmationModal("") confirmationModal.SetDoneFunc(func(_ int, buttonLabel string) { - MainPages.RemovePage(pageNameConfirmation) + mainPages.RemovePage(pageNameConfirmation) confirmationModal = nil if buttonLabel == "Yes" { @@ -327,7 +329,7 @@ func (home *Home) homeInputCapture(event *tcell.EventKey) *tcell.EventKey { } }) - MainPages.AddPage(pageNameConfirmation, confirmationModal, true, true) + mainPages.AddPage(pageNameConfirmation, confirmationModal, true, true) } case commands.HelpPopup: if table == nil || !table.GetIsEditing() { @@ -340,7 +342,7 @@ func (home *Home) homeInputCapture(event *tcell.EventKey) *tcell.EventKey { // } // return event // }) - MainPages.AddPage(pageNameHelp, home.HelpModal, true, true) + mainPages.AddPage(pageNameHelp, home.HelpModal, true, true) } } diff --git a/components/pages.go b/components/pages.go index 7bea031..89426a7 100644 --- a/components/pages.go +++ b/components/pages.go @@ -6,9 +6,11 @@ import ( "github.com/jorgerojas26/lazysql/app" ) -var MainPages = tview.NewPages() +var mainPages *tview.Pages -func init() { - MainPages.SetBackgroundColor(app.Styles.PrimitiveBackgroundColor) - MainPages.AddPage(pageNameConnections, NewConnectionPages().Flex, true, true) +func MainPages() *tview.Pages { + mainPages = tview.NewPages() + mainPages.SetBackgroundColor(app.Styles.PrimitiveBackgroundColor) + mainPages.AddPage(pageNameConnections, NewConnectionPages().Flex, true, true) + return mainPages } diff --git a/components/pagination.go b/components/pagination.go index 78bb8cf..a8ab56e 100644 --- a/components/pagination.go +++ b/components/pagination.go @@ -4,6 +4,8 @@ import ( "fmt" "github.com/rivo/tview" + + "github.com/jorgerojas26/lazysql/app" ) type PaginationState struct { @@ -18,8 +20,6 @@ type Pagination struct { textView *tview.TextView } -var defaultPageSize = 300 - func NewPagination() *Pagination { wrapper := tview.NewFlex() wrapper.SetBorderPadding(0, 0, 1, 1) @@ -36,11 +36,10 @@ func NewPagination() *Pagination { textView: textView, state: &PaginationState{ Offset: 0, - Limit: defaultPageSize, + Limit: app.App.Config().DefaultPageSize, TotalRecords: 0, }, } - } func (pagination *Pagination) GetOffset() int { diff --git a/components/result_table_filter.go b/components/result_table_filter.go index 002582d..ec138ea 100644 --- a/components/result_table_filter.go +++ b/components/result_table_filter.go @@ -14,7 +14,6 @@ type ResultsTableFilter struct { Label *tview.TextView currentFilter string subscribers []chan models.StateChange - filtering bool } func NewResultsFilter() *ResultsTableFilter { @@ -74,18 +73,10 @@ func (filter *ResultsTableFilter) Publish(message string) { } } -func (filter *ResultsTableFilter) GetIsFiltering() bool { - return filter.filtering -} - func (filter *ResultsTableFilter) GetCurrentFilter() string { return filter.currentFilter } -func (filter *ResultsTableFilter) SetIsFiltering(filtering bool) { - filter.filtering = filtering -} - // Function to blur func (filter *ResultsTableFilter) RemoveHighlight() { filter.SetBorderColor(app.Styles.InverseTextColor) diff --git a/components/results_table.go b/components/results_table.go index ffa11bd..9a95e0d 100644 --- a/components/results_table.go +++ b/components/results_table.go @@ -1119,7 +1119,6 @@ func (table *ResultsTable) AppendNewChange(changeType models.DMLType, rowIndex i } if !dmlChangeAlreadyExists { - switch changeType { case models.DMLDeleteType: table.SetRowColor(rowIndex, colorTableDelete) @@ -1137,7 +1136,6 @@ func (table *ResultsTable) AppendNewChange(changeType models.DMLType, rowIndex i } *table.state.listOfDBChanges = append(*table.state.listOfDBChanges, newDMLChange) - } logger.Info("AppendNewChange", map[string]any{"listOfDbChanges": *table.state.listOfDBChanges}) diff --git a/components/set_value_list.go b/components/set_value_list.go index ab24bca..a46eb48 100644 --- a/components/set_value_list.go +++ b/components/set_value_list.go @@ -78,13 +78,13 @@ func (list *SetValueList) OnFinish(callback func(selection models.CellValueType, func (list *SetValueList) Show(x, y, width int) { list.SetRect(x, y, width, len(VALUES)*2+1) - MainPages.AddPage(pageNameSetValue, list, false, true) + mainPages.AddPage(pageNameSetValue, list, false, true) App.SetFocus(list) App.ForceDraw() } func (list *SetValueList) Hide() { - MainPages.RemovePage(pageNameSetValue) + mainPages.RemovePage(pageNameSetValue) App.SetFocus(list) App.ForceDraw() } diff --git a/main.go b/main.go index d356df4..16d6f5d 100644 --- a/main.go +++ b/main.go @@ -56,12 +56,22 @@ func main() { log.Fatalf("Error setting MySQL logger: %v", err) } + // First load the config. + if err = app.LoadConfig(); err != nil { + log.Fatalf("Error loading config: %v", err) + } + + // Now we can initialize the main pages. + mainPages := components.MainPages() + + // Parse the command line arguments. args := flag.Args() switch len(args) { case 0: - // nothing to do. Launch into the connection picker. + // Launch into the connection picker. case 1: + // Set a connection from the command line. err := components.InitFromArg(args[0]) if err != nil { log.Fatal(err) @@ -70,7 +80,7 @@ func main() { log.Fatal("Only a single connection is allowed") } - if err = app.App.Run(components.MainPages); err != nil { + if err = app.App.Run(mainPages); err != nil { log.Fatalf("Error running app: %v", err) } } diff --git a/models/models.go b/models/models.go index 8aff0c8..f9bb3ed 100644 --- a/models/models.go +++ b/models/models.go @@ -4,6 +4,11 @@ import ( "github.com/rivo/tview" ) +type AppConfig struct { + DefaultPageSize int + DisableSidebar bool +} + type Connection struct { Name string Provider string