feat: Forth-style prefix command parser
Replace JSON command syntax with prefix notation: `word arg1 arg2`. Multiple commands per line separated by `.`. Coordinate pairs use `Category/Item`. Quoted strings for multi-word values. set-cell uses value-first: `set-cell 100 Region/East Measure/Revenue`. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
28
src/main.rs
28
src/main.rs
@ -320,21 +320,23 @@ fn run_headless_commands(cmds: &[String], file: &Option<PathBuf>) -> Result<()>
|
||||
let mut model = get_initial_model(file)?;
|
||||
let mut exit_code = 0;
|
||||
|
||||
for raw_cmd in cmds {
|
||||
let parsed: command::Command = match serde_json::from_str(raw_cmd) {
|
||||
Ok(c) => c,
|
||||
for line in cmds {
|
||||
let parsed = match command::parse_line(line) {
|
||||
Ok(cmds) => cmds,
|
||||
Err(e) => {
|
||||
let r = CommandResult::err(format!("JSON parse error: {e}"));
|
||||
let r = CommandResult::err(format!("Parse error: {e}"));
|
||||
println!("{}", serde_json::to_string(&r)?);
|
||||
exit_code = 1;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let result = command::dispatch(&mut model, &parsed);
|
||||
if !result.ok {
|
||||
exit_code = 1;
|
||||
for cmd in &parsed {
|
||||
let result = command::dispatch(&mut model, cmd);
|
||||
if !result.ok {
|
||||
exit_code = 1;
|
||||
}
|
||||
println!("{}", serde_json::to_string(&result)?);
|
||||
}
|
||||
println!("{}", serde_json::to_string(&result)?);
|
||||
}
|
||||
|
||||
if let Some(path) = file {
|
||||
@ -346,14 +348,8 @@ fn run_headless_commands(cmds: &[String], file: &Option<PathBuf>) -> Result<()>
|
||||
|
||||
fn run_headless_script(script_path: &PathBuf, file: &Option<PathBuf>) -> Result<()> {
|
||||
let content = std::fs::read_to_string(script_path)?;
|
||||
let cmds: Vec<String> = content
|
||||
.lines()
|
||||
.map(|l| l.trim())
|
||||
.filter(|l| !l.is_empty() && !l.starts_with("//") && !l.starts_with('#'))
|
||||
.map(String::from)
|
||||
.collect();
|
||||
|
||||
run_headless_commands(&cmds, file)
|
||||
let lines: Vec<String> = content.lines().map(String::from).collect();
|
||||
run_headless_commands(&lines, file)
|
||||
}
|
||||
|
||||
// ── Helpers ──────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user