From 52310761f67220c9c075cd847205825a720035ee Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 21 Feb 2026 23:38:32 +0900 Subject: feat(console): add structured error handling, verbosity, and suggestions Implement Phase 7.2 error handling & UX infrastructure: - Add exit_code module with MozartError, bail()/bail_silent() helpers, and Composer-compatible exit code constants (0-5, 100) - Redesign Console struct with Verbosity enum (Quiet/Normal/Verbose/ VeryVerbose/Debug), ANSI auto-detection via IsTerminal, and verbosity-gated output methods (info/verbose/debug/error) - Thread Console through all 33 command execute() signatures - Replace all std::process::exit() calls with structured MozartError returns handled in main() - Migrate eprintln\! status messages to console.info() for quiet-mode suppression - Add suggest module with Levenshtein distance and "Did you mean?" formatting for future package name suggestions Co-Authored-By: Claude Opus 4.6 --- crates/mozart/src/commands/reinstall.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'crates/mozart/src/commands/reinstall.rs') diff --git a/crates/mozart/src/commands/reinstall.rs b/crates/mozart/src/commands/reinstall.rs index 2015d62..78611b4 100644 --- a/crates/mozart/src/commands/reinstall.rs +++ b/crates/mozart/src/commands/reinstall.rs @@ -65,7 +65,11 @@ pub struct ReinstallArgs { // ─── Main entry point ───────────────────────────────────────────────────────── -pub fn execute(args: &ReinstallArgs, cli: &super::Cli) -> anyhow::Result<()> { +pub fn execute( + args: &ReinstallArgs, + cli: &super::Cli, + console: &crate::console::Console, +) -> anyhow::Result<()> { // Step 1: Resolve working directory let working_dir = match &cli.working_dir { Some(dir) => PathBuf::from(dir), @@ -167,7 +171,10 @@ pub fn execute(args: &ReinstallArgs, cli: &super::Cli) -> anyhow::Result<()> { let locked = match locked { Some(lp) => lp, None => { - eprintln!(" Warning: {} is not in the lock file; skipping.", pkg.name); + console.info(&format!( + " Warning: {} is not in the lock file; skipping.", + pkg.name + )); continue; } }; @@ -175,15 +182,18 @@ pub fn execute(args: &ReinstallArgs, cli: &super::Cli) -> anyhow::Result<()> { let dist = match &locked.dist { Some(d) => d, None => { - eprintln!( + console.info(&format!( " Warning: {} has no dist information; skipping.", locked.name - ); + )); continue; } }; - eprintln!(" - Reinstalling {} ({})", locked.name, locked.version); + console.info(&format!( + " - Reinstalling {} ({})", + locked.name, locked.version + )); // Remove vendor directory for this package let pkg_dir = vendor_dir.join(&locked.name); @@ -218,7 +228,7 @@ pub fn execute(args: &ReinstallArgs, cli: &super::Cli) -> anyhow::Result<()> { // Step 9: Regenerate autoloader unless --no-autoloader. if !args.no_autoloader { - eprintln!("Generating autoload files"); + console.info("Generating autoload files"); let dev_mode = !args.no_dev && installed.dev; let suffix = lock.content_hash.clone(); @@ -237,7 +247,7 @@ pub fn execute(args: &ReinstallArgs, cli: &super::Cli) -> anyhow::Result<()> { ignore_platform_reqs: args.ignore_platform_reqs, })?; - eprintln!("Generated autoload files"); + console.info("Generated autoload files"); } Ok(()) -- cgit v1.3.1