Skip to content

Commit

Permalink
Merge pull request #58 from pnx/keybinds
Browse files Browse the repository at this point in the history
Keybind support.
  • Loading branch information
jorgerojas26 committed Jun 13, 2024
2 parents 8bf3d17 + d35ba0e commit f7b6c31
Show file tree
Hide file tree
Showing 9 changed files with 315 additions and 29 deletions.
82 changes: 82 additions & 0 deletions app/Keymap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package app

import (
"github.com/gdamore/tcell/v2"
. "github.com/jorgerojas26/lazysql/commands"
. "github.com/jorgerojas26/lazysql/keymap"
)

// KeymapSystem is the actual key mapping system.
//
// A map can have several groups. But it always has a "Global" one.
type KeymapSystem struct {
Global Map
Groups map[string]Map
}

func (c KeymapSystem) Group(name string) Map {
// Global is special.
if name == "global" {
return c.Global
}

// Lookup the group
if group, ok := c.Groups[name]; ok {
return group
}

// Did not find any maps. Return a empty one
return Map{}
}

// Resolve translates a tcell.EventKey into a command based on the mappings in
// the global group
func (c KeymapSystem) Resolve(event *tcell.EventKey) Command {
return c.Global.Resolve(event)
}

// Define a global KeymapSystem object with default keybinds
var Keymaps KeymapSystem = KeymapSystem{
Global: Map{
Bind{Key: Key{Char: 'L'}, Cmd: MoveRight},
Bind{Key: Key{Char: 'H'}, Cmd: MoveLeft},
Bind{Key: Key{Code: tcell.KeyCtrlE}, Cmd: SwitchToEditorView},
Bind{Key: Key{Code: tcell.KeyCtrlS}, Cmd: Save},
Bind{Key: Key{Char: 'q'}, Cmd: Quit},
Bind{Key: Key{Code: tcell.KeyBackspace2}, Cmd: SwitchToConnectionsView},
},
Groups: map[string]Map{
"tree": {
Bind{Key: Key{Char: 'g'}, Cmd: GotoTop},
Bind{Key: Key{Char: 'G'}, Cmd: GotoBottom},
Bind{Key: Key{Code: tcell.KeyEnter}, Cmd: Execute},
Bind{Key: Key{Char: 'j'}, Cmd: MoveDown},
Bind{Key: Key{Code: tcell.KeyDown}, Cmd: MoveDown},
Bind{Key: Key{Char: 'k'}, Cmd: MoveUp},
Bind{Key: Key{Code: tcell.KeyUp}, Cmd: MoveUp},
},
"table": {
Bind{Key: Key{Char: '/'}, Cmd: Search},
Bind{Key: Key{Char: 'c'}, Cmd: Edit},
Bind{Key: Key{Char: 'd'}, Cmd: Delete},
Bind{Key: Key{Char: 'w'}, Cmd: GotoNext},
Bind{Key: Key{Char: 'b'}, Cmd: GotoPrev},
Bind{Key: Key{Char: '$'}, Cmd: GotoEnd},
Bind{Key: Key{Char: '0'}, Cmd: GotoStart},
Bind{Key: Key{Char: 'y'}, Cmd: Copy},
// Tabs
Bind{Key: Key{Char: '['}, Cmd: TabPrev},
Bind{Key: Key{Char: ']'}, Cmd: TabNext},
Bind{Key: Key{Char: '{'}, Cmd: TabFirst},
Bind{Key: Key{Char: '}'}, Cmd: TabLast},
Bind{Key: Key{Char: 'X'}, Cmd: TabClose},
// Pages
Bind{Key: Key{Char: '>'}, Cmd: PageNext},
Bind{Key: Key{Char: '<'}, Cmd: PagePrev},
},
"editor": {
Bind{Key: Key{Code: tcell.KeyCtrlR}, Cmd: Execute},
Bind{Key: Key{Code: tcell.KeyEscape}, Cmd: Quit},
},
},
}
114 changes: 114 additions & 0 deletions commands/commands.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package commands

type Command uint8

const (
Noop Command = iota

// Views
SwitchToEditorView
SwitchToConnectionsView

// Movement: Basic
MoveUp
MoveDown
MoveLeft
MoveRight
// Movement: Jumps
GotoNext
GotoPrev
GotoStart
GotoEnd
GotoTop
GotoBottom

// Movement: Page
PageNext
PagePrev

// Tabs
TabNext
TabPrev
TabFirst
TabLast
TabClose

// Operations
Copy
Edit
Save
Delete
Search
Quit
Execute
)

