envx_cli/
rename.rs

1use clap::{Args, arg};
2use color_eyre::Result;
3use comfy_table::{Table, presets::UTF8_FULL};
4use envx_core::{EnvVarManager, env::split_wildcard_pattern};
5
6#[derive(Args)]
7pub struct RenameArgs {
8    /// Pattern to match (supports wildcards with *)
9    pub pattern: String,
10
11    /// New name or pattern
12    pub replacement: String,
13
14    /// Dry run - show what would be renamed without making changes
15    #[arg(long)]
16    pub dry_run: bool,
17}
18
19/// Handle rename command to rename environment variables using patterns.
20///
21/// # Errors
22///
23/// This function will return an error if:
24/// - Environment variable operations fail (loading, renaming)
25/// - Pattern matching fails or produces invalid results
26/// - Variable names conflict or are invalid
27/// - File I/O operations fail when persisting changes
28/// - User input cannot be read from stdin during confirmation
29pub fn handle_rename(args: &RenameArgs) -> Result<()> {
30    let mut manager = EnvVarManager::new();
31    manager.load_all()?;
32
33    if args.dry_run {
34        // Show what would be renamed
35        let preview = preview_rename(&manager, &args.pattern, &args.replacement)?;
36
37        if preview.is_empty() {
38            println!("No variables match the pattern '{}'", args.pattern);
39        } else {
40            println!("Would rename {} variable(s):", preview.len());
41
42            let mut table = Table::new();
43            table.load_preset(UTF8_FULL);
44            table.set_header(vec!["Current Name", "New Name", "Value"]);
45
46            for (old, new, value) in preview {
47                table.add_row(vec![old, new, value]);
48            }
49
50            println!("{table}");
51            println!("\nUse without --dry-run to apply changes");
52        }
53    } else {
54        let renamed = manager.rename(&args.pattern, &args.replacement)?;
55
56        if renamed.is_empty() {
57            println!("No variables match the pattern '{}'", args.pattern);
58        } else {
59            println!("āœ… Renamed {} variable(s):", renamed.len());
60
61            let mut table = Table::new();
62            table.load_preset(UTF8_FULL);
63            table.set_header(vec!["Old Name", "New Name"]);
64
65            for (old, new) in &renamed {
66                table.add_row(vec![old.clone(), new.clone()]);
67            }
68
69            println!("{table}");
70
71            #[cfg(windows)]
72            println!("\nšŸ“ Note: You may need to restart your terminal for changes to take effect");
73        }
74    }
75
76    Ok(())
77}
78
79fn preview_rename(manager: &EnvVarManager, pattern: &str, replacement: &str) -> Result<Vec<(String, String, String)>> {
80    let mut preview = Vec::new();
81
82    if pattern.contains('*') {
83        let (prefix, suffix) = split_wildcard_pattern(pattern)?;
84        let (new_prefix, new_suffix) = split_wildcard_pattern(replacement)?;
85
86        for var in manager.list() {
87            if var.name.starts_with(&prefix)
88                && var.name.ends_with(&suffix)
89                && var.name.len() >= prefix.len() + suffix.len()
90            {
91                let middle = &var.name[prefix.len()..var.name.len() - suffix.len()];
92                let new_name = format!("{new_prefix}{middle}{new_suffix}");
93                preview.push((var.name.clone(), new_name, var.value.clone()));
94            }
95        }
96    } else if let Some(var) = manager.get(pattern) {
97        preview.push((var.name.clone(), replacement.to_string(), var.value.clone()));
98    }
99
100    Ok(preview)
101}