Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make fuzzy find popup scrollable #1734

Merged
merged 9 commits into from
Jul 8, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* allow `copy` file path on revision files and status tree [[@yanganto]](https://github.com/yanganto) ([#1516](https://github.com/extrawurst/gitui/pull/1516))
* print message of where log will be written if `-l` is set ([#1472](https://github.com/extrawurst/gitui/pull/1472))
* show remote branches in log [[@cruessler](https://github.com/cruessler)] ([#1501](https://github.com/extrawurst/gitui/issues/1501))
* scrolling functionality to fuzzy-find [[@AmmarAbouZor](https://github.com/AmmarAbouZor)] ([#1732](https://github.com/extrawurst/gitui/issues/1732))

### Fixes
* 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))
Expand Down
134 changes: 85 additions & 49 deletions src/components/fuzzy_find_popup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,90 @@ impl FuzzyFindPopup {

false
}

#[inline]
fn draw_matches_list<B: Backend>(
&self,
f: &mut Frame<B>,
mut area: Rect,
) {
{
// Block has two lines up and down which need to be considered
const HEIGHT_BLOCK_MARGIN: usize = 2;

let title = format!("Hits: {}", self.filtered.len());

let height = usize::from(area.height);
let width = usize::from(area.width);

let list_height =
height.saturating_sub(HEIGHT_BLOCK_MARGIN);

let scroll_skip =
self.selection.saturating_sub(list_height);

let items = self
.filtered
.iter()
.skip(scroll_skip)
.take(height)
.map(|(idx, indicies)| {
let selected = self
.selected_index
.map_or(false, |index| index == *idx);
let full_text =
trim_length_left(&self.contents[*idx], width);
let trim_length =
self.contents[*idx].graphemes(true).count()
- full_text.graphemes(true).count();
Line::from(
full_text
.graphemes(true)
.enumerate()
.map(|(c_idx, c)| {
Span::styled(
Cow::from(c.to_string()),
self.theme.text(
selected,
indicies.contains(
&(c_idx + trim_length),
),
),
)
})
.collect::<Vec<_>>(),
)
});

ui::draw_list_block(
f,
area,
Block::default()
.title(Span::styled(
title,
self.theme.title(true),
))
.borders(Borders::TOP),
items,
);

// Draw scrollbar when needed
if self.filtered.len() > list_height {
// Reset list area margin
area.width += 1;
area.height += 1;

ui::draw_scrollbar(
f,
area,
&self.theme,
self.filtered.len().saturating_sub(1),
self.selection,
ui::Orientation::Vertical,
);
}
}
}
}

impl DrawableComponent for FuzzyFindPopup {
Expand Down Expand Up @@ -233,55 +317,7 @@ impl DrawableComponent for FuzzyFindPopup {
self.find_text.draw(f, chunks[0])?;

if any_hits {
let title = format!("Hits: {}", self.filtered.len());

let height = usize::from(chunks[1].height);
let width = usize::from(chunks[1].width);

let items =
self.filtered.iter().take(height).map(
|(idx, indicies)| {
let selected = self
.selected_index
.map_or(false, |index| index == *idx);
let full_text = trim_length_left(
&self.contents[*idx],
width,
);
let trim_length = self.contents[*idx]
.graphemes(true)
.count() - full_text
.graphemes(true)
.count();
Line::from(
full_text
.graphemes(true)
.enumerate()
.map(|(c_idx, c)| {
Span::styled(
Cow::from(c.to_string()),
self.theme.text(
selected,
indicies.contains(&(c_idx + trim_length)),
),
)
})
.collect::<Vec<_>>(),
)
},
);

ui::draw_list_block(
f,
chunks[1],
Block::default()
.title(Span::styled(
title,
self.theme.title(true),
))
.borders(Borders::TOP),
items,
);
self.draw_matches_list(f, chunks[1]);
}
}
Ok(())
Expand Down