use super::*;
pub(crate) fn run_init(project_name: &str) {
let project_dir = Path::new(project_name);
if project_dir.exists() {
eprintln!("Error: directory '{project_name}' already exists");
process::exit(1);
}
let contracts_dir = project_dir.join("contracts");
fs::create_dir_all(&contracts_dir).unwrap_or_else(|e| {
eprintln!("Error: cannot create directory: {e}");
process::exit(1);
});
let toml_content = format!(
r#"[package]
name = "{project_name}"
version = "0.1.0"
[build]
target = "native" # "native" or "wasm32-wasi"
output = "generated"
[verify]
smt-solver = "z3" # "z3", "cvc5", or "portfolio"
layer = 1 # 0 = structural only, 1 = SMT
timeout = 1000 # SMT timeout in ms
[profile]
type = "minimal" # minimal, parser, database, etc.
# [ai]
# mode = "api" # "api" (direct HTTP) or "cli" (shell out)
# provider = "anthropic" # "anthropic", "openai", "ollama"
# model = "claude-sonnet-4-20250514"
#
# For CLI mode (any tool that accepts a prompt):
# mode = "cli"
# command = "claude" # or "aider", "sgpt", etc.
# args = ["-p", "{{prompt}}"] # {{prompt}} is replaced with the actual prompt
"#
);
let toml_path = project_dir.join("assura.toml");
fs::write(&toml_path, &toml_content).unwrap_or_else(|e| {
eprintln!("Error: cannot write {}: {e}", toml_path.display());
process::exit(1);
});
let contract_content = r#"// SafeDivision: ensures division by zero is impossible
//
// The requires clause guarantees callers must pass a non-zero divisor.
// The ensures clause states the result is always defined (not an error).
contract SafeDivision {
input(a: Int, b: Int)
output(result: Int)
requires { b != 0 }
ensures { b != 0 }
}
"#;
let contract_path = contracts_dir.join("lib.assura");
fs::write(&contract_path, contract_content).unwrap_or_else(|e| {
eprintln!("Error: cannot write {}: {e}", contract_path.display());
process::exit(1);
});
println!("Created new Assura project '{project_name}':");
println!(" {}", toml_path.display());
println!(" {}", contract_path.display());
}
pub(crate) fn run_explain(code: &str) {
match assura_diagnostics::explain(code) {
Some(info) => {
println!("{}: {}", info.code, info.name);
println!();
println!("{}", info.description);
println!();
println!("Example:");
println!();
println!("{}", info.example);
println!();
println!("How to fix:");
println!();
println!("{}", info.fix);
}
None => {
eprintln!("Unknown error code: {code}");
eprintln!();
eprintln!("Known error codes:");
let catalog = assura_diagnostics::error_catalog();
for info in &catalog {
eprintln!(" {} - {}", info.code, info.name);
}
process::exit(1);
}
}
}