use clap::{Arg, Command, ValueHint, crate_version};
use mathypad::{run_one_shot_mode, version};
use std::error::Error;
#[cfg(not(target_arch = "wasm32"))]
use mathypad::run_interactive_mode_with_file;
#[cfg(not(target_arch = "wasm32"))]
use std::path::PathBuf;
fn main() -> Result<(), Box<dyn Error>> {
if let Some(expression) = extract_one_shot_expression() {
return run_one_shot_mode(&expression);
}
let matches = build_cli().get_matches();
if let Some(shell) = matches.get_one::<String>("completions") {
print_completion_script(shell);
return Ok(());
}
if matches.get_flag("changelog") || matches.get_flag("whats-new") {
print_changelog();
return Ok(());
}
if let Err(e) = version::init_version_tracking() {
eprintln!("Warning: Could not initialize version tracking: {}", e);
}
#[cfg(not(target_arch = "wasm32"))]
{
let file_path = matches.get_one::<String>("file").map(PathBuf::from);
run_interactive_mode_with_file(file_path)
}
#[cfg(target_arch = "wasm32")]
{
eprintln!("Error: Interactive TUI mode is not available in WASM builds");
eprintln!("Use the GUI version or one-shot mode instead");
std::process::exit(1);
}
}
fn extract_one_shot_expression() -> Option<String> {
let mut args = std::env::args();
let dash_pos = args.position(|arg| arg == "--")?;
let remaining_args: Vec<String> = std::env::args().skip(dash_pos + 1).collect();
if remaining_args.is_empty() {
None
} else {
Some(remaining_args.join(" "))
}
}
fn build_cli() -> Command {
Command::new("mathypad")
.version(crate_version!())
.about("A mathematical notepad with unit conversion support")
.arg(
Arg::new("help_alt")
.short('?')
.action(clap::ArgAction::Help)
.help("Print help"),
)
.arg(
Arg::new("completions")
.long("completions")
.help("Generate shell completion files")
.value_name("SHELL")
.value_parser(["bash", "zsh", "fish"]),
)
.arg(
Arg::new("changelog")
.long("changelog")
.action(clap::ArgAction::SetTrue)
.help("Show the changelog"),
)
.arg(
Arg::new("whats-new")
.long("whats-new")
.action(clap::ArgAction::SetTrue)
.help("Show what's new (alias for --changelog)"),
)
.arg(
Arg::new("file")
.help("File to open")
.value_name("FILE")
.index(1)
.value_hint(ValueHint::FilePath),
)
.after_help(
"Examples:\n\
\x20 mathypad # Start empty interactive mode\n\
\x20 mathypad calculations.pad # Open file in interactive mode\n\
\x20 mathypad -- \"100 GB to GiB\" # One-shot calculation\n\
\x20 eval \"$(mathypad --completions bash)\" # Enable bash completions",
)
}
fn print_completion_script(shell: &str) {
let completion_script = match shell {
"bash" => include_str!("../../completions/mathypad.bash"),
"zsh" => include_str!("../../completions/mathypad.zsh"),
"fish" => include_str!("../../completions/mathypad.fish"),
_ => unreachable!("clap should prevent invalid shell values"),
};
print!("{}", completion_script);
}
fn print_changelog() {
let changelog = include_str!("../../CHANGELOG.md");
println!("{}", changelog);
}