lla 0.3.7

A lightweight ls replacement
use crate::config::Config;
use crate::error::Result;
use crate::plugin::PluginManager;
use colored::*;
use dialoguer::{theme::ColorfulTheme, MultiSelect};
use std::collections::HashSet;

pub fn list_plugins(plugin_manager: &mut PluginManager) -> Result<()> {
    if atty::is(atty::Stream::Stdout) {
        let plugins: Vec<(String, String, String)> =
            plugin_manager.list_plugins().into_iter().collect();

        let plugin_names: Vec<String> = plugins
            .iter()
            .map(|(name, version, desc)| {
                format!(
                    "{} {} - {}",
                    name.cyan(),
                    format!("v{}", version).yellow(),
                    desc
                )
            })
            .collect();

        println!("\n{}", "Plugin Manager".cyan().bold());
        println!("{}\n", "Space to toggle, Enter to confirm".bright_black());

        let theme = ColorfulTheme {
            active_item_style: dialoguer::console::Style::new().cyan().bold(),
            active_item_prefix: dialoguer::console::style("│ ⦿ ".to_string())
                .for_stderr()
                .cyan(),
            checked_item_prefix: dialoguer::console::style("".to_string())
                .for_stderr()
                .green(),
            unchecked_item_prefix: dialoguer::console::style("".to_string())
                .for_stderr()
                .red(),
            prompt_prefix: dialoguer::console::style("".to_string())
                .for_stderr()
                .cyan(),
            prompt_style: dialoguer::console::Style::new().for_stderr().cyan(),
            success_prefix: dialoguer::console::style("".to_string())
                .for_stderr()
                .cyan(),
            ..ColorfulTheme::default()
        };

        let selections = MultiSelect::with_theme(&theme)
            .with_prompt("Select plugins")
            .items(&plugin_names)
            .defaults(
                &plugins
                    .iter()
                    .map(|(name, _, _)| plugin_manager.enabled_plugins.contains(name))
                    .collect::<Vec<_>>(),
            )
            .interact()?;

        let mut updated_plugins = HashSet::new();

        for idx in selections {
            let (name, _, _) = &plugins[idx];
            updated_plugins.insert(name.to_string());
        }

        for (name, _, _) in &plugins {
            if updated_plugins.contains(name) {
                plugin_manager.enable_plugin(name)?;
            } else {
                plugin_manager.disable_plugin(name)?;
            }
        }
    } else {
        for (name, version, desc) in plugin_manager.list_plugins() {
            println!(
                "{} {} - {}",
                name.cyan(),
                format!("v{}", version).yellow(),
                desc
            );
        }
    }

    Ok(())
}

pub fn handle_plugin_action(
    config: &mut Config,
    plugin_name: &str,
    action: &str,
    args: &[String],
) -> Result<()> {
    let mut plugin_manager = PluginManager::new(config.clone());
    plugin_manager.discover_plugins(&config.plugins_dir)?;
    plugin_manager.perform_plugin_action(plugin_name, action, args)
}