From 3bc8b08bdf3f971be5066096ab2f42776d04721f Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Sat, 17 Aug 2024 01:46:37 +0300 Subject: [PATCH] feat(cli): Add passthrough mode to interface --- assets/en-US/cli.ftl | 3 +++ assets/tr-TR/cli.ftl | 3 +++ src/cli.rs | 5 ++++ src/config.rs | 4 +++ src/run/mod.rs | 1 - src/ui_ascii.rs | 61 ++++++++++++++++++++++++++++++++------------ src/ui_indicatif.rs | 58 ++++++++++++++++++++++++++++++++++++----- 7 files changed, 112 insertions(+), 23 deletions(-) diff --git a/assets/en-US/cli.ftl b/assets/en-US/cli.ftl index eced244b..af08f452 100644 --- a/assets/en-US/cli.ftl +++ b/assets/en-US/cli.ftl @@ -15,6 +15,9 @@ help-flag-language = help-flag-quiet = Enable extra debug output from tooling +help-flag-passthrough = + Eschew all UI output and just pass the subprocess output through + # Currently hard coded, see clap issue #1880 help-flag-verbose = Enable extra verbose output from tooling diff --git a/assets/tr-TR/cli.ftl b/assets/tr-TR/cli.ftl index 8ad09a45..114d05ff 100644 --- a/assets/tr-TR/cli.ftl +++ b/assets/tr-TR/cli.ftl @@ -2,6 +2,9 @@ help-description = CaSILE avadanlığı için komut satırı arayüzü, SILE ve benzer sihirbazlığından faydılanan bir yayınlama işi akışı. +help-flag-passthrough = + Tüm kullanıcı arayüzü çıktılarından vazgeçin ve sadece alt işlem çıktısını verin + help-subcommand-run = CaSILE ortamı içinde yardımcı komut dosyasını çalıştırın diff --git a/src/cli.rs b/src/cli.rs index b27dca1d..d4cca186 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -18,6 +18,11 @@ pub struct Cli { #[clap(short, long)] pub language: Option, + // FTL: help-flag-passthrough + /// Eschew all UI output and just pass the subprocess output through + #[clap(short, long)] + pub passthrough: bool, + // FTL: help-flag-project /// Set project root path #[clap(short = 'P', long, default_value = "./")] diff --git a/src/config.rs b/src/config.rs index 2446f1fa..1447a17f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -21,6 +21,7 @@ impl CONF { .set_default("quiet", false)? .set_default("verbose", false)? .set_default("language", crate::DEFAULT_LOCALE)? + .set_default("passthrough", false)? .set_default("project", "./")?; Ok(()) } @@ -60,6 +61,9 @@ impl CONF { } else if args.quiet { self.set_bool("quiet", true)?; } + if args.passthrough { + self.set_bool("passthrough", true)?; + } if let Some(path) = &args.project.to_str() { self.set_str("project", path)?; } diff --git a/src/run/mod.rs b/src/run/mod.rs index b029c067..c2555986 100644 --- a/src/run/mod.rs +++ b/src/run/mod.rs @@ -29,7 +29,6 @@ pub fn run(name: String, arguments: Vec) -> Result<()> { .cwd(workdir) .stderr(Redirection::Pipe) .stdout(Redirection::Pipe); - eprintln!("all the way to base whatsit"); let mut popen = process.popen()?; let bufstdout = io::BufReader::new(popen.stdout.as_mut().unwrap()); // let bufstderr = io::BufReader::new(popen.stderr.as_mut().unwrap()); diff --git a/src/ui_ascii.rs b/src/ui_ascii.rs index 46f0b5df..7d50aa01 100644 --- a/src/ui_ascii.rs +++ b/src/ui_ascii.rs @@ -22,11 +22,17 @@ impl Default for AsciiInterface { impl UserInterface for AsciiInterface { fn welcome(&self) { + if CONF.get_bool("passthrough").unwrap() { + return; + } let welcome = &self.messages.welcome; let welcome = style(welcome).cyan(); println!("{welcome}"); } fn farewell(&self) { + if CONF.get_bool("passthrough").unwrap() { + return; + } let time = HumanDuration(self.started.elapsed()); let farewell = LocalText::new("farewell").arg("duration", time).fmt(); let farewell = style(farewell).cyan(); @@ -56,6 +62,9 @@ impl AsciiSubcommandStatus { impl SubcommandStatus for AsciiSubcommandStatus { fn end(&self, _status: bool) {} fn error(&mut self, msg: String) { + if CONF.get_bool("passthrough").unwrap() { + return; + } let msg = style(msg).red().dim(); eprintln!("{msg}"); } @@ -82,12 +91,18 @@ impl AsciiSetupCheck { impl SetupCheck for AsciiSetupCheck { fn pass(&self) { + if CONF.get_bool("passthrough").unwrap() { + return; + } let msg = &self.message; let yes = LocalText::new("setup-true").fmt(); let yes = style(yes).green(); println!("{msg} {yes}"); } fn fail(&self) { + if CONF.get_bool("passthrough").unwrap() { + return; + } let msg = &self.message; let no = LocalText::new("setup-false").fmt(); let no = style(no).red(); @@ -103,15 +118,18 @@ pub struct AsciiJobStatus { impl AsciiJobStatus { fn new(target: MakeTarget) -> Self { - // Withouth this, copying the string in the terminal as a word brings a U+2069 with it - let mut printable_target: String = target.to_string(); - printable_target.push(' '); - let printable_target = style(printable_target).white().bold(); - let msg = LocalText::new("make-report-start") - .arg("target", printable_target) - .fmt(); - let msg = style(msg).yellow().bright(); - println!("{msg}"); + if !CONF.get_bool("passthrough").unwrap() { + // Without this, copying the string in the terminal as a word brings a U+2069 with it + // c.f. https://github.com/XAMPPRocky/fluent-templates/issues/72 + let mut printable_target: String = target.to_string(); + printable_target.push(' '); + let printable_target = style(printable_target).white().bold(); + let msg = LocalText::new("make-report-start") + .arg("target", printable_target) + .fmt(); + let msg = style(msg).yellow().bright(); + println!("{msg}"); + } Self { target, log: JobBacklog::default(), @@ -127,11 +145,13 @@ impl JobStatus for AsciiJobStatus { self.target.starts_with("debug") } fn dump(&self) { + if !CONF.get_bool("passthrough").unwrap() { + let start = LocalText::new("make-backlog-start") + .arg("target", self.target.clone()) + .fmt(); + println!("{}{start}", style("----- ").cyan()); + } let lines = self.log.lines.read().unwrap(); - let start = LocalText::new("make-backlog-start") - .arg("target", self.target.clone()) - .fmt(); - println!("{}{start}", style("----- ").cyan()); for line in lines.iter() { match line.stream { JobBacklogStream::StdOut => { @@ -144,11 +164,17 @@ impl JobStatus for AsciiJobStatus { } } } - let end = LocalText::new("make-backlog-end").fmt(); - println!("{} {end}", style("----- ").cyan()); + if !CONF.get_bool("passthrough").unwrap() { + let end = LocalText::new("make-backlog-end").fmt(); + println!("{} {end}", style("----- ").cyan()); + } } fn pass_msg(&self) { - // Withouth this, copying the string in the terminal as a word brings a U+2069 with it + if CONF.get_bool("passthrough").unwrap() { + return; + } + // Without this, copying the string in the terminal as a word brings a U+2069 with it + // c.f. https://github.com/XAMPPRocky/fluent-templates/issues/72 let mut printable_target: String = self.target.to_string(); printable_target.push(' '); let target = printable_target; @@ -160,6 +186,9 @@ impl JobStatus for AsciiJobStatus { println!("{msg}") } fn fail_msg(&self, code: u32) { + if CONF.get_bool("passthrough").unwrap() { + return; + } // Withouth this, copying the string in the terminal as a word brings a U+2069 with it let mut printable_target: String = self.target.to_string(); printable_target.push(' '); diff --git a/src/ui_indicatif.rs b/src/ui_indicatif.rs index 364d26e8..b073924f 100644 --- a/src/ui_indicatif.rs +++ b/src/ui_indicatif.rs @@ -4,7 +4,7 @@ use crate::ui::*; use crate::*; use console::style; -use indicatif::{HumanDuration, MultiProgress, ProgressBar, ProgressStyle}; +use indicatif::{HumanDuration, MultiProgress, ProgressBar, ProgressDrawTarget, ProgressStyle}; use std::time::Instant; fn finalize_bar(bar: ProgressBar, msg: String) { @@ -35,6 +35,9 @@ impl Default for IndicatifInterface { fn default() -> Self { let progress = MultiProgress::new(); progress.set_move_cursor(true); + if CONF.get_bool("passthrough").unwrap() { + progress.set_draw_target(ProgressDrawTarget::hidden()); + } let started = Instant::now(); let messages = UserInterfaceMessages::new(); Self { @@ -49,9 +52,13 @@ impl IndicatifInterface { pub fn bar(&self) -> ProgressBar { let prefix = style("⛫").cyan().to_string(); let pstyle = ProgressStyle::with_template("{prefix} {msg}").unwrap(); - ProgressBar::new_spinner() + let bar = ProgressBar::new_spinner() .with_style(pstyle) - .with_prefix(prefix) + .with_prefix(prefix); + if CONF.get_bool("passthrough").unwrap() { + bar.set_draw_target(ProgressDrawTarget::hidden()); + } + bar } pub fn show(&self, msg: String) { let bar = self.bar(); @@ -62,10 +69,16 @@ impl IndicatifInterface { impl UserInterface for IndicatifInterface { fn welcome(&self) { + if CONF.get_bool("passthrough").unwrap() { + return; + } let msg = &self.messages.welcome; self.show(msg.to_string()); } fn farewell(&self) { + if CONF.get_bool("passthrough").unwrap() { + return; + } let time = HumanDuration(self.started.elapsed()); let msg = LocalText::new("farewell").arg("duration", time).fmt(); self.show(msg); @@ -100,6 +113,9 @@ impl IndicatifSubcommandStatus { let bar = ProgressBar::new_spinner() .with_style(pstyle) .with_prefix(prefix); + if CONF.get_bool("passthrough").unwrap() { + bar.set_draw_target(ProgressDrawTarget::hidden()); + } let bar = ui.add(bar); let msg = style(messages.msg.to_owned()).yellow().bright().to_string(); bar.set_message(msg); @@ -111,6 +127,9 @@ impl IndicatifSubcommandStatus { } } pub fn pass(&self) { + if !CONF.get_bool("passthrough").unwrap() { + return; + } let prefix = style("✔").green().to_string(); self.set_prefix(prefix); let msg = style(self.messages.good_msg.to_owned()) @@ -120,6 +139,9 @@ impl IndicatifSubcommandStatus { finalize_bar(self.bar.clone(), msg); } pub fn fail(&self) { + if CONF.get_bool("passthrough").unwrap() { + return; + } let prefix = style("✗").red().to_string(); self.set_prefix(prefix); let msg = style(self.messages.bad_msg.to_owned()) @@ -135,6 +157,9 @@ impl SubcommandStatus for IndicatifSubcommandStatus { (status).then(|| self.pass()).unwrap_or_else(|| self.fail()); } fn error(&mut self, msg: String) { + if CONF.get_bool("passthrough").unwrap() { + return; + } self.bar.suspend(|| { eprintln!("{}", style(msg).red().dim()); }); @@ -161,7 +186,9 @@ impl std::ops::Deref for IndicatifSetupCheck { impl IndicatifSetupCheck { pub fn new(ui: &IndicatifInterface, key: &str) -> Self { let msg = LocalText::new(key).fmt(); - let bar = if CONF.get_bool("debug").unwrap() || CONF.get_bool("verbose").unwrap() { + let bar = if CONF.get_bool("passthrough").unwrap() { + ProgressBar::hidden() + } else if CONF.get_bool("debug").unwrap() || CONF.get_bool("verbose").unwrap() { let bar = ProgressBar::new_spinner() .with_prefix("-") .with_style(ProgressStyle::with_template("{msg}").unwrap()); @@ -169,13 +196,18 @@ impl IndicatifSetupCheck { } else { ProgressBar::hidden() }; - bar.set_message(msg); + if !bar.is_hidden() { + bar.set_message(msg); + } Self(bar) } } impl SetupCheck for IndicatifSetupCheck { fn pass(&self) { + if CONF.get_bool("passthrough").unwrap() { + return; + } let msg = self.message(); let yes = style(LocalText::new("setup-true").fmt()) .green() @@ -183,6 +215,9 @@ impl SetupCheck for IndicatifSetupCheck { finalize_bar(self.0.clone(), format!("{msg} {yes}")); } fn fail(&self) { + if CONF.get_bool("passthrough").unwrap() { + return; + } let msg = self.message(); let no = style(LocalText::new("setup-false").fmt()).red().to_string(); finalize_bar(self.0.clone(), format!("{msg} {no}")); @@ -206,7 +241,8 @@ impl std::ops::Deref for IndicatifJobStatus { impl IndicatifJobStatus { // pub fn new(ui: &IndicatifInterface, mut target: String) -> Self { pub fn new(subcommand: &IndicatifSubcommandStatus, target: MakeTarget) -> Self { - // Withouth this, copying the string in the terminal as a word brings a U+2069 with it + // Without this, copying the string in the terminal as a word brings a U+2069 with it + // c.f. https://github.com/XAMPPRocky/fluent-templates/issues/72 let mut printable_target: String = target.to_string(); printable_target.push(' '); let msg = style( @@ -224,6 +260,9 @@ impl IndicatifJobStatus { .with_prefix("✔") // not relevant for spinner, but we use it for our finalized mode .with_style(pstyle) .with_message(msg); + if CONF.get_bool("passthrough").unwrap() { + bar.set_draw_target(ProgressDrawTarget::hidden()); + } let bar = subcommand.progress.add(bar); bar.tick(); Self { @@ -247,11 +286,18 @@ impl JobStatus for IndicatifJobStatus { .fmt(); let start = format!("{} {start}", style(style("┄┄┄┄┄").cyan())); self.bar.println(start); + let was_hidden = self.bar.is_hidden(); + if was_hidden { + self.bar.set_draw_target(ProgressDrawTarget::stdout()); + } let lines = self.log.lines.read().unwrap(); for line in lines.iter() { let msg = style(line.line.as_str()).dim().to_string(); self.bar.println(msg); } + if was_hidden { + self.bar.set_draw_target(ProgressDrawTarget::hidden()); + } let end = LocalText::new("make-backlog-end").fmt(); let end = format!("{} {end}", style(style("┄┄┄┄┄").cyan())); self.bar.println(end);