use crate::config; use crate::compression_engine::CompressionType; use crate::meta_plugin::MetaPluginType; use clap::Command; use clap::error::ErrorKind; use comfy_table::{Table, ContentArrangement}; use log::debug; use regex::Regex; use std::collections::HashMap; use std::env; use std::str::FromStr; use strum::IntoEnumIterator; #[derive(Debug, Clone, strum::EnumString, strum::Display, PartialEq)] #[strum(ascii_case_insensitive)] pub enum OutputFormat { Table, Json, Yaml, } pub fn get_meta_from_env() -> HashMap { debug!("COMMON: Getting meta from KEEP_META_*"); let re = Regex::new(r"^KEEP_META_(.+)$").unwrap(); let mut meta_env: HashMap = HashMap::new(); for (key, value) in env::vars() { if let Some(meta_name_caps) = re.captures(key.as_str()) { let name = String::from(meta_name_caps.get(1).unwrap().as_str()); // Ignore KEEP_META_PLUGINS if name != "PLUGINS" { debug!("COMMON: Found meta: {}={}", name.clone(), value.clone()); meta_env.insert(name, value.clone()); } } } meta_env } pub fn format_size(size: u64, human_readable: bool) -> String { match human_readable { true => humansize::format_size(size, humansize::DECIMAL), false => size.to_string(), } } #[derive(Debug, Eq, PartialEq, Clone, strum::EnumIter, strum::Display, strum::EnumString)] #[strum(ascii_case_insensitive)] pub enum ColumnType { Id, Time, Size, Compression, FileSize, FilePath, Tags, Meta, } impl ColumnType { /// Returns a Result with error message if the string is not a valid ColumnType pub fn from_str(s: &str) -> anyhow::Result { if s.starts_with("meta:") { // Handle meta: pattern - this is still a Meta column type Ok(ColumnType::Meta) } else { // Handle regular column types Ok(Self::try_from(s)?) } } } // impl TryFrom<&str> for ColumnType is already implemented by strum_macros // so we remove this conflicting implementation pub fn settings_meta_plugin_types(cmd: &mut Command, settings: &config::Settings) -> Vec { let mut meta_plugin_types = Vec::new(); // Handle comma-separated values in each meta_plugins argument for meta_plugin_names_str in &settings.meta_plugins_names() { let meta_plugin_names: Vec<&str> = meta_plugin_names_str.split(',').collect(); for name in meta_plugin_names { let trimmed_name = name.trim(); if trimmed_name.is_empty() { continue; } // Try to find the MetaPluginType by meta name let mut found = false; for meta_plugin_type in MetaPluginType::iter() { let meta_plugin = crate::meta_plugin::get_meta_plugin(meta_plugin_type.clone(), None, None); if meta_plugin.meta_type().to_string() == trimmed_name { meta_plugin_types.push(meta_plugin_type); found = true; break; } } if !found { cmd.error( ErrorKind::InvalidValue, format!("Unknown meta plugin type: {}", trimmed_name), ) .exit(); } } } meta_plugin_types } pub fn settings_compression_type(cmd: &mut Command, settings: &config::Settings) -> CompressionType { let compression_name = settings .compression() .unwrap_or(CompressionType::LZ4.to_string()); let compression_type_opt = CompressionType::from_str(&compression_name); if compression_type_opt.is_err() { cmd.error( ErrorKind::InvalidValue, format!("Invalid compression algorithm '{}'. Supported algorithms: lz4, gzip, xz, zstd", compression_name), ) .exit(); } compression_type_opt.unwrap() } pub fn settings_output_format(settings: &config::Settings) -> OutputFormat { settings.output_format .as_ref() .and_then(|s| OutputFormat::from_str(s).ok()) .unwrap_or(OutputFormat::Table) } /// Create a table with consistent styling and terminal detection pub fn create_table(use_styling: bool) -> Table { let mut table = Table::new(); table.set_content_arrangement(ContentArrangement::Dynamic); if use_styling { table .load_preset(comfy_table::presets::UTF8_FULL) .apply_modifier(comfy_table::modifiers::UTF8_ROUND_CORNERS); } else { table.load_preset(comfy_table::presets::NOTHING); } table.force_no_tty_if(!std::io::stdout().is_terminal()); table }