refactor: split main code paths for clarity.
This commit is contained in:
123
src/main.rs
123
src/main.rs
@ -34,22 +34,70 @@ use ui::import_wizard_ui::ImportWizardWidget;
|
|||||||
use ui::tile_bar::TileBar;
|
use ui::tile_bar::TileBar;
|
||||||
use ui::view_panel::ViewPanel;
|
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 {
|
struct CmdLineArgs {
|
||||||
file_path: Option<PathBuf>,
|
file_path: Option<PathBuf>,
|
||||||
import_path: Option<PathBuf>,
|
import_path: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ArgConfig {
|
impl Runnable for CmdLineArgs {
|
||||||
Help,
|
fn run(self: Box<Self>) -> Result<()> {
|
||||||
Headless {
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct HeadlessArgs {
|
||||||
file_path: Option<PathBuf>,
|
file_path: Option<PathBuf>,
|
||||||
commands: Vec<String>,
|
commands: Vec<String>,
|
||||||
script: Option<PathBuf>,
|
script: Option<PathBuf>,
|
||||||
},
|
|
||||||
Default(CmdLineArgs),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_args(args: Vec<String>) -> ArgConfig {
|
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 file_path: Option<PathBuf> = None;
|
||||||
let mut headless_cmds: Vec<String> = Vec::new();
|
let mut headless_cmds: Vec<String> = Vec::new();
|
||||||
let mut headless_script: Option<PathBuf> = None;
|
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);
|
import_path = args.get(i).map(PathBuf::from);
|
||||||
}
|
}
|
||||||
"--help" | "-h" => {
|
"--help" | "-h" => {
|
||||||
return ArgConfig::Help;
|
return Box::new(HelpArgs {});
|
||||||
}
|
}
|
||||||
arg if !arg.starts_with('-') => {
|
arg if !arg.starts_with('-') => {
|
||||||
file_path = Some(PathBuf::from(arg));
|
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() {
|
if !headless_cmds.is_empty() || headless_script.is_some() {
|
||||||
return ArgConfig::Headless {
|
return Box::new(HeadlessArgs {
|
||||||
file_path,
|
file_path,
|
||||||
commands: headless_cmds,
|
commands: headless_cmds,
|
||||||
script: headless_script,
|
script: headless_script,
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return ArgConfig::Default(CmdLineArgs {
|
return Box::new(CmdLineArgs {
|
||||||
file_path,
|
file_path,
|
||||||
import_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(
|
fn run_headless(
|
||||||
model: &mut Model,
|
|
||||||
file_path: Option<PathBuf>,
|
file_path: Option<PathBuf>,
|
||||||
inline_cmds: Vec<String>,
|
inline_cmds: Vec<String>,
|
||||||
script: Option<PathBuf>,
|
script: Option<PathBuf>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
let mut model = get_initial_model(&file_path)?;
|
||||||
let mut cmds: Vec<String> = inline_cmds;
|
let mut cmds: Vec<String> = inline_cmds;
|
||||||
if let Some(script_path) = script {
|
if let Some(script_path) = script {
|
||||||
let content = std::fs::read_to_string(&script_path)?;
|
let content = std::fs::read_to_string(&script_path)?;
|
||||||
@ -191,7 +193,7 @@ fn run_headless(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let result = command::dispatch(model, &parsed);
|
let result = command::dispatch(&mut model, &parsed);
|
||||||
if !result.ok {
|
if !result.ok {
|
||||||
exit_code = 1;
|
exit_code = 1;
|
||||||
}
|
}
|
||||||
@ -199,7 +201,7 @@ fn run_headless(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(path) = file_path {
|
if let Some(path) = file_path {
|
||||||
persistence::save(model, &path)?;
|
persistence::save(&mut model, &path)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::process::exit(exit_code);
|
std::process::exit(exit_code);
|
||||||
@ -560,7 +562,7 @@ fn draw_welcome(f: &mut Frame, area: Rect, _app: &App) {
|
|||||||
|
|
||||||
// ── Usage ─────────────────────────────────────────────────────────────────────
|
// ── Usage ─────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
fn print_usage() {
|
fn print_usage() -> Result<()> {
|
||||||
println!("improvise — multi-dimensional data modeling TUI\n");
|
println!("improvise — multi-dimensional data modeling TUI\n");
|
||||||
println!("USAGE:");
|
println!("USAGE:");
|
||||||
println!(" improvise [file.improv] Open or create a model");
|
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!(" F C V Toggle Formulas / Categories / Views panel");
|
||||||
println!(" ZZ Save and quit");
|
println!(" ZZ Save and quit");
|
||||||
println!(" ? Help");
|
println!(" ? Help");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user