From 4080ed40a0675f89558c162faecc61fc041e7a8a Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 25 Feb 2022 19:10:48 -0600 Subject: [PATCH 1/4] test(search): Ensure we maintain quiet behavior --- tests/testsuite/search.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/testsuite/search.rs b/tests/testsuite/search.rs index abb709ebcb1..d24a86d2f88 100644 --- a/tests/testsuite/search.rs +++ b/tests/testsuite/search.rs @@ -190,3 +190,13 @@ fn multiple_query_params() { .with_stdout_contains(SEARCH_RESULTS) .run(); } + +#[cargo_test] +fn ignore_quiet() { + setup(); + set_cargo_config(); + + cargo_process("search -q postgres") + .with_stdout_contains(SEARCH_RESULTS) + .run(); +} From e2c5c2f0dde2b5083c8f08a247b1e4b7dadf9156 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 25 Feb 2022 19:22:17 -0600 Subject: [PATCH 2/4] feat(shell): General output support This provides a more general approach for writing output. This will respect the users choice for output support but the user must check the verbosity if its relevant to their output. --- src/cargo/core/shell.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/cargo/core/shell.rs b/src/cargo/core/shell.rs index 887b8967d25..5da210d9350 100644 --- a/src/cargo/core/shell.rs +++ b/src/cargo/core/shell.rs @@ -333,6 +333,17 @@ impl Shell { } } + /// Write a styled fragment + /// + /// Caller is responsible for deciding whether [`Shell::verbosity`] is affects output. + pub fn write_stdout( + &mut self, + fragment: impl fmt::Display, + color: &ColorSpec, + ) -> CargoResult<()> { + self.output.write_stdout(fragment, color) + } + /// Prints a message to stderr and translates ANSI escape code into console colors. pub fn print_ansi_stderr(&mut self, message: &[u8]) -> CargoResult<()> { if self.needs_clear { @@ -423,6 +434,22 @@ impl ShellOut { Ok(()) } + /// Write a styled fragment + fn write_stdout(&mut self, fragment: impl fmt::Display, color: &ColorSpec) -> CargoResult<()> { + match *self { + ShellOut::Stream { ref mut stdout, .. } => { + stdout.reset()?; + stdout.set_color(&color)?; + write!(stdout, "{}", fragment)?; + stdout.reset()?; + } + ShellOut::Write(ref mut w) => { + write!(w, "{}", fragment)?; + } + } + Ok(()) + } + /// Gets stdout as a `io::Write`. fn stdout(&mut self) -> &mut dyn Write { match *self { From 370c39535038957008edfbf698fa57444d5c3e71 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 25 Feb 2022 19:37:42 -0600 Subject: [PATCH 3/4] refactor(search): Use noop version of new write_stdout --- src/cargo/ops/registry.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index 2c67091ec85..902fcb15488 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -13,6 +13,7 @@ use crates_io::{self, NewCrate, NewCrateDependency, Registry}; use curl::easy::{Easy, InfoType, SslOpt, SslVersion}; use log::{log, Level}; use percent_encoding::{percent_encode, NON_ALPHANUMERIC}; +use termcolor::ColorSpec; use crate::core::dependency::DepKind; use crate::core::manifest::ManifestMetadata; @@ -955,15 +956,19 @@ pub fn search( } None => name, }; - drop_println!(config, "{}", line); + let _ = config + .shell() + .write_stdout(format_args!("{}\n", line), &ColorSpec::new()); } let search_max_limit = 100; if total_crates > limit && limit < search_max_limit { - drop_println!( - config, - "... and {} crates more (use --limit N to see more)", - total_crates - limit + let _ = config.shell().write_stdout( + format_args!( + "... and {} crates more (use --limit N to see more)\n", + total_crates - limit + ), + &ColorSpec::new(), ); } else if total_crates > limit && limit >= search_max_limit { let extra = if source_id.is_default_registry() { @@ -974,11 +979,9 @@ pub fn search( } else { String::new() }; - drop_println!( - config, - "... and {} crates more{}", - total_crates - limit, - extra + let _ = config.shell().write_stdout( + format_args!("... and {} crates more{}\n", total_crates - limit, extra), + &ColorSpec::new(), ); } From 1eb8913468291b517e97566f682635de4df669a8 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 25 Feb 2022 20:07:17 -0600 Subject: [PATCH 4/4] feat(search): Highlight search term This supersedes #10116 Fixes #9918 --- src/cargo/ops/registry.rs | 14 +++++++++++--- tests/testsuite/search.rs | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index 902fcb15488..43dfe4dd605 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -13,6 +13,7 @@ use crates_io::{self, NewCrate, NewCrateDependency, Registry}; use curl::easy::{Easy, InfoType, SslOpt, SslVersion}; use log::{log, Level}; use percent_encoding::{percent_encode, NON_ALPHANUMERIC}; +use termcolor::Color::Green; use termcolor::ColorSpec; use crate::core::dependency::DepKind; @@ -956,9 +957,16 @@ pub fn search( } None => name, }; - let _ = config - .shell() - .write_stdout(format_args!("{}\n", line), &ColorSpec::new()); + let mut fragments = line.split(query).peekable(); + while let Some(fragment) = fragments.next() { + let _ = config.shell().write_stdout(fragment, &ColorSpec::new()); + if fragments.peek().is_some() { + let _ = config + .shell() + .write_stdout(query, &ColorSpec::new().set_bold(true).set_fg(Some(Green))); + } + } + let _ = config.shell().write_stdout("\n", &ColorSpec::new()); } let search_max_limit = 100; diff --git a/tests/testsuite/search.rs b/tests/testsuite/search.rs index d24a86d2f88..eadc46c8b91 100644 --- a/tests/testsuite/search.rs +++ b/tests/testsuite/search.rs @@ -200,3 +200,17 @@ fn ignore_quiet() { .with_stdout_contains(SEARCH_RESULTS) .run(); } + +#[cargo_test] +fn colored_results() { + setup(); + set_cargo_config(); + + cargo_process("search --color=never postgres") + .with_stdout_does_not_contain("[..]\x1b[[..]") + .run(); + + cargo_process("search --color=always postgres") + .with_stdout_contains("[..]\x1b[[..]") + .run(); +}