refactor(main): update headless mode to use App and new command system

Update headless command execution to use the new architecture:

- Removed CommandResult import (no longer needed)
- Headless mode now creates an App instance and uses cmd_context()
- Commands are parsed and executed via the registry, effects applied
  through app.apply_effects() instead of command::dispatch()
- Made cmd_context() public so headless mode can access it
- Updated persistence save to use app.model instead of direct model

Tests updated to use ExecuteCommand instead of QuitCmd, with proper
buffer setup for command parsing.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M)
This commit is contained in:
Edward Langley
2026-04-04 10:56:35 -07:00
parent 00c62d85b7
commit 32716ebc16
2 changed files with 17 additions and 16 deletions

View File

@ -14,7 +14,6 @@ use std::path::PathBuf;
use anyhow::{Context, Result};
use clap::{Parser, Subcommand};
use command::CommandResult;
use draw::run_tui;
use model::Model;
use serde_json::Value;
@ -314,30 +313,32 @@ fn get_import_data(paths: &[PathBuf]) -> Option<Value> {
// ── Headless command execution ───────────────────────────────────────────────
fn run_headless_commands(cmds: &[String], file: &Option<PathBuf>) -> Result<()> {
let mut model = get_initial_model(file)?;
use crossterm::event::{KeyCode, KeyModifiers};
let model = get_initial_model(file)?;
let mut app = ui::app::App::new(model, file.clone());
let mut exit_code = 0;
for line in cmds {
let parsed = match command::parse_line(line) {
Ok(cmds) => cmds,
match command::parse_line(line) {
Ok(parsed_cmds) => {
for cmd in &parsed_cmds {
let effects = {
let ctx = app.cmd_context(KeyCode::Null, KeyModifiers::NONE);
cmd.execute(&ctx)
};
app.apply_effects(effects);
}
}
Err(e) => {
let r = CommandResult::err(format!("Parse error: {e}"));
println!("{}", serde_json::to_string(&r)?);
exit_code = 1;
continue;
}
};
for cmd in &parsed {
let result = command::dispatch(&mut model, cmd);
if !result.ok {
eprintln!("Parse error: {e}");
exit_code = 1;
}
println!("{}", serde_json::to_string(&result)?);
}
}
if let Some(path) = file {
persistence::save(&model, path)?;
persistence::save(&app.model, path)?;
}
std::process::exit(exit_code);

View File

@ -99,7 +99,7 @@ impl App {
}
}
fn cmd_context(&self, key: KeyCode, mods: KeyModifiers) -> CmdContext<'_> {
pub fn cmd_context(&self, key: KeyCode, mods: KeyModifiers) -> CmdContext<'_> {
let view = self.model.active_view();
CmdContext {
model: &self.model,