Skip to content

Commit fa2aabf

Browse files
author
Stephan Dilly
committed
support jumping to end in log (#43)
1 parent 45ee0e1 commit fa2aabf

File tree

2 files changed

+66
-25
lines changed

2 files changed

+66
-25
lines changed

Diff for: src/components/statustree.rs

-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ impl StatusTree {
6868
MoveSelection::Down => {
6969
self.selection_updown(selection, false)
7070
}
71-
7271
MoveSelection::Left => self.selection_left(selection),
7372
MoveSelection::Right => {
7473
self.selection_right(selection)

Diff for: src/tabs/revlog.rs

+66-24
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use tui::{
1919
Frame,
2020
};
2121

22+
#[derive(Default)]
2223
struct LogEntry {
2324
time: String,
2425
author: String,
@@ -62,14 +63,49 @@ const STYLE_MSG_SELECTED: Style =
6263
Style::new().fg(Color::Reset).bg(COLOR_SELECTION_BG);
6364

6465
static ELEMENTS_PER_LINE: usize = 10;
65-
static SLICE_SIZE: usize = 1000;
66+
static SLICE_SIZE: usize = 1200;
6667
static SLICE_OFFSET_RELOAD_THRESHOLD: usize = 100;
6768

69+
///
70+
#[derive(Default)]
71+
struct ItemBatch {
72+
index_offset: usize,
73+
items: Vec<LogEntry>,
74+
}
75+
76+
impl ItemBatch {
77+
fn last_idx(&self) -> usize {
78+
self.index_offset + self.items.len()
79+
}
80+
81+
fn set_items(
82+
&mut self,
83+
start_index: usize,
84+
commits: Vec<CommitInfo>,
85+
) {
86+
self.items.clear();
87+
self.items.extend(commits.into_iter().map(LogEntry::from));
88+
self.index_offset = start_index;
89+
}
90+
91+
fn needs_data(&self, idx: usize, idx_max: usize) -> bool {
92+
let want_min =
93+
idx.saturating_sub(SLICE_OFFSET_RELOAD_THRESHOLD);
94+
let want_max = idx
95+
.saturating_add(SLICE_OFFSET_RELOAD_THRESHOLD)
96+
.min(idx_max);
97+
98+
let needs_data_top = want_min < self.index_offset;
99+
let needs_data_bottom = want_max > self.last_idx();
100+
needs_data_bottom || needs_data_top
101+
}
102+
}
103+
68104
///
69105
pub struct Revlog {
70106
selection: usize,
71107
selection_max: usize,
72-
items: Vec<LogEntry>,
108+
items: ItemBatch,
73109
git_log: AsyncLog,
74110
visible: bool,
75111
first_open_done: bool,
@@ -81,7 +117,7 @@ impl Revlog {
81117
///
82118
pub fn new(sender: &Sender<AsyncNotification>) -> Self {
83119
Self {
84-
items: Vec::new(),
120+
items: ItemBatch::default(),
85121
git_log: AsyncLog::new(sender.clone()),
86122
selection: 0,
87123
selection_max: 0,
@@ -95,12 +131,13 @@ impl Revlog {
95131
///
96132
pub fn draw<B: Backend>(&self, f: &mut Frame<B>, area: Rect) {
97133
let height = area.height as usize;
98-
let selection = self.selection;
134+
let selection =
135+
self.selection.saturating_sub(self.items.index_offset);
99136
let height_d2 = height as usize / 2;
100137
let min = selection.saturating_sub(height_d2);
101138

102139
let mut txt = Vec::new();
103-
for (idx, e) in self.items.iter().enumerate() {
140+
for (idx, e) in self.items.items.iter().enumerate() {
104141
let tag = if let Some(tag_name) = self.tags.get(&e.hash) {
105142
tag_name.as_str()
106143
} else {
@@ -109,8 +146,10 @@ impl Revlog {
109146
Self::add_entry(e, idx == selection, &mut txt, tag);
110147
}
111148

112-
let title =
113-
format!("commit {}/{}", selection, self.selection_max);
149+
let title = format!(
150+
"commit {}/{}",
151+
self.selection, self.selection_max
152+
);
114153

115154
f.render_widget(
116155
Paragraph::new(
@@ -135,31 +174,30 @@ impl Revlog {
135174

136175
///
137176
pub fn update(&mut self) {
138-
let next_idx = self.items.len();
139-
140-
let requires_more_data = next_idx
141-
.saturating_sub(self.selection)
142-
< SLICE_OFFSET_RELOAD_THRESHOLD;
143-
144177
self.selection_max = self.git_log.count().saturating_sub(1);
145178

146-
if requires_more_data {
147-
let commits = sync::get_commits_info(
148-
CWD,
149-
&self.git_log.get_slice(next_idx, SLICE_SIZE),
150-
);
151-
152-
if let Ok(commits) = commits {
153-
self.items
154-
.extend(commits.into_iter().map(LogEntry::from));
155-
}
179+
if self.items.needs_data(self.selection, self.selection_max) {
180+
self.fetch_commits();
156181
}
157182

158183
if self.tags.is_empty() {
159184
self.tags = sync::get_tags(CWD).unwrap();
160185
}
161186
}
162187

188+
fn fetch_commits(&mut self) {
189+
let want_min = self.selection.saturating_sub(SLICE_SIZE / 2);
190+
191+
let commits = sync::get_commits_info(
192+
CWD,
193+
&self.git_log.get_slice(want_min, SLICE_SIZE),
194+
);
195+
196+
if let Ok(commits) = commits {
197+
self.items.set_items(want_min, commits);
198+
}
199+
}
200+
163201
fn move_selection(&mut self, scroll: ScrollType) {
164202
self.update_scroll_speed();
165203

@@ -176,7 +214,7 @@ impl Revlog {
176214
self.selection.saturating_add(speed_int)
177215
}
178216
ScrollType::Home => 0,
179-
_ => self.selection,
217+
ScrollType::End => self.selection_max,
180218
};
181219

182220
self.selection = cmp::min(self.selection, self.selection_max);
@@ -296,6 +334,10 @@ impl Component for Revlog {
296334
self.move_selection(ScrollType::Home);
297335
true
298336
}
337+
keys::SHIFT_DOWN | keys::END => {
338+
self.move_selection(ScrollType::End);
339+
true
340+
}
299341
_ => false,
300342
};
301343
}

0 commit comments

Comments
 (0)