Skip to content

Commit

Permalink
feat: enable vim inspired navigation to jump around views (0,$,G,g)
Browse files Browse the repository at this point in the history
  • Loading branch information
adasauce committed Mar 12, 2024
1 parent 5fec11c commit 909be88
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
10 changes: 10 additions & 0 deletions pkg/gui/keybindings.go
Expand Up @@ -151,6 +151,16 @@ func initialKeyBindings() []keyBinding {
}...)
}

// vim motion inspired keys navigation.
for _, viewName := range []string{"rows", "structure", "constraints"} {
bindings = append(bindings, []keyBinding{
{view: viewName, key: '0', mod: gocui.ModNone, handler: slamCursor("left")},
{view: viewName, key: '$', mod: gocui.ModNone, handler: slamCursor("right")},
{view: viewName, key: 'G', mod: gocui.ModNone, handler: slamCursor("down")},
{view: viewName, key: 'g', mod: gocui.ModNone, handler: slamCursor("up")},
}...)
}

// defines the navigation on the "tables" view.
bindings = append(bindings, []keyBinding{
{view: "tables", key: 'k', mod: gocui.ModNone, handler: moveCursorVertically("up")},
Expand Down
65 changes: 65 additions & 0 deletions pkg/gui/view_helpers.go
Expand Up @@ -79,6 +79,71 @@ func moveCursorHorizontally(direction string) func(g *gocui.Gui, v *gocui.View)
}
}

// slamCursor moves the cursor all the way in the given direction.
// it reads the whole buffer to check the bounds of how far we can go down
// and uses the current line contents to check how far we can go right.
func slamCursor(direction string) func(g *gocui.Gui, v *gocui.View) error {
return func(g *gocui.Gui, v *gocui.View) error {
if v != nil {
maxX, maxY := v.Size()

cx, cy := v.Cursor()
ox, oy := v.Origin()

currentLine, err := v.Line(cy)
if err != nil {
return err
}

var newCursorX, newCursorY int
var newOriginX, newOriginY int
switch direction {
case "up":
newCursorX = cx
newCursorY = 0
newOriginX = ox
newOriginY = 0
case "left":
newCursorX = 0
newCursorY = cy
newOriginY = oy
newOriginX = 0
case "down":
newCursorX = cx
newOriginX = ox

// the actual output len is consistently 2 less than the buffer lines
bufLines := v.BufferLines()
actualBufLineLen := len(bufLines) - 2

newCursorY = maxY - 1
if newCursorY >= actualBufLineLen {
newCursorY = actualBufLineLen
}
newOriginY = actualBufLineLen - newCursorY
case "right":
newCursorY = cy
newOriginY = oy

newCursorX = maxX - 1
if newCursorX >= len(currentLine) {
newCursorX = len(currentLine) - 1
}
newOriginX = len(currentLine) - newCursorX - 1
}

if err := v.SetCursor(newCursorX, newCursorY); err != nil {
return err
}
if err := v.SetOrigin(newOriginX, newOriginY); err != nil {
return err
}

}
return nil
}
}

// moveCursorVertically moves the cursor vertically given a direction.
// the down position is handled in a special way to prevent the cursor keep going
// down when there's no characters in the next lines.
Expand Down

0 comments on commit 909be88

Please sign in to comment.