use std::path::{Path, PathBuf};
use crate::{CliError, CliResult};
const RUST_CHEAT_SHEET: &str = "\
# Aristo annotation syntax — Rust
## Attribute form (preferred for fn / struct / impl / trait / mod / type / field / variant)
#[aristo::intent(\"text here\", verify = \"test\", id = \"snake_case_id\", parent = \"other_id\")]
fn the_thing() { ... }
## Function-like form (sub-item: before a statement / loop / block)
aristo::intent_stmt!(\"text here\", verify = \"test\");
for item in items { ... }
## Assume (no verify field; states external invariants you rely on)
#[aristo::assume(\"OS guarantee or library invariant\")]
fn the_thing() { ... }
## Parent linkage (singular or list)
parent = \"balance_no_duplicate_cells\"
parent = [\"a\", \"b\"]
## Verify levels
false | documentation only; no check ever runs
\"neural\" | AI-reasoned property check
\"test\" | mined assertions + existing test suite
\"full\" | server formal proof attempt (paid tier)
true | resolves to project default in aristo.toml [verify] default_method
## Namespace prefix
`aristos:` and `kanon:` prefixes are applied by `aristo canon accept`
when you accept a pending canon match. NEVER write them manually.
## Cargo features (in your `Cargo.toml`)
aristo_verify | injects mined assertions during `aristo verify --filter ...`
aristo_check | compile-time per-annotation validation
aristo_doc | rustdoc integration via include_str!
";
#[aristo::intent(
"The cheat sheet text MUST match the macros `aristo-macros` \
currently exports. Adding, renaming, or removing a macro requires \
updating the cheat sheet in the same change — agents are \
instructed to trust this output over their training data.",
verify = "test",
id = "lang_cheat_sheet_matches_macros"
)]
pub(crate) fn run(file: Option<PathBuf>) -> CliResult<()> {
let cwd = std::env::current_dir()?;
let lang = match file {
Some(path) => detect_for_file(&path)?,
None => detect_for_dir(&cwd)?,
};
emit_cheat_sheet(lang);
Ok(())
}
enum Lang {
Rust { manifest: PathBuf },
}
fn detect_for_dir(cwd: &Path) -> CliResult<Lang> {
let cargo_toml = cwd.join("Cargo.toml");
if cargo_toml.is_file() {
return Ok(Lang::Rust {
manifest: cargo_toml,
});
}
Err(unsupported_error())
}
fn detect_for_file(path: &Path) -> CliResult<Lang> {
if path.extension().and_then(|s| s.to_str()) == Some("rs") {
return Ok(Lang::Rust {
manifest: path.to_path_buf(),
});
}
Err(unsupported_error())
}
fn unsupported_error() -> CliError {
CliError::Other {
message: "Cannot detect a supported language in this repository.\n \
Aristo supports: Rust.\n \
Planned: Python, Go, TypeScript."
.to_string(),
exit_code: 2,
}
}
fn emit_cheat_sheet(lang: Lang) {
match lang {
Lang::Rust { manifest } => {
println!(
"Detected language: Rust (from Cargo.toml at {})",
manifest.display()
);
println!();
print!("{RUST_CHEAT_SHEET}");
}
}
}