Suppress all output to stderr when --quiet
(#771)
Suppress all warnings and error messages when `--quiet` is passed.
This commit is contained in:
parent
d398417de3
commit
86c2e52dc6
@ -483,14 +483,14 @@ impl Config {
|
||||
}
|
||||
|
||||
if let Completions { shell } = self.subcommand {
|
||||
return Subcommand::completions(&shell);
|
||||
return Subcommand::completions(self.verbosity, &shell);
|
||||
}
|
||||
|
||||
let search =
|
||||
Search::find(&self.search_config, &self.invocation_directory).eprint(self.color)?;
|
||||
|
||||
if self.subcommand == Edit {
|
||||
return Self::edit(&search);
|
||||
return self.edit(&search);
|
||||
}
|
||||
|
||||
let src = fs::read_to_string(&search.justfile)
|
||||
@ -502,6 +502,7 @@ impl Config {
|
||||
|
||||
let justfile = Compiler::compile(&src).eprint(self.color)?;
|
||||
|
||||
if self.verbosity.loud() {
|
||||
for warning in &justfile.warnings {
|
||||
if self.color.stderr().active() {
|
||||
eprintln!("{:#}", warning);
|
||||
@ -509,6 +510,7 @@ impl Config {
|
||||
eprintln!("{}", warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match &self.subcommand {
|
||||
Choose { overrides, chooser } =>
|
||||
@ -520,7 +522,7 @@ impl Config {
|
||||
arguments,
|
||||
overrides,
|
||||
} => self.run(justfile, &search, overrides, arguments)?,
|
||||
Show { ref name } => Self::show(&name, justfile)?,
|
||||
Show { ref name } => self.show(&name, justfile)?,
|
||||
Summary => self.summary(justfile),
|
||||
Variables => Self::variables(justfile),
|
||||
Completions { .. } | Edit | Init => unreachable!(),
|
||||
@ -544,7 +546,9 @@ impl Config {
|
||||
.collect::<Vec<&Recipe<Dependency>>>();
|
||||
|
||||
if recipes.is_empty() {
|
||||
if self.verbosity.loud() {
|
||||
eprintln!("Justfile contains no choosable recipes.");
|
||||
}
|
||||
return Err(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -565,11 +569,13 @@ impl Config {
|
||||
let mut child = match result {
|
||||
Ok(child) => child,
|
||||
Err(error) => {
|
||||
if self.verbosity.loud() {
|
||||
eprintln!(
|
||||
"Chooser `{}` invocation failed: {}",
|
||||
chooser.to_string_lossy(),
|
||||
error
|
||||
);
|
||||
}
|
||||
return Err(EXIT_FAILURE);
|
||||
},
|
||||
};
|
||||
@ -581,11 +587,13 @@ impl Config {
|
||||
.expect("Child was created with piped stdio")
|
||||
.write_all(format!("{}\n", recipe.name).as_bytes())
|
||||
{
|
||||
if self.verbosity.loud() {
|
||||
eprintln!(
|
||||
"Failed to write to chooser `{}`: {}",
|
||||
chooser.to_string_lossy(),
|
||||
error
|
||||
);
|
||||
}
|
||||
return Err(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@ -593,21 +601,25 @@ impl Config {
|
||||
let output = match child.wait_with_output() {
|
||||
Ok(output) => output,
|
||||
Err(error) => {
|
||||
if self.verbosity.loud() {
|
||||
eprintln!(
|
||||
"Failed to read output from chooser `{}`: {}",
|
||||
chooser.to_string_lossy(),
|
||||
error
|
||||
);
|
||||
}
|
||||
return Err(EXIT_FAILURE);
|
||||
},
|
||||
};
|
||||
|
||||
if !output.status.success() {
|
||||
if self.verbosity.loud() {
|
||||
eprintln!(
|
||||
"Chooser `{}` returned error: {}",
|
||||
chooser.to_string_lossy(),
|
||||
output.status
|
||||
);
|
||||
}
|
||||
return Err(output.status.code().unwrap_or(EXIT_FAILURE));
|
||||
}
|
||||
|
||||
@ -626,7 +638,7 @@ impl Config {
|
||||
println!("{}", justfile);
|
||||
}
|
||||
|
||||
pub(crate) fn edit(search: &Search) -> Result<(), i32> {
|
||||
pub(crate) fn edit(&self, search: &Search) -> Result<(), i32> {
|
||||
let editor = env::var_os("VISUAL")
|
||||
.or_else(|| env::var_os("EDITOR"))
|
||||
.unwrap_or_else(|| "vim".into());
|
||||
@ -641,15 +653,19 @@ impl Config {
|
||||
if status.success() {
|
||||
Ok(())
|
||||
} else {
|
||||
if self.verbosity.loud() {
|
||||
eprintln!("Editor `{}` failed: {}", editor.to_string_lossy(), status);
|
||||
}
|
||||
Err(status.code().unwrap_or(EXIT_FAILURE))
|
||||
},
|
||||
Err(error) => {
|
||||
if self.verbosity.loud() {
|
||||
eprintln!(
|
||||
"Editor `{}` invocation failed: {}",
|
||||
editor.to_string_lossy(),
|
||||
error
|
||||
);
|
||||
}
|
||||
Err(EXIT_FAILURE)
|
||||
},
|
||||
}
|
||||
@ -660,17 +676,23 @@ impl Config {
|
||||
Search::init(&self.search_config, &self.invocation_directory).eprint(self.color)?;
|
||||
|
||||
if search.justfile.exists() {
|
||||
if self.verbosity.loud() {
|
||||
eprintln!("Justfile `{}` already exists", search.justfile.display());
|
||||
}
|
||||
Err(EXIT_FAILURE)
|
||||
} else if let Err(err) = fs::write(&search.justfile, INIT_JUSTFILE) {
|
||||
if self.verbosity.loud() {
|
||||
eprintln!(
|
||||
"Failed to write justfile to `{}`: {}",
|
||||
search.justfile.display(),
|
||||
err
|
||||
);
|
||||
}
|
||||
Err(EXIT_FAILURE)
|
||||
} else {
|
||||
if self.verbosity.loud() {
|
||||
eprintln!("Wrote justfile to `{}`", search.justfile.display());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -766,7 +788,7 @@ impl Config {
|
||||
overrides: &BTreeMap<String, String>,
|
||||
arguments: &[String],
|
||||
) -> Result<(), i32> {
|
||||
if let Err(error) = InterruptHandler::install() {
|
||||
if let Err(error) = InterruptHandler::install(self.verbosity) {
|
||||
warn!("Failed to set CTRL-C handler: {}", error)
|
||||
}
|
||||
|
||||
@ -779,7 +801,7 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
fn show(name: &str, justfile: Justfile) -> Result<(), i32> {
|
||||
fn show(&self, name: &str, justfile: Justfile) -> Result<(), i32> {
|
||||
if let Some(alias) = justfile.get_alias(name) {
|
||||
let recipe = justfile.get_recipe(alias.target.name.lexeme()).unwrap();
|
||||
println!("{}", alias);
|
||||
@ -789,17 +811,21 @@ impl Config {
|
||||
println!("{}", recipe);
|
||||
Ok(())
|
||||
} else {
|
||||
if self.verbosity.loud() {
|
||||
eprintln!("Justfile does not contain recipe `{}`.", name);
|
||||
if let Some(suggestion) = justfile.suggest(name) {
|
||||
eprintln!("{}", suggestion);
|
||||
}
|
||||
}
|
||||
Err(EXIT_FAILURE)
|
||||
}
|
||||
}
|
||||
|
||||
fn summary(&self, justfile: Justfile) {
|
||||
if justfile.count() == 0 {
|
||||
if self.verbosity.loud() {
|
||||
eprintln!("Justfile contains no recipes.");
|
||||
}
|
||||
} else {
|
||||
let summary = justfile
|
||||
.public_recipes(self.unsorted)
|
||||
|
@ -3,10 +3,13 @@ use crate::common::*;
|
||||
pub(crate) struct InterruptHandler {
|
||||
blocks: u32,
|
||||
interrupted: bool,
|
||||
verbosity: Verbosity,
|
||||
}
|
||||
|
||||
impl InterruptHandler {
|
||||
pub(crate) fn install() -> Result<(), ctrlc::Error> {
|
||||
pub(crate) fn install(verbosity: Verbosity) -> Result<(), ctrlc::Error> {
|
||||
let mut instance = Self::instance();
|
||||
instance.verbosity = verbosity;
|
||||
ctrlc::set_handler(|| Self::instance().interrupt())
|
||||
}
|
||||
|
||||
@ -30,6 +33,7 @@ impl InterruptHandler {
|
||||
Self {
|
||||
blocks: 0,
|
||||
interrupted: false,
|
||||
verbosity: Verbosity::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,9 +57,11 @@ impl InterruptHandler {
|
||||
|
||||
pub(crate) fn unblock(&mut self) {
|
||||
if self.blocks == 0 {
|
||||
if self.verbosity.loud() {
|
||||
eprintln!("{}", RuntimeError::Internal {
|
||||
message: "attempted to unblock interrupt handler, but handler was not blocked".to_owned(),
|
||||
});
|
||||
}
|
||||
std::process::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ impl<'src, D> Recipe<'src, D> {
|
||||
evaluated_lines.push(evaluator.evaluate_line(line, false)?);
|
||||
}
|
||||
|
||||
if config.dry_run || self.quiet {
|
||||
if config.verbosity.loud() && (config.dry_run || self.quiet) {
|
||||
for line in &evaluated_lines {
|
||||
eprintln!("{}", line);
|
||||
}
|
||||
|
@ -203,18 +203,25 @@ const BASH_COMPLETION_REPLACEMENTS: &[(&str, &str)] = &[(
|
||||
)];
|
||||
|
||||
impl Subcommand {
|
||||
pub(crate) fn completions(shell: &str) -> Result<(), i32> {
|
||||
pub(crate) fn completions(verbosity: Verbosity, shell: &str) -> Result<(), i32> {
|
||||
use clap::Shell;
|
||||
|
||||
fn replace(haystack: &mut String, needle: &str, replacement: &str) -> Result<(), i32> {
|
||||
fn replace(
|
||||
verbosity: Verbosity,
|
||||
haystack: &mut String,
|
||||
needle: &str,
|
||||
replacement: &str,
|
||||
) -> Result<(), i32> {
|
||||
if let Some(index) = haystack.find(needle) {
|
||||
haystack.replace_range(index..index + needle.len(), replacement);
|
||||
Ok(())
|
||||
} else {
|
||||
if verbosity.loud() {
|
||||
eprintln!("Failed to find text:");
|
||||
eprintln!("{}", needle);
|
||||
eprintln!("…in completion script:");
|
||||
eprintln!("{}", haystack);
|
||||
}
|
||||
Err(EXIT_FAILURE)
|
||||
}
|
||||
}
|
||||
@ -232,19 +239,19 @@ impl Subcommand {
|
||||
match shell {
|
||||
Shell::Bash =>
|
||||
for (needle, replacement) in BASH_COMPLETION_REPLACEMENTS {
|
||||
replace(&mut script, needle, replacement)?;
|
||||
replace(verbosity, &mut script, needle, replacement)?;
|
||||
},
|
||||
Shell::Fish => {
|
||||
script.insert_str(0, FISH_RECIPE_COMPLETIONS);
|
||||
},
|
||||
Shell::PowerShell =>
|
||||
for (needle, replacement) in POWERSHELL_COMPLETION_REPLACEMENTS {
|
||||
replace(&mut script, needle, replacement)?;
|
||||
replace(verbosity, &mut script, needle, replacement)?;
|
||||
},
|
||||
|
||||
Shell::Zsh =>
|
||||
for (needle, replacement) in ZSH_COMPLETION_REPLACEMENTS {
|
||||
replace(&mut script, needle, replacement)?;
|
||||
replace(verbosity, &mut script, needle, replacement)?;
|
||||
},
|
||||
Shell::Elvish => {},
|
||||
}
|
||||
|
@ -21,6 +21,10 @@ impl Verbosity {
|
||||
matches!(self, Quiet)
|
||||
}
|
||||
|
||||
pub(crate) fn loud(self) -> bool {
|
||||
!self.quiet()
|
||||
}
|
||||
|
||||
pub(crate) fn loquacious(self) -> bool {
|
||||
match self {
|
||||
Quiet | Taciturn => false,
|
||||
@ -35,3 +39,9 @@ impl Verbosity {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Verbosity {
|
||||
fn default() -> Self {
|
||||
Self::Taciturn
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ mod init;
|
||||
mod interrupts;
|
||||
mod invocation_directory;
|
||||
mod misc;
|
||||
mod quiet;
|
||||
mod readme;
|
||||
mod search;
|
||||
mod shell;
|
||||
|
@ -666,71 +666,6 @@ test! {
|
||||
status: EXIT_FAILURE,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: quiet_flag_no_stdout,
|
||||
justfile: r#"
|
||||
default:
|
||||
@echo hello
|
||||
"#,
|
||||
args: ("--quiet"),
|
||||
stdout: "",
|
||||
}
|
||||
|
||||
test! {
|
||||
name: quiet_flag_no_stderr,
|
||||
justfile: r#"
|
||||
default:
|
||||
@echo hello 1>&2
|
||||
"#,
|
||||
args: ("--quiet"),
|
||||
stdout: "",
|
||||
}
|
||||
|
||||
test! {
|
||||
name: quiet_flag_no_command_echoing,
|
||||
justfile: r#"
|
||||
default:
|
||||
exit
|
||||
"#,
|
||||
args: ("--quiet"),
|
||||
stdout: "",
|
||||
}
|
||||
|
||||
test! {
|
||||
name: quiet_flag_no_error_messages,
|
||||
justfile: r#"
|
||||
default:
|
||||
exit 100
|
||||
"#,
|
||||
args: ("--quiet"),
|
||||
stdout: "",
|
||||
status: 100,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: quiet_flag_no_assignment_backtick_stderr,
|
||||
justfile: r#"
|
||||
a := `echo hello 1>&2`
|
||||
default:
|
||||
exit 100
|
||||
"#,
|
||||
args: ("--quiet"),
|
||||
stdout: "",
|
||||
status: 100,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: quiet_flag_no_interpolation_backtick_stderr,
|
||||
justfile: r#"
|
||||
default:
|
||||
echo `echo hello 1>&2`
|
||||
exit 100
|
||||
"#,
|
||||
args: ("--quiet"),
|
||||
stdout: "",
|
||||
status: 100,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: argument_single,
|
||||
justfile: "
|
||||
|
147
tests/quiet.rs
Normal file
147
tests/quiet.rs
Normal file
@ -0,0 +1,147 @@
|
||||
use crate::common::*;
|
||||
|
||||
test! {
|
||||
name: no_stdout,
|
||||
justfile: r#"
|
||||
default:
|
||||
@echo hello
|
||||
"#,
|
||||
args: ("--quiet"),
|
||||
stdout: "",
|
||||
}
|
||||
|
||||
test! {
|
||||
name: stderr,
|
||||
justfile: r#"
|
||||
default:
|
||||
@echo hello 1>&2
|
||||
"#,
|
||||
args: ("--quiet"),
|
||||
stdout: "",
|
||||
}
|
||||
|
||||
test! {
|
||||
name: command_echoing,
|
||||
justfile: r#"
|
||||
default:
|
||||
exit
|
||||
"#,
|
||||
args: ("--quiet"),
|
||||
stdout: "",
|
||||
}
|
||||
|
||||
test! {
|
||||
name: error_messages,
|
||||
justfile: r#"
|
||||
default:
|
||||
exit 100
|
||||
"#,
|
||||
args: ("--quiet"),
|
||||
stdout: "",
|
||||
status: 100,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: assignment_backtick_stderr,
|
||||
justfile: r#"
|
||||
a := `echo hello 1>&2`
|
||||
default:
|
||||
exit 100
|
||||
"#,
|
||||
args: ("--quiet"),
|
||||
stdout: "",
|
||||
status: 100,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: interpolation_backtick_stderr,
|
||||
justfile: r#"
|
||||
default:
|
||||
echo `echo hello 1>&2`
|
||||
exit 100
|
||||
"#,
|
||||
args: ("--quiet"),
|
||||
stdout: "",
|
||||
status: 100,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: warning,
|
||||
justfile: "
|
||||
foo = 'bar'
|
||||
|
||||
baz:
|
||||
",
|
||||
args: ("--quiet"),
|
||||
}
|
||||
|
||||
test! {
|
||||
name: choose_none,
|
||||
justfile: "",
|
||||
args: ("--choose", "--quiet"),
|
||||
status: EXIT_FAILURE,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: choose_invocation,
|
||||
justfile: "foo:",
|
||||
args: ("--choose", "--quiet", "--shell", "asdfasdfasfdasdfasdfadsf"),
|
||||
status: EXIT_FAILURE,
|
||||
shell: false,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: choose_status,
|
||||
justfile: "foo:",
|
||||
args: ("--choose", "--quiet", "--chooser", "/usr/bin/env false"),
|
||||
status: EXIT_FAILURE,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: edit_invocation,
|
||||
justfile: "foo:",
|
||||
args: ("--edit", "--quiet"),
|
||||
env: {
|
||||
"VISUAL": "adsfasdfasdfadsfadfsaf",
|
||||
},
|
||||
status: EXIT_FAILURE,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: edit_status,
|
||||
justfile: "foo:",
|
||||
args: ("--edit", "--quiet"),
|
||||
env: {
|
||||
"VISUAL": "false",
|
||||
},
|
||||
status: EXIT_FAILURE,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: init_exists,
|
||||
justfile: "foo:",
|
||||
args: ("--init", "--quiet"),
|
||||
status: EXIT_FAILURE,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: show_missing,
|
||||
justfile: "foo:",
|
||||
args: ("--show", "bar", "--quiet"),
|
||||
status: EXIT_FAILURE,
|
||||
}
|
||||
|
||||
test! {
|
||||
name: summary_none,
|
||||
justfile: "",
|
||||
args: ("--summary", "--quiet"),
|
||||
}
|
||||
|
||||
test! {
|
||||
name: quiet_shebang,
|
||||
justfile: "
|
||||
@foo:
|
||||
#!/bin/sh
|
||||
",
|
||||
args: ("--quiet"),
|
||||
}
|
Loading…
Reference in New Issue
Block a user