use crate::{gpr, tools};
use clap::Parser;
use std::{path::PathBuf, time::Duration};
#[derive(Debug, Parser)]
#[clap(author, version, about, long_about = None)]
#[clap(group(
clap::ArgGroup::new("step_choice")
.required(false)
.args(&["steps", "default", "default_with_topo"]),
))
]
#[clap(group(
clap::ArgGroup::new("exit_choice")
.required(false)
.args(&["show_default", "info", "show_all_steps", "output"]),
))
]
pub struct Args {
#[clap(short, long)]
pub filepath: Option<String>,
#[clap(short, long, default_value = "0.168")]
pub velocity: f32,
#[clap(short, long)]
pub info: bool,
#[clap(short, long)]
pub cor: Option<PathBuf>,
#[clap(short, long)]
pub dem: Option<PathBuf>,
#[clap(long)]
pub crs: Option<String>,
#[clap(short, long)]
pub track: Option<Option<PathBuf>>,
#[clap(long)]
pub default: bool,
#[clap(long)]
pub default_with_topo: bool,
#[clap(long)]
pub show_default: bool,
#[clap(long)]
pub show_all_steps: bool,
#[clap(long)]
pub steps: Option<String>,
#[clap(short, long)]
pub output: Option<PathBuf>,
#[clap(short, long)]
pub quiet: bool,
#[clap(short, long)]
pub render: Option<Option<PathBuf>>,
#[clap(long)]
pub no_export: bool,
#[clap(long)]
pub merge: Option<String>,
#[clap(long)]
pub override_antenna_mhz: Option<f32>,
}
pub enum CliAction {
Run(gpr::RunParams),
Error(String),
Done,
}
pub fn args_to_action(args: &Args) -> CliAction {
if args.show_all_steps {
println!("Name\t\tDescription");
for line in gpr::all_available_steps() {
println!("{}\n{}\n{}\n", line[0], "-".repeat(line[0].len()), line[1]);
}
return CliAction::Done;
}
if args.show_default {
for line in gpr::default_processing_profile() {
println!("{}", line);
}
return CliAction::Done;
}
let merge: Option<Duration> = match &args.merge {
Some(merge_string) => match parse_duration::parse(merge_string) {
Ok(d) => Some(d),
Err(e) => return CliAction::Error(format!("Error parsing --merge string: {:?}", e)),
},
None => None,
};
let filepaths = match &args.filepath {
Some(fp) => glob::glob(fp)
.unwrap()
.map(|v| v.unwrap())
.collect::<Vec<PathBuf>>(),
None => {
return CliAction::Error(
"No filepath given.\nUse the help text (\"-h\" or \"--help\") for assistance."
.to_string(),
)
}
};
let steps: Vec<String> = match args.info {
true => Vec::new(),
false => match args.default_with_topo {
true => {
let mut profile = gpr::default_processing_profile();
profile.push("correct_topography".to_string());
profile
}
false => match args.default {
true => gpr::default_processing_profile(),
false => match &args.steps {
Some(steps) => match tools::parse_step_list(steps) {
Ok(s) => s,
Err(e) => return CliAction::Error(e),
},
None => {
println!("No processing steps specified. Saving raw data.");
vec![]
}
},
},
},
};
let allowed_steps = gpr::all_available_steps()
.iter()
.map(|s| s[0])
.collect::<Vec<&str>>();
for step in &steps {
if !allowed_steps.iter().any(|allowed| step.contains(allowed)) {
return CliAction::Error(format!("Unrecognized step: {}", step));
}
}
let params = gpr::RunParams {
filepaths,
output_path: args.output.clone(),
only_info: args.info,
dem_path: args.dem.clone(),
cor_path: args.cor.clone(),
medium_velocity: args.velocity,
crs: args.crs.clone(),
quiet: args.quiet,
track_path: args.track.clone(),
steps,
no_export: args.no_export,
render_path: args.render.clone(),
merge,
override_antenna_mhz: args.override_antenna_mhz,
};
CliAction::Run(params)
}
#[cfg(feature = "cli")]
#[allow(dead_code)] pub fn main(arguments: Args) -> i32 {
match args_to_action(&arguments) {
CliAction::Run(params) => match gpr::run(params) {
Ok(_) => 0,
Err(e) => error(&format!("{e:?}"), 1),
},
CliAction::Error(message) => error(&message, 1),
CliAction::Done => 0,
}
}
#[cfg(feature = "cli")]
#[allow(dead_code)] fn error(message: &str, code: i32) -> i32 {
eprintln!("{}", message);
code
}