diff --git a/crates/nu-command/src/filters/find.rs b/crates/nu-command/src/filters/find.rs index 09ecf2cd6826..61e408acd2f5 100644 --- a/crates/nu-command/src/filters/find.rs +++ b/crates/nu-command/src/filters/find.rs @@ -80,9 +80,9 @@ impl Command for Find { result: None, }, 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"#, - 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 { description: "Search a number or a file size in a list of numbers", @@ -96,7 +96,7 @@ impl Command for Find { description: "Search a char in a list of string", example: r#"[moe larry curly] | find l"#, 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(), )), }, @@ -281,6 +281,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)] fn highlight_terms_in_record_with_search_columns( search_cols: &[String], @@ -374,6 +399,14 @@ fn find_with_rest_and_highlight( string_style, highlight_style, ), + Value::String { .. } => highlight_terms_in_string( + &x, + span, + &config, + &terms, + string_style, + highlight_style, + ), _ => x, } }, diff --git a/crates/nu-command/tests/commands/find.rs b/crates/nu-command/tests/commands/find.rs index 139244496bba..a1c4a208a872 100644 --- a/crates/nu-command/tests/commands/find.rs +++ b/crates/nu-command/tests/commands/find.rs @@ -4,14 +4,17 @@ use nu_test_support::nu; fn find_with_list_search_with_string() { 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] fn find_with_list_search_with_char() { 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] @@ -25,7 +28,10 @@ fn find_with_list_search_with_number() { fn find_with_string_search_with_string() { 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] @@ -40,7 +46,10 @@ fn find_with_filepath_search_with_string() { let actual = 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] @@ -48,7 +57,7 @@ fn find_with_filepath_search_with_multiple_patterns() { let actual = 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]