Skip to content

Commit c899b9e

Browse files
authored
feat: add n (next file) and p/N (previous file) shortcuts to jump between files (#98)
## Summary - Add `n` to jump to the next file and `p`/`N` to jump to the previous file, skipping directory nodes - Works from any panel (file tree or diff viewer) Closes #12
1 parent 41f1c16 commit c899b9e

5 files changed

Lines changed: 91 additions & 4 deletions

File tree

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,10 @@ If you want the exact delta configuration I'm using - [it can be found here](htt
144144

145145
| Key | Description |
146146
| :---------------- | :------------------------------- |
147-
| <kbd>j</kbd> | Next file |
148-
| <kbd>k</kbd> | Previous file |
147+
| <kbd>j</kbd> | Next node |
148+
| <kbd>k</kbd> | Previous node |
149+
| <kbd>n</kbd> | Next file |
150+
| <kbd>p</kbd> / <kbd>N</kbd> | Previous file |
149151
| <kbd>Ctrl-d</kbd> | Scroll the diff down |
150152
| <kbd>Ctrl-u</kbd> | Scroll the diff up |
151153
| <kbd>e</kbd> | Toggle the file tree |

pkg/ui/keys.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ type KeyMap struct {
88
ToggleNode key.Binding
99
Up key.Binding
1010
Down key.Binding
11+
NextFile key.Binding
12+
PrevFile key.Binding
1113
CtrlD key.Binding
1214
CtrlU key.Binding
1315
ToggleFileTree key.Binding
@@ -42,6 +44,14 @@ var keys = &KeyMap{
4244
key.WithKeys("down", "j"),
4345
key.WithHelp("↓/j", "next file"),
4446
),
47+
NextFile: key.NewBinding(
48+
key.WithKeys("n"),
49+
key.WithHelp("n", "next file"),
50+
),
51+
PrevFile: key.NewBinding(
52+
key.WithKeys("p", "N"),
53+
key.WithHelp("p/N", "prev file"),
54+
),
4555
CtrlD: key.NewBinding(
4656
key.WithKeys("ctrl+d"),
4757
key.WithHelp("ctrl+d", "diff down"),
@@ -93,6 +103,8 @@ func KeyGroups() [][]key.Binding {
93103
keys.SwitchPanel,
94104
keys.Up,
95105
keys.Down,
106+
keys.NextFile,
107+
keys.PrevFile,
96108
keys.CtrlD,
97109
keys.CtrlU,
98110
}, {

pkg/ui/panes/diffviewer/diffviewer.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
6969
switch msg := msg.(type) {
7070
case tea.KeyMsg:
7171
switch msg.String() {
72-
case "down", "j":
72+
case "down", "j", "n":
7373
break
74-
case "up", "k":
74+
case "up", "k", "N", "p":
7575
break
7676
default:
7777
vp, vpCmd := m.vp.Update(msg)

pkg/ui/panes/filetree/filetree.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,52 @@ func (m *Model) Up() {
131131
m.t.Up()
132132
}
133133

134+
// NextFile moves the cursor to the next file node, skipping directories.
135+
func (m *Model) NextFile() bool {
136+
curr := m.t.NodeAtCurrentOffset()
137+
if curr == nil {
138+
return false
139+
}
140+
nodes := m.t.AllNodes()
141+
found := false
142+
for _, node := range nodes {
143+
if !found {
144+
if node.YOffset() == curr.YOffset() {
145+
found = true
146+
}
147+
continue
148+
}
149+
if _, ok := node.GivenValue().(*filenode.FileNode); ok {
150+
m.t.SetYOffset(node.YOffset())
151+
return true
152+
}
153+
}
154+
return false
155+
}
156+
157+
// PrevFile moves the cursor to the previous file node, skipping directories.
158+
func (m *Model) PrevFile() bool {
159+
curr := m.t.NodeAtCurrentOffset()
160+
if curr == nil {
161+
return false
162+
}
163+
nodes := m.t.AllNodes()
164+
lastFileOffset := -1
165+
for _, node := range nodes {
166+
if node.YOffset() >= curr.YOffset() {
167+
break
168+
}
169+
if _, ok := node.GivenValue().(*filenode.FileNode); ok {
170+
lastFileOffset = node.YOffset()
171+
}
172+
}
173+
if lastFileOffset >= 0 {
174+
m.t.SetYOffset(lastFileOffset)
175+
return true
176+
}
177+
return false
178+
}
179+
134180
func (m *Model) SetCursorByPath(path string) {
135181
if len(m.files) == 0 {
136182
return

pkg/ui/tui.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,12 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
187187
m.activePanel = FileTreePanel
188188
}
189189
}
190+
case key.Matches(msg, keys.PrevFile):
191+
m, cmd = m.moveToFile(-1)
192+
cmds = append(cmds, cmd)
193+
case key.Matches(msg, keys.NextFile):
194+
m, cmd = m.moveToFile(1)
195+
cmds = append(cmds, cmd)
190196
case key.Matches(msg, keys.Up):
191197
if m.activePanel == FileTreePanel {
192198
m, cmd = m.moveCursor(-1)
@@ -750,6 +756,27 @@ func abs(x int) int {
750756
return x
751757
}
752758

759+
func (m mainModel) moveToFile(movement int) (mainModel, tea.Cmd) {
760+
var cmd tea.Cmd
761+
var moved bool
762+
switch movement {
763+
case -1:
764+
moved = m.fileTree.PrevFile()
765+
case 1:
766+
moved = m.fileTree.NextFile()
767+
}
768+
769+
if !moved {
770+
return m, nil
771+
}
772+
773+
node := m.fileTree.GetCurrNode()
774+
m, cmd = m.setNodeDiff(node)
775+
m.diffViewer.GoToTop()
776+
777+
return m, cmd
778+
}
779+
753780
func (m mainModel) moveCursor(movement int) (mainModel, tea.Cmd) {
754781
var cmd tea.Cmd
755782
switch movement {

0 commit comments

Comments
 (0)