func (c Command) String() string {
switch c {
case Noop:
return "Noop"
// Views
case SwitchToEditorView:
return "SwitchToEditorView"
case SwitchToConnectionsView:
return "SwitchToConnectionsView"

// Movement: Basic
case MoveUp:
return "MoveUp"
case MoveDown:
return "MoveDown"
case MoveLeft:
return "MoveRight"
case MoveRight:
return "MoveRight"
// Movement: Jumps
case GotoNext:
return "GotoNext"
case GotoPrev:
return "GotoPrev"
case GotoStart:
return "GotoStart"
case GotoEnd:
return "GotoEnd"
case GotoTop:
return "GotoTop"
case GotoBottom:
return "GotoBottom"

// Movement: Page
case PageNext:
return "PageNext"
case PagePrev:
return "PagePrev"

// Tabs
case TabNext:
return "TabNext"
case TabPrev:
return "TabPrev"
case TabFirst:
return "TabFirst"
case TabLast:
return "TabLast"
case TabClose:
return "TabClose"

// Operations
case Copy:
return "Copy"
case Edit:
return "Edit"
case Save:
return "Save"
case Delete:
return "Delete"
case Search:
return "Search"
case Quit:
return "Quit"
case Execute:
return "Execute"
}
return "Unknown"
}
31 changes: 18 additions & 13 deletions components/Home.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package components

