acp/commands/
chain.rs

1//! @acp:module "Chain Command"
2//! @acp:summary "Show variable inheritance chain"
3//! @acp:domain cli
4//! @acp:layer handler
5
6use std::path::PathBuf;
7
8use anyhow::Result;
9use console::style;
10
11use crate::vars::{VarExpander, VarResolver, VarsFile};
12
13/// Options for the chain command
14#[derive(Debug, Clone)]
15pub struct ChainOptions {
16    /// Variable name
17    pub name: String,
18    /// Vars file path
19    pub vars: PathBuf,
20    /// Show as tree
21    pub tree: bool,
22}
23
24/// Execute the chain command
25pub fn execute_chain(options: ChainOptions) -> Result<()> {
26    let vars_file = VarsFile::from_json(&options.vars)?;
27    let resolver = VarResolver::new(vars_file);
28    let expander = VarExpander::new(resolver);
29
30    let name = options.name.trim_start_matches('$');
31    let chain = expander.get_inheritance_chain(name);
32
33    if options.tree {
34        println!("{}", style(format!("${}", name)).cyan().bold());
35        print_chain_tree(&chain.chain, 0);
36    } else {
37        println!("Root: {}", style(&chain.root).cyan());
38        println!("Depth: {}", chain.depth);
39        println!("Chain: {}", chain.chain.join(" → "));
40    }
41
42    Ok(())
43}
44
45/// Print inheritance chain as a tree
46fn print_chain_tree(chain: &[String], depth: usize) {
47    for (i, item) in chain.iter().enumerate() {
48        let prefix = if i == chain.len() - 1 {
49            "└── "
50        } else {
51            "├── "
52        };
53        let indent = "    ".repeat(depth);
54        println!("{}{}{}", indent, prefix, style(item).dim());
55    }
56}