Skip to content

Commit 20befd8

Browse files
hyperpolymathclaude
andcommitted
feat(jtv-cli): add jtv fmt subcommand
Exposes the existing format_code() formatter as a CLI command: jtv fmt <file> print formatted source to stdout jtv fmt - write read stdin, write formatted back to file jtv fmt --write <file> overwrite file in place jtv fmt --check <file> exit 1 if file would be reformatted (CI mode) Closes the last item in TECHNICAL_ROADMAP.md §7 Planned Commands. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 2678ff9 commit 20befd8

1 file changed

Lines changed: 47 additions & 0 deletions

File tree

crates/jtv-cli/src/main.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,20 @@ enum Commands {
8585
/// Start the interactive REPL
8686
Repl,
8787

88+
/// Format a JtV source file (prints to stdout; use shell redirection to overwrite)
89+
Fmt {
90+
/// Path to the .jtv file (use '-' for stdin)
91+
file: String,
92+
93+
/// Write result back to the file instead of stdout
94+
#[arg(short, long)]
95+
write: bool,
96+
97+
/// Exit with non-zero status if the file would change (check mode)
98+
#[arg(long)]
99+
check: bool,
100+
},
101+
88102
/// Lower live extern coproc decls to Zig FFI + Idris2 ABI + C headers
89103
Lower {
90104
/// Path to the .jtv source file
@@ -156,6 +170,12 @@ fn main() {
156170
std::process::exit(1);
157171
}
158172
}
173+
Commands::Fmt { file, write, check } => {
174+
if let Err(e) = fmt_file(&file, write, check) {
175+
eprintln!("{} {}", "Error:".red().bold(), e);
176+
std::process::exit(1);
177+
}
178+
}
159179
Commands::Lower { file, pata, target, features, output_dir } => {
160180
let feats: Vec<&str> = if features.is_empty() {
161181
vec![]
@@ -272,6 +292,33 @@ fn check_file(file_path: &str) -> Result<(), String> {
272292
Ok(())
273293
}
274294

295+
fn fmt_file(file_path: &str, write: bool, check: bool) -> Result<(), String> {
296+
let original = read_file(file_path)?;
297+
let formatted = format_code(&original).map_err(|e| format!("Format error: {}", e))?;
298+
299+
if check {
300+
if formatted == original {
301+
println!("{} {}", "✓".green().bold(), file_path);
302+
} else {
303+
eprintln!("{} {} would be reformatted", "✗".red().bold(), file_path);
304+
std::process::exit(1);
305+
}
306+
return Ok(());
307+
}
308+
309+
if write {
310+
if file_path == "-" {
311+
return Err("--write cannot be used with stdin input".into());
312+
}
313+
fs::write(file_path, &formatted).map_err(|e| format!("Write error: {}", e))?;
314+
println!("{} {}", "✓".green().bold(), file_path);
315+
} else {
316+
print!("{}", formatted);
317+
}
318+
319+
Ok(())
320+
}
321+
275322
fn read_file(file_path: &str) -> Result<String, String> {
276323
if file_path == "-" {
277324
let mut buffer = String::new();

0 commit comments

Comments
 (0)