use std::collections::BTreeSet;
use std::sync::Arc;
use eyre::Result;
use rayon::prelude::*;
use tabled::settings::object::Columns;
use tabled::settings::{Margin, Modify, Padding, Style};
use tabled::Tabled;
use crate::config::Config;
use crate::plugins::{ExternalPlugin, PluginType};
#[derive(Debug, clap::Args)]
#[clap(visible_alias = "list", after_long_help = AFTER_LONG_HELP, verbatim_doc_comment)]
pub struct PluginsLs {
#[clap(short, long, hide = true, verbatim_doc_comment)]
pub all: bool,
#[clap(short, long, verbatim_doc_comment, conflicts_with = "all")]
pub core: bool,
#[clap(long, verbatim_doc_comment, conflicts_with = "all")]
pub user: bool,
#[clap(short, long, alias = "url", verbatim_doc_comment)]
pub urls: bool,
#[clap(long, hide = true, verbatim_doc_comment)]
pub refs: bool,
}
impl PluginsLs {
pub fn run(self, config: &Config) -> Result<()> {
let mut tools = config.list_plugins().into_iter().collect::<BTreeSet<_>>();
if self.all {
for (plugin, url) in config.get_shorthands() {
let mut ep = ExternalPlugin::new(plugin.clone());
ep.repo_url = Some(url.to_string());
tools.insert(Arc::new(ep));
}
} else if self.user && self.core {
} else if self.core {
tools.retain(|p| matches!(p.get_type(), PluginType::Core));
} else {
tools.retain(|p| matches!(p.get_type(), PluginType::External));
}
if self.urls || self.refs {
let data = tools
.into_par_iter()
.map(|p| {
let mut row = Row {
plugin: p.name().to_string(),
url: p.get_remote_url().unwrap_or_default(),
ref_: String::new(),
sha: String::new(),
};
if p.is_installed() {
row.ref_ = p.current_abbrev_ref().unwrap_or_default();
row.sha = p.current_sha_short().unwrap_or_default();
}
row
})
.collect::<Vec<_>>();
let mut table = tabled::Table::new(data);
table
.with(Style::empty())
.with(Margin::new(0, 0, 0, 0))
.with(Modify::new(Columns::first()).with(Padding::new(0, 1, 0, 0)))
.with(Modify::new(Columns::last()).with(Padding::zero()));
rtxprintln!("{table}");
} else {
for tool in tools {
rtxprintln!("{tool}");
}
}
Ok(())
}
}
#[derive(Tabled)]
#[tabled(rename_all = "PascalCase")]
struct Row {
plugin: String,
url: String,
ref_: String,
sha: String,
}
static AFTER_LONG_HELP: &str = color_print::cstr!(
r#"<bold><underline>Examples:</underline></bold>
$ <bold>rtx plugins ls</bold>
node
ruby
$ <bold>rtx plugins ls --urls</bold>
node https://github.com/asdf-vm/asdf-node.git
ruby https://github.com/asdf-vm/asdf-ruby.git
"#
);
#[cfg(test)]
mod tests {
use crate::cli::tests::grep;
#[test]
fn test_plugin_list() {
assert_cli_snapshot!("plugin", "list");
}
#[test]
fn test_plugin_list_urls() {
let stdout = assert_cli!("plugin", "list", "--urls");
assert!(stdout.contains("dummy"))
}
#[test]
fn test_plugin_list_all() {
let stdout = assert_cli!("plugin", "list", "--all", "--urls");
assert_snapshot!(grep(stdout, "zephyr"));
}
#[test]
fn test_plugin_refs() {
let stdout = assert_cli!("plugin", "list", "--refs");
assert!(stdout.contains("dummy"))
}
}