use crate::cli_lang::CliLang;
use cure_java_simplify::{all_java_rules, default_java_rules};
pub(crate) const REPO_URL: &str = "https://github.com/ejfkdev/cure";
pub(crate) fn print_help() {
match CliLang::detect() {
CliLang::Zh => print_help_zh(),
CliLang::En => print_help_en(),
}
}
pub(crate) fn print_version() {
match CliLang::detect() {
CliLang::Zh => println!(
"cure {}(容错式代码简化/格式化器;后端:java、typescript/javascript、python 2.7/3.x)\n{REPO_URL}",
env!("CARGO_PKG_VERSION")
),
CliLang::En => println!(
"cure {} — fault-tolerant code simplifier/formatter (backends: java, typescript/javascript, python 2.7/3.x)\n{REPO_URL}",
env!("CARGO_PKG_VERSION")
),
}
}
fn print_help_en() {
let v = env!("CARGO_PKG_VERSION");
println!("cure {v} — fault-tolerant, semantic-preserving code simplifier/formatter");
println!("Decompiled code in, human-written-looking code out.");
println!("Supported languages: java, typescript/javascript (ts/tsx/mts/cts/js/jsx/mjs/cjs), python 2.7/3.x (py/pyi).");
println!("{REPO_URL} (MIT license)");
println!();
println!("Usage:");
println!(" cure [OPTIONS] <file>... files; single file → stdout by default");
println!(" cure [OPTIONS] <dir>... directory (recursive, parallel)");
println!(" cure [OPTIONS] - read stdin, write stdout");
println!(" cure rules list all simplification rules");
println!(" cure help [COMMAND] this help, or one command's");
println!(" cure version | -h | -V");
println!();
println!("Languages: java, typescript/javascript, python 2.7/3.x (this release).");
println!("The CLI and engine are language-agnostic: a new backend registers in");
println!("LANG_BACKENDS and gets the whole pipeline (traversal, parallelism,");
println!("--check/--diff/--stats, batched I/O).");
println!();
println!("Language: CURE_LANG=zh|en forces; otherwise auto-detected from the");
println!("locale environment (on Windows: the system UI language).");
println!();
println!("Directory mode mirrors the tree into <dir>-cure-out/ (hierarchy");
println!("preserved); -o sets another root, -w rewrites in place. Broken");
println!("regions of a file are preserved verbatim — a parse error never");
println!("aborts the run (--strict makes it exit 1 for CI).");
println!();
println!("Options:");
println!(" -o, --output <path> output path (single file) or output root (dir)");
println!(" -w, --write rewrite input files in place");
println!(" --check dry run: exit 2 if rewritable; write nothing");
println!(" -j, --threads <N> worker threads (default: CPU cores × 1.5)");
println!(" --format-only format only, no simplification");
println!(" -l, --lang <name> force java | ts/js/typescript/javascript | py/python/python3/pyi");
println!(" --ext <list> only given extensions (comma/space separated)");
println!(" --copy-other dir mode: copy non-source files verbatim");
println!(" --diff print unified diffs of rewritten files");
println!(" --stats summary statistics (files/lines/rules)");
println!(" --report per-file rewrite statistics on stderr");
println!(" --disable <rule> disable a rule (repeatable; `cure rules` lists all)");
println!(" --dead-code opt-in: drop dead private methods/fields and no-op calls");
println!(" --preserve-function-source");
println!(" TS/JS: print functions/classes/object literals");
println!(" byte-for-byte (Function.prototype.toString);");
println!(" disables simplification inside those regions");
println!(" --jdk-home <path> verify Class.forName targets against that JDK (default: java.base whitelist)");
println!(" --strict exit 1 on any parse error (default: warn)");
println!(" -h, --help this help");
println!(" -V, --version version and repository");
println!();
println!("Exit status: 0 ok; 1 --strict with parse errors; 2 usage error /");
println!("--check found rewrites.");
println!();
println!("Examples:");
println!(" # one file to stdout");
println!(" echo 'class A{{int m(){{int a=foo();int b=a;return b;}}}}' | cure -");
println!(" cure Input.java");
println!();
println!(" # Python 2.7 / 3.x (.py/.pyi auto-detected; -l py forces it)");
println!(" cure Script.py");
println!(" cure src/ -l py");
println!();
println!(" # a directory — mirror into src-cure-out/, hierarchy preserved");
println!(" cure src/");
println!(" cure src/ -o out/ # another output root");
println!(" cure src/ -w # rewrite in place");
println!();
println!(" # CI gate: exit 2 when anything is rewritable, write nothing");
println!(" cure --check src/");
println!();
println!(" # see what changed");
println!(" cure --diff src/ | less");
println!(" cure --stats src/");
println!();
println!(" # tuning");
println!(" cure -j 32 big-corpus/ # worker threads");
println!(" cure --disable cff_recover src/ # turn one rule off");
}
fn print_help_zh() {
let v = env!("CARGO_PKG_VERSION");
println!("cure {v} — 容错式、语义保持的代码简化 / 格式化器");
println!("反编译代码进,像人手写的代码出。");
println!("已支持语言:java、typescript/javascript(ts/tsx/mts/cts/js/jsx/mjs/cjs)、python 2.7/3.x(py/pyi)。");
println!("{REPO_URL} (MIT 许可证)");
println!();
println!("用法:");
println!(" cure [选项] <文件>... 文件;单文件默认输出到 stdout");
println!(" cure [选项] <目录>... 目录(递归、并行)");
println!(" cure [选项] - 读 stdin、写 stdout");
println!(" cure rules 列出全部简化规则");
println!(" cure help [子命令] 本帮助,或某子命令的帮助");
println!(" cure version | -h | -V");
println!();
println!("语言后端: java、typescript/javascript、python 2.7/3.x(本版)。");
println!("CLI 与引擎均语言无关:在 LANG_BACKENDS 登记一条即获得全部基础设施");
println!("(目录遍历/并行/--check/--diff/--stats/批量 I/O)。");
println!();
println!("语言: CURE_LANG=zh|en 强制指定;否则按 locale 环境自动检测");
println!("(Windows:系统 UI 语言)。");
println!();
println!("目录模式默认镜像到 <目录>-cure-out/(保持层级结构);-o 指定别的");
println!("输出根,-w 原地覆写。文件的坏区域原文保留——语法错误不中断运行");
println!("(--strict 时退出码 1,供 CI 使用)。");
println!();
println!("选项:");
println!(" -o, --output <路径> 输出路径(单文件)或输出根目录(目录)");
println!(" -w, --write 原地覆写输入文件");
println!(" --check 干跑:有可优化改写 → 退出码 2,不写出");
println!(" -j, --threads <N> 并行工作线程数(默认=CPU 核心数 × 1.5)");
println!(" --format-only 仅格式化,不做简化");
println!(
" -l, --lang <语言> 强制 java | ts/js/typescript/javascript | py/python/python3/pyi"
);
println!(" --ext <后缀列表> 只处理指定后缀(逗号或空格分隔)");
println!(" --copy-other 目录模式:不受处理的文件原样拷入输出树");
println!(" --diff 打印被改写文件的统一 diff");
println!(" --stats 汇总统计(文件数/行数/逐规则)");
println!(" --report stderr 打印逐文件改写统计");
println!(" --disable <规则名> 禁用指定规则(可多次;`cure rules` 列出全部)");
println!(" --dead-code 选配:删除零引用 private 方法/字段与空方法 no-op 调用");
println!(" --preserve-function-source");
println!(" TS/JS:函数/类/对象字面量逐字节原样输出");
println!(" (兼容 Function.prototype.toString);");
println!(" 这些区域内部不做简化");
println!(" --jdk-home <路径> 用该 JDK 精确验证 Class.forName 目标类(默认 java.base 白名单)");
println!(" --strict 有解析错误 → 退出码 1(默认仅 stderr 提示)");
println!(" -h, --help 本帮助");
println!(" -V, --version 版本与仓库地址");
println!();
println!("退出码: 0 正常;1 --strict 且有解析错误;2 参数错误 / --check 发现有可改写。");
println!();
println!("示例:");
println!(" # 单文件到 stdout");
println!(" echo 'class A{{int m(){{int a=foo();int b=a;return b;}}}}' | cure -");
println!(" cure Input.java");
println!();
println!(" # Python 2.7 / 3.x(.py/.pyi 自动识别;-l py 强制指定)");
println!(" cure Script.py");
println!(" cure src/ -l py");
println!();
println!(" # 目录——镜像到 src-cure-out/,保持层级结构");
println!(" cure src/");
println!(" cure src/ -o out/ # 指定别的输出根");
println!(" cure src/ -w # 原地覆写");
println!();
println!(" # CI 门禁:有可优化改写 → 退出码 2,不写出任何内容");
println!(" cure --check src/");
println!();
println!(" # 看改了什么");
println!(" cure --diff src/ | less");
println!(" cure --stats src/");
println!();
println!(" # 调优");
println!(" cure -j 32 big-corpus/ # 指定线程数");
println!(" cure --disable cff_recover src/ # 关掉某条规则");
}
pub(crate) fn print_rules_help() {
match CliLang::detect() {
CliLang::Zh => print_rules_zh(),
CliLang::En => print_rules_en(),
}
}
fn rule_catalog() -> (Vec<&'static str>, Vec<&'static str>) {
let defaults: Vec<&'static str> = default_java_rules().iter().map(|r| r.name()).collect();
let all: Vec<&'static str> = all_java_rules().iter().map(|r| r.name()).collect();
let opt_in: Vec<&'static str> =
all.into_iter().filter(|n| !defaults.contains(n)).collect();
(defaults, opt_in)
}
fn print_rules_en() {
let (defaults, opt_in) = rule_catalog();
let py = cure_python_simplify::default_rules();
let java = defaults.len() + opt_in.len();
println!(
"cure rules — {} simplification rules ({} Java + {} Python)",
java + py.len(),
java,
py.len()
);
println!("Names are what --disable takes.");
println!();
println!("Java enabled by default ({}):", defaults.len());
for n in &defaults {
println!(" {n}");
}
println!();
println!(
"Java opt-in ({}; available through the library API):",
opt_in.len()
);
for n in &opt_in {
println!(" {n}");
}
println!();
println!("Python (default, {}):", py.len());
for n in py {
println!(" {n}");
}
println!();
println!("Example: cure --disable cff_recover --disable xor_noise src/");
}
fn print_rules_zh() {
let (defaults, opt_in) = rule_catalog();
let py = cure_python_simplify::default_rules();
let java = defaults.len() + opt_in.len();
println!(
"cure rules — 共 {} 条简化规则(Java {} + Python {})",
java + py.len(),
java,
py.len()
);
println!("名字即 --disable 的取值。");
println!();
println!("Java 默认启用({} 条):", defaults.len());
for n in &defaults {
println!(" {n}");
}
println!();
println!(
"Java 选配({} 条;通过库 API 启用):",
opt_in.len()
);
for n in &opt_in {
println!(" {n}");
}
println!();
println!("Python(默认启用,{} 条):", py.len());
for n in py {
println!(" {n}");
}
println!();
println!("示例: cure --disable cff_recover --disable xor_noise src/");
}