diff --git a/src/cli/backends/ls.rs b/src/cli/backends/ls.rs new file mode 100644 index 000000000..201a8228a --- /dev/null +++ b/src/cli/backends/ls.rs @@ -0,0 +1,41 @@ +use eyre::Result; + +use crate::forge::{self, ForgeType}; + +/// List built-in backends +#[derive(Debug, clap::Args)] +#[clap(visible_alias = "list", after_long_help = AFTER_LONG_HELP, verbatim_doc_comment)] +pub struct BackendsLs {} + +impl BackendsLs { + pub fn run(self) -> Result<()> { + let mut forges = forge::list_forge_types(); + forges.retain(|f| *f != ForgeType::Asdf); + + for forge in forges { + miseprintln!("{}", forge); + } + Ok(()) + } +} + +static AFTER_LONG_HELP: &str = color_print::cstr!( + r#"Examples: + + $ mise backends ls + cargo + go + npm + pipx + ubi +"# +); + +#[cfg(test)] +mod tests { + + #[test] + fn test_backends_list() { + assert_cli_snapshot!("backends", "list"); + } +} diff --git a/src/cli/backends/mod.rs b/src/cli/backends/mod.rs new file mode 100644 index 000000000..f571ae66d --- /dev/null +++ b/src/cli/backends/mod.rs @@ -0,0 +1,32 @@ +use clap::Subcommand; +use eyre::Result; + +mod ls; + +#[derive(Debug, clap::Args)] +#[clap(about = "Manage backends", visible_alias = "b", aliases = ["backend", "backend-list"])] +pub struct Backends { + #[clap(subcommand)] + command: Option, +} + +#[derive(Debug, Subcommand)] +enum Commands { + Ls(ls::BackendsLs), +} + +impl Commands { + pub fn run(self) -> Result<()> { + match self { + Self::Ls(cmd) => cmd.run(), + } + } +} + +impl Backends { + pub fn run(self) -> Result<()> { + let cmd = self.command.unwrap_or(Commands::Ls(ls::BackendsLs {})); + + cmd.run() + } +} diff --git a/src/cli/backends/snapshots/mise__cli__backends__ls__tests__backends_list.snap b/src/cli/backends/snapshots/mise__cli__backends__ls__tests__backends_list.snap new file mode 100644 index 000000000..c402d45b0 --- /dev/null +++ b/src/cli/backends/snapshots/mise__cli__backends__ls__tests__backends_list.snap @@ -0,0 +1,9 @@ +--- +source: src/cli/backends/ls.rs +expression: output +--- +cargo +go +npm +pipx +ubi diff --git a/src/cli/doctor.rs b/src/cli/doctor.rs index 756c7d3b2..db17a4772 100644 --- a/src/cli/doctor.rs +++ b/src/cli/doctor.rs @@ -10,6 +10,7 @@ use crate::cli::version; use crate::cli::version::VERSION; use crate::config::{Config, Settings}; use crate::file::display_path; +use crate::forge::ForgeType; use crate::git::Git; use crate::plugins::core::CORE_PLUGINS; use crate::plugins::PluginType; @@ -100,6 +101,7 @@ impl Doctor { let config = config.as_ref(); section("config_files", render_config_files(config))?; + section("backends", render_backends())?; section("plugins", render_plugins())?; for plugin in forge::list() { @@ -239,11 +241,22 @@ fn render_config_files(config: &Config) -> String { .join("\n") } +fn render_backends() -> String { + let mut s = vec![]; + let backends = forge::list_forge_types() + .into_iter() + .filter(|f| *f != ForgeType::Asdf); + for b in backends { + s.push(format!("{}", b)); + } + s.join("\n") +} + fn render_plugins() -> String { let mut s = vec![]; let plugins = forge::list() .into_iter() - .filter(|p| p.is_installed()) + .filter(|p| p.is_installed() && p.get_type() == ForgeType::Asdf) .collect::>(); let max_plugin_name_len = plugins .iter() diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 1b8e80950..14efd4469 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -8,6 +8,7 @@ mod activate; mod alias; pub mod args; mod asdf; +pub mod backends; mod bin_paths; mod cache; mod completion; @@ -62,6 +63,7 @@ pub enum Commands { Activate(activate::Activate), Alias(alias::Alias), Asdf(asdf::Asdf), + Backends(backends::Backends), BinPaths(bin_paths::BinPaths), Cache(cache::Cache), Completion(completion::Completion), @@ -117,6 +119,7 @@ impl Commands { Self::Activate(cmd) => cmd.run(), Self::Alias(cmd) => cmd.run(), Self::Asdf(cmd) => cmd.run(), + Self::Backends(cmd) => cmd.run(), Self::BinPaths(cmd) => cmd.run(), Self::Cache(cmd) => cmd.run(), Self::Completion(cmd) => cmd.run(), diff --git a/src/forge/mod.rs b/src/forge/mod.rs index e68d1877f..bee30db99 100644 --- a/src/forge/mod.rs +++ b/src/forge/mod.rs @@ -1,5 +1,5 @@ use std::collections::BTreeMap; -use std::fmt::{Debug, Display}; +use std::fmt::{Debug, Display, Formatter}; use std::fs::File; use std::hash::Hash; use std::path::{Path, PathBuf}; @@ -12,6 +12,7 @@ use eyre::WrapErr; use itertools::Itertools; use rayon::prelude::*; use regex::Regex; +use strum::IntoEnumIterator; use versions::Versioning; use crate::cli::args::ForgeArg; @@ -41,7 +42,9 @@ pub type AForge = Arc; pub type ForgeMap = BTreeMap; pub type ForgeList = Vec; -#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, EnumString, AsRefStr, Ord, PartialOrd)] +#[derive( + Debug, PartialEq, Eq, Hash, Clone, Copy, EnumString, EnumIter, AsRefStr, Ord, PartialOrd, +)] #[strum(serialize_all = "snake_case")] pub enum ForgeType { Asdf, @@ -52,6 +55,12 @@ pub enum ForgeType { Ubi, } +impl Display for ForgeType { + fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result { + write!(formatter, "{}", format!("{:?}", self).to_lowercase()) + } +} + static FORGES: Mutex> = Mutex::new(None); fn load_forges() -> ForgeMap { @@ -95,6 +104,10 @@ pub fn list() -> ForgeList { load_forges().values().cloned().collect() } +pub fn list_forge_types() -> Vec { + ForgeType::iter().collect() +} + pub fn get(fa: &ForgeArg) -> AForge { if let Some(forge) = load_forges().get(fa) { forge.clone()