use std::path::Path;
pub fn run(file: &Path, block_spec: &str, _file_auto: bool) -> Result<(), String> {
let source = std::fs::read_to_string(file)
.map_err(|e| format!("cannot read {}: {}", file.display(), e))?;
let mut source_map = crate::lang::span::SourceMap::new();
let file_id = source_map.add_file(file.display().to_string(), source.clone());
let (_, diags) = crate::lang::parse(&source, file_id);
if diags.has_errors() {
for d in diags.diagnostics() {
if d.is_error() {
eprintln!("{}", super::format_diagnostic(d, &source_map, file));
}
}
return Err(format!("parse errors in {}", file.display()));
}
let parts: Vec<&str> = block_spec.splitn(2, ' ').collect();
let (block_kind, block_id) = match parts.as_slice() {
[kind, id] => (*kind, Some(*id)),
[kind] => (*kind, None),
_ => return Err(format!("invalid block spec: {}", block_spec)),
};
let block_text = match block_id {
Some(id) => format!("{} {} {{\n}}\n", block_kind, id),
None => format!("{} {{\n}}\n", block_kind),
};
let mut result = source.clone();
if !result.ends_with('\n') {
result.push('\n');
}
if !result.ends_with("\n\n") {
result.push('\n');
}
result.push_str(&block_text);
let (_, new_diags) = crate::lang::parse(&result, file_id);
if new_diags.has_errors() {
return Err(format!(
"generated block does not parse cleanly; check block spec: {}",
block_spec
));
}
std::fs::write(file, &result).map_err(|e| format!("cannot write {}: {}", file.display(), e))?;
let id_display = block_id.map(|id| format!(" {}", id)).unwrap_or_default();
println!("added {}{} to {}", block_kind, id_display, file.display());
Ok(())
}