97 lines
2.8 KiB
Rust
97 lines
2.8 KiB
Rust
use regex::bytes::Regex;
|
|
|
|
use crate::tui::{
|
|
log_viewer::{FieldMatcher, InputTarget, LogViewer},
|
|
model::{LogEntry, pretty_print_value},
|
|
};
|
|
|
|
pub enum MatcherValue {
|
|
Exact(String),
|
|
Regex(Regex),
|
|
Prefix(String),
|
|
Contains(String),
|
|
}
|
|
|
|
impl MatcherValue {
|
|
pub fn from_field_matcher(fm: FieldMatcher, selected: Option<String>) -> Option<Self> {
|
|
match fm {
|
|
FieldMatcher::EqualTo => Some(Self::Exact(selected?)),
|
|
FieldMatcher::Prefix(p) => Some(Self::Prefix(p)),
|
|
FieldMatcher::Regex(r) => Some(Self::Regex(Regex::new(&r).ok()?)),
|
|
FieldMatcher::Contains(c) => Some(Self::Contains(c)),
|
|
}
|
|
}
|
|
|
|
pub fn matches(&self, v: &str) -> bool {
|
|
match self {
|
|
MatcherValue::Exact(e) => e == v,
|
|
MatcherValue::Regex(regex) => regex.is_match(v.as_bytes()),
|
|
MatcherValue::Prefix(p) => v.starts_with(p),
|
|
MatcherValue::Contains(c) => v.contains(c),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub enum Matcher {
|
|
Field { name: String, value: MatcherValue },
|
|
Message { value: MatcherValue },
|
|
Specific { hash: u64 },
|
|
}
|
|
|
|
impl Matcher {
|
|
pub fn matches(&self, entry: &LogEntry) -> bool {
|
|
match self {
|
|
Matcher::Specific { hash } => entry.hash() == *hash,
|
|
Matcher::Field { name, value } => entry
|
|
.all_fields()
|
|
.fields
|
|
.get(name)
|
|
.is_some_and(|v| value.matches(v)),
|
|
Matcher::Message { value } => {
|
|
entry.message_or_name().is_some_and(|v| value.matches(&v))
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn from_input(target: InputTarget, lv: &LogViewer) -> Option<Self> {
|
|
match target {
|
|
InputTarget::Fields(fm) => {
|
|
let value = lv.footer_fields().get(lv.footer_list.selected?)?.clone();
|
|
Some(Self::Field {
|
|
name: value.0,
|
|
value: MatcherValue::from_field_matcher(fm?, Some(value.1))?,
|
|
})
|
|
}
|
|
InputTarget::Text(fm) => Some(Self::Message {
|
|
value: MatcherValue::from_field_matcher(
|
|
fm,
|
|
lv.selected().and_then(|(i, _)| i.message_or_name()),
|
|
)?,
|
|
}),
|
|
InputTarget::This => lv
|
|
.selected()
|
|
.map(|(i, _)| Self::Specific { hash: i.hash() }),
|
|
InputTarget::Surround => todo!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub enum FilterKind {
|
|
Inline,
|
|
Remove,
|
|
}
|
|
|
|
pub struct Filter {
|
|
pub matcher: Matcher,
|
|
pub kind: FilterKind,
|
|
}
|
|
|
|
impl Filter {
|
|
pub fn removes(&self, elem: &LogEntry) -> bool {
|
|
match self.kind {
|
|
FilterKind::Inline => false,
|
|
FilterKind::Remove => self.matcher.matches(elem),
|
|
}
|
|
}
|
|
}
|