Skip to content

Commit 8f4d1fc

Browse files
authored
Select commits in Detail and UserCommand views (#109)
* Add select_(up|down) user event * Handle select_(up|down) user event * Implement select_(older|newer)_commit * Extract functions * Reset offset when select commit * Update README * Update helps * Fix word * Fix README
1 parent 2480cf0 commit 8f4d1fc

9 files changed

Lines changed: 134 additions & 21 deletions

File tree

README.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ The default key bindings can be overridden. Please refer to [default-keybind.tom
190190
| Key | Description | Corresponding keybind |
191191
| ------------------------------------ | -------------------------------------------------- | -------------------------------------------- |
192192
| <kbd>Down/Up</kbd> <kbd>j/k</kbd> | Move down/up | `navigate_down` `navigate_up` |
193+
| <kbd>J/K</kbd> | Move down/up | `select_down` `select_up` |
193194
| <kbd>Alt-Down</kbd> <kbd>Alt-j</kbd> | Move to parent commit | `go_to_parent` |
194195
| <kbd>g/G</kbd> | Go to top/bottom | `go_to_top` `go_to_bottom` |
195196
| <kbd>Ctrl-f/b</kbd> | Scroll page down/up | `page_down` `page_up` |
@@ -215,6 +216,7 @@ The default key bindings can be overridden. Please refer to [default-keybind.tom
215216
| <kbd>Ctrl-f/b</kbd> | Scroll page down/up | `page_down` `page_up` |
216217
| <kbd>Ctrl-d/u</kbd> | Scroll half page down/up | `half_page_down` `half_page_up` |
217218
| <kbd>g/G</kbd> | Go to top/bottom | `go_to_top` `go_to_bottom` |
219+
| <kbd>J/K</kbd> | Select older/newer commit | `select_down` `select_up` |
218220
| <kbd>c/C</kbd> | Copy commit short/full hash | `short_copy` `full_copy` |
219221
| <kbd>d</kbd> | Toggle custom user command view | `user_command_view_toggle_1` |
220222

@@ -224,26 +226,30 @@ The default key bindings can be overridden. Please refer to [default-keybind.tom
224226
| -------------------------------------------------- | ---------------- | ---------------------------------- |
225227
| <kbd>Esc</kbd> <kbd>Backspace</kbd> <kbd>Tab</kbd> | Close refs list | `close` `cancel` `ref_list_toggle` |
226228
| <kbd>Down/Up</kbd> <kbd>j/k</kbd> | Move down/up | `navigate_down` `navigate_up` |
229+
| <kbd>J/K</kbd> | Move down/up | `select_down` `select_up` |
227230
| <kbd>g/G</kbd> | Go to top/bottom | `go_to_top` `go_to_bottom` |
228231
| <kbd>Right/Left</kbd> <kbd>l/h</kbd> | Open/Close node | `navigate_right` `navigate_left` |
229232
| <kbd>c</kbd> | Copy ref name | `short_copy` |
230233

231234
#### User Command
232235

233-
| Key | Description | Corresponding keybind |
234-
| ------------------------------------------------ | ------------------------ | ------------------------------- |
235-
| <kbd>Esc</kbd> <kbd>Backspace</kbd> <kbd>?</kbd> | Close user command | `close` `cancel` `help_toggle` |
236-
| <kbd>Down/Up</kbd> <kbd>j/k</kbd> | Scroll down/up | `navigate_down` `navigate_up` |
237-
| <kbd>Ctrl-f/b</kbd> | Scroll page down/up | `page_down` `page_up` |
238-
| <kbd>Ctrl-d/u</kbd> | Scroll half page down/up | `half_page_down` `half_page_up` |
239-
| <kbd>g/G</kbd> | Go to top/bottom | `go_to_top` `go_to_bottom` |
236+
| Key | Description | Corresponding keybind |
237+
| ------------------------------------------------ | --------------------------- | ------------------------------- |
238+
| <kbd>Esc</kbd> <kbd>Backspace</kbd> <kbd>?</kbd> | Close user command | `close` `cancel` `help_toggle` |
239+
| <kbd>Down/Up</kbd> <kbd>j/k</kbd> | Scroll down/up | `navigate_down` `navigate_up` |
240+
| <kbd>J/K</kbd> | Scroll down/up | `select_down` `select_up` |
241+
| <kbd>Ctrl-f/b</kbd> | Scroll page down/up | `page_down` `page_up` |
242+
| <kbd>Ctrl-d/u</kbd> | Scroll half page down/up | `half_page_down` `half_page_up` |
243+
| <kbd>g/G</kbd> | Go to top/bottom | `go_to_top` `go_to_bottom` |
244+
| <kbd>J/K</kbd> | Select older/newer commit | `select_down` `select_up` |
240245

241246
#### Help
242247

243248
| Key | Description | Corresponding keybind |
244249
| ------------------------------------------------ | ------------------------ | ------------------------------- |
245250
| <kbd>Esc</kbd> <kbd>Backspace</kbd> <kbd>?</kbd> | Close help | `close` `cancel` `help_toggle` |
246251
| <kbd>Down/Up</kbd> <kbd>j/k</kbd> | Scroll down/up | `navigate_down` `navigate_up` |
252+
| <kbd>J/K</kbd> | Scroll down/up | `select_down` `select_up` |
247253
| <kbd>Ctrl-f/b</kbd> | Scroll page down/up | `page_down` `page_up` |
248254
| <kbd>Ctrl-d/u</kbd> | Scroll half page down/up | `half_page_down` `half_page_up` |
249255
| <kbd>g/G</kbd> | Go to top/bottom | `go_to_top` `go_to_bottom` |

assets/default-keybind.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ navigate_down = ["j", "down"]
99
navigate_right = ["l", "right"]
1010
navigate_left = ["h", "left"]
1111
go_to_parent = ["alt-j", "alt-down"]
12+
select_up = ["shift-k"]
13+
select_down = ["shift-j"]
1214

1315
go_to_top = ["g"]
1416
go_to_bottom = ["shift-g"]

src/app.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,12 @@ impl App<'_> {
230230
AppEvent::ClearHelp => {
231231
self.clear_help();
232232
}
233+
AppEvent::SelectOlderCommit => {
234+
self.select_older_commit();
235+
}
236+
AppEvent::SelectNewerCommit => {
237+
self.select_newer_commit();
238+
}
233239
AppEvent::CopyToClipboard { name, value } => {
234240
self.copy_to_clipboard(name, value);
235241
}
@@ -531,6 +537,22 @@ impl App<'_> {
531537
}
532538
}
533539

540+
fn select_older_commit(&mut self) {
541+
if let View::Detail(ref mut view) = self.view {
542+
view.select_older_commit(self.repository);
543+
} else if let View::UserCommand(ref mut view) = self.view {
544+
view.select_older_commit(self.repository, self.view_area);
545+
}
546+
}
547+
548+
fn select_newer_commit(&mut self) {
549+
if let View::Detail(ref mut view) = self.view {
550+
view.select_newer_commit(self.repository);
551+
} else if let View::UserCommand(ref mut view) = self.view {
552+
view.select_newer_commit(self.repository, self.view_area);
553+
}
554+
}
555+
534556
fn clear_status_line(&mut self) {
535557
self.status_line = StatusLine::None;
536558
}

src/event.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ pub enum AppEvent {
2525
OpenHelp,
2626
CloseHelp,
2727
ClearHelp,
28+
SelectNewerCommit,
29+
SelectOlderCommit,
2830
CopyToClipboard { name: String, value: String },
2931
ClearStatusLine,
3032
UpdateStatusInput(String, Option<u16>, Option<String>),
@@ -99,6 +101,8 @@ pub enum UserEvent {
99101
NavigateDown,
100102
NavigateRight,
101103
NavigateLeft,
104+
SelectUp,
105+
SelectDown,
102106
GoToTop,
103107
GoToBottom,
104108
GoToParent,
@@ -160,6 +164,8 @@ impl<'de> Deserialize<'de> for UserEvent {
160164
"navigate_down" => Ok(UserEvent::NavigateDown),
161165
"navigate_right" => Ok(UserEvent::NavigateRight),
162166
"navigate_left" => Ok(UserEvent::NavigateLeft),
167+
"select_up" => Ok(UserEvent::SelectUp),
168+
"select_down" => Ok(UserEvent::SelectDown),
163169
"go_to_top" => Ok(UserEvent::GoToTop),
164170
"go_to_bottom" => Ok(UserEvent::GoToBottom),
165171
"go_to_parent" => Ok(UserEvent::GoToParent),

src/view/detail.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
color::ColorTheme,
1010
config::UiConfig,
1111
event::{AppEvent, Sender, UserEvent, UserEventWithCount},
12-
git::{Commit, FileChange, Ref},
12+
git::{Commit, FileChange, Ref, Repository},
1313
protocol::ImageProtocol,
1414
widget::{
1515
commit_detail::{CommitDetail, CommitDetailState},
@@ -99,6 +99,12 @@ impl<'a> DetailView<'a> {
9999
UserEvent::GoToBottom => {
100100
self.commit_detail_state.select_last();
101101
}
102+
UserEvent::SelectDown => {
103+
self.tx.send(AppEvent::SelectOlderCommit);
104+
}
105+
UserEvent::SelectUp => {
106+
self.tx.send(AppEvent::SelectNewerCommit);
107+
}
102108
UserEvent::ShortCopy => {
103109
self.copy_commit_short_hash();
104110
}
@@ -157,6 +163,30 @@ impl<'a> DetailView<'a> {
157163
self.commit_list_state.as_mut().unwrap()
158164
}
159165

166+
pub fn select_older_commit(&mut self, repository: &Repository) {
167+
self.update_selected_commit(repository, |state| state.select_next());
168+
}
169+
170+
pub fn select_newer_commit(&mut self, repository: &Repository) {
171+
self.update_selected_commit(repository, |state| state.select_prev());
172+
}
173+
174+
fn update_selected_commit<F>(&mut self, repository: &Repository, update_commit_list_state: F)
175+
where
176+
F: FnOnce(&mut CommitListState<'a>),
177+
{
178+
let commit_list_state = self.as_mut_list_state();
179+
update_commit_list_state(commit_list_state);
180+
let selected = commit_list_state.selected_commit_hash().clone();
181+
let (commit, changes) = repository.commit_detail(&selected);
182+
let refs = repository.refs(&selected).into_iter().cloned().collect();
183+
self.commit = commit;
184+
self.changes = changes;
185+
self.refs = refs;
186+
187+
self.commit_detail_state.select_first();
188+
}
189+
160190
pub fn clear(&mut self) {
161191
self.clear = true;
162192
}

src/view/help.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,12 @@ impl HelpView<'_> {
7272
self.tx.send(AppEvent::ClearHelp); // hack: reset the rendering of the image area
7373
self.tx.send(AppEvent::CloseHelp);
7474
}
75-
UserEvent::NavigateDown => {
75+
UserEvent::NavigateDown | UserEvent::SelectDown => {
7676
for _ in 0..count {
7777
self.scroll_down();
7878
}
7979
}
80-
UserEvent::NavigateUp => {
80+
UserEvent::NavigateUp | UserEvent::SelectUp => {
8181
for _ in 0..count {
8282
self.scroll_up();
8383
}
@@ -238,8 +238,8 @@ fn build_lines(
238238

239239
let help_helps = vec![
240240
(vec![UserEvent::HelpToggle, UserEvent::Cancel, UserEvent::Close], "Close help".into()),
241-
(vec![UserEvent::NavigateDown], "Scroll down".into()),
242-
(vec![UserEvent::NavigateUp], "Scroll up".into()),
241+
(vec![UserEvent::NavigateDown, UserEvent::SelectDown], "Scroll down".into()),
242+
(vec![UserEvent::NavigateUp, UserEvent::SelectUp], "Scroll up".into()),
243243
(vec![UserEvent::PageDown], "Scroll page down".into()),
244244
(vec![UserEvent::PageUp], "Scroll page up".into()),
245245
(vec![UserEvent::HalfPageDown], "Scroll half page down".into()),
@@ -250,8 +250,8 @@ fn build_lines(
250250
let (help_key_lines, help_value_lines) = build_block_lines("Help:", help_helps, color_theme, keybind);
251251

252252
let mut list_helps = vec![
253-
(vec![UserEvent::NavigateDown], "Move down".into()),
254-
(vec![UserEvent::NavigateUp], "Move up".into()),
253+
(vec![UserEvent::NavigateDown, UserEvent::SelectDown], "Move down".into()),
254+
(vec![UserEvent::NavigateUp, UserEvent::SelectUp], "Move up".into()),
255255
(vec![UserEvent::GoToParent], "Go to parent".into()),
256256
(vec![UserEvent::GoToTop], "Go to top".into()),
257257
(vec![UserEvent::GoToBottom], "Go to bottom".into()),
@@ -288,6 +288,8 @@ fn build_lines(
288288
(vec![UserEvent::HalfPageUp], "Scroll half page up".into()),
289289
(vec![UserEvent::GoToTop], "Go to top".into()),
290290
(vec![UserEvent::GoToBottom], "Go to bottom".into()),
291+
(vec![UserEvent::SelectDown], "Select older commit".into()),
292+
(vec![UserEvent::SelectUp], "Select newer commit".into()),
291293
(vec![UserEvent::ShortCopy], "Copy commit short hash".into()),
292294
(vec![UserEvent::FullCopy], "Copy commit hash".into()),
293295
];
@@ -296,8 +298,8 @@ fn build_lines(
296298

297299
let refs_helps = vec![
298300
(vec![UserEvent::Cancel, UserEvent::Close, UserEvent::RefListToggle], "Close refs list".into()),
299-
(vec![UserEvent::NavigateDown], "Move down".into()),
300-
(vec![UserEvent::NavigateUp], "Move up".into()),
301+
(vec![UserEvent::NavigateDown, UserEvent::SelectDown], "Move down".into()),
302+
(vec![UserEvent::NavigateUp, UserEvent::SelectUp], "Move up".into()),
301303
(vec![UserEvent::GoToTop], "Go to top".into()),
302304
(vec![UserEvent::GoToBottom], "Go to bottom".into()),
303305
(vec![UserEvent::NavigateRight], "Open node".into()),
@@ -316,6 +318,8 @@ fn build_lines(
316318
(vec![UserEvent::HalfPageUp], "Scroll half page up".into()),
317319
(vec![UserEvent::GoToTop], "Go to top".into()),
318320
(vec![UserEvent::GoToBottom], "Go to bottom".into()),
321+
(vec![UserEvent::SelectDown], "Select older commit".into()),
322+
(vec![UserEvent::SelectUp], "Select newer commit".into()),
319323
];
320324
user_command_helps.extend(user_command_view_toggle_helps);
321325
let (user_command_key_lines, user_command_value_lines) = build_block_lines("User Command:", user_command_helps, color_theme, keybind);

src/view/list.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ impl<'a> ListView<'a> {
6363
UserEvent::Quit => {
6464
self.tx.send(AppEvent::Quit);
6565
}
66-
UserEvent::NavigateDown => {
66+
UserEvent::NavigateDown | UserEvent::SelectDown => {
6767
for _ in 0..count {
6868
self.as_mut_list_state().select_next();
6969
}
7070
}
71-
UserEvent::NavigateUp => {
71+
UserEvent::NavigateUp | UserEvent::SelectUp => {
7272
for _ in 0..count {
7373
self.as_mut_list_state().select_prev();
7474
}

src/view/refs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,13 @@ impl<'a> RefsView<'a> {
5656
UserEvent::Cancel | UserEvent::Close | UserEvent::RefListToggle => {
5757
self.tx.send(AppEvent::CloseRefs);
5858
}
59-
UserEvent::NavigateDown => {
59+
UserEvent::NavigateDown | UserEvent::SelectDown => {
6060
for _ in 0..count {
6161
self.ref_list_state.select_next();
6262
}
6363
self.update_commit_list_selected();
6464
}
65-
UserEvent::NavigateUp => {
65+
UserEvent::NavigateUp | UserEvent::SelectUp => {
6666
for _ in 0..count {
6767
self.ref_list_state.select_prev();
6868
}

src/view/user_command.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
config::{CoreConfig, UiConfig},
1313
event::{AppEvent, Sender, UserEvent, UserEventWithCount},
1414
external::exec_user_command,
15-
git::Commit,
15+
git::{Commit, Repository},
1616
protocol::ImageProtocol,
1717
widget::{
1818
commit_list::{CommitList, CommitListState},
@@ -34,6 +34,7 @@ pub struct UserCommandView<'a> {
3434
user_command_number: usize,
3535
user_command_output_lines: Vec<Line<'a>>,
3636

37+
core_config: &'a CoreConfig,
3738
ui_config: &'a UiConfig,
3839
color_theme: &'a ColorTheme,
3940
image_protocol: ImageProtocol,
@@ -72,6 +73,7 @@ impl<'a> UserCommandView<'a> {
7273
commit_user_command_state: CommitUserCommandState::default(),
7374
user_command_number,
7475
user_command_output_lines,
76+
core_config,
7577
ui_config,
7678
color_theme,
7779
image_protocol,
@@ -122,6 +124,12 @@ impl<'a> UserCommandView<'a> {
122124
UserEvent::GoToBottom => {
123125
self.commit_user_command_state.select_last();
124126
}
127+
UserEvent::SelectDown => {
128+
self.tx.send(AppEvent::SelectOlderCommit);
129+
}
130+
UserEvent::SelectUp => {
131+
self.tx.send(AppEvent::SelectNewerCommit);
132+
}
125133
UserEvent::HelpToggle => {
126134
self.tx.send(AppEvent::OpenHelp);
127135
}
@@ -178,6 +186,41 @@ impl<'a> UserCommandView<'a> {
178186
self.commit_list_state.as_mut().unwrap()
179187
}
180188

189+
pub fn select_older_commit(&mut self, repository: &Repository, view_area: Rect) {
190+
self.update_selected_commit(repository, view_area, |state| state.select_next());
191+
}
192+
193+
pub fn select_newer_commit(&mut self, repository: &Repository, view_area: Rect) {
194+
self.update_selected_commit(repository, view_area, |state| state.select_prev());
195+
}
196+
197+
fn update_selected_commit<F>(
198+
&mut self,
199+
repository: &Repository,
200+
view_area: Rect,
201+
update_commit_list_state: F,
202+
) where
203+
F: FnOnce(&mut CommitListState<'a>),
204+
{
205+
let commit_list_state = self.as_mut_list_state();
206+
update_commit_list_state(commit_list_state);
207+
let selected = commit_list_state.selected_commit_hash().clone();
208+
let (commit, _) = repository.commit_detail(&selected);
209+
self.user_command_output_lines = build_user_command_output_lines(
210+
&commit,
211+
self.user_command_number,
212+
view_area,
213+
self.core_config,
214+
self.ui_config,
215+
)
216+
.unwrap_or_else(|err| {
217+
self.tx.send(AppEvent::NotifyError(err));
218+
vec![]
219+
});
220+
221+
self.commit_user_command_state.select_first();
222+
}
223+
181224
pub fn clear(&mut self) {
182225
self.clear = true;
183226
}

0 commit comments

Comments
 (0)