mirror of
https://github.com/gitui-org/gitui
synced 2026-05-24 09:28:21 +00:00
parent
153c79a828
commit
899168e1ce
4 changed files with 55 additions and 35 deletions
|
|
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
## Added
|
||||
- add `trace-libgit` feature to make git tracing optional [[@dm9pZCAq](https://github.com/dm9pZCAq)] ([#902](https://github.com/extrawurst/gitui/issues/902))
|
||||
- support merging and rebasing remote branches ([#920](https://github.com/extrawurst/gitui/issues/920))
|
||||
- add highlighting matches in fuzzy finder ([#893](https://github.com/extrawurst/gitui/issues/893))
|
||||
|
||||
## [0.18] - 2021-10-11
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use std::borrow::Cow;
|
|||
use tui::{
|
||||
backend::Backend,
|
||||
layout::{Constraint, Direction, Layout, Margin, Rect},
|
||||
text::Span,
|
||||
text::{Span, Spans},
|
||||
widgets::{Block, Borders, Clear},
|
||||
Frame,
|
||||
};
|
||||
|
|
@ -31,7 +31,7 @@ pub struct FileFindPopup {
|
|||
files: Vec<TreeFile>,
|
||||
selection: usize,
|
||||
selected_index: Option<usize>,
|
||||
files_filtered: Vec<usize>,
|
||||
files_filtered: Vec<(usize, Vec<usize>)>,
|
||||
key_config: SharedKeyConfig,
|
||||
}
|
||||
|
||||
|
|
@ -91,8 +91,9 @@ impl FileFindPopup {
|
|||
self.files_filtered.extend(
|
||||
self.files.iter().enumerate().filter_map(|a| {
|
||||
a.1.path.to_str().and_then(|path| {
|
||||
//TODO: use fuzzy_indices and highlight hits
|
||||
matcher.fuzzy_match(path, q).map(|_| a.0)
|
||||
matcher
|
||||
.fuzzy_indices(path, q)
|
||||
.map(|(_, indicies)| (a.0, indicies))
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
|
@ -104,7 +105,7 @@ impl FileFindPopup {
|
|||
|
||||
fn refresh_selection(&mut self) {
|
||||
let selection =
|
||||
self.files_filtered.get(self.selection).copied();
|
||||
self.files_filtered.get(self.selection).map(|a| a.0);
|
||||
|
||||
if self.selected_index != selection {
|
||||
self.selected_index = selection;
|
||||
|
|
@ -217,24 +218,36 @@ impl DrawableComponent for FileFindPopup {
|
|||
let height = usize::from(chunks[1].height);
|
||||
let width = usize::from(chunks[1].width);
|
||||
|
||||
let items =
|
||||
self.files_filtered.iter().take(height).map(
|
||||
|idx| {
|
||||
let selected = self
|
||||
.selected_index
|
||||
.map_or(false, |index| index == *idx);
|
||||
Span::styled(
|
||||
Cow::from(trim_length_left(
|
||||
self.files[*idx]
|
||||
.path
|
||||
.to_str()
|
||||
.unwrap_or_default(),
|
||||
width,
|
||||
)),
|
||||
self.theme.text(selected, false),
|
||||
)
|
||||
},
|
||||
);
|
||||
let items = self
|
||||
.files_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.files[*idx]
|
||||
.path
|
||||
.to_str()
|
||||
.unwrap_or_default(),
|
||||
width,
|
||||
);
|
||||
Spans::from(
|
||||
full_text
|
||||
.char_indices()
|
||||
.map(|(c_idx, c)| {
|
||||
Span::styled(
|
||||
Cow::from(c.to_string()),
|
||||
self.theme.text(
|
||||
selected,
|
||||
indicies.contains(&c_idx),
|
||||
),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
});
|
||||
|
||||
ui::draw_list_block(
|
||||
f,
|
||||
|
|
|
|||
|
|
@ -5,15 +5,16 @@ use tui::{
|
|||
buffer::Buffer,
|
||||
layout::Rect,
|
||||
style::Style,
|
||||
text::Span,
|
||||
text::{Span, Text},
|
||||
widgets::{Block, Borders, List, ListItem, Widget},
|
||||
Frame,
|
||||
};
|
||||
|
||||
///
|
||||
struct ScrollableList<'b, L>
|
||||
struct ScrollableList<'b, L, S>
|
||||
where
|
||||
L: Iterator<Item = Span<'b>>,
|
||||
S: Into<Text<'b>>,
|
||||
L: Iterator<Item = S>,
|
||||
{
|
||||
block: Option<Block<'b>>,
|
||||
/// Items to be displayed
|
||||
|
|
@ -22,9 +23,10 @@ where
|
|||
style: Style,
|
||||
}
|
||||
|
||||
impl<'b, L> ScrollableList<'b, L>
|
||||
impl<'b, L, S> ScrollableList<'b, L, S>
|
||||
where
|
||||
L: Iterator<Item = Span<'b>>,
|
||||
S: Into<Text<'b>>,
|
||||
L: Iterator<Item = S>,
|
||||
{
|
||||
fn new(items: L) -> Self {
|
||||
Self {
|
||||
|
|
@ -40,9 +42,10 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'b, L> Widget for ScrollableList<'b, L>
|
||||
impl<'b, L, S> Widget for ScrollableList<'b, L, S>
|
||||
where
|
||||
L: Iterator<Item = Span<'b>>,
|
||||
S: Into<Text<'b>>,
|
||||
L: Iterator<Item = S>,
|
||||
{
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
// Render items
|
||||
|
|
@ -55,7 +58,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub fn draw_list<'b, B: Backend, L>(
|
||||
pub fn draw_list<'b, B: Backend, L, S>(
|
||||
f: &mut Frame<B>,
|
||||
r: Rect,
|
||||
title: &'b str,
|
||||
|
|
@ -63,7 +66,8 @@ pub fn draw_list<'b, B: Backend, L>(
|
|||
selected: bool,
|
||||
theme: &SharedTheme,
|
||||
) where
|
||||
L: Iterator<Item = Span<'b>>,
|
||||
S: Into<Text<'b>>,
|
||||
L: Iterator<Item = S>,
|
||||
{
|
||||
let list = ScrollableList::new(items).block(
|
||||
Block::default()
|
||||
|
|
@ -74,13 +78,14 @@ pub fn draw_list<'b, B: Backend, L>(
|
|||
f.render_widget(list, r);
|
||||
}
|
||||
|
||||
pub fn draw_list_block<'b, B: Backend, L>(
|
||||
pub fn draw_list_block<'b, B: Backend, L, S>(
|
||||
f: &mut Frame<B>,
|
||||
r: Rect,
|
||||
block: Block<'b>,
|
||||
items: L,
|
||||
) where
|
||||
L: Iterator<Item = Span<'b>>,
|
||||
S: Into<Text<'b>>,
|
||||
L: Iterator<Item = S>,
|
||||
{
|
||||
let list = ScrollableList::new(items).block(block);
|
||||
f.render_widget(list, r);
|
||||
|
|
|
|||
|
|
@ -117,7 +117,8 @@ impl Theme {
|
|||
|
||||
pub fn text(&self, enabled: bool, selected: bool) -> Style {
|
||||
match (enabled, selected) {
|
||||
(false, _) => Style::default().fg(self.disabled_fg),
|
||||
(false, false) => Style::default().fg(self.disabled_fg),
|
||||
(false, true) => Style::default().bg(self.selection_bg),
|
||||
(true, false) => Style::default(),
|
||||
(true, true) => Style::default()
|
||||
.fg(self.command_fg)
|
||||
|
|
|
|||
Loading…
Reference in a new issue