mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-07-29 08:34:36 +02:00
refactor/bug: moved search logic; fix quoted words
This commit is contained in:
parent
ecc111b21a
commit
5e874eab77
262
src/app/query.rs
262
src/app/query.rs
@ -1,7 +1,267 @@
|
|||||||
|
use super::ProcWidgetState;
|
||||||
use crate::{
|
use crate::{
|
||||||
data_conversion::ConvertedProcessData,
|
data_conversion::ConvertedProcessData,
|
||||||
utils::error::{BottomError, Result},
|
utils::error::{
|
||||||
|
BottomError::{self, QueryError},
|
||||||
|
Result,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
const DELIMITER_LIST: [char; 5] = ['=', '>', '<', '(', ')'];
|
||||||
|
|
||||||
|
/// I only separated this as otherwise, the states.rs file gets huge... and this should
|
||||||
|
/// belong in another file anyways, IMO.
|
||||||
|
pub trait ProcessQuery {
|
||||||
|
/// In charge of parsing the given query.
|
||||||
|
/// We are defining the following language for a query (case-insensitive prefixes):
|
||||||
|
///
|
||||||
|
/// - Process names: No prefix required, can use regex, match word, or case.
|
||||||
|
/// Enclosing anything, including prefixes, in quotes, means we treat it as an entire process
|
||||||
|
/// rather than a prefix.
|
||||||
|
/// - PIDs: Use prefix `pid`, can use regex or match word (case is irrelevant).
|
||||||
|
/// - CPU: Use prefix `cpu`, cannot use r/m/c (regex, match word, case). Can compare.
|
||||||
|
/// - MEM: Use prefix `mem`, cannot use r/m/c. Can compare.
|
||||||
|
/// - STATE: Use prefix `state`, TODO when we update how state looks in 0.5 probably.
|
||||||
|
/// - Read/s: Use prefix `r`. Can compare.
|
||||||
|
/// - Write/s: Use prefix `w`. Can compare.
|
||||||
|
/// - Total read: Use prefix `read`. Can compare.
|
||||||
|
/// - Total write: Use prefix `write`. Can compare.
|
||||||
|
///
|
||||||
|
/// For queries, whitespaces are our delimiters. We will merge together any adjacent non-prefixed
|
||||||
|
/// or quoted elements after splitting to treat as process names.
|
||||||
|
/// Furthermore, we want to support boolean joiners like AND and OR, and brackets.
|
||||||
|
fn parse_query(&self) -> Result<Query>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProcessQuery for ProcWidgetState {
|
||||||
|
fn parse_query(&self) -> Result<Query> {
|
||||||
|
fn process_string_to_filter(query: &mut VecDeque<String>) -> Result<Query> {
|
||||||
|
Ok(Query {
|
||||||
|
query: process_and(query)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_and(query: &mut VecDeque<String>) -> Result<And> {
|
||||||
|
let mut lhs = process_or(query)?;
|
||||||
|
let mut rhs: Option<Box<Or>> = None;
|
||||||
|
|
||||||
|
while let Some(queue_top) = query.front() {
|
||||||
|
if queue_top.to_lowercase() == "and" {
|
||||||
|
query.pop_front();
|
||||||
|
rhs = Some(Box::new(process_or(query)?));
|
||||||
|
|
||||||
|
if let Some(queue_next) = query.front() {
|
||||||
|
if queue_next.to_lowercase() == "and" {
|
||||||
|
// Must merge LHS and RHS
|
||||||
|
lhs = Or {
|
||||||
|
lhs: Prefix {
|
||||||
|
and: Some(Box::new(And { lhs, rhs })),
|
||||||
|
regex_prefix: None,
|
||||||
|
compare_prefix: None,
|
||||||
|
},
|
||||||
|
rhs: None,
|
||||||
|
};
|
||||||
|
rhs = None;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(And { lhs, rhs })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_or(query: &mut VecDeque<String>) -> Result<Or> {
|
||||||
|
let mut lhs = process_prefix(query)?;
|
||||||
|
let mut rhs: Option<Box<Prefix>> = None;
|
||||||
|
|
||||||
|
while let Some(queue_top) = query.front() {
|
||||||
|
if queue_top.to_lowercase() == "or" {
|
||||||
|
query.pop_front();
|
||||||
|
rhs = Some(Box::new(process_prefix(query)?));
|
||||||
|
|
||||||
|
if let Some(queue_next) = query.front() {
|
||||||
|
if queue_next.to_lowercase() == "or" {
|
||||||
|
// Must merge LHS and RHS
|
||||||
|
lhs = Prefix {
|
||||||
|
and: Some(Box::new(And {
|
||||||
|
lhs: Or { lhs, rhs },
|
||||||
|
rhs: None,
|
||||||
|
})),
|
||||||
|
regex_prefix: None,
|
||||||
|
compare_prefix: None,
|
||||||
|
};
|
||||||
|
rhs = None;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Or { lhs, rhs })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_prefix(query: &mut VecDeque<String>) -> Result<Prefix> {
|
||||||
|
if let Some(queue_top) = query.pop_front() {
|
||||||
|
if queue_top == "(" {
|
||||||
|
// Get content within bracket; and check if paren is complete
|
||||||
|
let and = process_and(query)?;
|
||||||
|
if let Some(close_paren) = query.pop_front() {
|
||||||
|
if close_paren.to_lowercase() == ")" {
|
||||||
|
return Ok(Prefix {
|
||||||
|
and: Some(Box::new(and)),
|
||||||
|
regex_prefix: None,
|
||||||
|
compare_prefix: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Err(QueryError("Missing closing parentheses".into()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(QueryError("Missing closing parentheses".into()));
|
||||||
|
}
|
||||||
|
} else if queue_top == ")" {
|
||||||
|
// This is actually caught by the regex creation, but it seems a bit
|
||||||
|
// sloppy to leave that up to that to do so...
|
||||||
|
|
||||||
|
return Err(QueryError("Missing opening parentheses".into()));
|
||||||
|
} else {
|
||||||
|
// Get prefix type...
|
||||||
|
let prefix_type = queue_top.parse::<PrefixType>()?;
|
||||||
|
let content = if let PrefixType::Name = prefix_type {
|
||||||
|
Some(queue_top)
|
||||||
|
} else {
|
||||||
|
query.pop_front()
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(content) = content {
|
||||||
|
match &prefix_type {
|
||||||
|
PrefixType::Name => {
|
||||||
|
return Ok(Prefix {
|
||||||
|
and: None,
|
||||||
|
regex_prefix: Some((
|
||||||
|
prefix_type,
|
||||||
|
StringQuery::Value(content.trim_matches('\"').to_owned()),
|
||||||
|
)),
|
||||||
|
compare_prefix: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
PrefixType::Pid => {
|
||||||
|
// We have to check if someone put an "="...
|
||||||
|
if content == "=" {
|
||||||
|
// Check next string if possible
|
||||||
|
if let Some(queue_next) = query.pop_front() {
|
||||||
|
return Ok(Prefix {
|
||||||
|
and: None,
|
||||||
|
regex_prefix: Some((
|
||||||
|
prefix_type,
|
||||||
|
StringQuery::Value(queue_next),
|
||||||
|
)),
|
||||||
|
compare_prefix: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Ok(Prefix {
|
||||||
|
and: None,
|
||||||
|
regex_prefix: Some((
|
||||||
|
prefix_type,
|
||||||
|
StringQuery::Value(content),
|
||||||
|
)),
|
||||||
|
compare_prefix: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// Now we gotta parse the content... yay.
|
||||||
|
|
||||||
|
let mut condition: Option<QueryComparison> = None;
|
||||||
|
let mut value: Option<f64> = None;
|
||||||
|
|
||||||
|
if content == "=" {
|
||||||
|
// TODO: Do we want to allow just an empty space to work here too? ie: cpu 5?
|
||||||
|
condition = Some(QueryComparison::Equal);
|
||||||
|
if let Some(queue_next) = query.pop_front() {
|
||||||
|
value = queue_next.parse::<f64>().ok();
|
||||||
|
}
|
||||||
|
} else if content == ">" || content == "<" {
|
||||||
|
// We also have to check if the next string is an "="...
|
||||||
|
if let Some(queue_next) = query.pop_front() {
|
||||||
|
if queue_next == "=" {
|
||||||
|
condition = Some(if content == ">" {
|
||||||
|
QueryComparison::GreaterOrEqual
|
||||||
|
} else {
|
||||||
|
QueryComparison::LessOrEqual
|
||||||
|
});
|
||||||
|
if let Some(queue_next_next) = query.pop_front() {
|
||||||
|
value = queue_next_next.parse::<f64>().ok();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
condition = Some(if content == ">" {
|
||||||
|
QueryComparison::Greater
|
||||||
|
} else {
|
||||||
|
QueryComparison::Less
|
||||||
|
});
|
||||||
|
value = queue_next.parse::<f64>().ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(condition) = condition {
|
||||||
|
if let Some(value) = value {
|
||||||
|
return Ok(Prefix {
|
||||||
|
and: None,
|
||||||
|
regex_prefix: None,
|
||||||
|
compare_prefix: Some((
|
||||||
|
prefix_type,
|
||||||
|
NumericalQuery { condition, value },
|
||||||
|
)),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(QueryError("Failed to parse comparator.".into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut split_query = VecDeque::new();
|
||||||
|
|
||||||
|
self.get_current_search_query()
|
||||||
|
.split_whitespace()
|
||||||
|
.for_each(|s| {
|
||||||
|
// From https://stackoverflow.com/a/56923739 in order to get a split but include the parentheses
|
||||||
|
let mut last = 0;
|
||||||
|
for (index, matched) in s.match_indices(|x| DELIMITER_LIST.contains(&x)) {
|
||||||
|
if last != index {
|
||||||
|
split_query.push_back(s[last..index].to_owned());
|
||||||
|
}
|
||||||
|
split_query.push_back(matched.to_owned());
|
||||||
|
last = index + matched.len();
|
||||||
|
}
|
||||||
|
if last < s.len() {
|
||||||
|
split_query.push_back(s[last..].to_owned());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut process_filter = process_string_to_filter(&mut split_query)?;
|
||||||
|
process_filter.process_regexes(
|
||||||
|
self.process_search_state.is_searching_whole_word,
|
||||||
|
self.process_search_state.is_ignoring_case,
|
||||||
|
self.process_search_state.is_searching_with_regex,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(process_filter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Query {
|
pub struct Query {
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
use std::{
|
use std::{collections::HashMap, time::Instant};
|
||||||
collections::{HashMap, VecDeque},
|
|
||||||
time::Instant,
|
|
||||||
};
|
|
||||||
|
|
||||||
use unicode_segmentation::GraphemeCursor;
|
use unicode_segmentation::GraphemeCursor;
|
||||||
|
|
||||||
@ -11,7 +8,6 @@ use crate::{
|
|||||||
app::{layout_manager::BottomWidgetType, query::*},
|
app::{layout_manager::BottomWidgetType, query::*},
|
||||||
constants,
|
constants,
|
||||||
data_harvester::processes,
|
data_harvester::processes,
|
||||||
utils::error::{BottomError::*, Result},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -241,257 +237,6 @@ impl ProcWidgetState {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The filtering function. Based on the results of the query.
|
|
||||||
pub fn matches_filter(&self) -> bool {
|
|
||||||
// The way this will have to work is that given a "query" structure, we have
|
|
||||||
// to filter based on it.
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
/// In charge of parsing the given query.
|
|
||||||
/// We are defining the following language for a query (case-insensitive prefixes):
|
|
||||||
///
|
|
||||||
/// - Process names: No prefix required, can use regex, match word, or case.
|
|
||||||
/// Enclosing anything, including prefixes, in quotes, means we treat it as an entire process
|
|
||||||
/// rather than a prefix.
|
|
||||||
/// - PIDs: Use prefix `pid`, can use regex or match word (case is irrelevant).
|
|
||||||
/// - CPU: Use prefix `cpu`, cannot use r/m/c (regex, match word, case). Can compare.
|
|
||||||
/// - MEM: Use prefix `mem`, cannot use r/m/c. Can compare.
|
|
||||||
/// - STATE: Use prefix `state`, TODO when we update how state looks in 0.5 probably.
|
|
||||||
/// - Read/s: Use prefix `r`. Can compare.
|
|
||||||
/// - Write/s: Use prefix `w`. Can compare.
|
|
||||||
/// - Total read: Use prefix `read`. Can compare.
|
|
||||||
/// - Total write: Use prefix `write`. Can compare.
|
|
||||||
///
|
|
||||||
/// For queries, whitespaces are our delimiters. We will merge together any adjacent non-prefixed
|
|
||||||
/// or quoted elements after splitting to treat as process names.
|
|
||||||
/// Furthermore, we want to support boolean joiners like AND and OR, and brackets.
|
|
||||||
fn parse_query(&self) -> Result<Query> {
|
|
||||||
fn process_string_to_filter(query: &mut VecDeque<String>) -> Result<Query> {
|
|
||||||
Ok(Query {
|
|
||||||
query: process_and(query)?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_and(query: &mut VecDeque<String>) -> Result<And> {
|
|
||||||
let mut lhs = process_or(query)?;
|
|
||||||
let mut rhs: Option<Box<Or>> = None;
|
|
||||||
|
|
||||||
while let Some(queue_top) = query.front() {
|
|
||||||
if queue_top.to_lowercase() == "and" {
|
|
||||||
query.pop_front();
|
|
||||||
rhs = Some(Box::new(process_or(query)?));
|
|
||||||
|
|
||||||
if let Some(queue_next) = query.front() {
|
|
||||||
if queue_next.to_lowercase() == "and" {
|
|
||||||
// Must merge LHS and RHS
|
|
||||||
lhs = Or {
|
|
||||||
lhs: Prefix {
|
|
||||||
and: Some(Box::new(And { lhs, rhs })),
|
|
||||||
regex_prefix: None,
|
|
||||||
compare_prefix: None,
|
|
||||||
},
|
|
||||||
rhs: None,
|
|
||||||
};
|
|
||||||
rhs = None;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(And { lhs, rhs })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_or(query: &mut VecDeque<String>) -> Result<Or> {
|
|
||||||
let mut lhs = process_prefix(query)?;
|
|
||||||
let mut rhs: Option<Box<Prefix>> = None;
|
|
||||||
|
|
||||||
while let Some(queue_top) = query.front() {
|
|
||||||
if queue_top.to_lowercase() == "or" {
|
|
||||||
query.pop_front();
|
|
||||||
rhs = Some(Box::new(process_prefix(query)?));
|
|
||||||
|
|
||||||
if let Some(queue_next) = query.front() {
|
|
||||||
if queue_next.to_lowercase() == "or" {
|
|
||||||
// Must merge LHS and RHS
|
|
||||||
lhs = Prefix {
|
|
||||||
and: Some(Box::new(And {
|
|
||||||
lhs: Or { lhs, rhs },
|
|
||||||
rhs: None,
|
|
||||||
})),
|
|
||||||
regex_prefix: None,
|
|
||||||
compare_prefix: None,
|
|
||||||
};
|
|
||||||
rhs = None;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Or { lhs, rhs })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_prefix(query: &mut VecDeque<String>) -> Result<Prefix> {
|
|
||||||
if let Some(queue_top) = query.pop_front() {
|
|
||||||
if queue_top == "(" {
|
|
||||||
// Get content within bracket; and check if paren is complete
|
|
||||||
let and = process_and(query)?;
|
|
||||||
if let Some(close_paren) = query.pop_front() {
|
|
||||||
if close_paren.to_lowercase() == ")" {
|
|
||||||
return Ok(Prefix {
|
|
||||||
and: Some(Box::new(and)),
|
|
||||||
regex_prefix: None,
|
|
||||||
compare_prefix: None,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Err(QueryError("Missing closing parentheses".into()));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(QueryError("Missing closing parentheses".into()));
|
|
||||||
}
|
|
||||||
} else if queue_top == ")" {
|
|
||||||
// This is actually caught by the regex creation, but it seems a bit
|
|
||||||
// sloppy to leave that up to that to do so...
|
|
||||||
|
|
||||||
return Err(QueryError("Missing opening parentheses".into()));
|
|
||||||
} else {
|
|
||||||
// Get prefix type...
|
|
||||||
let prefix_type = queue_top.parse::<PrefixType>()?;
|
|
||||||
let content = if let PrefixType::Name = prefix_type {
|
|
||||||
Some(queue_top)
|
|
||||||
} else {
|
|
||||||
query.pop_front()
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(content) = content {
|
|
||||||
match &prefix_type {
|
|
||||||
PrefixType::Name => {
|
|
||||||
return Ok(Prefix {
|
|
||||||
and: None,
|
|
||||||
regex_prefix: Some((prefix_type, StringQuery::Value(content))),
|
|
||||||
compare_prefix: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
PrefixType::Pid => {
|
|
||||||
// We have to check if someone put an "="...
|
|
||||||
if content == "=" {
|
|
||||||
// Check next string if possible
|
|
||||||
if let Some(queue_next) = query.pop_front() {
|
|
||||||
return Ok(Prefix {
|
|
||||||
and: None,
|
|
||||||
regex_prefix: Some((
|
|
||||||
prefix_type,
|
|
||||||
StringQuery::Value(queue_next),
|
|
||||||
)),
|
|
||||||
compare_prefix: None,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Ok(Prefix {
|
|
||||||
and: None,
|
|
||||||
regex_prefix: Some((
|
|
||||||
prefix_type,
|
|
||||||
StringQuery::Value(content),
|
|
||||||
)),
|
|
||||||
compare_prefix: None,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// Now we gotta parse the content... yay.
|
|
||||||
|
|
||||||
let mut condition: Option<QueryComparison> = None;
|
|
||||||
let mut value: Option<f64> = None;
|
|
||||||
|
|
||||||
if content == "=" {
|
|
||||||
// TODO: Do we want to allow just an empty space to work here too? ie: cpu 5?
|
|
||||||
condition = Some(QueryComparison::Equal);
|
|
||||||
if let Some(queue_next) = query.pop_front() {
|
|
||||||
value = queue_next.parse::<f64>().ok();
|
|
||||||
}
|
|
||||||
} else if content == ">" || content == "<" {
|
|
||||||
// We also have to check if the next string is an "="...
|
|
||||||
if let Some(queue_next) = query.pop_front() {
|
|
||||||
if queue_next == "=" {
|
|
||||||
condition = Some(if content == ">" {
|
|
||||||
QueryComparison::GreaterOrEqual
|
|
||||||
} else {
|
|
||||||
QueryComparison::LessOrEqual
|
|
||||||
});
|
|
||||||
if let Some(queue_next_next) = query.pop_front() {
|
|
||||||
value = queue_next_next.parse::<f64>().ok();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
condition = Some(if content == ">" {
|
|
||||||
QueryComparison::Greater
|
|
||||||
} else {
|
|
||||||
QueryComparison::Less
|
|
||||||
});
|
|
||||||
value = queue_next.parse::<f64>().ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(condition) = condition {
|
|
||||||
if let Some(value) = value {
|
|
||||||
return Ok(Prefix {
|
|
||||||
and: None,
|
|
||||||
regex_prefix: None,
|
|
||||||
compare_prefix: Some((
|
|
||||||
prefix_type,
|
|
||||||
NumericalQuery { condition, value },
|
|
||||||
)),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(QueryError("Failed to parse comparator.".into()))
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut split_query = VecDeque::new();
|
|
||||||
|
|
||||||
self.get_current_search_query()
|
|
||||||
.split_whitespace()
|
|
||||||
.for_each(|s| {
|
|
||||||
// From https://stackoverflow.com/a/56923739 in order to get a split but include the parentheses
|
|
||||||
let mut last = 0;
|
|
||||||
for (index, matched) in s.match_indices(|x| ['=', '>', '<', '(', ')'].contains(&x))
|
|
||||||
{
|
|
||||||
if last != index {
|
|
||||||
split_query.push_back(s[last..index].to_owned());
|
|
||||||
}
|
|
||||||
split_query.push_back(matched.to_owned());
|
|
||||||
last = index + matched.len();
|
|
||||||
}
|
|
||||||
if last < s.len() {
|
|
||||||
split_query.push_back(s[last..].to_owned());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut process_filter = process_string_to_filter(&mut split_query)?;
|
|
||||||
process_filter.process_regexes(
|
|
||||||
self.process_search_state.is_searching_whole_word,
|
|
||||||
self.process_search_state.is_ignoring_case,
|
|
||||||
self.process_search_state.is_searching_with_regex,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(process_filter)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ProcState {
|
pub struct ProcState {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user