mirror of
https://github.com/ClementTsang/bottom.git
synced 2026-10-14 13:19:18 +00:00
bug: fix issue with parsing quoted delimiters in process search (#2069)
Noticed this when trying to parse something with `<` and `>` in the name, even when quoted. The fix is to just check for quotes when delimiting.
This commit is contained in:
1 parent
acb0ddfa53
commit
6daf7ebd3f
2 files changed
+67
-4
No files matched your search
@@ -26,6 +26,7 @@ That said, these are more guidelines rather than hard rules, though the project
|
||||
|
||||
- [#2035](https://github.com/ClementTsang/bottom/pull/2035): Fix panic when deleting unicode words in search.
|
||||
- [#2042](https://github.com/ClementTsang/bottom/pull/2042): Address possible memory usage growth for AMD GPU stat gathering on Linux.
|
||||
- [#2069](https://github.com/ClementTsang/bottom/pull/2069): Fix issue in process search with parsing quoted delimiters.
|
||||
|
||||
### Features
|
||||
|
||||
|
||||
@@ -120,16 +120,30 @@ pub(crate) fn parse_query(search_query: &str, options: &QueryOptions) -> QueryRe
|
||||
}
|
||||
|
||||
let mut split_query = VecDeque::new();
|
||||
let mut in_quotes = false;
|
||||
|
||||
search_query.split_whitespace().for_each(|s| {
|
||||
// From https://stackoverflow.com/a/56923739 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());
|
||||
if matched == "\"" {
|
||||
// Always split on quote delimiters to open/close quoted sections.
|
||||
if last != index {
|
||||
split_query.push_back(s[last..index].to_owned());
|
||||
}
|
||||
split_query.push_back(matched.to_owned());
|
||||
last = index + matched.len();
|
||||
in_quotes = !in_quotes;
|
||||
} else if !in_quotes {
|
||||
// Only split on other delimiters when outside a quoted section,
|
||||
// so that special chars like `<` and `>` in `"Thread<15>"` are
|
||||
// preserved as literals.
|
||||
if last != index {
|
||||
split_query.push_back(s[last..index].to_owned());
|
||||
}
|
||||
split_query.push_back(matched.to_owned());
|
||||
last = index + matched.len();
|
||||
}
|
||||
split_query.push_back(matched.to_owned());
|
||||
last = index + matched.len();
|
||||
}
|
||||
if last < s.len() {
|
||||
split_query.push_back(s[last..].to_owned());
|
||||
@@ -1098,6 +1112,54 @@ mod tests {
|
||||
assert!(!query.check(&without, false));
|
||||
}
|
||||
|
||||
/// Quoted angle brackets should be treated as literal characters in name matches.
|
||||
#[test]
|
||||
fn quoted_angle_brackets_match_literal() {
|
||||
let query = parse_query_no_options("\"Thread<15>\"").unwrap();
|
||||
|
||||
let matching = simple_process("Thread<15>");
|
||||
let non_matching = simple_process("Thread");
|
||||
|
||||
assert!(query.check(&matching, false));
|
||||
assert!(!query.check(&non_matching, false));
|
||||
}
|
||||
|
||||
/// A quoted `=` should be treated as a literal character in name matches.
|
||||
#[test]
|
||||
fn quoted_equals_matches_literal() {
|
||||
let query = parse_query_no_options("\"a=b\"").unwrap();
|
||||
|
||||
let matching = simple_process("a=b");
|
||||
let non_matching = simple_process("ab");
|
||||
|
||||
assert!(query.check(&matching, false));
|
||||
assert!(!query.check(&non_matching, false));
|
||||
}
|
||||
|
||||
/// A quoted `!=` should be treated as a literal character sequence in name matches.
|
||||
#[test]
|
||||
fn quoted_not_equals_matches_literal() {
|
||||
let query = parse_query_no_options("\"a!=b\"").unwrap();
|
||||
|
||||
let matching = simple_process("a!=b");
|
||||
let non_matching = simple_process("ab");
|
||||
|
||||
assert!(query.check(&matching, false));
|
||||
assert!(!query.check(&non_matching, false));
|
||||
}
|
||||
|
||||
/// Quoted parentheses should be treated as literal characters in name matches.
|
||||
#[test]
|
||||
fn quoted_parens_match_literal() {
|
||||
let query = parse_query_no_options("\"a(b)\"").unwrap();
|
||||
|
||||
let matching = simple_process("a(b)");
|
||||
let non_matching = simple_process("ab");
|
||||
|
||||
assert!(query.check(&matching, false));
|
||||
assert!(!query.check(&non_matching, false));
|
||||
}
|
||||
|
||||
/// Trailing operators with no RHS must error.
|
||||
#[test]
|
||||
fn not_equal_missing_value_is_rejected() {
|
||||
|
||||
Reference in new issue
Block a user