From f83a556078f453e33619b52148a30575c1aa273a Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Wed, 13 Dec 2023 15:22:43 -0600 Subject: [PATCH] refactor: simplified stdout/stderr mocking in tests (#1163) --- .markdown-link-check.json | 6 +- src/cli/activate.rs | 5 +- src/cli/alias/get.rs | 5 +- src/cli/alias/ls.rs | 8 +-- src/cli/alias/mod.rs | 15 ++-- src/cli/alias/set.rs | 3 +- src/cli/alias/unset.rs | 3 +- src/cli/asdf.rs | 22 +++--- src/cli/bin_paths.rs | 6 +- src/cli/cache/clear.rs | 7 +- src/cli/cache/mod.rs | 11 ++- src/cli/completion.rs | 5 +- src/cli/current.rs | 20 ++---- src/cli/deactivate.rs | 8 +-- src/cli/direnv/activate.rs | 4 +- src/cli/direnv/envrc.rs | 6 +- src/cli/direnv/exec.rs | 6 +- src/cli/direnv/mod.rs | 13 ++-- src/cli/doctor.rs | 32 ++++----- src/cli/env.rs | 16 ++--- src/cli/env_vars.rs | 5 +- src/cli/exec.rs | 4 +- src/cli/global.rs | 4 +- src/cli/hook_env.rs | 16 ++--- src/cli/implode.rs | 6 +- src/cli/install.rs | 4 +- src/cli/latest.rs | 8 +-- src/cli/link.rs | 4 +- src/cli/local.rs | 16 ++--- src/cli/ls.rs | 30 ++++---- src/cli/ls_remote.rs | 16 ++--- src/cli/mod.rs | 110 +++++++++++++++--------------- src/cli/outdated.rs | 9 +-- src/cli/plugins/install.rs | 4 +- src/cli/plugins/link.rs | 4 +- src/cli/plugins/ls.rs | 16 ++--- src/cli/plugins/ls_remote.rs | 5 +- src/cli/plugins/mod.rs | 19 +++--- src/cli/plugins/uninstall.rs | 4 +- src/cli/plugins/update.rs | 6 +- src/cli/prune.rs | 4 +- src/cli/render_completion.rs | 5 +- src/cli/render_help.rs | 3 +- src/cli/render_mangen.rs | 3 +- src/cli/reshim.rs | 4 +- src/cli/self_update.rs | 8 +-- src/cli/settings/get.rs | 5 +- src/cli/settings/ls.rs | 5 +- src/cli/settings/mod.rs | 15 ++-- src/cli/settings/set.rs | 3 +- src/cli/settings/unset.rs | 3 +- src/cli/shell.rs | 5 +- src/cli/sync/mod.rs | 11 ++- src/cli/sync/node.rs | 21 +++--- src/cli/sync/python.rs | 6 +- src/cli/trust.rs | 7 +- src/cli/uninstall.rs | 4 +- src/cli/upgrade.rs | 12 ++-- src/cli/use.rs | 5 +- src/cli/version.rs | 16 ++--- src/cli/where.rs | 6 +- src/cli/which.rs | 10 +-- src/config/config_file/mod.rs | 6 +- src/main.rs | 9 +-- src/output.rs | 124 +++++++++++++--------------------- src/shims.rs | 6 +- 66 files changed, 354 insertions(+), 443 deletions(-) diff --git a/.markdown-link-check.json b/.markdown-link-check.json index 60967aea0..2fc2c67da 100644 --- a/.markdown-link-check.json +++ b/.markdown-link-check.json @@ -1,7 +1,3 @@ { - "ignorePatterns": [ - { - "pattern": "^https://crates.io" - } - ] + "ignorePatterns": [{ "pattern": "^https://crates.io" }] } diff --git a/src/cli/activate.rs b/src/cli/activate.rs index 514fd889b..2dd46b511 100644 --- a/src/cli/activate.rs +++ b/src/cli/activate.rs @@ -4,7 +4,6 @@ use crate::config::Config; use crate::dirs; use crate::env::RTX_EXE; use crate::file::touch_dir; -use crate::output::Output; use crate::shell::{get_shell, ShellType}; /// Initializes rtx in the current shell @@ -46,7 +45,7 @@ pub struct Activate { } impl Activate { - pub fn run(self, _config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, _config: Config) -> Result<()> { let shell = get_shell(self.shell_type.or(self.shell)) .expect("no shell provided, use `--shell=zsh`"); @@ -54,7 +53,7 @@ impl Activate { let _ = touch_dir(&dirs::DATA); let output = shell.activate(&RTX_EXE, self.status); - out.stdout.write(output); + rtxprint!("{output}"); Ok(()) } diff --git a/src/cli/alias/get.rs b/src/cli/alias/get.rs index 3640f4b00..ee505da5e 100644 --- a/src/cli/alias/get.rs +++ b/src/cli/alias/get.rs @@ -1,7 +1,6 @@ use color_eyre::eyre::{eyre, Result}; use crate::config::Config; -use crate::output::Output; /// Show an alias for a plugin /// @@ -17,10 +16,10 @@ pub struct AliasGet { } impl AliasGet { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { match config.get_all_aliases().get(&self.plugin) { Some(plugin) => match plugin.get(&self.alias) { - Some(alias) => Ok(rtxprintln!(out, "{}", alias)), + Some(alias) => Ok(rtxprintln!("{}", alias)), None => Err(eyre!("Unknown alias: {}", &self.alias)), }, None => Err(eyre!("Unknown plugin: {}", &self.plugin)), diff --git a/src/cli/alias/ls.rs b/src/cli/alias/ls.rs index 88e0589f5..fae6e7349 100644 --- a/src/cli/alias/ls.rs +++ b/src/cli/alias/ls.rs @@ -1,7 +1,7 @@ use color_eyre::eyre::Result; use crate::config::Config; -use crate::output::Output; + use crate::plugins::PluginName; /// List aliases @@ -21,7 +21,7 @@ pub struct AliasLs { } impl AliasLs { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { for (plugin_name, aliases) in config.get_all_aliases() { if let Some(plugin) = &self.plugin { if plugin_name != plugin { @@ -35,9 +35,9 @@ impl AliasLs { continue; } if self.plugin.is_some() { - rtxprintln!(out, "{:20} {}", from, to); + rtxprintln!("{:20} {}", from, to); } else { - rtxprintln!(out, "{:20} {:20} {}", plugin_name, from, to); + rtxprintln!("{:20} {:20} {}", plugin_name, from, to); } } } diff --git a/src/cli/alias/mod.rs b/src/cli/alias/mod.rs index 3a64a6771..2d07861d8 100644 --- a/src/cli/alias/mod.rs +++ b/src/cli/alias/mod.rs @@ -2,7 +2,6 @@ use clap::Subcommand; use color_eyre::eyre::Result; use crate::config::Config; -use crate::output::Output; use crate::plugins::PluginName; mod get; @@ -30,22 +29,22 @@ enum Commands { } impl Commands { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { match self { - Self::Get(cmd) => cmd.run(config, out), - Self::Ls(cmd) => cmd.run(config, out), - Self::Set(cmd) => cmd.run(config, out), - Self::Unset(cmd) => cmd.run(config, out), + Self::Get(cmd) => cmd.run(config), + Self::Ls(cmd) => cmd.run(config), + Self::Set(cmd) => cmd.run(config), + Self::Unset(cmd) => cmd.run(config), } } } impl Alias { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let cmd = self.command.unwrap_or(Commands::Ls(ls::AliasLs { plugin: self.plugin, })); - cmd.run(config, out) + cmd.run(config) } } diff --git a/src/cli/alias/set.rs b/src/cli/alias/set.rs index 5ce37dbf7..c24e43044 100644 --- a/src/cli/alias/set.rs +++ b/src/cli/alias/set.rs @@ -2,7 +2,6 @@ use color_eyre::eyre::Result; use crate::config::config_file::ConfigFile; use crate::config::Config; -use crate::output::Output; /// Add/update an alias for a plugin /// @@ -19,7 +18,7 @@ pub struct AliasSet { } impl AliasSet { - pub fn run(self, mut config: Config, _out: &mut Output) -> Result<()> { + pub fn run(self, mut config: Config) -> Result<()> { config .global_config .set_alias(&self.plugin, &self.alias, &self.value); diff --git a/src/cli/alias/unset.rs b/src/cli/alias/unset.rs index 10373368e..777b3b221 100644 --- a/src/cli/alias/unset.rs +++ b/src/cli/alias/unset.rs @@ -2,7 +2,6 @@ use color_eyre::eyre::Result; use crate::config::config_file::ConfigFile; use crate::config::Config; -use crate::output::Output; /// Clears an alias for a plugin /// @@ -17,7 +16,7 @@ pub struct AliasUnset { } impl AliasUnset { - pub fn run(self, mut config: Config, _out: &mut Output) -> Result<()> { + pub fn run(self, mut config: Config) -> Result<()> { config.global_config.remove_alias(&self.plugin, &self.alias); config.global_config.save() } diff --git a/src/cli/asdf.rs b/src/cli/asdf.rs index 06ec017dd..a7a650764 100644 --- a/src/cli/asdf.rs +++ b/src/cli/asdf.rs @@ -4,7 +4,7 @@ use itertools::Itertools; use crate::cli::Cli; use crate::config::Config; -use crate::output::Output; + use crate::toolset::ToolsetBuilder; /// [internal] simulates asdf for plugins that call "asdf" internally @@ -17,32 +17,32 @@ pub struct Asdf { } impl Asdf { - pub fn run(mut self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(mut self, config: Config) -> Result<()> { let mut args = vec![String::from("rtx")]; args.append(&mut self.args); match args.get(1).map(|s| s.as_str()) { - Some("reshim") => Cli::new().run(config, &args, out), - Some("list") => list_versions(config, out, &args), + Some("reshim") => Cli::new().run(config, &args), + Some("list") => list_versions(config, &args), Some("install") => { if args.len() == 4 { let version = args.pop().unwrap(); args[2] = format!("{}@{}", args[2], version); } - Cli::new().run(config, &args, out) + Cli::new().run(config, &args) } - _ => Cli::new().run(config, &args, out), + _ => Cli::new().run(config, &args), } } } -fn list_versions(config: Config, out: &mut Output, args: &Vec) -> Result<()> { +fn list_versions(config: Config, args: &Vec) -> Result<()> { if args[2] == "all" { let mut new_args: Vec = vec!["rtx".into(), "ls-remote".into()]; if args.len() >= 3 { new_args.push(args[3].clone()); } - return Cli::new().run(config, &new_args, out); + return Cli::new().run(config, &new_args); } let ts = ToolsetBuilder::new().build(&config)?; let mut versions = ts.list_installed_versions(&config)?; @@ -53,16 +53,16 @@ fn list_versions(config: Config, out: &mut Output, args: &Vec) -> Result if let Some(plugin) = plugin { versions.retain(|(_, v)| v.plugin_name.as_str() == plugin); for (_, version) in versions { - rtxprintln!(out, "{}", version.version); + rtxprintln!("{}", version.version); } } else { for (plugin, versions) in &versions .into_iter() .group_by(|(_, v)| v.plugin_name.to_string()) { - rtxprintln!(out, "{}", plugin); + rtxprintln!("{}", plugin); for (_, tv) in versions { - rtxprintln!(out, " {}", tv.version); + rtxprintln!(" {}", tv.version); } } } diff --git a/src/cli/bin_paths.rs b/src/cli/bin_paths.rs index c05327f05..2d124c8e7 100644 --- a/src/cli/bin_paths.rs +++ b/src/cli/bin_paths.rs @@ -1,7 +1,7 @@ use color_eyre::eyre::Result; use crate::config::Config; -use crate::output::Output; + use crate::toolset::ToolsetBuilder; /// List all the active runtime bin paths @@ -10,10 +10,10 @@ use crate::toolset::ToolsetBuilder; pub struct BinPaths {} impl BinPaths { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let ts = ToolsetBuilder::new().build(&config)?; for p in ts.list_paths(&config) { - rtxprintln!(out, "{}", p.display()); + rtxprintln!("{}", p.display()); } Ok(()) } diff --git a/src/cli/cache/clear.rs b/src/cli/cache/clear.rs index 5906d6b7d..06d414683 100644 --- a/src/cli/cache/clear.rs +++ b/src/cli/cache/clear.rs @@ -3,7 +3,6 @@ use color_eyre::eyre::Result; use crate::config::Config; use crate::dirs::CACHE; use crate::file::{display_path, remove_all}; -use crate::output::Output; /// Deletes all cache files in rtx #[derive(Debug, clap::Args)] @@ -15,7 +14,7 @@ pub struct CacheClear { } impl CacheClear { - pub fn run(self, _config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, _config: Config) -> Result<()> { let cache_dirs = match &self.plugin { Some(plugins) => plugins.iter().map(|p| CACHE.join(p)).collect(), None => vec![CACHE.to_path_buf()], @@ -27,8 +26,8 @@ impl CacheClear { } } match &self.plugin { - Some(plugins) => rtxstatusln!(out, "cache cleared for {}", plugins.join(", ")), - None => rtxstatusln!(out, "cache cleared"), + Some(plugins) => rtxstatusln!("cache cleared for {}", plugins.join(", ")), + None => rtxstatusln!("cache cleared"), } Ok(()) } diff --git a/src/cli/cache/mod.rs b/src/cli/cache/mod.rs index 06bffdea7..10339f440 100644 --- a/src/cli/cache/mod.rs +++ b/src/cli/cache/mod.rs @@ -3,7 +3,6 @@ use color_eyre::eyre::Result; use crate::config::Config; use crate::env; -use crate::output::Output; mod clear; @@ -23,20 +22,20 @@ enum Commands { } impl Commands { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { match self { - Self::Clear(cmd) => cmd.run(config, out), + Self::Clear(cmd) => cmd.run(config), } } } impl Cache { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { match self.command { - Some(cmd) => cmd.run(config, out), + Some(cmd) => cmd.run(config), None => { // just show the cache dir - rtxprintln!(out, "{}", env::RTX_CACHE_DIR.display()); + rtxprintln!("{}", env::RTX_CACHE_DIR.display()); Ok(()) } } diff --git a/src/cli/completion.rs b/src/cli/completion.rs index a13a16dee..3d449a121 100644 --- a/src/cli/completion.rs +++ b/src/cli/completion.rs @@ -4,7 +4,6 @@ use color_eyre::eyre::Result; use std::fmt::Display; use crate::config::Config; -use crate::output::Output; /// Generate shell completions #[derive(Debug, clap::Args)] @@ -20,13 +19,13 @@ pub struct Completion { } impl Completion { - pub fn run(self, _config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, _config: Config) -> Result<()> { let c = match self.shell.or(self.shell_type).unwrap() { Shell::Bash => include_str!("../../completions/rtx.bash"), Shell::Fish => include_str!("../../completions/rtx.fish"), Shell::Zsh => include_str!("../../completions/_rtx"), }; - rtxprintln!(out, "{}", c.trim()); + rtxprintln!("{}", c.trim()); Ok(()) } diff --git a/src/cli/current.rs b/src/cli/current.rs index 92fc67b4c..2b95c2433 100644 --- a/src/cli/current.rs +++ b/src/cli/current.rs @@ -2,7 +2,7 @@ use color_eyre::eyre::Result; use std::sync::Arc; use crate::config::Config; -use crate::output::Output; + use crate::plugins::{unalias_plugin, Plugin}; use crate::toolset::{Toolset, ToolsetBuilder}; @@ -20,7 +20,7 @@ pub struct Current { } impl Current { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let ts = ToolsetBuilder::new().build(&config)?; match &self.plugin { Some(plugin_name) => { @@ -29,19 +29,13 @@ impl Current { if !plugin.is_installed() { bail!("Plugin {} is not installed", plugin_name); } - self.one(&config, ts, out, plugin.clone()) + self.one(&config, ts, plugin.clone()) } - None => self.all(&config, ts, out), + None => self.all(&config, ts), } } - fn one( - &self, - config: &Config, - ts: Toolset, - out: &mut Output, - tool: Arc, - ) -> Result<()> { + fn one(&self, config: &Config, ts: Toolset, tool: Arc) -> Result<()> { if !tool.is_installed() { warn!("Plugin {} is not installed", tool.name()); return Ok(()); @@ -53,7 +47,6 @@ impl Current { { Some((_, versions)) => { rtxprintln!( - out, "{}", versions .iter() @@ -69,7 +62,7 @@ impl Current { Ok(()) } - fn all(&self, config: &Config, ts: Toolset, out: &mut Output) -> Result<()> { + fn all(&self, config: &Config, ts: Toolset) -> Result<()> { for (plugin, versions) in ts.list_versions_by_plugin(config) { if versions.is_empty() { continue; @@ -84,7 +77,6 @@ impl Current { } } rtxprintln!( - out, "{} {}", &plugin.name(), versions diff --git a/src/cli/deactivate.rs b/src/cli/deactivate.rs index b0bdc9caf..d9eb45c61 100644 --- a/src/cli/deactivate.rs +++ b/src/cli/deactivate.rs @@ -3,7 +3,7 @@ use console::style; use crate::config::Config; use crate::hook_env; -use crate::output::Output; + use crate::shell::get_shell; /// Disable rtx for current shell session @@ -14,16 +14,16 @@ use crate::shell::get_shell; pub struct Deactivate {} impl Deactivate { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { if !config.is_activated() { err_inactive()?; } let shell = get_shell(None).expect("no shell detected"); - out.stdout.write(hook_env::clear_old_env(&*shell)); + rtxprint!("{}", hook_env::clear_old_env(&*shell)); let output = shell.deactivate(); - out.stdout.write(output); + rtxprint!("{output}"); Ok(()) } diff --git a/src/cli/direnv/activate.rs b/src/cli/direnv/activate.rs index 621037843..4b0ccecde 100644 --- a/src/cli/direnv/activate.rs +++ b/src/cli/direnv/activate.rs @@ -1,7 +1,6 @@ use color_eyre::eyre::Result; use crate::config::Config; -use crate::output::Output; /// Output direnv function to use rtx inside direnv /// @@ -15,9 +14,8 @@ use crate::output::Output; pub struct DirenvActivate {} impl DirenvActivate { - pub fn run(self, _config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, _config: Config) -> Result<()> { rtxprintln!( - out, // source_env "$(rtx direnv envrc "$@")" indoc! {r#" ### Do not edit. This was autogenerated by 'rtx direnv' ### diff --git a/src/cli/direnv/envrc.rs b/src/cli/direnv/envrc.rs index 651cbf5ae..48a512a88 100644 --- a/src/cli/direnv/envrc.rs +++ b/src/cli/direnv/envrc.rs @@ -6,7 +6,7 @@ use color_eyre::eyre::Result; use crate::config::Config; use crate::hash::hash_to_str; -use crate::output::Output; + use crate::toolset::ToolsetBuilder; use crate::{dirs, env}; @@ -17,7 +17,7 @@ use crate::{dirs, env}; pub struct Envrc {} impl Envrc { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let ts = ToolsetBuilder::new().build(&config)?; let envrc_path = env::RTX_TMP_DIR @@ -51,7 +51,7 @@ impl Envrc { writeln!(file, "PATH_add {}", path.to_string_lossy())?; } - rtxprintln!(out, "{}", envrc_path.to_string_lossy()); + rtxprintln!("{}", envrc_path.to_string_lossy()); Ok(()) } } diff --git a/src/cli/direnv/exec.rs b/src/cli/direnv/exec.rs index 70d3e4cfe..e7b9f5d03 100644 --- a/src/cli/direnv/exec.rs +++ b/src/cli/direnv/exec.rs @@ -4,7 +4,7 @@ use eyre::WrapErr; use serde_derive::Deserialize; use crate::config::Config; -use crate::output::Output; + use crate::toolset::ToolsetBuilder; /// [internal] This is an internal command that writes an envrc file @@ -20,7 +20,7 @@ struct DirenvWatches { } impl DirenvExec { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let ts = ToolsetBuilder::new().build(&config)?; let mut cmd = env_cmd(); @@ -35,7 +35,7 @@ impl DirenvExec { let w: DirenvWatches = serde_json::from_str(&json)?; cmd = cmd.env("DIRENV_WATCHES", w.watches); - rtxprint!(out, "{}", cmd.read()?); + rtxprint!("{}", cmd.read()?); Ok(()) } } diff --git a/src/cli/direnv/mod.rs b/src/cli/direnv/mod.rs index 3911f85ab..681fe3f33 100644 --- a/src/cli/direnv/mod.rs +++ b/src/cli/direnv/mod.rs @@ -2,7 +2,6 @@ use clap::Subcommand; use color_eyre::eyre::Result; use crate::config::Config; -use crate::output::Output; mod activate; mod envrc; @@ -30,20 +29,20 @@ enum Commands { } impl Commands { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { match self { - Self::Activate(cmd) => cmd.run(config, out), - Self::Envrc(cmd) => cmd.run(config, out), - Self::Exec(cmd) => cmd.run(config, out), + Self::Activate(cmd) => cmd.run(config), + Self::Envrc(cmd) => cmd.run(config), + Self::Exec(cmd) => cmd.run(config), } } } impl Direnv { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let cmd = self .command .unwrap_or(Commands::Activate(activate::DirenvActivate {})); - cmd.run(config, out) + cmd.run(config) } } diff --git a/src/cli/doctor.rs b/src/cli/doctor.rs index a1bfbee51..aed61ac0e 100644 --- a/src/cli/doctor.rs +++ b/src/cli/doctor.rs @@ -9,7 +9,7 @@ use crate::build_time::built_info; use crate::cli::version::VERSION; use crate::config::Config; use crate::git::Git; -use crate::output::Output; + use crate::plugins::PluginType; use crate::shell::ShellType; use crate::toolset::ToolsetBuilder; @@ -22,27 +22,21 @@ use crate::{duration, env}; pub struct Doctor {} impl Doctor { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let ts = ToolsetBuilder::new().build(&config)?; - rtxprintln!(out, "{}", rtx_version()); - rtxprintln!(out, "{}", build_info()); - rtxprintln!(out, "{}", shell()); - rtxprintln!(out, "{}", rtx_data_dir()); - rtxprintln!(out, "{}", rtx_env_vars()); + rtxprintln!("{}", rtx_version()); + rtxprintln!("{}", build_info()); + rtxprintln!("{}", shell()); + rtxprintln!("{}", rtx_data_dir()); + rtxprintln!("{}", rtx_env_vars()); rtxprintln!( - out, "{}\n{}\n", style("settings:").bold(), indent(config.settings.to_string()) ); - rtxprintln!(out, "{}", render_config_files(&config)); - rtxprintln!(out, "{}", render_plugins(&config)); - rtxprintln!( - out, - "{}\n{}\n", - style("toolset:").bold(), - indent(ts.to_string()) - ); + rtxprintln!("{}", render_config_files(&config)); + rtxprintln!("{}", render_plugins(&config)); + rtxprintln!("{}\n{}\n", style("toolset:").bold(), indent(ts.to_string())); let mut checks = Vec::new(); for plugin in config.list_plugins() { @@ -73,13 +67,13 @@ impl Doctor { } if checks.is_empty() { - rtxprintln!(out, "No problems found"); + rtxprintln!("No problems found"); } else { let checks_plural = if checks.len() == 1 { "" } else { "s" }; let summary = format!("{} problem{checks_plural} found:", checks.len()); - rtxprintln!(out, "{}", style(summary).red().bold()); + rtxprintln!("{}", style(summary).red().bold()); for check in &checks { - rtxprintln!(out, "{}\n", check); + rtxprintln!("{}\n", check); } exit(1); } diff --git a/src/cli/env.rs b/src/cli/env.rs index 2d3f7b235..b48deb182 100644 --- a/src/cli/env.rs +++ b/src/cli/env.rs @@ -2,7 +2,7 @@ use color_eyre::eyre::Result; use crate::cli::args::tool::{ToolArg, ToolArgParser}; use crate::config::Config; -use crate::output::Output; + use crate::shell::{get_shell, ShellType}; use crate::toolset::{Toolset, ToolsetBuilder}; @@ -27,30 +27,30 @@ pub struct Env { } impl Env { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let mut ts = ToolsetBuilder::new().with_args(&self.tool).build(&config)?; ts.install_arg_versions(&config)?; if self.json { - self.output_json(config, out, ts) + self.output_json(config, ts) } else { - self.output_shell(config, out, ts) + self.output_shell(config, ts) } } - fn output_json(&self, config: Config, out: &mut Output, ts: Toolset) -> Result<()> { + fn output_json(&self, config: Config, ts: Toolset) -> Result<()> { let env = ts.env_with_path(&config); - rtxprintln!(out, "{}", serde_json::to_string_pretty(&env)?); + rtxprintln!("{}", serde_json::to_string_pretty(&env)?); Ok(()) } - fn output_shell(&self, config: Config, out: &mut Output, ts: Toolset) -> Result<()> { + fn output_shell(&self, config: Config, ts: Toolset) -> Result<()> { let default_shell = get_shell(Some(ShellType::Bash)).unwrap(); let shell = get_shell(self.shell).unwrap_or(default_shell); for (k, v) in ts.env_with_path(&config) { let k = k.to_string(); let v = v.to_string(); - rtxprint!(out, "{}", shell.set_env(&k, &v)); + rtxprint!("{}", shell.set_env(&k, &v)); } Ok(()) } diff --git a/src/cli/env_vars.rs b/src/cli/env_vars.rs index 8a216b6e5..e1c5372e1 100644 --- a/src/cli/env_vars.rs +++ b/src/cli/env_vars.rs @@ -6,7 +6,6 @@ use crate::config::Config; use crate::dirs; use crate::env::RTX_DEFAULT_CONFIG_FILENAME; use crate::file::display_path; -use crate::output::Output; use super::args::env_var::{EnvVarArg, EnvVarArgParser}; @@ -36,11 +35,11 @@ pub struct EnvVars { } impl EnvVars { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { if self.remove.is_none() && self.env_vars.is_none() { for (key, value) in &config.env { let source = config.env_sources.get(key).unwrap(); - rtxprintln!(out, "{key}={value} {}", display_path(source)); + rtxprintln!("{key}={value} {}", display_path(source)); } return Ok(()); } diff --git a/src/cli/exec.rs b/src/cli/exec.rs index ba9cb3583..6dfbed2ab 100644 --- a/src/cli/exec.rs +++ b/src/cli/exec.rs @@ -11,7 +11,7 @@ use crate::cli::args::tool::{ToolArg, ToolArgParser}; use crate::cmd; use crate::config::Config; use crate::env; -use crate::output::Output; + use crate::toolset::ToolsetBuilder; /// Execute a command with tool(s) set @@ -45,7 +45,7 @@ pub struct Exec { } impl Exec { - pub fn run(self, config: Config, _out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let mut ts = ToolsetBuilder::new().with_args(&self.tool).build(&config)?; ts.install_arg_versions(&config)?; diff --git a/src/cli/global.rs b/src/cli/global.rs index 60decf3ec..87042e439 100644 --- a/src/cli/global.rs +++ b/src/cli/global.rs @@ -5,7 +5,6 @@ use color_eyre::eyre::Result; use crate::cli::args::tool::{ToolArg, ToolArgParser}; use crate::cli::local::local; use crate::config::Config; -use crate::output::Output; use crate::plugins::PluginName; use crate::{dirs, env}; @@ -49,10 +48,9 @@ pub struct Global { } impl Global { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { local( config, - out, &global_file(), self.tool, self.remove, diff --git a/src/cli/hook_env.rs b/src/cli/hook_env.rs index 7df80c107..fdd023107 100644 --- a/src/cli/hook_env.rs +++ b/src/cli/hook_env.rs @@ -14,7 +14,7 @@ use crate::config::Settings; use crate::direnv::DirenvDiff; use crate::env::__RTX_DIFF; use crate::env_diff::{EnvDiff, EnvDiffOperation}; -use crate::output::Output; + use crate::shell::{get_shell, ShellType}; use crate::toolset::{Toolset, ToolsetBuilder}; use crate::{env, hook_env}; @@ -33,10 +33,10 @@ pub struct HookEnv { } impl HookEnv { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let ts = ToolsetBuilder::new().build(&config)?; let shell = get_shell(self.shell).expect("no shell provided, use `--shell=zsh`"); - out.stdout.write(hook_env::clear_old_env(&*shell)); + rtxprint!("{}", hook_env::clear_old_env(&*shell)); let mut env = ts.env(&config); let env_path = env.remove("PATH"); let mut diff = EnvDiff::new(&env::PRISTINE_ENV, env); @@ -54,15 +54,15 @@ impl HookEnv { patches.push(self.build_watch_operation(&config)?); let output = hook_env::build_env_commands(&*shell, &patches); - out.stdout.write(output); + rtxprint!("{output}"); if self.status { - self.display_status(&config, &ts, out); + self.display_status(&config, &ts); } Ok(()) } - fn display_status(&self, config: &Config, ts: &Toolset, out: &mut Output) { + fn display_status(&self, config: &Config, ts: &Toolset) { let installed_versions = ts .list_current_installed_versions(config) .into_iter() @@ -76,12 +76,12 @@ impl HookEnv { } as usize; let w = max(w, 40); let status = installed_versions.into_iter().rev().join(" "); - rtxstatusln!(out, "{}", truncate_str(&status, w - 4, "...")); + rtxstatusln!("{}", truncate_str(&status, w - 4, "...")); } let env_diff = EnvDiff::new(&env::PRISTINE_ENV, config.env.clone()).to_patches(); if !env_diff.is_empty() { let env_diff = env_diff.into_iter().map(patch_to_status).join(" "); - rtxstatusln!(out, "{env_diff}"); + rtxstatusln!("{env_diff}"); } } diff --git a/src/cli/implode.rs b/src/cli/implode.rs index a52af9d6b..6a62a35e8 100644 --- a/src/cli/implode.rs +++ b/src/cli/implode.rs @@ -4,7 +4,7 @@ use color_eyre::eyre::Result; use crate::config::Config; use crate::file::remove_all; -use crate::output::Output; + use crate::ui::prompt; use crate::{dirs, env, file}; @@ -24,14 +24,14 @@ pub struct Implode { } impl Implode { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let mut files = vec![&*dirs::DATA, &*dirs::CACHE, &*env::RTX_EXE]; if self.config { files.push(&*dirs::CONFIG); } for f in files.into_iter().filter(|d| d.exists()) { if self.dry_run { - rtxprintln!(out, "rm -rf {}", f.display()); + rtxprintln!("rm -rf {}", f.display()); } if self.confirm_remove(&config, f)? { diff --git a/src/cli/install.rs b/src/cli/install.rs index a6bb7ebc1..b77419041 100644 --- a/src/cli/install.rs +++ b/src/cli/install.rs @@ -2,7 +2,7 @@ use color_eyre::eyre::Result; use crate::cli::args::tool::{ToolArg, ToolArgParser}; use crate::config::Config; -use crate::output::Output; + use crate::toolset::{ ToolVersion, ToolVersionOptions, ToolVersionRequest, Toolset, ToolsetBuilder, }; @@ -34,7 +34,7 @@ pub struct Install { } impl Install { - pub fn run(self, config: Config, _out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { match &self.tool { Some(runtime) => self.install_runtimes(config, runtime)?, None => self.install_missing_runtimes(config)?, diff --git a/src/cli/latest.rs b/src/cli/latest.rs index 1f8d01ff7..edeaeb548 100644 --- a/src/cli/latest.rs +++ b/src/cli/latest.rs @@ -3,7 +3,7 @@ use console::style; use crate::cli::args::tool::{ToolArg, ToolArgParser}; use crate::config::Config; -use crate::output::Output; + use crate::toolset::ToolVersionRequest; /// Gets the latest available version for a plugin @@ -26,7 +26,7 @@ pub struct Latest { } impl Latest { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let mut prefix = match self.tool.tvr { None => self.asdf_version, Some(ToolVersionRequest::Version(_, version)) => Some(version), @@ -48,7 +48,7 @@ impl Latest { plugin.latest_version(&config.settings, prefix)? }; if let Some(version) = latest_version { - rtxprintln!(out, "{}", version); + rtxprintln!("{}", version); } Ok(()) } @@ -101,6 +101,6 @@ mod tests { #[test] fn test_latest_alias() { let stdout = assert_cli!("latest", "tiny@lts"); - assert_str_eq!(stdout, "3.1.0\n"); + assert_str_eq!(stdout, "3.1.0"); } } diff --git a/src/cli/link.rs b/src/cli/link.rs index e95721196..31468931b 100644 --- a/src/cli/link.rs +++ b/src/cli/link.rs @@ -8,7 +8,7 @@ use path_absolutize::Absolutize; use crate::cli::args::tool::{ToolArg, ToolArgParser}; use crate::config::Config; use crate::file::{make_symlink, remove_all}; -use crate::output::Output; + use crate::{dirs, file}; /// Symlinks a tool version into rtx @@ -33,7 +33,7 @@ pub struct Link { } impl Link { - pub fn run(self, config: Config, _out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let version = match self.tool.tvr { Some(ref tvr) => tvr.version(), None => { diff --git a/src/cli/local.rs b/src/cli/local.rs index 89f2e3456..d2162affd 100644 --- a/src/cli/local.rs +++ b/src/cli/local.rs @@ -8,7 +8,7 @@ use crate::cli::args::tool::{ToolArg, ToolArgParser}; use crate::config::{config_file, Config}; use crate::env::{RTX_DEFAULT_CONFIG_FILENAME, RTX_DEFAULT_TOOL_VERSIONS_FILENAME}; use crate::file::display_path; -use crate::output::Output; + use crate::plugins::PluginName; use crate::{dirs, env, file}; @@ -54,7 +54,7 @@ pub struct Local { } impl Local { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let path = if self.parent { get_parent_path()? } else { @@ -62,7 +62,6 @@ impl Local { }; local( config, - out, &path, self.tool, self.remove, @@ -94,7 +93,6 @@ pub fn get_parent_path() -> Result { #[allow(clippy::too_many_arguments)] pub fn local( config: Config, - out: &mut Output, path: &Path, runtime: Vec, remove: Option>, @@ -104,7 +102,7 @@ pub fn local( ) -> Result<()> { let mut cf = config_file::parse_or_init(&config.settings, path)?; if show_path { - rtxprintln!(out, "{}", path.display()); + rtxprintln!("{}", path.display()); return Ok(()); } @@ -114,7 +112,6 @@ pub fn local( } let tools = plugins.iter().map(|r| r.to_string()).join(" "); rtxprintln!( - out, "{} {} {}", style("rtx").dim(), display_path(path), @@ -124,14 +121,13 @@ pub fn local( if !runtime.is_empty() { let runtimes = ToolArg::double_tool_condition(&runtime); - if cf.display_runtime(out, &runtimes)? { + if cf.display_runtime(&runtimes)? { return Ok(()); } let pin = pin || (config.settings.asdf_compat && !fuzzy); cf.add_runtimes(&config, &runtimes, pin)?; let tools = runtimes.iter().map(|r| r.to_string()).join(" "); rtxprintln!( - out, "{} {} {}", style("rtx").dim(), display_path(path), @@ -142,7 +138,7 @@ pub fn local( if !runtime.is_empty() || remove.is_some() { cf.save()?; } else { - rtxprint!(out, "{}", cf.dump()); + rtxprint!("{}", cf.dump()); } Ok(()) @@ -248,7 +244,7 @@ mod tests { run_test(|| { assert_cli!("local", "tiny", "2"); let stdout = assert_cli!("local", "tiny"); - assert_str_eq!(stdout, "2\n"); + assert_str_eq!(stdout, "2"); }); } diff --git a/src/cli/ls.rs b/src/cli/ls.rs index e18a8d2d4..7a27e2fa7 100644 --- a/src/cli/ls.rs +++ b/src/cli/ls.rs @@ -13,7 +13,6 @@ use versions::Versioning; use crate::config::Config; use crate::errors::Error::PluginNotInstalled; -use crate::output::Output; use crate::plugins::{unalias_plugin, Plugin, PluginName}; use crate::toolset::{ToolSource, ToolVersion, ToolsetBuilder}; @@ -59,7 +58,7 @@ pub struct Ls { } impl Ls { - pub fn run(mut self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(mut self, config: Config) -> Result<()> { self.plugin = self .plugin .clone() @@ -83,11 +82,11 @@ impl Ls { runtimes.retain(|(_, tv, _)| tv.version.starts_with(prefix)); } if self.json { - self.display_json(runtimes, out) + self.display_json(runtimes) } else if self.parseable { - self.display_parseable(runtimes, out) + self.display_parseable(runtimes) } else { - self.display_user(&config, runtimes, out) + self.display_user(&config, runtimes) } } @@ -104,7 +103,7 @@ impl Ls { Ok(()) } - fn display_json(&self, runtimes: Vec, out: &mut Output) -> Result<()> { + fn display_json(&self, runtimes: Vec) -> Result<()> { if let Some(plugin) = &self.plugin { // only runtimes for 1 plugin let runtimes: Vec = runtimes @@ -112,7 +111,7 @@ impl Ls { .filter(|(p, _, _)| plugin.eq(&p.name())) .map(|row| row.into()) .collect(); - out.stdout.writeln(serde_json::to_string_pretty(&runtimes)?); + rtxprintln!("{}", serde_json::to_string_pretty(&runtimes)?); return Ok(()); } @@ -124,11 +123,11 @@ impl Ls { let runtimes = runtimes.map(|row| row.into()).collect(); plugins.insert(plugin_name.clone(), runtimes); } - out.stdout.writeln(serde_json::to_string_pretty(&plugins)?); + rtxprintln!("{}", serde_json::to_string_pretty(&plugins)?); Ok(()) } - fn display_parseable(&self, runtimes: Vec, out: &mut Output) -> Result<()> { + fn display_parseable(&self, runtimes: Vec) -> Result<()> { warn!("The parseable output format is deprecated and will be removed in a future release."); warn!("Please use the regular output format instead which has been modified to be more easily parseable."); runtimes @@ -138,20 +137,15 @@ impl Ls { .for_each(|(_, tv)| { if self.plugin.is_some() { // only displaying 1 plugin so only show the version - rtxprintln!(out, "{}", tv.version); + rtxprintln!("{}", tv.version); } else { - rtxprintln!(out, "{} {}", tv.plugin_name, tv.version); + rtxprintln!("{} {}", tv.plugin_name, tv.version); } }); Ok(()) } - fn display_user( - &self, - config: &Config, - runtimes: Vec, - out: &mut Output, - ) -> Result<()> { + fn display_user(&self, config: &Config, runtimes: Vec) -> Result<()> { let output = runtimes .into_iter() .map(|(p, tv, source)| { @@ -204,7 +198,7 @@ impl Ls { format!("{} {}", plugin, version) } }; - rtxprintln!(out, "{}", line.trim_end()); + rtxprintln!("{}", line.trim_end()); } Ok(()) } diff --git a/src/cli/ls_remote.rs b/src/cli/ls_remote.rs index f49afb8fa..89eba68da 100644 --- a/src/cli/ls_remote.rs +++ b/src/cli/ls_remote.rs @@ -7,7 +7,7 @@ use rayon::prelude::*; use crate::cli::args::tool::ToolArg; use crate::cli::args::tool::ToolArgParser; use crate::config::Config; -use crate::output::Output; + use crate::plugins::Plugin; use crate::toolset::ToolVersionRequest; @@ -33,15 +33,15 @@ pub struct LsRemote { } impl LsRemote { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { if let Some(plugin) = self.get_plugin(&config)? { - self.run_single(config, out, plugin) + self.run_single(config, plugin) } else { - self.run_all(config, out) + self.run_all(config) } } - fn run_single(self, config: Config, out: &mut Output, plugin: Arc) -> Result<()> { + fn run_single(self, config: Config, plugin: Arc) -> Result<()> { let prefix = match &self.plugin { Some(tool_arg) => match &tool_arg.tvr { Some(ToolVersionRequest::Version(_, v)) => Some(v.clone()), @@ -60,13 +60,13 @@ impl LsRemote { }; for version in versions { - rtxprintln!(out, "{}", version); + rtxprintln!("{}", version); } Ok(()) } - fn run_all(self, config: Config, out: &mut Output) -> Result<()> { + fn run_all(self, config: Config) -> Result<()> { let versions = config .list_plugins() .into_par_iter() @@ -80,7 +80,7 @@ impl LsRemote { .collect::>(); for (plugin, versions) in versions { for v in versions { - rtxprintln!(out, "{}@{v}", plugin); + rtxprintln!("{}@{v}", plugin); } } Ok(()) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index c44d12c6f..22f6eb69f 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -3,7 +3,6 @@ use clap::{FromArgMatches, Subcommand}; use color_eyre::Result; use crate::config::Config; -use crate::output::Output; mod activate; mod alias; @@ -106,53 +105,53 @@ pub enum Commands { } impl Commands { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { match self { - Self::Activate(cmd) => cmd.run(config, out), - Self::Alias(cmd) => cmd.run(config, out), - Self::Asdf(cmd) => cmd.run(config, out), - Self::BinPaths(cmd) => cmd.run(config, out), - Self::Cache(cmd) => cmd.run(config, out), - Self::Completion(cmd) => cmd.run(config, out), - Self::Current(cmd) => cmd.run(config, out), - Self::Deactivate(cmd) => cmd.run(config, out), - Self::Direnv(cmd) => cmd.run(config, out), - Self::Doctor(cmd) => cmd.run(config, out), - Self::Env(cmd) => cmd.run(config, out), - Self::EnvVars(cmd) => cmd.run(config, out), - Self::Exec(cmd) => cmd.run(config, out), - Self::Global(cmd) => cmd.run(config, out), - Self::HookEnv(cmd) => cmd.run(config, out), - Self::Implode(cmd) => cmd.run(config, out), - Self::Install(cmd) => cmd.run(config, out), - Self::Latest(cmd) => cmd.run(config, out), - Self::Link(cmd) => cmd.run(config, out), - Self::Local(cmd) => cmd.run(config, out), - Self::Ls(cmd) => cmd.run(config, out), - Self::LsRemote(cmd) => cmd.run(config, out), - Self::Outdated(cmd) => cmd.run(config, out), - Self::Plugins(cmd) => cmd.run(config, out), - Self::Prune(cmd) => cmd.run(config, out), - Self::Reshim(cmd) => cmd.run(config, out), - Self::Settings(cmd) => cmd.run(config, out), - Self::Shell(cmd) => cmd.run(config, out), - Self::Sync(cmd) => cmd.run(config, out), - Self::Trust(cmd) => cmd.run(config, out), - Self::Uninstall(cmd) => cmd.run(config, out), - Self::Upgrade(cmd) => cmd.run(config, out), - Self::Use(cmd) => cmd.run(config, out), - Self::Version(cmd) => cmd.run(config, out), - Self::Where(cmd) => cmd.run(config, out), - Self::Which(cmd) => cmd.run(config, out), + Self::Activate(cmd) => cmd.run(config), + Self::Alias(cmd) => cmd.run(config), + Self::Asdf(cmd) => cmd.run(config), + Self::BinPaths(cmd) => cmd.run(config), + Self::Cache(cmd) => cmd.run(config), + Self::Completion(cmd) => cmd.run(config), + Self::Current(cmd) => cmd.run(config), + Self::Deactivate(cmd) => cmd.run(config), + Self::Direnv(cmd) => cmd.run(config), + Self::Doctor(cmd) => cmd.run(config), + Self::Env(cmd) => cmd.run(config), + Self::EnvVars(cmd) => cmd.run(config), + Self::Exec(cmd) => cmd.run(config), + Self::Global(cmd) => cmd.run(config), + Self::HookEnv(cmd) => cmd.run(config), + Self::Implode(cmd) => cmd.run(config), + Self::Install(cmd) => cmd.run(config), + Self::Latest(cmd) => cmd.run(config), + Self::Link(cmd) => cmd.run(config), + Self::Local(cmd) => cmd.run(config), + Self::Ls(cmd) => cmd.run(config), + Self::LsRemote(cmd) => cmd.run(config), + Self::Outdated(cmd) => cmd.run(config), + Self::Plugins(cmd) => cmd.run(config), + Self::Prune(cmd) => cmd.run(config), + Self::Reshim(cmd) => cmd.run(config), + Self::Settings(cmd) => cmd.run(config), + Self::Shell(cmd) => cmd.run(config), + Self::Sync(cmd) => cmd.run(config), + Self::Trust(cmd) => cmd.run(config), + Self::Uninstall(cmd) => cmd.run(config), + Self::Upgrade(cmd) => cmd.run(config), + Self::Use(cmd) => cmd.run(config), + Self::Version(cmd) => cmd.run(config), + Self::Where(cmd) => cmd.run(config), + Self::Which(cmd) => cmd.run(config), #[cfg(feature = "clap_complete")] - Self::RenderCompletion(cmd) => cmd.run(config, out), + Self::RenderCompletion(cmd) => cmd.run(config), #[cfg(debug_assertions)] - Self::RenderHelp(cmd) => cmd.run(config, out), + Self::RenderHelp(cmd) => cmd.run(config), #[cfg(feature = "clap_mangen")] - Self::RenderMangen(cmd) => cmd.run(config, out), + Self::RenderMangen(cmd) => cmd.run(config), } } } @@ -197,11 +196,11 @@ impl Cli { ) } - pub fn run(self, mut config: Config, args: &Vec, out: &mut Output) -> Result<()> { + pub fn run(self, mut config: Config, args: &Vec) -> Result<()> { debug!("{}", &args.join(" ")); if args[1..] == ["-v"] { // normally this would be considered --verbose - return version::Version {}.run(config, out); + return version::Version {}.run(config); } let matches = self.command.get_matches_from(args); if let Some(jobs) = matches.get_one::("jobs") { @@ -225,12 +224,12 @@ impl Cli { } if let Some((command, sub_m)) = matches.subcommand() { if command == "self-update" { - return SelfUpdate::from_arg_matches(sub_m)?.run(config, out); + return SelfUpdate::from_arg_matches(sub_m)?.run(config); } external::execute(&config, command, sub_m, self.external_commands)?; } let cmd = Commands::from_arg_matches(&matches)?; - cmd.run(config, out) + cmd.run(config) } } @@ -269,25 +268,28 @@ pub mod tests { use color_eyre::{Section, SectionExt}; use crate::dirs; + use crate::output::tests::{STDERR, STDOUT}; use super::*; - pub fn cli_run(args: &Vec) -> Result { + pub fn cli_run(args: &Vec) -> Result<()> { + STDOUT.lock().unwrap().clear(); + STDERR.lock().unwrap().clear(); let config = Config::load()?; - let mut out = Output::tracked(); Cli::new_with_external_commands(&config) - .run(config, args, &mut out) + .run(config, args) .with_section(|| format!("{}", args.join(" ").header("Command:")))?; - Ok(out) + Ok(()) } #[macro_export] macro_rules! assert_cli { ($($args:expr),+) => {{ let args = &vec!["rtx".into(), $($args.into()),+]; - let output = $crate::cli::tests::cli_run(args).unwrap().stdout.content; - console::strip_ansi_codes(&output).to_string() + $crate::cli::tests::cli_run(args).unwrap(); + let output = $crate::output::tests::STDOUT.lock().unwrap().join("\n"); + console::strip_ansi_codes(&output).trim().to_string() }}; } @@ -295,7 +297,8 @@ pub mod tests { macro_rules! assert_cli_snapshot { ($($args:expr),+) => {{ let args = &vec!["rtx".into(), $($args.into()),+]; - let output = $crate::cli::tests::cli_run(args).unwrap().stdout.content; + $crate::cli::tests::cli_run(args).unwrap(); + let output = $crate::output::tests::STDOUT.lock().unwrap().join("\n"); let output = console::strip_ansi_codes(&output.trim()).to_string(); let output = output.replace($crate::dirs::HOME.to_string_lossy().as_ref(), "~"); let output = $crate::test::replace_path(&output); @@ -307,7 +310,8 @@ pub mod tests { macro_rules! assert_cli_snapshot_stderr { ($($args:expr),+) => {{ let args = &vec!["rtx".into(), $($args.into()),+]; - let output = $crate::cli::tests::cli_run(args).unwrap().stderr.content; + $crate::cli::tests::cli_run(args).unwrap(); + let output = $crate::output::tests::STDERR.lock().unwrap().join("\n"); let output = console::strip_ansi_codes(&output.trim()).to_string(); let output = output.replace($crate::dirs::HOME.to_string_lossy().as_ref(), "~"); let output = $crate::test::replace_path(&output); diff --git a/src/cli/outdated.rs b/src/cli/outdated.rs index d2da32457..c5a673c80 100644 --- a/src/cli/outdated.rs +++ b/src/cli/outdated.rs @@ -6,7 +6,6 @@ use console::{pad_str, style, Alignment}; use crate::cli::args::tool::{ToolArg, ToolArgParser}; use crate::config::Config; -use crate::output::Output; use crate::plugins::Plugin; use crate::toolset::{ToolVersion, ToolsetBuilder}; @@ -22,7 +21,7 @@ pub struct Outdated { } impl Outdated { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let mut ts = ToolsetBuilder::new().with_args(&self.tool).build(&config)?; let tool_set = self .tool @@ -35,13 +34,13 @@ impl Outdated { if outdated.is_empty() { info!("All tools are up to date"); } else { - self.display(outdated, out); + self.display(outdated); } Ok(()) } - fn display(&self, outdated: OutputVec, out: &mut Output) { + fn display(&self, outdated: OutputVec) { // TODO: make a generic table printer in src/ui/table let plugins = outdated .iter() @@ -90,7 +89,6 @@ impl Outdated { let pad_requested = |s| pad_str(s, requested_width, Alignment::Left, None); let pad_current = |s| pad_str(s, current_width, Alignment::Left, None); rtxprintln!( - out, "{} {} {} {}", style(pad_plugin("Tool")).dim(), style(pad_requested("Requested")).dim(), @@ -99,7 +97,6 @@ impl Outdated { ); for i in 0..outdated.len() { rtxprintln!( - out, "{} {} {} {}", pad_plugin(plugins[i]), pad_requested(&requests[i]), diff --git a/src/cli/plugins/install.rs b/src/cli/plugins/install.rs index b3c72ba06..6f837f51c 100644 --- a/src/cli/plugins/install.rs +++ b/src/cli/plugins/install.rs @@ -2,7 +2,7 @@ use color_eyre::eyre::{eyre, Result}; use url::Url; use crate::config::Config; -use crate::output::Output; + use crate::plugins::{unalias_plugin, ExternalPlugin, Plugin, PluginName}; use crate::toolset::ToolsetBuilder; use crate::ui::multi_progress_report::MultiProgressReport; @@ -46,7 +46,7 @@ pub struct PluginsInstall { } impl PluginsInstall { - pub fn run(self, config: Config, _out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let mpr = MultiProgressReport::new(&config.settings); if self.all { return self.install_all_missing_plugins(config, mpr); diff --git a/src/cli/plugins/link.rs b/src/cli/plugins/link.rs index 5cc4ea571..ffe6400ef 100644 --- a/src/cli/plugins/link.rs +++ b/src/cli/plugins/link.rs @@ -7,7 +7,7 @@ use path_absolutize::Absolutize; use crate::config::Config; use crate::file::{make_symlink, remove_all}; -use crate::output::Output; + use crate::plugins::unalias_plugin; use crate::{dirs, file}; @@ -33,7 +33,7 @@ pub struct PluginsLink { } impl PluginsLink { - pub fn run(self, _config: Config, _out: &mut Output) -> Result<()> { + pub fn run(self, _config: Config) -> Result<()> { let (name, path) = match self.path { Some(path) => (self.name, path), None => { diff --git a/src/cli/plugins/ls.rs b/src/cli/plugins/ls.rs index bdba3e470..18bb1c1b4 100644 --- a/src/cli/plugins/ls.rs +++ b/src/cli/plugins/ls.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use color_eyre::eyre::Result; use crate::config::Config; -use crate::output::Output; + use crate::plugins::{ExternalPlugin, PluginType}; /// List installed plugins @@ -42,7 +42,7 @@ pub struct PluginsLs { } impl PluginsLs { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let mut tools = config.list_plugins().into_iter().collect::>(); if self.all { @@ -60,25 +60,25 @@ impl PluginsLs { if self.urls || self.refs { for tool in tools { - rtxprint!(out, "{:29}", tool.name()); + rtxprint!("{:29}", tool.name()); if self.urls { if let Some(url) = tool.get_remote_url() { - rtxprint!(out, " {}", url); + rtxprint!(" {}", url); } } if self.refs { if let Ok(aref) = tool.current_abbrev_ref() { - rtxprint!(out, " {}", aref); + rtxprint!(" {}", aref); } if let Ok(sha) = tool.current_sha_short() { - rtxprint!(out, " {}", sha); + rtxprint!(" {}", sha); } } - rtxprint!(out, "\n"); + rtxprint!("\n"); } } else { for tool in tools { - rtxprintln!(out, "{tool}"); + rtxprintln!("{tool}"); } } Ok(()) diff --git a/src/cli/plugins/ls_remote.rs b/src/cli/plugins/ls_remote.rs index 944ee6b1b..539ab1686 100644 --- a/src/cli/plugins/ls_remote.rs +++ b/src/cli/plugins/ls_remote.rs @@ -5,7 +5,6 @@ use console::{measure_text_width, pad_str, Alignment}; use itertools::Itertools; use crate::config::Config; -use crate::output::Output; /// List all available remote plugins #[derive(Debug, clap::Args)] @@ -23,7 +22,7 @@ pub struct PluginsLsRemote { } impl PluginsLsRemote { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let installed_plugins = config .list_plugins() .into_iter() @@ -50,7 +49,7 @@ impl PluginsLsRemote { }; let url = if self.urls { repo } else { "" }; let plugin = pad_str(plugin, max_plugin_len, Alignment::Left, None); - rtxprintln!(out, "{} {}{}", plugin, installed, url); + rtxprintln!("{} {}{}", plugin, installed, url); } Ok(()) diff --git a/src/cli/plugins/mod.rs b/src/cli/plugins/mod.rs index dde5e2f4d..91a82efec 100644 --- a/src/cli/plugins/mod.rs +++ b/src/cli/plugins/mod.rs @@ -2,7 +2,6 @@ use clap::Subcommand; use color_eyre::eyre::Result; use crate::config::Config; -use crate::output::Output; mod install; mod link; @@ -59,20 +58,20 @@ enum Commands { } impl Commands { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { match self { - Self::Install(cmd) => cmd.run(config, out), - Self::Link(cmd) => cmd.run(config, out), - Self::Ls(cmd) => cmd.run(config, out), - Self::LsRemote(cmd) => cmd.run(config, out), - Self::Uninstall(cmd) => cmd.run(config, out), - Self::Update(cmd) => cmd.run(config, out), + Self::Install(cmd) => cmd.run(config), + Self::Link(cmd) => cmd.run(config), + Self::Ls(cmd) => cmd.run(config), + Self::LsRemote(cmd) => cmd.run(config), + Self::Uninstall(cmd) => cmd.run(config), + Self::Update(cmd) => cmd.run(config), } } } impl Plugins { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let cmd = self.command.unwrap_or(Commands::Ls(ls::PluginsLs { all: self.all, core: self.core, @@ -81,6 +80,6 @@ impl Plugins { user: self.user, })); - cmd.run(config, out) + cmd.run(config) } } diff --git a/src/cli/plugins/uninstall.rs b/src/cli/plugins/uninstall.rs index 92bd26228..46cbe74d6 100644 --- a/src/cli/plugins/uninstall.rs +++ b/src/cli/plugins/uninstall.rs @@ -2,7 +2,7 @@ use color_eyre::eyre::Result; use console::style; use crate::config::Config; -use crate::output::Output; + use crate::plugins::unalias_plugin; use crate::ui::multi_progress_report::MultiProgressReport; @@ -24,7 +24,7 @@ pub struct PluginsUninstall { } impl PluginsUninstall { - pub fn run(self, config: Config, _out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let mpr = MultiProgressReport::new(&config.settings); let plugins = match self.all { diff --git a/src/cli/plugins/update.rs b/src/cli/plugins/update.rs index 75d43eeae..200d853ca 100644 --- a/src/cli/plugins/update.rs +++ b/src/cli/plugins/update.rs @@ -1,7 +1,7 @@ use color_eyre::eyre::Result; use crate::config::Config; -use crate::output::Output; + use crate::plugins::{unalias_plugin, PluginName}; /// Updates a plugin to the latest version @@ -20,7 +20,7 @@ pub struct Update { } impl Update { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let plugins: Vec<_> = match self.plugin { Some(plugins) => plugins .into_iter() @@ -42,7 +42,7 @@ impl Update { }; for (plugin, ref_) in plugins { - rtxprintln!(out, "updating plugin {plugin}"); + rtxprintln!("updating plugin {plugin}"); plugin.update(ref_)?; } Ok(()) diff --git a/src/cli/prune.rs b/src/cli/prune.rs index 420cdf35e..675f508a6 100644 --- a/src/cli/prune.rs +++ b/src/cli/prune.rs @@ -5,7 +5,7 @@ use color_eyre::eyre::Result; use console::style; use crate::config::Config; -use crate::output::Output; + use crate::plugins::{Plugin, PluginName}; use crate::toolset::{ToolVersion, ToolsetBuilder}; use crate::ui::multi_progress_report::MultiProgressReport; @@ -30,7 +30,7 @@ pub struct Prune { } impl Prune { - pub fn run(self, config: Config, _out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let ts = ToolsetBuilder::new().build(&config)?; let mut to_delete = ts .list_installed_versions(&config)? diff --git a/src/cli/render_completion.rs b/src/cli/render_completion.rs index 65a221bed..73591ee8c 100644 --- a/src/cli/render_completion.rs +++ b/src/cli/render_completion.rs @@ -6,7 +6,6 @@ use color_eyre::eyre::Result; use crate::cli::self_update::SelfUpdate; use crate::config::Config; -use crate::output::Output; use crate::shell::completions; /// Generate shell completions @@ -23,7 +22,7 @@ pub struct RenderCompletion { } impl RenderCompletion { - pub fn run(self, _config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, _config: Config) -> Result<()> { let shell = self.shell.or(self.shell_type).unwrap(); let mut cmd = crate::cli::Cli::command().subcommand(SelfUpdate::command()); @@ -37,7 +36,7 @@ impl RenderCompletion { String::from_utf8(c.into_inner()).unwrap() } }; - rtxprintln!(out, "{}", script.trim()); + rtxprintln!("{}", script.trim()); Ok(()) } diff --git a/src/cli/render_help.rs b/src/cli/render_help.rs index 7df6cdad4..b10bad218 100644 --- a/src/cli/render_help.rs +++ b/src/cli/render_help.rs @@ -7,7 +7,6 @@ use crate::cli::self_update::SelfUpdate; use crate::cli::Cli; use crate::config::Config; use crate::file; -use crate::output::Output; /// internal command to generate markdown from help #[derive(Debug, clap::Args)] @@ -15,7 +14,7 @@ use crate::output::Output; pub struct RenderHelp {} impl RenderHelp { - pub fn run(self, _config: Config, _out: &mut Output) -> Result<()> { + pub fn run(self, _config: Config) -> Result<()> { let readme = file::read_to_string("README.md")?; let mut current_readme = readme.split(""); diff --git a/src/cli/render_mangen.rs b/src/cli/render_mangen.rs index 7e1aa987a..9a9678724 100644 --- a/src/cli/render_mangen.rs +++ b/src/cli/render_mangen.rs @@ -7,7 +7,6 @@ use eyre::Result; use crate::cli::self_update::SelfUpdate; use crate::cli::{version, Cli}; use crate::config::Config; -use crate::output::Output; /// internal command to generate markdown from help #[derive(Debug, clap::Args)] @@ -15,7 +14,7 @@ use crate::output::Output; pub struct RenderMangen {} impl RenderMangen { - pub fn run(self, _config: Config, _out: &mut Output) -> Result<()> { + pub fn run(self, _config: Config) -> Result<()> { let cli = Cli::command() .subcommand(SelfUpdate::command()) .version(&*version::RAW_VERSION) diff --git a/src/cli/reshim.rs b/src/cli/reshim.rs index bb565aa41..9c8e50e01 100644 --- a/src/cli/reshim.rs +++ b/src/cli/reshim.rs @@ -1,7 +1,7 @@ use color_eyre::eyre::Result; use crate::config::Config; -use crate::output::Output; + use crate::shims; use crate::toolset::ToolsetBuilder; @@ -30,7 +30,7 @@ pub struct Reshim { } impl Reshim { - pub fn run(self, config: Config, _out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let ts = ToolsetBuilder::new().build(&config)?; shims::reshim(&config, &ts) diff --git a/src/cli/self_update.rs b/src/cli/self_update.rs index fe5735e3a..8b85ef041 100644 --- a/src/cli/self_update.rs +++ b/src/cli/self_update.rs @@ -7,7 +7,7 @@ use self_update::{cargo_crate_version, Status}; use crate::cli::version::{ARCH, OS}; use crate::config::Config; -use crate::output::Output; + use crate::{cmd, env}; /// Updates rtx itself @@ -34,14 +34,14 @@ pub struct SelfUpdate { } impl SelfUpdate { - pub fn run(self, _config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, _config: Config) -> Result<()> { let status = self.do_update()?; if status.updated() { let version = style(status.version()).bright().yellow(); - rtxprintln!(out, "Updated rtx to {version}"); + rtxprintln!("Updated rtx to {version}"); } else { - rtxprintln!(out, "rtx is already up to date"); + rtxprintln!("rtx is already up to date"); } if !self.no_plugins { cmd!(&*env::RTX_EXE, "plugins", "update").run()?; diff --git a/src/cli/settings/get.rs b/src/cli/settings/get.rs index da0a9097a..2547c4b73 100644 --- a/src/cli/settings/get.rs +++ b/src/cli/settings/get.rs @@ -1,7 +1,6 @@ use color_eyre::eyre::{eyre, Result}; use crate::config::Config; -use crate::output::Output; /// Show a current setting /// @@ -17,9 +16,9 @@ pub struct SettingsGet { } impl SettingsGet { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { match config.settings.to_index_map().get(&self.key) { - Some(value) => Ok(rtxprintln!(out, "{}", value)), + Some(value) => Ok(rtxprintln!("{}", value)), None => Err(eyre!("Unknown setting: {}", self.key)), } } diff --git a/src/cli/settings/ls.rs b/src/cli/settings/ls.rs index 5526797f7..eb3a6391c 100644 --- a/src/cli/settings/ls.rs +++ b/src/cli/settings/ls.rs @@ -1,7 +1,6 @@ use color_eyre::eyre::Result; use crate::config::Config; -use crate::output::Output; /// Show current settings /// @@ -14,9 +13,9 @@ use crate::output::Output; pub struct SettingsLs {} impl SettingsLs { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { for (key, value) in config.settings.to_index_map() { - rtxprintln!(out, "{} = {}", key, value); + rtxprintln!("{} = {}", key, value); } Ok(()) } diff --git a/src/cli/settings/mod.rs b/src/cli/settings/mod.rs index a7509c221..5dfb50289 100644 --- a/src/cli/settings/mod.rs +++ b/src/cli/settings/mod.rs @@ -2,7 +2,6 @@ use clap::Subcommand; use color_eyre::eyre::Result; use crate::config::Config; -use crate::output::Output; mod get; mod ls; @@ -25,20 +24,20 @@ enum Commands { } impl Commands { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { match self { - Self::Get(cmd) => cmd.run(config, out), - Self::Ls(cmd) => cmd.run(config, out), - Self::Set(cmd) => cmd.run(config, out), - Self::Unset(cmd) => cmd.run(config, out), + Self::Get(cmd) => cmd.run(config), + Self::Ls(cmd) => cmd.run(config), + Self::Set(cmd) => cmd.run(config), + Self::Unset(cmd) => cmd.run(config), } } } impl Settings { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let cmd = self.command.unwrap_or(Commands::Ls(ls::SettingsLs {})); - cmd.run(config, out) + cmd.run(config) } } diff --git a/src/cli/settings/set.rs b/src/cli/settings/set.rs index b567db0b5..e78089bc9 100644 --- a/src/cli/settings/set.rs +++ b/src/cli/settings/set.rs @@ -2,7 +2,6 @@ use color_eyre::eyre::{eyre, Result}; use crate::config::config_file::ConfigFile; use crate::config::Config; -use crate::output::Output; /// Add/update a setting /// @@ -18,7 +17,7 @@ pub struct SettingsSet { } impl SettingsSet { - pub fn run(self, mut config: Config, _out: &mut Output) -> Result<()> { + pub fn run(self, mut config: Config) -> Result<()> { let value: toml_edit::Value = match self.key.as_str() { "experimental" => parse_bool(&self.value)?, "always_keep_download" => parse_bool(&self.value)?, diff --git a/src/cli/settings/unset.rs b/src/cli/settings/unset.rs index 99e50c227..f71b756ed 100644 --- a/src/cli/settings/unset.rs +++ b/src/cli/settings/unset.rs @@ -2,7 +2,6 @@ use color_eyre::eyre::Result; use crate::config::config_file::ConfigFile; use crate::config::Config; -use crate::output::Output; /// Clears a setting /// @@ -15,7 +14,7 @@ pub struct SettingsUnset { } impl SettingsUnset { - pub fn run(self, mut config: Config, _out: &mut Output) -> Result<()> { + pub fn run(self, mut config: Config) -> Result<()> { config.global_config.remove_setting(&self.key); config.global_config.save() } diff --git a/src/cli/shell.rs b/src/cli/shell.rs index a1f1d4dc7..cddea016a 100644 --- a/src/cli/shell.rs +++ b/src/cli/shell.rs @@ -3,7 +3,6 @@ use console::style; use crate::cli::args::tool::{ToolArg, ToolArgParser}; use crate::config::Config; -use crate::output::Output; use crate::shell::get_shell; use crate::toolset::{ToolSource, ToolsetBuilder}; @@ -23,7 +22,7 @@ pub struct Shell { } impl Shell { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { if !config.is_activated() { err_inactive()?; } @@ -42,7 +41,7 @@ impl Shell { } else { shell.set_env(&k, &tv.version) }; - out.stdout.writeln(op); + rtxprintln!("{op}"); } } diff --git a/src/cli/sync/mod.rs b/src/cli/sync/mod.rs index 4fa53055f..2db3317fe 100644 --- a/src/cli/sync/mod.rs +++ b/src/cli/sync/mod.rs @@ -2,7 +2,6 @@ use clap::Subcommand; use color_eyre::eyre::Result; use crate::config::Config; -use crate::output::Output; mod node; mod python; @@ -21,16 +20,16 @@ enum Commands { } impl Commands { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { match self { - Self::Node(cmd) => cmd.run(config, out), - Self::Python(cmd) => cmd.run(config, out), + Self::Node(cmd) => cmd.run(config), + Self::Python(cmd) => cmd.run(config), } } } impl Sync { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { - self.command.run(config, out) + pub fn run(self, config: Config) -> Result<()> { + self.command.run(config) } } diff --git a/src/cli/sync/node.rs b/src/cli/sync/node.rs index 1c9279c8a..ee7957d4e 100644 --- a/src/cli/sync/node.rs +++ b/src/cli/sync/node.rs @@ -6,7 +6,6 @@ use itertools::sorted; use crate::config::Config; use crate::env::{NODENV_ROOT, NVM_DIR}; use crate::file; -use crate::output::Output; use crate::plugins::PluginName; use crate::{cmd, dirs}; @@ -37,18 +36,18 @@ pub struct SyncNodeType { } impl SyncNode { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { if self._type.brew { - self.run_brew(config, out)?; + self.run_brew(config)?; } else if self._type.nvm { - self.run_nvm(config, out)?; + self.run_nvm(config)?; } else if self._type.nodenv { - self.run_nodenv(config, out)?; + self.run_nodenv(config)?; } Ok(()) } - fn run_brew(self, config: Config, out: &mut Output) -> Result<()> { + fn run_brew(self, config: Config) -> Result<()> { let tool = config.get_or_create_plugin(&PluginName::from("node")); let brew_prefix = PathBuf::from(cmd!("brew", "--prefix").read()?).join("opt"); @@ -63,13 +62,13 @@ impl SyncNode { } let v = entry.trim_start_matches("node@"); tool.create_symlink(v, &brew_prefix.join(&entry))?; - rtxprintln!(out, "Synced node@{} from Homebrew", v); + rtxprintln!("Synced node@{} from Homebrew", v); } config.rebuild_shims_and_runtime_symlinks() } - fn run_nvm(self, config: Config, out: &mut Output) -> Result<()> { + fn run_nvm(self, config: Config) -> Result<()> { let tool = config.get_or_create_plugin(&PluginName::from("node")); let nvm_versions_path = NVM_DIR.join("versions").join("node"); @@ -81,13 +80,13 @@ impl SyncNode { for entry in sorted(subdirs) { let v = entry.trim_start_matches('v'); tool.create_symlink(v, &nvm_versions_path.join(&entry))?; - rtxprintln!(out, "Synced node@{} from nvm", v); + rtxprintln!("Synced node@{} from nvm", v); } config.rebuild_shims_and_runtime_symlinks() } - fn run_nodenv(self, config: Config, out: &mut Output) -> Result<()> { + fn run_nodenv(self, config: Config) -> Result<()> { let tool = config.get_or_create_plugin(&PluginName::from("node")); let nodenv_versions_path = NODENV_ROOT.join("versions"); @@ -98,7 +97,7 @@ impl SyncNode { let subdirs = file::dir_subdirs(&nodenv_versions_path)?; for v in sorted(subdirs) { tool.create_symlink(&v, &nodenv_versions_path.join(&v))?; - rtxprintln!(out, "Synced node@{} from nodenv", v); + rtxprintln!("Synced node@{} from nodenv", v); } config.rebuild_shims_and_runtime_symlinks() diff --git a/src/cli/sync/python.rs b/src/cli/sync/python.rs index ae28e2faf..9e0e38de7 100644 --- a/src/cli/sync/python.rs +++ b/src/cli/sync/python.rs @@ -5,7 +5,7 @@ use crate::config::Config; use crate::dirs; use crate::env::PYENV_ROOT; use crate::file; -use crate::output::Output; + use crate::plugins::PluginName; /// Symlinks all tool versions from an external tool into rtx @@ -20,7 +20,7 @@ pub struct SyncPython { } impl SyncPython { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let python = config.get_or_create_plugin(&PluginName::from("python")); let pyenv_versions_path = PYENV_ROOT.join("versions"); @@ -34,7 +34,7 @@ impl SyncPython { let subdirs = file::dir_subdirs(&pyenv_versions_path)?; for v in sorted(subdirs) { python.create_symlink(&v, &pyenv_versions_path.join(&v))?; - rtxprintln!(out, "Synced python@{} from pyenv", v); + rtxprintln!("Synced python@{} from pyenv", v); } config.rebuild_shims_and_runtime_symlinks() diff --git a/src/cli/trust.rs b/src/cli/trust.rs index e412ac33c..c679eb3c1 100644 --- a/src/cli/trust.rs +++ b/src/cli/trust.rs @@ -5,7 +5,6 @@ use color_eyre::eyre::Result; use crate::cli::local; use crate::config::{config_file, Config}; -use crate::output::Output; /// Marks a config file as trusted /// @@ -29,17 +28,17 @@ pub struct Trust { } impl Trust { - pub fn run(self, _config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, _config: Config) -> Result<()> { let path = match &self.config_file { Some(filename) => PathBuf::from(filename), None => local::get_parent_path()?, }; if self.untrust { config_file::untrust(&path)?; - rtxprintln!(out, "untrusted {}", &path.canonicalize()?.display()); + rtxprintln!("untrusted {}", &path.canonicalize()?.display()); } else { config_file::trust(&path)?; - rtxprintln!(out, "trusted {}", &path.canonicalize()?.display()); + rtxprintln!("trusted {}", &path.canonicalize()?.display()); } Ok(()) } diff --git a/src/cli/uninstall.rs b/src/cli/uninstall.rs index 387ebbc65..f4861fca5 100644 --- a/src/cli/uninstall.rs +++ b/src/cli/uninstall.rs @@ -6,7 +6,7 @@ use std::sync::Arc; use crate::cli::args::tool::{ToolArg, ToolArgParser}; use crate::config::Config; -use crate::output::Output; + use crate::plugins::Plugin; use crate::toolset::{ToolVersion, ToolVersionRequest, ToolsetBuilder}; use crate::ui::multi_progress_report::MultiProgressReport; @@ -30,7 +30,7 @@ pub struct Uninstall { } impl Uninstall { - pub fn run(self, config: Config, _out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let tool_versions = if self.tool.is_empty() && self.all { self.get_all_tool_versions(&config)? } else { diff --git a/src/cli/upgrade.rs b/src/cli/upgrade.rs index aaa49eed4..60c536b23 100644 --- a/src/cli/upgrade.rs +++ b/src/cli/upgrade.rs @@ -6,7 +6,7 @@ use eyre::WrapErr; use crate::cli::args::tool::{ToolArg, ToolArgParser}; use crate::config::Config; -use crate::output::Output; + use crate::plugins::Plugin; use crate::runtime_symlinks; use crate::shims; @@ -30,7 +30,7 @@ pub struct Upgrade { } impl Upgrade { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let mut ts = ToolsetBuilder::new().with_args(&self.tool).build(&config)?; let tool_set = self .tool @@ -43,13 +43,13 @@ impl Upgrade { if outdated.is_empty() { info!("All tools are up to date"); } else { - self.upgrade(&config, outdated, out)?; + self.upgrade(&config, outdated)?; } Ok(()) } - fn upgrade(&self, config: &Config, outdated: OutputVec, out: &mut Output) -> Result<()> { + fn upgrade(&self, config: &Config, outdated: OutputVec) -> Result<()> { let mpr = MultiProgressReport::new(&config.settings); let mut ts = ToolsetBuilder::new().with_args(&self.tool).build(config)?; @@ -70,10 +70,10 @@ impl Upgrade { if self.dry_run { for (tool, tv) in &to_remove { - rtxprintln!(out, "Would uninstall {} {}", tool, tv); + rtxprintln!("Would uninstall {} {}", tool, tv); } for tv in &new_versions { - rtxprintln!(out, "Would install {}", tv); + rtxprintln!("Would install {}", tv); } return Ok(()); } diff --git a/src/cli/use.rs b/src/cli/use.rs index 22b6f357c..78666f05a 100644 --- a/src/cli/use.rs +++ b/src/cli/use.rs @@ -9,7 +9,7 @@ use crate::config::config_file::ConfigFile; use crate::config::{config_file, Config}; use crate::env::{RTX_DEFAULT_CONFIG_FILENAME, RTX_DEFAULT_TOOL_VERSIONS_FILENAME}; use crate::file::display_path; -use crate::output::Output; + use crate::plugins::PluginName; use crate::toolset::ToolsetBuilder; use crate::{dirs, env, file}; @@ -64,7 +64,7 @@ pub struct Use { } impl Use { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let mut ts = ToolsetBuilder::new().with_args(&self.tool).build(&config)?; ts.install_arg_versions(&config)?; @@ -95,7 +95,6 @@ impl Use { cf.save()?; let tools = self.tool.iter().map(|t| t.to_string()).join(" "); rtxprintln!( - out, "{} {} {}", style("rtx").dim(), display_path(cf.get_path()), diff --git a/src/cli/version.rs b/src/cli/version.rs index 388c9e154..b155ea3b5 100644 --- a/src/cli/version.rs +++ b/src/cli/version.rs @@ -11,7 +11,7 @@ use crate::cli::self_update::SelfUpdate; use crate::config::Config; use crate::env::CI; use crate::file::modified_duration; -use crate::output::Output; + use crate::{dirs, duration, file}; #[derive(Debug, clap::Args)] @@ -44,24 +44,24 @@ pub static VERSION: Lazy = Lazy::new(|| { pub static RAW_VERSION: Lazy = Lazy::new(|| env!("CARGO_PKG_VERSION").to_string()); impl Version { - pub fn run(self, _config: Config, out: &mut Output) -> Result<()> { - show_version(out); + pub fn run(self, _config: Config) -> Result<()> { + show_version(); Ok(()) } } -pub fn print_version_if_requested(args: &[String], out: &mut Output) { +pub fn print_version_if_requested(args: &[String]) { if args.len() == 2 && (args[0] == "rtx" || args[0].ends_with("/rtx")) { let cmd = &args[1].to_lowercase(); if cmd == "version" || cmd == "-v" || cmd == "--version" { - show_version(out); + show_version(); std::process::exit(0); } } } -fn show_version(out: &mut Output) { - rtxprintln!(out, "{}", *VERSION); +fn show_version() { + rtxprintln!("{}", *VERSION); show_latest(); } @@ -137,6 +137,6 @@ mod tests { #[test] fn test_version() { let stdout = assert_cli!("version"); - assert_str_eq!(stdout, VERSION.to_string() + "\n"); + assert_str_eq!(stdout, VERSION.to_string()); } } diff --git a/src/cli/where.rs b/src/cli/where.rs index ee81e5e7b..8be4c1471 100644 --- a/src/cli/where.rs +++ b/src/cli/where.rs @@ -3,7 +3,7 @@ use color_eyre::eyre::Result; use crate::cli::args::tool::{ToolArg, ToolArgParser}; use crate::config::Config; use crate::errors::Error::VersionNotInstalled; -use crate::output::Output; + use crate::toolset::ToolsetBuilder; /// Display the installation path for a runtime @@ -28,7 +28,7 @@ pub struct Where { } impl Where { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let runtime = match self.tool.tvr { None => match self.asdf_version { Some(version) => self.tool.with_version(&version), @@ -55,7 +55,7 @@ impl Where { .map(|tvr| tvr.resolve(&config, plugin.clone(), Default::default(), false)) { Some(Ok(tv)) if plugin.is_version_installed(&tv) => { - rtxprintln!(out, "{}", tv.install_path().to_string_lossy()); + rtxprintln!("{}", tv.install_path().to_string_lossy()); Ok(()) } _ => Err(VersionNotInstalled( diff --git a/src/cli/which.rs b/src/cli/which.rs index f580a3501..c0aa7f4d4 100644 --- a/src/cli/which.rs +++ b/src/cli/which.rs @@ -2,7 +2,7 @@ use color_eyre::eyre::{eyre, Result}; use crate::cli::args::tool::{ToolArg, ToolArgParser}; use crate::config::Config; -use crate::output::Output; + use crate::toolset::{Toolset, ToolsetBuilder}; /// Shows the path that a bin name points to @@ -28,18 +28,18 @@ pub struct Which { } impl Which { - pub fn run(self, config: Config, out: &mut Output) -> Result<()> { + pub fn run(self, config: Config) -> Result<()> { let ts = self.get_toolset(&config)?; match ts.which(&config, &self.bin_name) { Some((p, tv)) => { if self.version { - rtxprintln!(out, "{}", tv.version); + rtxprintln!("{}", tv.version); } else if self.plugin { - rtxprintln!(out, "{p}"); + rtxprintln!("{p}"); } else { let path = p.which(&config, &ts, &tv, &self.bin_name)?; - rtxprintln!(out, "{}", path.unwrap().display()); + rtxprintln!("{}", path.unwrap().display()); } Ok(()) } diff --git a/src/config/config_file/mod.rs b/src/config/config_file/mod.rs index 97c7a08b4..3d1532572 100644 --- a/src/config/config_file/mod.rs +++ b/src/config/config_file/mod.rs @@ -13,7 +13,7 @@ use crate::config::settings::SettingsPartial; use crate::config::{global_config_files, AliasMap, Config, Settings}; use crate::file::{display_path, replace_path}; use crate::hash::hash_to_str; -use crate::output::Output; + use crate::plugins::PluginName; use crate::toolset::{ToolVersion, ToolVersionList, Toolset}; use crate::ui::multi_progress_report::MultiProgressReport; @@ -121,7 +121,7 @@ impl dyn ConfigFile { /// this is for `rtx local|global TOOL` which will display the version instead of setting it /// it's only valid to use a single tool in this case /// returns "true" if the tool was displayed which means the CLI should exit - pub fn display_runtime(&self, out: &mut Output, runtimes: &[ToolArg]) -> Result { + pub fn display_runtime(&self, runtimes: &[ToolArg]) -> Result { // in this situation we just print the current version in the config file if runtimes.len() == 1 && runtimes[0].tvr.is_none() { let plugin = &runtimes[0].plugin; @@ -140,7 +140,7 @@ impl dyn ConfigFile { .iter() .map(|(tvr, _)| tvr.version()) .collect::>(); - rtxprintln!(out, "{}", tvl.join(" ")); + rtxprintln!("{}", tvl.join(" ")); return Ok(true); } // check for something like `rtx local node python@latest` which is invalid diff --git a/src/main.rs b/src/main.rs index 228a00195..8dd232f7c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,7 +15,6 @@ use console::{style, Term}; use crate::cli::version::VERSION; use crate::cli::Cli; use crate::config::Config; -use crate::output::Output; #[macro_use] mod output; @@ -80,19 +79,17 @@ fn main() -> Result<()> { } fn run(args: &Vec) -> Result<()> { - let out = &mut Output::new(); - // show version before loading config in case of error - cli::version::print_version_if_requested(&env::ARGS, out); + cli::version::print_version_if_requested(&env::ARGS); migrate::run(); let config = Config::load()?; - let config = shims::handle_shim(config, args, out)?; + let config = shims::handle_shim(config, args)?; if config.should_exit_early { return Ok(()); } let cli = Cli::new_with_external_commands(&config); - cli.run(config, args, out) + cli.run(config, args) } fn handle_ctrlc() { diff --git a/src/output.rs b/src/output.rs index 87f1a1c11..59567a1f9 100644 --- a/src/output.rs +++ b/src/output.rs @@ -1,97 +1,67 @@ -use std::io; -use std::io::Write; -use std::process::ExitCode; - -#[derive(Debug)] -pub enum OutputType { - Stdout, - Stderr, -} - -#[derive(Debug)] -pub struct Output { - pub stdout: OutputStream, - pub stderr: OutputStream, - pub status: ExitCode, -} - -impl Output { - pub fn new() -> Self { - Self { - stdout: OutputStream::new(OutputType::Stdout), - stderr: OutputStream::new(OutputType::Stderr), - status: ExitCode::from(0), - } - } - - #[cfg(test)] - pub fn tracked() -> Self { - let mut output = Self::new(); - output.stdout.track = true; - output.stderr.track = true; - - output - } -} - -impl Default for Output { - fn default() -> Self { - Self::new() - } -} - -#[derive(Debug)] -pub struct OutputStream { - pub content: String, - pub output_type: OutputType, - pub track: bool, -} - -impl OutputStream { - pub fn new(output_type: OutputType) -> Self { - Self { - content: Default::default(), - track: false, - output_type, - } - } - pub fn write(&mut self, content: String) { - if self.track { - self.content.push_str(&content); - } else { - let _ = match self.output_type { - OutputType::Stdout => io::stdout().write(content.as_bytes()), - OutputType::Stderr => io::stderr().write(content.as_bytes()), - }; - } - } - - pub fn writeln(&mut self, content: String) { - self.write(format!("{content}\n")); - } +#[cfg(test)] +#[macro_export] +macro_rules! rtxprintln { + () => { + rtxprint!("\n") + }; + ($($arg:tt)*) => {{ + let mut stdout = $crate::output::tests::STDOUT.lock().unwrap(); + stdout.push(format!($($arg)*)); + }}; } +#[cfg(not(test))] #[macro_export] macro_rules! rtxprintln { () => { rtxprint!("\n") }; - ($out:ident, $($arg:tt)*) => {{ - $out.stdout.writeln(format!($($arg)*)); + ($($arg:tt)*) => {{ + println!($($arg)*); }}; } +#[cfg(test)] #[macro_export] macro_rules! rtxprint { - ($out:ident, $($arg:tt)*) => {{ - $out.stdout.write(format!($($arg)*)); + ($($arg:tt)*) => {{ + let mut stdout = $crate::output::tests::STDOUT.lock().unwrap(); + let cur = stdout.pop().unwrap_or_default(); + stdout.push(cur + &format!($($arg)*)); }}; } +#[cfg(not(test))] +#[macro_export] +macro_rules! rtxprint { + ($($arg:tt)*) => {{ + print!($($arg)*); + }}; +} + +#[cfg(test)] #[macro_export] macro_rules! rtxstatusln { - ($out:ident, $($arg:tt)*) => {{ + ($($arg:tt)*) => {{ + let mut stderr = $crate::output::tests::STDERR.lock().unwrap(); + let rtx = console::style("rtx ").dim().for_stderr(); + stderr.push(format!("{}{}", rtx, format!($($arg)*))); + }}; + } + +#[cfg(not(test))] +#[macro_export] +macro_rules! rtxstatusln { + ($($arg:tt)*) => {{ let rtx = console::style("rtx ").dim().for_stderr(); - $out.stderr.writeln(format!("{}{}", rtx, format!($($arg)*))); + eprintln!("{}{}", rtx, format!($($arg)*)); }}; } + +#[cfg(test)] +pub mod tests { + use std::sync::Mutex; + + pub static STDOUT: Mutex> = Mutex::new(Vec::new()); + pub static STDERR: Mutex> = Mutex::new(Vec::new()); +} diff --git a/src/shims.rs b/src/shims.rs index fc2f644dd..212ffc620 100644 --- a/src/shims.rs +++ b/src/shims.rs @@ -16,14 +16,14 @@ use crate::env; use crate::fake_asdf; use crate::file::{create_dir_all, display_path, remove_all}; use crate::lock_file::LockFile; -use crate::output::Output; + use crate::plugins::Plugin; use crate::toolset::{ToolVersion, Toolset, ToolsetBuilder}; use crate::{dirs, file}; // executes as if it was a shim if the command is not "rtx", e.g.: "node" #[allow(dead_code)] -pub fn handle_shim(config: Config, args: &[String], out: &mut Output) -> Result { +pub fn handle_shim(config: Config, args: &[String]) -> Result { let (_, bin_name) = args[0].rsplit_once('/').unwrap_or(("", &args[0])); if bin_name == "rtx" { return Ok(config); @@ -36,7 +36,7 @@ pub fn handle_shim(config: Config, args: &[String], out: &mut Output) -> Result< command: Some(args), cd: None, }; - exec.run(config, out)?; + exec.run(config)?; exit(0); }