allow filtering group by menu

This commit is contained in:
Robin Appelman 2025-08-21 19:15:16 +02:00
commit b33aa02997
3 changed files with 46 additions and 3 deletions

View file

@ -198,6 +198,13 @@ impl GroupingOptions {
.into_iter()
}
pub fn matches(&self, filter: &str) -> bool {
if filter.is_empty() {
return true;
}
self.as_str().to_ascii_lowercase().contains(filter)
}
pub fn group_key(&self, line: &LogLine) -> Option<u64> {
let mut hasher = AHasher::default();
match self {

View file

@ -165,6 +165,7 @@ fn ui(frame: &mut Frame, app: &App, state: &mut UiState) {
options,
previous,
list_state,
filter,
..
}) => {
ui(frame, app, previous);
@ -173,8 +174,18 @@ fn ui(frame: &mut Frame, app: &App, state: &mut UiState) {
Constraint::Percentage(20),
Constraint::Length(options.len() as u16 + 2), // top and bottom border + content
);
let popup = SelectList::new(options.iter().map(|option| option.as_str()))
.block(Block::bordered().title("Group By"));
let mut block = Block::bordered().title("Group By");
if !filter.is_empty() {
block = block.title_bottom(filter.as_str());
}
let popup = SelectList::new(
options
.iter()
.filter(|o| o.matches(filter))
.map(|option| option.as_str()),
)
.block(block);
frame.render_widget(Clear, area);
frame.render_stateful_widget(popup, area, list_state);
}

View file

@ -35,6 +35,7 @@ impl<'a> UiState<'a> {
previous: Some(_),
..
})
| UiState::GroupByMenu(_)
| UiState::Distinct(DistinctLogsState { .. })
| UiState::Log(LogState { .. })
| UiState::Errors(ErrorLinesState { .. })
@ -112,6 +113,7 @@ pub struct GroupByMenuState<'a> {
pub previous: Box<UiState<'a>>,
pub list_state: SizedListState,
pub next: UiPage,
pub filter: String,
}
impl PartialEq for GroupByMenuState<'_> {
@ -126,7 +128,16 @@ impl<'a> GroupByMenuState<'a> {
}
pub fn enter(self, selected: usize) -> UiState<'a> {
let group_option = self.options[selected];
let Some(group_option) = self
.options
.iter()
.filter(|o| o.matches(&self.filter))
.copied()
.nth(selected)
else {
return self.into();
};
let lines = match self.previous.as_ref() {
UiState::Group(group) => &group.result.lines.lines,
UiState::Distinct(group) => &group.lines,
@ -166,6 +177,7 @@ impl<'a> GroupState<'a> {
previous: Box::new(self.into()),
list_state: SizedListState::new(GroupingOptions::all().count()),
next: UiPage::Group,
filter: String::new(),
})
}
@ -248,6 +260,7 @@ impl<'a> DistinctLogsState<'a> {
previous: Box::new(self.into()),
list_state: SizedListState::new(GroupingOptions::all().count()),
next: UiPage::DistinctLogs,
filter: String::new(),
})
}
@ -382,6 +395,7 @@ impl<'a> UiState<'a> {
match self {
UiState::GroupList(state) => state.mode,
UiState::Group(state) => state.mode,
UiState::GroupByMenu(_) => Mode::FilterInput,
UiState::Distinct(state) => state.mode,
_ => Mode::Normal,
}
@ -578,6 +592,17 @@ impl<'a> UiState<'a> {
let selected = state.selected();
(true, state.enter(selected))
}
(UiState::GroupByMenu(mut state), UiEvent::Text(c)) => {
state.filter.push(c);
(true, state.into())
}
(UiState::GroupByMenu(mut state), UiEvent::PopText(PopMode::Character)) => {
state.filter.pop();
(true, state.into())
}
(UiState::GroupByMenu(GroupByMenuState { previous, .. }), UiEvent::ClearFilter) => {
(true, *previous)
}
(UiState::Distinct(state), UiEvent::Select) => {
let selected = state.selected();
(true, state.enter(selected, app))