1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#[cfg(not(target_family = "wasm"))]
use rudof_cli::{
cli::parser::{Cli, Command},
commands::{CommandContext, CommandFactory},
};
#[cfg(not(target_family = "wasm"))]
use std::env;
#[cfg(target_family = "wasm")]
fn main() {}
#[cfg(not(target_family = "wasm"))]
fn main() -> std::process::ExitCode {
// Initialize logging, environment variables, and global settings
setup();
match run() {
Ok(()) => std::process::ExitCode::SUCCESS,
Err(err) => {
// Not `{err:?}` (anyhow's default `Termination` formatting for a
// bare `fn main() -> anyhow::Result<()>`, which this replaces):
// several of this crate's error types already embed their full
// wrapped-cause text into their own `Display`, which anyhow's
// "walk `source()` and print every link" default then repeats a
// second time. `format_error` prints each genuinely new piece
// of information once, on its own line.
eprintln!(
"{} {}",
rudof_cli::output::error_prefix(),
rudof_cli::output::format_error(&err)
);
std::process::ExitCode::FAILURE
},
}
}
#[cfg(not(target_family = "wasm"))]
fn run() -> anyhow::Result<()> {
use clap::Parser;
// Use args_os to safely handle non-UTF8 paths/arguments from the system
let args = clientele::args_os()?;
let cli = Cli::parse_from(args);
// Dispatch the command if present, otherwise exit with a clean error message
match &cli.command {
Some(cmd) => execute(cmd, cli.debug)?,
None => anyhow::bail!("Command not specified. Use --help for available commands."),
}
Ok(())
}
#[cfg(not(target_family = "wasm"))]
/// Sets up the application environment including logging and signal handling.
fn setup() {
clientele::dotenv().ok();
unsafe {
env::set_var("RUSTEMO_NOTRACE", "1");
}
rudof_cli::logging::init();
}
#[cfg(not(target_family = "wasm"))]
/// Orchestrates the command lifecycle: Creation -> Validation -> Execution.
fn execute(cli_command: &Command, debug: u8) -> anyhow::Result<()> {
// Convert CLI enum into a Command Trait Object
let command = CommandFactory::create(cli_command.clone())?;
// Prepare the execution context (writers, colors, config)
let mut ctx = CommandContext::from_cli(cli_command, debug)?;
// Run the core logic
command.execute(&mut ctx)?;
Ok(())
}