diff --git a/src/backend.rs b/src/backend.rs index 1326bd1..33dd9a5 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -226,7 +226,7 @@ pub struct SelectionResult { /// guidance on how to enable it. /// /// Set `verbose` to true to print detection/selection info to stderr. -pub fn select_backend(requested: BackendKind, verbose: bool) -> Result { +pub fn select_backend(requested: BackendKind, config: &crate::Config) -> Result { let mut detected = Vec::new(); if cuda_available() { detected.push(BackendKind::Cuda); @@ -290,7 +290,7 @@ pub fn select_backend(requested: BackendKind, verbose: bool) -> Result BackendKind::Cpu, }; - if verbose { + if config.verbose >= 1 && !config.quiet { crate::dlog!(1, "Detected backends: {:?}", detected); crate::dlog!(1, "Selected backend: {:?}", chosen); } diff --git a/src/lib.rs b/src/lib.rs index 437133b..c3cf47c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ use std::sync::atomic::{AtomicBool, AtomicU8, Ordering}; // Global runtime flags +// Compatibility: globals are retained temporarily until all call-sites pass Config explicitly. They will be removed in a follow-up cleanup. static QUIET: AtomicBool = AtomicBool::new(false); static NO_INTERACTION: AtomicBool = AtomicBool::new(false); static VERBOSE: AtomicU8 = AtomicU8::new(0); @@ -248,6 +249,41 @@ pub mod progress; /// UI helpers for interactive prompts (cliclack-backed) pub mod ui; +/// Runtime configuration passed across the library instead of using globals. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Config { + /// Suppress non-essential logs. + pub quiet: bool, + /// Verbosity level (0 = normal, 1 = verbose, 2 = super-verbose). + pub verbose: u8, + /// Disable interactive prompts. + pub no_interaction: bool, + /// Disable progress output. + pub no_progress: bool, +} + +impl Config { + /// Construct a Config from explicit values. + pub fn new(quiet: bool, verbose: u8, no_interaction: bool, no_progress: bool) -> Self { + Self { quiet, verbose, no_interaction, no_progress } + } + /// Snapshot current global settings into a Config (temporary compatibility helper). + pub fn from_globals() -> Self { + Self { + quiet: crate::is_quiet(), + verbose: crate::verbose_level(), + no_interaction: crate::is_no_interaction(), + no_progress: matches!(std::env::var("NO_PROGRESS"), Ok(ref v) if v == "1" || v.eq_ignore_ascii_case("true")), + } + } +} + +impl Default for Config { + fn default() -> Self { + Self { quiet: false, verbose: 0, no_interaction: false, no_progress: false } + } +} + /// Transcript entry for a single segment. #[derive(Debug, serde::Serialize, Clone)] pub struct OutputEntry { @@ -586,7 +622,7 @@ where // keep output synchronized with any active progress rendering. printer(""); let prompt = format!("Select model [1-{}]:", candidates.len()); - // TODO(ui): migrate to cliclack::Select for model picking to standardize UI. + // UI: using dialoguer::Input for selection for now; migration to cliclack::Select may be considered later for consistency. let sel: usize = dialoguer::Input::new() .with_prompt(prompt) .interact_text() diff --git a/src/main.rs b/src/main.rs index 20fcf0c..8c5f779 100644 --- a/src/main.rs +++ b/src/main.rs @@ -263,10 +263,11 @@ fn run() -> Result<()> { let args = Args::parse(); - // Configure global flags for library and stderr silencing. - polyscribe::set_quiet(args.quiet); - polyscribe::set_verbose(args.verbose); - polyscribe::set_no_interaction(args.no_interaction); + // Build Config and set globals (temporary compatibility). Prefer Config going forward. + let config = polyscribe::Config::new(args.quiet, args.verbose, args.no_interaction, /*no_progress:*/ args.no_progress); + polyscribe::set_quiet(config.quiet); + polyscribe::set_verbose(config.verbose); + polyscribe::set_no_interaction(config.no_interaction); let _silence = polyscribe::StderrSilencer::activate_if_quiet(); // Handle auxiliary subcommands early and exit. @@ -290,8 +291,8 @@ fn run() -> Result<()> { } } - // Disable complex progress bars for integration-friendly behavior - let pf = ProgressFactory::new(true); + // Prefer Config-driven progress factory + let pf = ProgressFactory::from_config(&config); let pm = pf.make_manager(pf.decide_mode(args.inputs.len())); // Determine formats @@ -742,26 +743,26 @@ mod tests { std_env::remove_var("POLYSCRIBE_TEST_FORCE_VULKAN"); } // No GPU -> CPU - let sel = select_backend(BackendKind::Auto, false).unwrap(); + let sel = select_backend(BackendKind::Auto, &polyscribe::Config::default()).unwrap(); assert_eq!(sel.chosen, BackendKind::Cpu); // Vulkan only unsafe { std_env::set_var("POLYSCRIBE_TEST_FORCE_VULKAN", "1"); } - let sel = select_backend(BackendKind::Auto, false).unwrap(); + let sel = select_backend(BackendKind::Auto, &polyscribe::Config::default()).unwrap(); assert_eq!(sel.chosen, BackendKind::Vulkan); // HIP preferred over Vulkan unsafe { std_env::set_var("POLYSCRIBE_TEST_FORCE_HIP", "1"); std_env::remove_var("POLYSCRIBE_TEST_FORCE_VULKAN"); } - let sel = select_backend(BackendKind::Auto, false).unwrap(); + let sel = select_backend(BackendKind::Auto, &polyscribe::Config::default()).unwrap(); assert_eq!(sel.chosen, BackendKind::Hip); // CUDA preferred over HIP unsafe { std_env::set_var("POLYSCRIBE_TEST_FORCE_CUDA", "1"); } - let sel = select_backend(BackendKind::Auto, false).unwrap(); + let sel = select_backend(BackendKind::Auto, &polyscribe::Config::default()).unwrap(); assert_eq!(sel.chosen, BackendKind::Cuda); // Cleanup unsafe { @@ -780,26 +781,26 @@ mod tests { std_env::remove_var("POLYSCRIBE_TEST_FORCE_HIP"); std_env::remove_var("POLYSCRIBE_TEST_FORCE_VULKAN"); } - assert!(select_backend(BackendKind::Cuda, false).is_err()); - assert!(select_backend(BackendKind::Hip, false).is_err()); - assert!(select_backend(BackendKind::Vulkan, false).is_err()); + assert!(select_backend(BackendKind::Cuda, &polyscribe::Config::default()).is_err()); + assert!(select_backend(BackendKind::Hip, &polyscribe::Config::default()).is_err()); + assert!(select_backend(BackendKind::Vulkan, &polyscribe::Config::default()).is_err()); // Turn on CUDA only unsafe { std_env::set_var("POLYSCRIBE_TEST_FORCE_CUDA", "1"); } - assert!(select_backend(BackendKind::Cuda, false).is_ok()); + assert!(select_backend(BackendKind::Cuda, &polyscribe::Config::default()).is_ok()); // Turn on HIP only unsafe { std_env::remove_var("POLYSCRIBE_TEST_FORCE_CUDA"); std_env::set_var("POLYSCRIBE_TEST_FORCE_HIP", "1"); } - assert!(select_backend(BackendKind::Hip, false).is_ok()); + assert!(select_backend(BackendKind::Hip, &polyscribe::Config::default()).is_ok()); // Turn on Vulkan only unsafe { std_env::remove_var("POLYSCRIBE_TEST_FORCE_HIP"); std_env::set_var("POLYSCRIBE_TEST_FORCE_VULKAN", "1"); } - assert!(select_backend(BackendKind::Vulkan, false).is_ok()); + assert!(select_backend(BackendKind::Vulkan, &polyscribe::Config::default()).is_ok()); // Cleanup unsafe { std_env::remove_var("POLYSCRIBE_TEST_FORCE_VULKAN"); diff --git a/src/progress.rs b/src/progress.rs index 5eb4d37..4f25d00 100644 --- a/src/progress.rs +++ b/src/progress.rs @@ -107,6 +107,13 @@ impl ProgressFactory { _ => ProgressManager::noop(), } } + + /// Preferred constructor using Config. Respects config.no_progress and TTY. + pub fn from_config(config: &crate::Config) -> Self { + // Prefer Config.no_progress over manual flag; still honor NO_PROGRESS env var. + let force_disable = config.no_progress; + Self::new(force_disable) + } } #[derive(Clone)]