Skip to content

Commit

Permalink
Merge pull request #95 from jorgerojas26/status-bar
Browse files Browse the repository at this point in the history
Help modal with keybindings
  • Loading branch information
jorgerojas26 authored Aug 30, 2024
2 parents 058d7ca + c2ceddb commit 686462e
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 46 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ Support for multiple RDBMS is a work in progress.
| q | Quit |
| CTRL + e | Open SQL editor |
| Backspace | Return to connection selection |
| ? | Show keybindings popup |

### Table

Expand Down
65 changes: 33 additions & 32 deletions app/Keymap.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,47 +46,48 @@ func (c KeymapSystem) Resolve(event *tcell.EventKey) cmd.Command {
// Define a global KeymapSystem object with default keybinds
var Keymaps = KeymapSystem{
Global: Map{
Bind{Key: Key{Char: 'L'}, Cmd: cmd.MoveRight},
Bind{Key: Key{Char: 'H'}, Cmd: cmd.MoveLeft},
Bind{Key: Key{Code: tcell.KeyCtrlE}, Cmd: cmd.SwitchToEditorView},
Bind{Key: Key{Code: tcell.KeyCtrlS}, Cmd: cmd.Save},
Bind{Key: Key{Char: 'q'}, Cmd: cmd.Quit},
Bind{Key: Key{Code: tcell.KeyBackspace2}, Cmd: cmd.SwitchToConnectionsView},
Bind{Key: Key{Char: 'L'}, Cmd: cmd.MoveRight, Description: "Focus table"},
Bind{Key: Key{Char: 'H'}, Cmd: cmd.MoveLeft, Description: "Focus tree"},
Bind{Key: Key{Code: tcell.KeyCtrlE}, Cmd: cmd.SwitchToEditorView, Description: "Open SQL editor"},
Bind{Key: Key{Code: tcell.KeyCtrlS}, Cmd: cmd.Save, Description: "Execute pending changes"},
Bind{Key: Key{Char: 'q'}, Cmd: cmd.Quit, Description: "Quit"},
Bind{Key: Key{Code: tcell.KeyBackspace2}, Cmd: cmd.SwitchToConnectionsView, Description: "Switch to connections list"},
Bind{Key: Key{Char: '?'}, Cmd: cmd.HelpPopup, Description: "Help"},
},
Groups: map[string]Map{
"tree": {
Bind{Key: Key{Char: 'g'}, Cmd: cmd.GotoTop},
Bind{Key: Key{Char: 'G'}, Cmd: cmd.GotoBottom},
Bind{Key: Key{Code: tcell.KeyEnter}, Cmd: cmd.Execute},
Bind{Key: Key{Char: 'j'}, Cmd: cmd.MoveDown},
Bind{Key: Key{Code: tcell.KeyDown}, Cmd: cmd.MoveDown},
Bind{Key: Key{Char: 'k'}, Cmd: cmd.MoveUp},
Bind{Key: Key{Code: tcell.KeyUp}, Cmd: cmd.MoveUp},
Bind{Key: Key{Char: 'g'}, Cmd: cmd.GotoTop, Description: "Go to top"},
Bind{Key: Key{Char: 'G'}, Cmd: cmd.GotoBottom, Description: "Go to bottom"},
Bind{Key: Key{Code: tcell.KeyEnter}, Cmd: cmd.Execute, Description: "Open"},
Bind{Key: Key{Char: 'j'}, Cmd: cmd.MoveDown, Description: "Go down"},
Bind{Key: Key{Code: tcell.KeyDown}, Cmd: cmd.MoveDown, Description: "Go down"},
Bind{Key: Key{Char: 'k'}, Cmd: cmd.MoveUp, Description: "Go up"},
Bind{Key: Key{Code: tcell.KeyUp}, Cmd: cmd.MoveUp, Description: "Go up"},
},
"table": {
Bind{Key: Key{Char: '/'}, Cmd: cmd.Search},
Bind{Key: Key{Char: 'c'}, Cmd: cmd.Edit},
Bind{Key: Key{Char: 'd'}, Cmd: cmd.Delete},
Bind{Key: Key{Char: 'w'}, Cmd: cmd.GotoNext},
Bind{Key: Key{Char: 'b'}, Cmd: cmd.GotoPrev},
Bind{Key: Key{Char: '$'}, Cmd: cmd.GotoEnd},
Bind{Key: Key{Char: '0'}, Cmd: cmd.GotoStart},
Bind{Key: Key{Char: 'y'}, Cmd: cmd.Copy},
Bind{Key: Key{Char: 'o'}, Cmd: cmd.AppendNewRow},
Bind{Key: Key{Char: '/'}, Cmd: cmd.Search, Description: "Search"},
Bind{Key: Key{Char: 'c'}, Cmd: cmd.Edit, Description: "Change cell"},
Bind{Key: Key{Char: 'd'}, Cmd: cmd.Delete, Description: "Delete row"},
Bind{Key: Key{Char: 'w'}, Cmd: cmd.GotoNext, Description: "Go to next cell"},
Bind{Key: Key{Char: 'b'}, Cmd: cmd.GotoPrev, Description: "Go to previous cell"},
Bind{Key: Key{Char: '$'}, Cmd: cmd.GotoEnd, Description: "Go to last cell"},
Bind{Key: Key{Char: '0'}, Cmd: cmd.GotoStart, Description: "Go to first cell"},
Bind{Key: Key{Char: 'y'}, Cmd: cmd.Copy, Description: "Copy cell to clipboard"},
Bind{Key: Key{Char: 'o'}, Cmd: cmd.AppendNewRow, Description: "Append new row"},
// Tabs
Bind{Key: Key{Char: '['}, Cmd: cmd.TabPrev},
Bind{Key: Key{Char: ']'}, Cmd: cmd.TabNext},
Bind{Key: Key{Char: '{'}, Cmd: cmd.TabFirst},
Bind{Key: Key{Char: '}'}, Cmd: cmd.TabLast},
Bind{Key: Key{Char: 'X'}, Cmd: cmd.TabClose},
Bind{Key: Key{Char: '['}, Cmd: cmd.TabPrev, Description: "Switch to previous tab"},
Bind{Key: Key{Char: ']'}, Cmd: cmd.TabNext, Description: "Switch to next tab"},
Bind{Key: Key{Char: '{'}, Cmd: cmd.TabFirst, Description: "Switch to first tab"},
Bind{Key: Key{Char: '}'}, Cmd: cmd.TabLast, Description: "Switch to last tab"},
Bind{Key: Key{Char: 'X'}, Cmd: cmd.TabClose, Description: "Close tab"},
// Pages
Bind{Key: Key{Char: '>'}, Cmd: cmd.PageNext},
Bind{Key: Key{Char: '<'}, Cmd: cmd.PagePrev},
Bind{Key: Key{Char: '>'}, Cmd: cmd.PageNext, Description: "Switch to next page"},
Bind{Key: Key{Char: '<'}, Cmd: cmd.PagePrev, Description: "Switch to previous page"},
},
"editor": {
Bind{Key: Key{Code: tcell.KeyCtrlR}, Cmd: cmd.Execute},
Bind{Key: Key{Code: tcell.KeyEscape}, Cmd: cmd.Quit},
Bind{Key: Key{Code: tcell.KeyCtrlSpace}, Cmd: cmd.OpenInExternalEditor},
Bind{Key: Key{Code: tcell.KeyCtrlR}, Cmd: cmd.Execute, Description: "Execute query"},
Bind{Key: Key{Code: tcell.KeyEscape}, Cmd: cmd.Quit, Description: "Unfocus editor"},
Bind{Key: Key{Code: tcell.KeyCtrlSpace}, Cmd: cmd.OpenInExternalEditor, Description: "Open in external editor"},
},
},
}
3 changes: 3 additions & 0 deletions commands/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const (
// Views
SwitchToEditorView
SwitchToConnectionsView
HelpPopup

// Movement: Basic
MoveUp
Expand Down Expand Up @@ -54,6 +55,8 @@ func (c Command) String() string {
return "SwitchToEditorView"
case SwitchToConnectionsView:
return "SwitchToConnectionsView"
case HelpPopup:
return "HelpPopup"

// Movement: Basic
case MoveUp:
Expand Down
94 changes: 94 additions & 0 deletions components/HelpModal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package components

import (
"strings"

"github.com/gdamore/tcell/v2"
"github.com/jorgerojas26/lazysql/app"
"github.com/jorgerojas26/lazysql/commands"
"github.com/jorgerojas26/lazysql/keymap"
"github.com/rivo/tview"
)

type HelpModal struct {
tview.Primitive
}

func NewHelpModal() *HelpModal {
// Returns a new primitive which puts the provided primitive in the center and
// sets its size to the given width and height.
modal := func(p tview.Primitive, width, height int) tview.Primitive {
return tview.NewFlex().
AddItem(nil, 0, 1, false).
AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
AddItem(nil, 0, 1, false).
AddItem(p, height, 1, true).
AddItem(nil, 0, 1, false), width, 1, true).
AddItem(nil, 0, 1, false)
}

table := tview.NewTable()

// table.SetBorders(true)
table.SetBorder(true)
table.SetBorderColor(tview.Styles.PrimaryTextColor)
table.SetTitle(" Keybindings ")
table.SetSelectable(true, false)
table.SetSelectedStyle(tcell.StyleDefault.Background(tview.Styles.SecondaryTextColor).Foreground(tview.Styles.ContrastSecondaryTextColor))

keymapGroups := make(map[string]keymap.Map, len(app.Keymaps.Groups)+1)

keymapGroups["global"] = app.Keymaps.Global

for name, group := range app.Keymaps.Groups {
keymapGroups[name] = group
}

mostLengthyKey := ""

for groupName := range keymapGroups {
for _, key := range keymapGroups[groupName] {
if len(key.Key.String()) > len(mostLengthyKey) {
mostLengthyKey = key.Key.String()
}
}
}

for groupName, keys := range keymapGroups {
rowCount := table.GetRowCount()
groupNameCell := tview.NewTableCell(strings.ToUpper(groupName))
groupNameCell.SetTextColor(tview.Styles.TertiaryTextColor)
groupNameCell.SetSelectable(rowCount == 0)

table.SetCell(rowCount, 0, tview.NewTableCell("").SetSelectable(false))
table.SetCell(rowCount+1, 0, groupNameCell)
table.SetCell(rowCount+2, 0, tview.NewTableCell("").SetSelectable(false))

for i, key := range keys {
keyText := key.Key.String()

if len(keyText) < len(mostLengthyKey) {
keyText = strings.Repeat(" ", len(mostLengthyKey)-len(keyText)) + keyText
}
table.SetCell(rowCount+3+i, 0, tview.NewTableCell(keyText).SetAlign(tview.AlignRight).SetTextColor(tview.Styles.SecondaryTextColor))
table.SetCell(rowCount+3+i, 1, tview.NewTableCell(key.Description).SetAlign(tview.AlignLeft).SetExpansion(1))
}

}

table.Select(3, 0)

table.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
command := app.Keymaps.Group("global").Resolve(event)
if command == commands.Quit {
App.Stop()
} else if command == commands.HelpPopup {
MainPages.RemovePage(HelpPageName)
}
return event
})

r := &HelpModal{modal(table, 0, 30)}

return r
}
54 changes: 54 additions & 0 deletions components/HelpStatus.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package components

