Highlights find upgrade (#11509)

this PR should close #9105

# Description
I have implemented highlights for find which work for all strings. The
implementation also works for lists, but with exceptions (for example,
it does not work for list of lists). The implementation is also not
implemented for --regex.

---------

Co-authored-by: Georgiana <geo@LAPTOP-EQP6H37N>
Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
This commit is contained in:
Georgiana Grigoreanu 2024-01-30 16:06:20 +02:00 committed by GitHub
parent c08f46f836
commit 6530403ff8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 50 additions and 8 deletions

View File

@ -75,9 +75,9 @@ impl Command for Find {
result: None, result: None,
}, },
Example { Example {
description: "Search for a term in a string", description: "Search and highlight text for a term in a string",
example: r#"'Cargo.toml' | find toml"#, example: r#"'Cargo.toml' | find toml"#,
result: Some(Value::test_string("Cargo.toml".to_owned())), result: Some(Value::test_string("\u{1b}[37mCargo.\u{1b}[0m\u{1b}[41;37mtoml\u{1b}[0m\u{1b}[37m\u{1b}[0m".to_owned())),
}, },
Example { Example {
description: "Search a number or a file size in a list of numbers", description: "Search a number or a file size in a list of numbers",
@ -91,7 +91,7 @@ impl Command for Find {
description: "Search a char in a list of string", description: "Search a char in a list of string",
example: r#"[moe larry curly] | find l"#, example: r#"[moe larry curly] | find l"#,
result: Some(Value::list( result: Some(Value::list(
vec![Value::test_string("larry"), Value::test_string("curly")], vec![Value::test_string("\u{1b}[37m\u{1b}[0m\u{1b}[41;37ml\u{1b}[0m\u{1b}[37marry\u{1b}[0m"), Value::test_string("\u{1b}[37mcur\u{1b}[0m\u{1b}[41;37ml\u{1b}[0m\u{1b}[37my\u{1b}[0m")],
Span::test_data(), Span::test_data(),
)), )),
}, },
@ -276,6 +276,31 @@ where
}) })
} }
fn highlight_terms_in_string(
val: &Value,
span: Span,
config: &Config,
terms: &[Value],
string_style: Style,
highlight_style: Style,
) -> Value {
let val_str = val.into_string("", config);
if let Some(term) = terms
.iter()
.find(|term| contains_ignore_case(&val_str, &term.into_string("", config)))
{
let term_str = term.into_string("", config);
let highlighted_str =
highlight_search_string(&val_str, &term_str, &string_style, &highlight_style)
.unwrap_or_else(|_| string_style.paint(&term_str).to_string());
return Value::string(highlighted_str, span);
}
val.clone()
}
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn highlight_terms_in_record_with_search_columns( fn highlight_terms_in_record_with_search_columns(
search_cols: &[String], search_cols: &[String],
@ -369,6 +394,14 @@ fn find_with_rest_and_highlight(
string_style, string_style,
highlight_style, highlight_style,
), ),
Value::String { .. } => highlight_terms_in_string(
&x,
span,
&config,
&terms,
string_style,
highlight_style,
),
_ => x, _ => x,
} }
}, },

View File

@ -4,14 +4,17 @@ use nu_test_support::nu;
fn find_with_list_search_with_string() { fn find_with_list_search_with_string() {
let actual = nu!("[moe larry curly] | find moe | get 0"); let actual = nu!("[moe larry curly] | find moe | get 0");
assert_eq!(actual.out, "moe"); assert_eq!(
actual.out,
"\u{1b}[37m\u{1b}[0m\u{1b}[41;37mmoe\u{1b}[0m\u{1b}[37m\u{1b}[0m"
);
} }
#[test] #[test]
fn find_with_list_search_with_char() { fn find_with_list_search_with_char() {
let actual = nu!("[moe larry curly] | find l | to json -r"); let actual = nu!("[moe larry curly] | find l | to json -r");
assert_eq!(actual.out, r#"["larry","curly"]"#); assert_eq!(actual.out, "[\"\u{1b}[37m\u{1b}[0m\u{1b}[41;37ml\u{1b}[0m\u{1b}[37marry\u{1b}[0m\",\"\u{1b}[37mcur\u{1b}[0m\u{1b}[41;37ml\u{1b}[0m\u{1b}[37my\u{1b}[0m\"]");
} }
#[test] #[test]
@ -25,7 +28,10 @@ fn find_with_list_search_with_number() {
fn find_with_string_search_with_string() { fn find_with_string_search_with_string() {
let actual = nu!("echo Cargo.toml | find toml"); let actual = nu!("echo Cargo.toml | find toml");
assert_eq!(actual.out, "Cargo.toml"); assert_eq!(
actual.out,
"\u{1b}[37mCargo.\u{1b}[0m\u{1b}[41;37mtoml\u{1b}[0m\u{1b}[37m\u{1b}[0m"
);
} }
#[test] #[test]
@ -40,7 +46,10 @@ fn find_with_filepath_search_with_string() {
let actual = let actual =
nu!(r#"["amigos.txt","arepas.clu","los.txt","tres.txt"] | find arep | to json -r"#); nu!(r#"["amigos.txt","arepas.clu","los.txt","tres.txt"] | find arep | to json -r"#);
assert_eq!(actual.out, r#"["arepas.clu"]"#); assert_eq!(
actual.out,
"[\"\u{1b}[37m\u{1b}[0m\u{1b}[41;37marep\u{1b}[0m\u{1b}[37mas.clu\u{1b}[0m\"]"
);
} }
#[test] #[test]
@ -48,7 +57,7 @@ fn find_with_filepath_search_with_multiple_patterns() {
let actual = let actual =
nu!(r#"["amigos.txt","arepas.clu","los.txt","tres.txt"] | find arep ami | to json -r"#); nu!(r#"["amigos.txt","arepas.clu","los.txt","tres.txt"] | find arep ami | to json -r"#);
assert_eq!(actual.out, r#"["amigos.txt","arepas.clu"]"#); assert_eq!(actual.out, "[\"\u{1b}[37m\u{1b}[0m\u{1b}[41;37mami\u{1b}[0m\u{1b}[37mgos.txt\u{1b}[0m\",\"\u{1b}[37m\u{1b}[0m\u{1b}[41;37marep\u{1b}[0m\u{1b}[37mas.clu\u{1b}[0m\"]");
} }
#[test] #[test]