use clap::*; use is_terminal::IsTerminal; use std::path::PathBuf; use std::str::FromStr; use log::debug; use crate::modes::common::OutputFormat; use crate::config; use serde_json; use serde_yaml; use prettytable::row; use prettytable::{Attr, Cell, Row, Table}; use prettytable::format::consts::{FORMAT_BOX_CHARS, FORMAT_NO_BORDER_LINE_SEPARATOR}; use crate::meta_plugin::{MetaPluginType, get_meta_plugin}; use crate::common::status::{MetaPluginInfo, CompressionInfo}; use crate::services::filter_service::get_available_filter_plugins; use prettytable::color; fn build_meta_plugin_table(meta_plugin_info: &std::collections::HashMap) -> Table { let mut meta_plugin_table = Table::new(); if std::io::stdout().is_terminal() { meta_plugin_table.set_format(*FORMAT_BOX_CHARS); } else { meta_plugin_table.set_format(*FORMAT_NO_BORDER_LINE_SEPARATOR); } meta_plugin_table.set_titles(row!( b->"Plugin Name", b->"Options", b->"Outputs")); // Sort meta plugin info by plugin name let mut sorted_meta_plugin_info: Vec<&MetaPluginInfo> = meta_plugin_info.values().collect(); sorted_meta_plugin_info.sort_by(|a, b| a.meta_name.cmp(&b.meta_name)); for info in sorted_meta_plugin_info { // Get default options for the meta plugin let meta_plugin_type = match MetaPluginType::from_str(&info.meta_name) { Ok(plugin_type) => plugin_type, Err(_) => continue, }; // Create a default plugin to get its default options let default_plugin = get_meta_plugin( meta_plugin_type.clone(), None, None, ); // Get and sort options let mut options: Vec<_> = default_plugin.options().iter().collect(); options.sort_by(|a, b| a.0.cmp(b.0)); // Format options as YAML string, each on a new line let options_str = if options.is_empty() { "{}".to_string() } else { let options_map: std::collections::BTreeMap<_, _> = options.into_iter().collect(); serde_yaml::to_string(&options_map) .unwrap_or_else(|_| "Unable to serialize options".to_string()) .trim() .to_string() }; // Get and sort output keys let mut output_keys: Vec = info.outputs.keys().map(|k| k.to_string()).collect(); output_keys.sort(); let outputs_display = if output_keys.is_empty() { "{}".to_string() } else { output_keys.join("\n") }; meta_plugin_table.add_row(Row::new(vec![ Cell::new(&info.meta_name), Cell::new(&options_str), Cell::new(&outputs_display), ])); } meta_plugin_table } fn build_compression_table(compression_info: &Vec) -> Table { let mut compression_table = Table::new(); if std::io::stdout().is_terminal() { compression_table.set_format(*FORMAT_BOX_CHARS); } else { compression_table.set_format(*FORMAT_NO_BORDER_LINE_SEPARATOR); } compression_table.set_titles(row!( b->"Type", b->"Found", b->"Enabled", b->"Binary", b->"Compress", b->"Decompress")); for info in compression_info { compression_table.add_row(Row::new(vec![ Cell::new(&info.compression_type), match info.found { true => Cell::new("Yes").with_style(Attr::ForegroundColor(color::GREEN)), false => Cell::new("No").with_style(Attr::ForegroundColor(color::RED)), }, match info.default { true => Cell::new("Yes").with_style(Attr::ForegroundColor(color::GREEN)), false => Cell::new("No"), }, match info.binary.as_str() { "" => Cell::new(&info.binary).with_style(Attr::ForegroundColor(color::BRIGHT_BLACK)), _ => Cell::new(&info.binary), }, Cell::new(&info.compress), Cell::new(&info.decompress), ])); } compression_table } fn build_filter_plugin_table(filter_plugins: &Vec) -> Table { let mut filter_plugin_table = Table::new(); if std::io::stdout().is_terminal() { filter_plugin_table.set_format(*FORMAT_BOX_CHARS); } else { filter_plugin_table.set_format(*FORMAT_NO_BORDER_LINE_SEPARATOR); } filter_plugin_table.set_titles(row!( b->"Plugin Name", b->"Options", b->"Description")); // Sort plugins by name let mut sorted_plugin_names = filter_plugins.clone(); sorted_plugin_names.sort(); for plugin_name in sorted_plugin_names { // Get the plugin creator let filter_plugins_map = crate::filter_plugin::get_available_filter_plugins(); if let Some(plugin_creator) = filter_plugins_map.get(&plugin_name) { // Create a temporary instance to get options let plugin = plugin_creator(); // Get options let options = plugin.options(); // Format options as YAML string let options_str = if options.is_empty() { "{}".to_string() } else { let options_map: std::collections::BTreeMap<_, _> = options .iter() .map(|opt| (opt.name.clone(), serde_yaml::to_value(opt).unwrap())) .collect(); serde_yaml::to_string(&options_map) .unwrap_or_else(|_| "Unable to serialize options".to_string()) .trim() .to_string() }; // Get description from the first option or use a default let description = if let Some(first_opt) = options.first() { first_opt.description.clone().unwrap_or_else(|| "Filter plugin".to_string()) } else { "Filter plugin".to_string() }; filter_plugin_table.add_row(Row::new(vec![ Cell::new(&plugin_name), Cell::new(&options_str), Cell::new(&description), ])); } } // If no filter plugins are available, add a row indicating that if filter_plugins.is_empty() { filter_plugin_table.add_row(Row::new(vec![ Cell::new("No filter plugins available"), Cell::new("{}"), Cell::new(""), ])); } filter_plugin_table } pub fn mode_status_plugins( cmd: &mut Command, settings: &config::Settings, data_path: PathBuf, db_path: PathBuf, ) -> Result<(), anyhow::Error> { debug!("STATUS_PLUGINS: Starting mode_status_plugins function"); let status_service = crate::services::status_service::StatusService::new(); let output_format = crate::modes::common::settings_output_format(settings); debug!("STATUS_PLUGINS: About to generate status info"); let status_info = status_service.generate_status(cmd, settings, data_path, db_path); debug!("STATUS_PLUGINS: Status info generated successfully"); match output_format { OutputFormat::Table => { println!("META PLUGINS:"); build_meta_plugin_table(&status_info.meta_plugins).printstd(); println!(); println!("COMPRESSION PLUGINS:"); build_compression_table(&status_info.compression).printstd(); println!(); println!("FILTER PLUGINS:"); build_filter_plugin_table(&status_info.filter_plugins).printstd(); println!(); Ok(()) }, OutputFormat::Json => { // Create a subset for plugins only let plugins_info = serde_json::json!({ "meta_plugins_available": status_info.meta_plugins, "meta_plugins_configured": settings.meta_plugins, "filter_plugins": status_info.filter_plugins }); println!("{}", serde_json::to_string_pretty(&plugins_info)?); Ok(()) }, OutputFormat::Yaml => { // Create a proper structure for plugins info use serde_yaml::Mapping; let mut plugins_mapping = Mapping::new(); // Add available plugins plugins_mapping.insert( serde_yaml::Value::String("meta_plugins_available".to_string()), serde_yaml::to_value(&status_info.meta_plugins)?, ); // Add configured plugins if they exist if let Some(configured_plugins) = &settings.meta_plugins { plugins_mapping.insert( serde_yaml::Value::String("meta_plugins_configured".to_string()), serde_yaml::to_value(configured_plugins)?, ); } // Add filter plugins plugins_mapping.insert( serde_yaml::Value::String("filter_plugins".to_string()), serde_yaml::to_value(&status_info.filter_plugins)?, ); println!("{}", serde_yaml::to_string(&plugins_mapping)?); Ok(()) } } }