Skip to content

Commit 2675934

Browse files
authored
Index of search result (#1840)
1 parent c68fa3e commit 2675934

File tree

5 files changed

+64
-37
lines changed

5 files changed

+64
-37
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ easy-cast = "0.5"
3636
filetreelist = { path = "./filetreelist", version = "0.5" }
3737
fuzzy-matcher = "0.3"
3838
gh-emoji = { version = "1.0", optional = true }
39+
indexmap = "1.9"
3940
itertools = "0.11"
4041
log = "0.4"
4142
notify = "5.1"

src/components/commitlist.rs

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use asyncgit::sync::{
1818
};
1919
use chrono::{DateTime, Local};
2020
use crossterm::event::Event;
21+
use indexmap::IndexSet;
2122
use itertools::Itertools;
2223
use ratatui::{
2324
backend::Backend,
@@ -28,12 +29,8 @@ use ratatui::{
2829
Frame,
2930
};
3031
use std::{
31-
borrow::Cow,
32-
cell::Cell,
33-
cmp,
34-
collections::{BTreeMap, HashSet},
35-
convert::TryFrom,
36-
time::Instant,
32+
borrow::Cow, cell::Cell, cmp, collections::BTreeMap,
33+
convert::TryFrom, rc::Rc, time::Instant,
3734
};
3835

3936
const ELEMENTS_PER_LINE: usize = 9;
@@ -44,8 +41,9 @@ pub struct CommitList {
4441
repo: RepoPathRef,
4542
title: Box<str>,
4643
selection: usize,
44+
highlighted_selection: Option<usize>,
4745
items: ItemBatch,
48-
highlights: Option<HashSet<CommitId>>,
46+
highlights: Option<Rc<IndexSet<CommitId>>>,
4947
commits: Vec<CommitId>,
5048
marked: Vec<(usize, CommitId)>,
5149
scroll_state: (Instant, f32),
@@ -73,6 +71,7 @@ impl CommitList {
7371
items: ItemBatch::default(),
7472
marked: Vec::with_capacity(2),
7573
selection: 0,
74+
highlighted_selection: None,
7675
commits: Vec::new(),
7776
highlights: None,
7877
scroll_state: (Instant::now(), 0_f32),
@@ -240,10 +239,11 @@ impl CommitList {
240239
///
241240
pub fn set_highlighting(
242241
&mut self,
243-
highlighting: Option<HashSet<CommitId>>,
242+
highlighting: Option<Rc<IndexSet<CommitId>>>,
244243
) {
245244
self.highlights = highlighting;
246245
self.select_next_highlight();
246+
self.set_highlighted_selection_index();
247247
self.fetch_commits();
248248
}
249249

@@ -253,12 +253,32 @@ impl CommitList {
253253

254254
if let Some(position) = position {
255255
self.selection = position;
256+
self.set_highlighted_selection_index();
256257
Ok(())
257258
} else {
258259
anyhow::bail!("Could not select commit. It might not be loaded yet or it might be on a different branch.");
259260
}
260261
}
261262

263+
///
264+
pub fn highlighted_selection_info(&self) -> (usize, usize) {
265+
let amount = self
266+
.highlights
267+
.as_ref()
268+
.map(|highlights| highlights.len())
269+
.unwrap_or_default();
270+
(self.highlighted_selection.unwrap_or_default(), amount)
271+
}
272+
273+
fn set_highlighted_selection_index(&mut self) {
274+
self.highlighted_selection =
275+
self.highlights.as_ref().and_then(|highlights| {
276+
highlights.iter().position(|entry| {
277+
entry == &self.commits[self.selection]
278+
})
279+
});
280+
}
281+
262282
const fn selection(&self) -> usize {
263283
self.selection
264284
}
@@ -318,6 +338,7 @@ impl CommitList {
318338
self.selection = new_selection;
319339

320340
if self.selection_highlighted() {
341+
self.set_highlighted_selection_index();
321342
return Ok(true);
322343
}
323344
}
@@ -703,12 +724,7 @@ impl CommitList {
703724
);
704725

705726
if let Ok(commits) = commits {
706-
self.items.set_items(
707-
want_min,
708-
commits,
709-
//TODO: optimize via sharable data (BTreeMap that preserves order and lookup)
710-
&self.highlights.clone(),
711-
);
727+
self.items.set_items(want_min, commits, &self.highlights);
712728
}
713729
}
714730
}

src/components/utils/logitems.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use asyncgit::sync::{CommitId, CommitInfo};
22
use chrono::{DateTime, Duration, Local, NaiveDateTime, Utc};
3-
use std::{collections::HashSet, slice::Iter};
3+
use indexmap::IndexSet;
4+
use std::{rc::Rc, slice::Iter};
45

56
#[cfg(feature = "ghemoji")]
67
use super::emoji::emojifi_string;
@@ -111,7 +112,7 @@ impl ItemBatch {
111112
&mut self,
112113
start_index: usize,
113114
commits: Vec<CommitInfo>,
114-
highlighted: &Option<HashSet<CommitId>>,
115+
highlighted: &Option<Rc<IndexSet<CommitId>>>,
115116
) {
116117
self.items.clear();
117118
self.items.extend(commits.into_iter().map(|c| {

src/tabs/revlog.rs

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,18 @@ use asyncgit::{
2323
};
2424
use crossbeam_channel::Sender;
2525
use crossterm::event::Event;
26+
use indexmap::IndexSet;
2627
use ratatui::{
2728
backend::Backend,
2829
layout::{Alignment, Constraint, Direction, Layout, Rect},
2930
text::Span,
3031
widgets::{Block, Borders, Paragraph},
3132
Frame,
3233
};
33-
use std::{collections::HashSet, rc::Rc, time::Duration};
34+
use std::{rc::Rc, time::Duration};
3435
use sync::CommitTags;
3536

3637
struct LogSearchResult {
37-
commits: usize,
3838
options: LogFilterSearchOptions,
3939
duration: Duration,
4040
}
@@ -280,16 +280,14 @@ impl Revlog {
280280
false
281281
} else {
282282
let results = search.extract_items()?;
283-
let commits = results.len();
284283
let duration = search.get_last_duration()?;
285284

286-
self.list.set_highlighting(Some(
287-
results.into_iter().collect::<HashSet<_>>(),
288-
));
285+
self.list.set_highlighting(Some(Rc::new(
286+
results.into_iter().collect::<IndexSet<_>>(),
287+
)));
289288

290289
self.search =
291290
LogSearch::Results(LogSearchResult {
292-
commits,
293291
options: options.clone(),
294292
duration,
295293
});
@@ -306,30 +304,40 @@ impl Revlog {
306304
}
307305

308306
fn draw_search<B: Backend>(&self, f: &mut Frame<B>, area: Rect) {
309-
let text = match &self.search {
310-
LogSearch::Searching(_, options) => {
311-
format!(
312-
"'{}' (pending results...)",
313-
options.search_pattern.clone()
314-
)
315-
}
307+
let (text, title) = match &self.search {
308+
LogSearch::Searching(_, options) => (
309+
format!("'{}'", options.search_pattern.clone()),
310+
String::from("(pending results...)"),
311+
),
316312
LogSearch::Results(results) => {
317-
format!(
318-
"'{}' (hits: {}) (duration: {:?})",
319-
results.options.search_pattern.clone(),
320-
results.commits,
321-
results.duration,
313+
let info = self.list.highlighted_selection_info();
314+
315+
(
316+
format!(
317+
"'{}' (duration: {:?})",
318+
results.options.search_pattern.clone(),
319+
results.duration,
320+
),
321+
format!(
322+
"({}/{})",
323+
(info.0 + 1).min(info.1),
324+
info.1
325+
),
322326
)
323327
}
324-
LogSearch::Off => String::new(),
328+
LogSearch::Off => (String::new(), String::new()),
325329
};
326330

327331
f.render_widget(
328332
Paragraph::new(text)
329333
.block(
330334
Block::default()
331335
.title(Span::styled(
332-
strings::POPUP_TITLE_LOG_SEARCH,
336+
format!(
337+
"{} {}",
338+
strings::POPUP_TITLE_LOG_SEARCH,
339+
title
340+
),
333341
self.theme.title(true),
334342
))
335343
.borders(Borders::ALL)

0 commit comments

Comments
 (0)