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 { diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index 2c67091ec85..43dfe4dd605 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -13,6 +13,8 @@ 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; use crate::core::manifest::ManifestMetadata; @@ -955,15 +957,26 @@ pub fn search( } None => name, }; - drop_println!(config, "{}", line); + 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; 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 +987,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(), ); } diff --git a/tests/testsuite/search.rs b/tests/testsuite/search.rs index abb709ebcb1..eadc46c8b91 100644 --- a/tests/testsuite/search.rs +++ b/tests/testsuite/search.rs @@ -190,3 +190,27 @@ 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(); +} + +#[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(); +}