Skip to content

Commit d1395a6

Browse files
committed
feat: support 'n'/'p' key to move to the next/prev hunk.
fix make check errors
1 parent ff48840 commit d1395a6

File tree

4 files changed

+90
-2
lines changed

4 files changed

+90
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3636
* allow `copy` file path on revision files and status tree [[@yanganto]](https://github.com/yanganto) ([#1516](https://github.com/extrawurst/gitui/pull/1516))
3737
* print message of where log will be written if `-l` is set ([#1472](https://github.com/extrawurst/gitui/pull/1472))
3838
* show remote branches in log [[@cruessler](https://github.com/cruessler)] ([#1501](https://github.com/extrawurst/gitui/issues/1501))
39+
* support 'n'/'p' key to move to the next/prev hunk in diff component [[@hamflx](https://github.com/hamflx)] ([#1523](https://github.com/extrawurst/gitui/issues/1523))
3940

4041
### Fixes
4142
* fixed side effect of crossterm 0.26 on windows that caused double input of all keys [[@pm100]](https://github/pm100) ([#1686](https://github.com/extrawurst/gitui/pull/1686))

src/components/diff.rs

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,44 @@ impl DiffComponent {
629629
Ok(())
630630
}
631631

632+
fn calc_hunk_move_target(
633+
&self,
634+
direction: isize,
635+
) -> Option<usize> {
636+
let diff = self.diff.as_ref()?;
637+
if diff.hunks.is_empty() {
638+
return None;
639+
}
640+
let max = diff.hunks.len() - 1;
641+
let target_index = self.selected_hunk.map_or(0, |i| {
642+
let target = if direction >= 0 {
643+
i.saturating_add(direction.unsigned_abs())
644+
} else {
645+
i.saturating_sub(direction.unsigned_abs())
646+
};
647+
std::cmp::min(max, target)
648+
});
649+
Some(target_index)
650+
}
651+
652+
fn diff_hunk_move_up_down(&mut self, direction: isize) {
653+
let Some(diff) = &self.diff else { return };
654+
let target_index = self.calc_hunk_move_target(direction);
655+
// return if selected_hunk not change
656+
if self.selected_hunk == target_index {
657+
return;
658+
}
659+
if let Some(target_index) = target_index {
660+
let lines = diff
661+
.hunks
662+
.iter()
663+
.take(target_index)
664+
.fold(0, |sum, hunk| sum + hunk.lines.len());
665+
self.selection = Selection::Single(lines);
666+
self.selected_hunk = Some(target_index);
667+
}
668+
}
669+
632670
const fn is_stage(&self) -> bool {
633671
self.current.is_stage
634672
}
@@ -710,7 +748,16 @@ impl Component for DiffComponent {
710748
self.can_scroll(),
711749
self.focused(),
712750
));
713-
751+
out.push(CommandInfo::new(
752+
strings::commands::diff_hunk_next(&self.key_config),
753+
self.calc_hunk_move_target(1) != self.selected_hunk,
754+
self.focused(),
755+
));
756+
out.push(CommandInfo::new(
757+
strings::commands::diff_hunk_prev(&self.key_config),
758+
self.calc_hunk_move_target(-1) != self.selected_hunk,
759+
self.focused(),
760+
));
714761
out.push(
715762
CommandInfo::new(
716763
strings::commands::diff_home_end(&self.key_config),
@@ -769,7 +816,7 @@ impl Component for DiffComponent {
769816
CommandBlocking::PassingOn
770817
}
771818

772-
#[allow(clippy::cognitive_complexity)]
819+
#[allow(clippy::cognitive_complexity, clippy::too_many_lines)]
773820
fn event(&mut self, ev: &Event) -> Result<EventState> {
774821
if self.focused() {
775822
if let Event::Key(e) = ev {
@@ -815,6 +862,18 @@ impl Component for DiffComponent {
815862
self.horizontal_scroll
816863
.move_right(HorizontalScrollType::Left);
817864
Ok(EventState::Consumed)
865+
} else if key_match(
866+
e,
867+
self.key_config.keys.diff_hunk_next,
868+
) {
869+
self.diff_hunk_move_up_down(1);
870+
Ok(EventState::Consumed)
871+
} else if key_match(
872+
e,
873+
self.key_config.keys.diff_hunk_prev,
874+
) {
875+
self.diff_hunk_move_up_down(-1);
876+
Ok(EventState::Consumed)
818877
} else if key_match(
819878
e,
820879
self.key_config.keys.stage_unstage_item,

src/keys/key_list.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ pub struct KeysList {
109109
pub pull: GituiKeyEvent,
110110
pub abort_merge: GituiKeyEvent,
111111
pub undo_commit: GituiKeyEvent,
112+
pub diff_hunk_next: GituiKeyEvent,
113+
pub diff_hunk_prev: GituiKeyEvent,
112114
pub stage_unstage_item: GituiKeyEvent,
113115
pub tag_annotate: GituiKeyEvent,
114116
pub view_submodules: GituiKeyEvent,
@@ -193,6 +195,8 @@ impl Default for KeysList {
193195
open_file_tree: GituiKeyEvent::new(KeyCode::Char('F'), KeyModifiers::SHIFT),
194196
file_find: GituiKeyEvent::new(KeyCode::Char('f'), KeyModifiers::empty()),
195197
branch_find: GituiKeyEvent::new(KeyCode::Char('f'), KeyModifiers::empty()),
198+
diff_hunk_next: GituiKeyEvent::new(KeyCode::Char('n'), KeyModifiers::empty()),
199+
diff_hunk_prev: GituiKeyEvent::new(KeyCode::Char('p'), KeyModifiers::empty()),
196200
stage_unstage_item: GituiKeyEvent::new(KeyCode::Enter, KeyModifiers::empty()),
197201
tag_annotate: GituiKeyEvent::new(KeyCode::Char('a'), KeyModifiers::CONTROL),
198202
view_submodules: GituiKeyEvent::new(KeyCode::Char('S'), KeyModifiers::SHIFT),

src/strings.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,30 @@ pub mod commands {
603603
CMD_GROUP_LOG,
604604
)
605605
}
606+
pub fn diff_hunk_next(
607+
key_config: &SharedKeyConfig,
608+
) -> CommandText {
609+
CommandText::new(
610+
format!(
611+
"Next hunk [{}]",
612+
key_config.get_hint(key_config.keys.diff_hunk_next),
613+
),
614+
"move cursor to next hunk",
615+
CMD_GROUP_DIFF,
616+
)
617+
}
618+
pub fn diff_hunk_prev(
619+
key_config: &SharedKeyConfig,
620+
) -> CommandText {
621+
CommandText::new(
622+
format!(
623+
"Prev hunk [{}]",
624+
key_config.get_hint(key_config.keys.diff_hunk_prev),
625+
),
626+
"move cursor to prev hunk",
627+
CMD_GROUP_DIFF,
628+
)
629+
}
606630
pub fn diff_home_end(
607631
key_config: &SharedKeyConfig,
608632
) -> CommandText {

0 commit comments

Comments
 (0)