use anyhow::anyhow;
use anyhow::Result;
use clap::ArgGroup;
use clap::Parser;
use llmcc::run_main;
use llmcc::LlmccOptions;
use llmcc_python::LangPython;
use llmcc_rust::LangRust;
#[derive(Parser, Debug)]
#[command(
name = "llmcc",
about = "llmcc: llm context compiler",
version,
group = ArgGroup::new("inputs").required(true).args(["files", "dirs"])
)]
pub struct Cli {
#[arg(
short = 'f',
long = "file",
value_name = "FILE",
num_args = 1..,
action = clap::ArgAction::Append,
conflicts_with = "dirs"
)]
files: Vec<String>,
#[arg(
short = 'd',
long = "dir",
value_name = "DIR",
num_args = 1..,
action = clap::ArgAction::Append,
conflicts_with = "files"
)]
dirs: Vec<String>,
#[arg(long, value_name = "LANG", default_value = "rust")]
lang: String,
#[arg(long, default_value_t = false)]
print_ir: bool,
#[arg(long, default_value_t = false)]
print_block: bool,
#[arg(
long = "design-graph",
default_value_t = false,
conflicts_with_all = ["depends", "dependents", "query"]
)]
design_graph: bool,
#[arg(long, default_value_t = false)]
summary: bool,
#[arg(long, default_value_t = false)]
pagerank: bool,
#[arg(long, value_name = "K", requires = "pagerank")]
top_k: Option<usize>,
#[arg(long, value_name = "NAME")]
query: Option<String>,
#[arg(long, default_value_t = false)]
recursive: bool,
#[arg(long, default_value_t = false, conflicts_with = "dependents")]
depends: bool,
#[arg(long, default_value_t = false, conflicts_with = "depends")]
dependents: bool,
}
pub fn run(args: Cli) -> Result<()> {
if std::env::var("RUST_LOG").is_ok() {
tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.with_writer(std::io::stderr)
.init();
}
if args.query.is_none() && (args.depends || args.dependents) {
eprintln!("Warning: --depends/--dependents flags are ignored without --query");
}
if args.pagerank && !args.design_graph {
return Err(anyhow!("--pagerank requires --design-graph"));
}
let opts = LlmccOptions {
files: args.files,
dirs: args.dirs,
print_ir: args.print_ir,
print_block: args.print_block,
design_graph: args.design_graph,
pagerank: args.pagerank,
top_k: args.top_k,
query: args.query,
depends: args.depends,
dependents: args.dependents,
recursive: args.recursive,
summary: args.summary,
};
let result = match args.lang.as_str() {
"rust" => run_main::<LangRust>(&opts),
"python" => run_main::<LangPython>(&opts),
_ => Err(format!("Unknown language: {}", args.lang).into()),
};
if let Ok(Some(output)) = result {
println!("{output}");
}
Ok(())
}
pub fn main() -> Result<()> {
let args = Cli::parse();
run(args)
}