diff --git a/README.md b/README.md
index 14a366d..593c4bd 100644
--- a/README.md
+++ b/README.md
@@ -144,8 +144,10 @@ If you want the exact delta configuration I'm using - [it can be found here](htt
| Key | Description |
| :---------------- | :------------------------------- |
-| j | Next file |
-| k | Previous file |
+| j | Next node |
+| k | Previous node |
+| n | Next file |
+| p / N | Previous file |
| Ctrl-d | Scroll the diff down |
| Ctrl-u | Scroll the diff up |
| e | Toggle the file tree |
diff --git a/pkg/ui/keys.go b/pkg/ui/keys.go
index caa9c88..0eb127d 100644
--- a/pkg/ui/keys.go
+++ b/pkg/ui/keys.go
@@ -8,6 +8,8 @@ type KeyMap struct {
ToggleNode key.Binding
Up key.Binding
Down key.Binding
+ NextFile key.Binding
+ PrevFile key.Binding
CtrlD key.Binding
CtrlU key.Binding
ToggleFileTree key.Binding
@@ -42,6 +44,14 @@ var keys = &KeyMap{
key.WithKeys("down", "j"),
key.WithHelp("↓/j", "next file"),
),
+ NextFile: key.NewBinding(
+ key.WithKeys("n"),
+ key.WithHelp("n", "next file"),
+ ),
+ PrevFile: key.NewBinding(
+ key.WithKeys("p", "N"),
+ key.WithHelp("p/N", "prev file"),
+ ),
CtrlD: key.NewBinding(
key.WithKeys("ctrl+d"),
key.WithHelp("ctrl+d", "diff down"),
@@ -93,6 +103,8 @@ func KeyGroups() [][]key.Binding {
keys.SwitchPanel,
keys.Up,
keys.Down,
+ keys.NextFile,
+ keys.PrevFile,
keys.CtrlD,
keys.CtrlU,
}, {
diff --git a/pkg/ui/panes/diffviewer/diffviewer.go b/pkg/ui/panes/diffviewer/diffviewer.go
index 94c02a1..b0cb03b 100644
--- a/pkg/ui/panes/diffviewer/diffviewer.go
+++ b/pkg/ui/panes/diffviewer/diffviewer.go
@@ -69,9 +69,9 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
- case "down", "j":
+ case "down", "j", "n":
break
- case "up", "k":
+ case "up", "k", "N", "p":
break
default:
vp, vpCmd := m.vp.Update(msg)
diff --git a/pkg/ui/panes/filetree/filetree.go b/pkg/ui/panes/filetree/filetree.go
index 202a1a3..002a783 100644
--- a/pkg/ui/panes/filetree/filetree.go
+++ b/pkg/ui/panes/filetree/filetree.go
@@ -131,6 +131,52 @@ func (m *Model) Up() {
m.t.Up()
}
+// NextFile moves the cursor to the next file node, skipping directories.
+func (m *Model) NextFile() bool {
+ curr := m.t.NodeAtCurrentOffset()
+ if curr == nil {
+ return false
+ }
+ nodes := m.t.AllNodes()
+ found := false
+ for _, node := range nodes {
+ if !found {
+ if node.YOffset() == curr.YOffset() {
+ found = true
+ }
+ continue
+ }
+ if _, ok := node.GivenValue().(*filenode.FileNode); ok {
+ m.t.SetYOffset(node.YOffset())
+ return true
+ }
+ }
+ return false
+}
+
+// PrevFile moves the cursor to the previous file node, skipping directories.
+func (m *Model) PrevFile() bool {
+ curr := m.t.NodeAtCurrentOffset()
+ if curr == nil {
+ return false
+ }
+ nodes := m.t.AllNodes()
+ lastFileOffset := -1
+ for _, node := range nodes {
+ if node.YOffset() >= curr.YOffset() {
+ break
+ }
+ if _, ok := node.GivenValue().(*filenode.FileNode); ok {
+ lastFileOffset = node.YOffset()
+ }
+ }
+ if lastFileOffset >= 0 {
+ m.t.SetYOffset(lastFileOffset)
+ return true
+ }
+ return false
+}
+
func (m *Model) SetCursorByPath(path string) {
if len(m.files) == 0 {
return
diff --git a/pkg/ui/tui.go b/pkg/ui/tui.go
index f791f7f..0cf97a3 100644
--- a/pkg/ui/tui.go
+++ b/pkg/ui/tui.go
@@ -180,6 +180,12 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.activePanel = FileTreePanel
}
}
+ case key.Matches(msg, keys.PrevFile):
+ m, cmd = m.moveToFile(-1)
+ cmds = append(cmds, cmd)
+ case key.Matches(msg, keys.NextFile):
+ m, cmd = m.moveToFile(1)
+ cmds = append(cmds, cmd)
case key.Matches(msg, keys.Up):
if m.activePanel == FileTreePanel {
m, cmd = m.moveCursor(-1)
@@ -743,6 +749,27 @@ func abs(x int) int {
return x
}
+func (m mainModel) moveToFile(movement int) (mainModel, tea.Cmd) {
+ var cmd tea.Cmd
+ var moved bool
+ switch movement {
+ case -1:
+ moved = m.fileTree.PrevFile()
+ case 1:
+ moved = m.fileTree.NextFile()
+ }
+
+ if !moved {
+ return m, nil
+ }
+
+ node := m.fileTree.GetCurrNode()
+ m, cmd = m.setNodeDiff(node)
+ m.diffViewer.GoToTop()
+
+ return m, cmd
+}
+
func (m mainModel) moveCursor(movement int) (mainModel, tea.Cmd) {
var cmd tea.Cmd
switch movement {