import (
"github.com/jorgerojas26/lazysql/commands"
"github.com/jorgerojas26/lazysql/models"

"github.com/jorgerojas26/lazysql/app"
Expand Down Expand Up @@ -164,19 +165,21 @@ func (home *Home) focusLeftWrapper() {
func (home *Home) rightWrapperInputCapture(event *tcell.EventKey) *tcell.EventKey {
var tab *Tab

if event.Rune() == '[' {
command := app.Keymaps.Group("table").Resolve(event)

if command == commands.TabPrev {
focusTab(home.TabbedPane.SwitchToPreviousTab())
return nil
} else if event.Rune() == ']' {
} else if command == commands.TabNext {
focusTab(home.TabbedPane.SwitchToNextTab())
return nil
} else if event.Rune() == '{' {
} else if command == commands.TabFirst {
focusTab(home.TabbedPane.SwitchToFirstTab())
return nil
} else if event.Rune() == '}' {
} else if command == commands.TabLast {
focusTab(home.TabbedPane.SwitchToLastTab())
return nil
} else if event.Rune() == 'X' {
} else if command == commands.TabClose {
tab = home.TabbedPane.GetCurrentTab()

if tab != nil {
Expand All @@ -191,7 +194,7 @@ func (home *Home) rightWrapperInputCapture(event *tcell.EventKey) *tcell.EventKe
}
}
}
} else if event.Rune() == '<' {
} else if command == commands.PagePrev {
tab = home.TabbedPane.GetCurrentTab()

if tab != nil {
Expand All @@ -205,7 +208,7 @@ func (home *Home) rightWrapperInputCapture(event *tcell.EventKey) *tcell.EventKe

}

} else if event.Rune() == '>' {
} else if command == commands.PageNext {
tab = home.TabbedPane.GetCurrentTab()

if tab != nil {
Expand All @@ -230,15 +233,17 @@ func (home *Home) homeInputCapture(event *tcell.EventKey) *tcell.EventKey {
table = tab.Content
}

if event.Rune() == 'H' {
command := app.Keymaps.Resolve(event)

if command == commands.MoveLeft {
if table != nil && !table.GetIsEditing() && !table.GetIsFiltering() && home.FocusedWrapper == "right" {
home.focusLeftWrapper()
}
} else if event.Rune() == 'L' {
} else if command == commands.MoveRight {
if table != nil && !table.GetIsEditing() && !table.GetIsFiltering() && home.FocusedWrapper == "left" {
home.focusRightWrapper()
}
} else if event.Rune() == 5 {
} else if command == commands.SwitchToEditorView {
tab := home.TabbedPane.GetTabByName("Editor")

if tab != nil {
Expand All @@ -250,11 +255,11 @@ func (home *Home) homeInputCapture(event *tcell.EventKey) *tcell.EventKey {
}
home.focusRightWrapper()
App.ForceDraw()
} else if event.Rune() == 127 {
} else if command == commands.SwitchToConnectionsView {
if (table != nil && !table.GetIsEditing() && !table.GetIsFiltering() && !table.GetIsLoading()) || table == nil {
MainPages.SwitchToPage("Connections")
}
} else if event.Rune() == 'q' {
} else if command == commands.Quit {
if tab != nil {
table := tab.Content

Expand All @@ -264,7 +269,7 @@ func (home *Home) homeInputCapture(event *tcell.EventKey) *tcell.EventKey {
} else {
App.Stop()
}
} else if event.Rune() == 19 {
} else if command == commands.Save {
if (home.ListOfDbChanges != nil && len(home.ListOfDbChanges) > 0) || (home.ListOfDbInserts != nil && len(home.ListOfDbInserts) > 0) && !table.GetIsEditing() {
confirmationModal := NewConfirmationModal("")

Expand Down
24 changes: 14 additions & 10 deletions components/ResultsTable.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"strings"

"github.com/jorgerojas26/lazysql/app"
"github.com/jorgerojas26/lazysql/commands"
"github.com/jorgerojas26/lazysql/models"

"github.com/jorgerojas26/lazysql/drivers"
Expand Down Expand Up @@ -258,7 +260,9 @@ func (table *ResultsTable) tableInputCapture(event *tcell.EventKey) *tcell.Event
return nil
}

if eventKey == '/' {
command := app.Keymaps.Group("table").Resolve(event)

if command == commands.Search {
if table.Editor != nil {
App.SetFocus(table.Editor)
table.Editor.Highlight()
Expand Down Expand Up @@ -356,29 +360,29 @@ func (table *ResultsTable) tableInputCapture(event *tcell.EventKey) *tcell.Event

}
table.SetInputCapture(nil)
} else if eventKey == 'c' {
} else if command == commands.Edit {
table.StartEditingCell(selectedRowIndex, selectedColumnIndex, func(newValue string, row, col int) {
cellReference := table.GetCell(row, 0).GetReference()

if cellReference != nil {
table.MutateInsertedRowCell(cellReference.(uuid.UUID), col, newValue)
}
})
} else if eventKey == 'w' {
} else if command == commands.GotoNext {
if selectedColumnIndex+1 < colCount {
table.Select(selectedRowIndex, selectedColumnIndex+1)
}
} else if eventKey == 'b' {
} else if command == commands.GotoPrev {
if selectedColumnIndex > 0 {
table.Select(selectedRowIndex, selectedColumnIndex-1)
}
} else if eventKey == '$' {
} else if command == commands.GotoEnd {
table.Select(selectedRowIndex, colCount-1)
} else if eventKey == '0' {
} else if command == commands.GotoStart {
table.Select(selectedRowIndex, 0)
} else if eventKey == 'g' {
} else if command == commands.GotoBottom {
go table.Select(1, selectedColumnIndex)
} else if eventKey == 'G' {
} else if command == commands.GotoTop {
go table.Select(rowCount-1, selectedColumnIndex)
} else if eventKey == 4 { // Ctrl + D
if selectedRowIndex+7 > rowCount-1 {
Expand All @@ -392,7 +396,7 @@ func (table *ResultsTable) tableInputCapture(event *tcell.EventKey) *tcell.Event
} else {
go table.Select(selectedRowIndex-7, selectedColumnIndex)
}
} else if eventKey == 'd' {
} else if command == commands.Delete {
if table.Menu.GetSelectedOption() == 1 {
isAnInsertedRow := false
indexOfInsertedRow := -1
Expand Down Expand Up @@ -486,7 +490,7 @@ func (table *ResultsTable) tableInputCapture(event *tcell.EventKey) *tcell.Event
currentColumnName := table.GetColumnNameByIndex(selectedColumnIndex)
table.Pagination.SetOffset(0)
table.SetSortedBy(currentColumnName, "ASC")
} else if eventKey == 'y' {
} else if command == commands.Copy {
selectedCell := table.GetCell(selectedRowIndex, selectedColumnIndex)

if selectedCell != nil {
Expand Down
8 changes: 6 additions & 2 deletions components/SQLEditor.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package components

import (
"github.com/jorgerojas26/lazysql/app"
"github.com/jorgerojas26/lazysql/commands"
"github.com/jorgerojas26/lazysql/models"

"github.com/gdamore/tcell/v2"
Expand Down Expand Up @@ -32,10 +34,12 @@ func NewSQLEditor() *SQLEditor {
}

sqlEditor.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
if event.Rune() == 18 { // Ctrl + R
command := app.Keymaps.Group("editor").Resolve(event)

if command == commands.Execute {
sqlEditor.Publish("Query", sqlEditor.GetText())
return nil
} else if event.Key() == tcell.KeyEscape {
} else if command == commands.Quit {
sqlEditor.Publish("Escape", "")
}

Expand Down
Loading

0 comments on commit f7b6c31

Please sign in to comment.