import (
"github.com/rivo/tview"

"github.com/jorgerojas26/lazysql/app"
"github.com/jorgerojas26/lazysql/keymap"
)

type HelpStatus struct {
*tview.TextView
}

func NewHelpStatus() HelpStatus {

status := HelpStatus{tview.NewTextView().SetTextColor(tview.Styles.TertiaryTextColor)}

status.SetStatusOnTree()

return status
}

func (status *HelpStatus) UpdateText(binds []keymap.Bind) {

newtext := ""

for i, key := range binds {

newtext += key.Cmd.String()

newtext += ": "

newtext += key.Key.String()

islast := i == len(binds)-1

if !islast {
newtext += " | "
}

}

status.SetText(newtext)
}

func (status *HelpStatus) SetStatusOnTree() {
status.UpdateText(app.Keymaps.Global)
}
func (status *HelpStatus) SetStatusOnEditorView() {
status.UpdateText(app.Keymaps.Group("editor"))
}
func (status *HelpStatus) SetStatusOnTableView() {
status.UpdateText(app.Keymaps.Group("table"))
}
52 changes: 40 additions & 12 deletions components/Home.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ type Home struct {
TabbedPane *TabbedPane
LeftWrapper *tview.Flex
RightWrapper *tview.Flex
HelpStatus HelpStatus
HelpModal *HelpModal
DBDriver drivers.Driver
FocusedWrapper string
ListOfDbChanges []models.DbDmlChange
Expand All @@ -28,12 +30,16 @@ func NewHomePage(connection models.Connection, dbdriver drivers.Driver) *Home {
leftWrapper := tview.NewFlex()
rightWrapper := tview.NewFlex()

maincontent := tview.NewFlex()

home := &Home{
Flex: tview.NewFlex(),
Flex: tview.NewFlex().SetDirection(tview.FlexRow),
Tree: tree,
TabbedPane: tabbedPane,
LeftWrapper: leftWrapper,
RightWrapper: rightWrapper,
HelpStatus: NewHelpStatus(),
HelpModal: NewHelpModal(),
ListOfDbChanges: []models.DbDmlChange{},
ListOfDbInserts: []models.DbInsert{},
DBDriver: dbdriver,
Expand All @@ -51,8 +57,11 @@ func NewHomePage(connection models.Connection, dbdriver drivers.Driver) *Home {
rightWrapper.AddItem(tabbedPane.HeaderContainer, 1, 0, false)
rightWrapper.AddItem(tabbedPane.Pages, 0, 1, false)

home.AddItem(leftWrapper, 30, 1, false)
home.AddItem(rightWrapper, 0, 5, false)
maincontent.AddItem(leftWrapper, 30, 1, false)
maincontent.AddItem(rightWrapper, 0, 5, false)

home.AddItem(maincontent, 0, 1, false)
// home.AddItem(home.HelpStatus, 1, 1, false)

home.SetInputCapture(home.homeInputCapture)

Expand Down Expand Up @@ -111,13 +120,13 @@ func (home *Home) focusRightWrapper() {
tab := home.TabbedPane.GetCurrentTab()

if tab != nil {
focusTab(tab)
home.focusTab(tab)
}

home.FocusedWrapper = "right"
}

func focusTab(tab *Tab) {
func (home *Home) focusTab(tab *Tab) {
if tab != nil {
table := tab.Content
table.HighlightAll()
Expand All @@ -140,6 +149,11 @@ func focusTab(tab *Tab) {
App.SetFocus(table)
}

if tab.Name == EditorTabName {
home.HelpStatus.SetStatusOnEditorView()
} else {
home.HelpStatus.SetStatusOnTableView()
}
}
}

Expand Down Expand Up @@ -171,16 +185,16 @@ func (home *Home) rightWrapperInputCapture(event *tcell.EventKey) *tcell.EventKe
command := app.Keymaps.Group("table").Resolve(event)

if command == commands.TabPrev {
focusTab(home.TabbedPane.SwitchToPreviousTab())
home.focusTab(home.TabbedPane.SwitchToPreviousTab())
return nil
} else if command == commands.TabNext {
focusTab(home.TabbedPane.SwitchToNextTab())
home.focusTab(home.TabbedPane.SwitchToNextTab())
return nil
} else if command == commands.TabFirst {
focusTab(home.TabbedPane.SwitchToFirstTab())
home.focusTab(home.TabbedPane.SwitchToFirstTab())
return nil
} else if command == commands.TabLast {
focusTab(home.TabbedPane.SwitchToLastTab())
home.focusTab(home.TabbedPane.SwitchToLastTab())
return nil
} else if command == commands.TabClose {
tab = home.TabbedPane.GetCurrentTab()
Expand Down Expand Up @@ -247,15 +261,16 @@ func (home *Home) homeInputCapture(event *tcell.EventKey) *tcell.EventKey {
home.focusRightWrapper()
}
} else if command == commands.SwitchToEditorView {
tab := home.TabbedPane.GetTabByName("Editor")
tab := home.TabbedPane.GetTabByName(EditorTabName)

if tab != nil {
home.TabbedPane.SwitchToTabByName("Editor")
home.TabbedPane.SwitchToTabByName(EditorTabName)
} else {
tableWithEditor := NewResultsTable(&home.ListOfDbChanges, &home.ListOfDbInserts, home.Tree, home.DBDriver).WithEditor()
home.TabbedPane.AppendTab("Editor", tableWithEditor)
home.TabbedPane.AppendTab(EditorTabName, tableWithEditor)
tableWithEditor.SetIsFiltering(true)
}
home.HelpStatus.SetStatusOnEditorView()
home.focusRightWrapper()
App.ForceDraw()
} else if command == commands.SwitchToConnectionsView {
Expand Down Expand Up @@ -300,6 +315,19 @@ func (home *Home) homeInputCapture(event *tcell.EventKey) *tcell.EventKey {

MainPages.AddPage("Confirmation", confirmationModal, true, true)
}
} else if command == commands.HelpPopup {
if table == nil || !table.GetIsEditing() {
// home.HelpModal.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
// command := app.Keymaps.Resolve(event)
// if command == commands.Quit {
// App.Stop()
// } else if event.Key() == tcell.KeyEsc {
// MainPages.RemovePage(HelpPageName)
// }
// return event
// })
MainPages.AddPage(HelpPageName, home.HelpModal, true, true)
}
}

return event
Expand Down
3 changes: 3 additions & 0 deletions components/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ package components
import "github.com/jorgerojas26/lazysql/app"

var App = app.App

const EditorTabName string = "Editor"
const HelpPageName string = "Help"
Loading

0 comments on commit 686462e

Please sign in to comment.