refactor: split main code paths for clarity.

This commit is contained in:
Edward Langley
2026-03-31 20:50:27 -07:00
parent aae8392f46
commit c32e800128

View File

@ -34,22 +34,70 @@ use ui::import_wizard_ui::ImportWizardWidget;
use ui::tile_bar::TileBar;
use ui::view_panel::ViewPanel;
fn main() -> Result<()> {
let args: Vec<String> = std::env::args().collect();
let arg_config = parse_args(args);
arg_config.run()
}
trait Runnable {
fn run(self: Box<Self>) -> Result<()>;
}
struct CmdLineArgs {
file_path: Option<PathBuf>,
import_path: Option<PathBuf>,
}
enum ArgConfig {
Help,
Headless {
file_path: Option<PathBuf>,
commands: Vec<String>,
script: Option<PathBuf>,
},
Default(CmdLineArgs),
impl Runnable for CmdLineArgs {
fn run(self: Box<Self>) -> Result<()> {
// Load or create model
let model = get_initial_model(&self.file_path)?;
// Pre-TUI import: parse JSON and open wizard
let import_json = if let Some(ref path) = self.import_path {
match std::fs::read_to_string(path) {
Err(e) => {
eprintln!("Cannot read '{}': {e}", path.display());
return Ok(());
}
Ok(content) => match serde_json::from_str::<serde_json::Value>(&content) {
Err(e) => {
eprintln!("JSON parse error: {e}");
return Ok(());
}
Ok(json) => Some(json),
},
}
} else {
None
};
run_tui(model, self.file_path, import_json)
}
}
fn parse_args(args: Vec<String>) -> ArgConfig {
struct HeadlessArgs {
file_path: Option<PathBuf>,
commands: Vec<String>,
script: Option<PathBuf>,
}
impl Runnable for HeadlessArgs {
fn run(self: Box<Self>) -> Result<()> {
run_headless(self.file_path, self.commands, self.script)
}
}
struct HelpArgs {}
impl Runnable for HelpArgs {
fn run(self: Box<Self>) -> Result<()> {
print_usage()
}
}
fn parse_args(args: Vec<String>) -> Box<dyn Runnable> {
let mut file_path: Option<PathBuf> = None;
let mut headless_cmds: Vec<String> = Vec::new();
let mut headless_script: Option<PathBuf> = None;
@ -73,7 +121,7 @@ fn parse_args(args: Vec<String>) -> ArgConfig {
import_path = args.get(i).map(PathBuf::from);
}
"--help" | "-h" => {
return ArgConfig::Help;
return Box::new(HelpArgs {});
}
arg if !arg.starts_with('-') => {
file_path = Some(PathBuf::from(arg));
@ -84,14 +132,14 @@ fn parse_args(args: Vec<String>) -> ArgConfig {
}
if !headless_cmds.is_empty() || headless_script.is_some() {
return ArgConfig::Headless {
return Box::new(HeadlessArgs {
file_path,
commands: headless_cmds,
script: headless_script,
};
});
}
return ArgConfig::Default(CmdLineArgs {
return Box::new(CmdLineArgs {
file_path,
import_path,
});
@ -117,58 +165,12 @@ fn get_initial_model(file_path: &Option<PathBuf>) -> Result<Model> {
};
}
fn main() -> Result<()> {
let args: Vec<String> = std::env::args().collect();
let arg_config = parse_args(args);
match arg_config {
ArgConfig::Default(cmd_line_args) => {
// Load or create model
let model = get_initial_model(&cmd_line_args.file_path)?;
// Pre-TUI import: parse JSON and open wizard
let import_json = if let Some(ref path) = cmd_line_args.import_path {
match std::fs::read_to_string(path) {
Err(e) => {
eprintln!("Cannot read '{}': {e}", path.display());
return Ok(());
}
Ok(content) => match serde_json::from_str::<serde_json::Value>(&content) {
Err(e) => {
eprintln!("JSON parse error: {e}");
return Ok(());
}
Ok(json) => Some(json),
},
}
} else {
None
};
run_tui(model, cmd_line_args.file_path, import_json)
}
ArgConfig::Headless {
file_path,
commands,
script,
} => {
let mut model = get_initial_model(&file_path)?;
return run_headless(&mut model, file_path, commands, script);
}
ArgConfig::Help => {
print_usage();
Ok(())
}
}
}
fn run_headless(
model: &mut Model,
file_path: Option<PathBuf>,
inline_cmds: Vec<String>,
script: Option<PathBuf>,
) -> Result<()> {
let mut model = get_initial_model(&file_path)?;
let mut cmds: Vec<String> = inline_cmds;
if let Some(script_path) = script {
let content = std::fs::read_to_string(&script_path)?;
@ -191,7 +193,7 @@ fn run_headless(
continue;
}
};
let result = command::dispatch(model, &parsed);
let result = command::dispatch(&mut model, &parsed);
if !result.ok {
exit_code = 1;
}
@ -199,7 +201,7 @@ fn run_headless(
}
if let Some(path) = file_path {
persistence::save(model, &path)?;
persistence::save(&mut model, &path)?;
}
std::process::exit(exit_code);
@ -560,7 +562,7 @@ fn draw_welcome(f: &mut Frame, area: Rect, _app: &App) {
// ── Usage ─────────────────────────────────────────────────────────────────────
fn print_usage() {
fn print_usage() -> Result<()> {
println!("improvise — multi-dimensional data modeling TUI\n");
println!("USAGE:");
println!(" improvise [file.improv] Open or create a model");
@ -583,4 +585,5 @@ fn print_usage() {
println!(" F C V Toggle Formulas / Categories / Views panel");
println!(" ZZ Save and quit");
println!(" ? Help");
Ok(())
}