diff --git a/src/cli.rs b/src/cli.rs index dfa6bd6..8620141 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -12,7 +12,7 @@ pub struct Args { #[arg(short, long)] pub track: Option, - /// Boundary GeoJSON in WGS84 / EPSG:4326. + /// Boundary GeoJSON. #[arg(short, long)] pub boundaries: PathBuf, @@ -24,9 +24,17 @@ pub struct Args { #[arg(long, default_value = "ARS")] pub id_field: String, - /// Output GPX. Writes to stdout when omitted or set to '-'. + /// Output GPX file. Writes to stdout when omitted or set to '-'. #[arg(short, long)] pub output: Option, + + /// Explicit name for the generated GPX track. + /// + /// When omitted, the name is derived from GPX metadata, + /// output filename, or input filename and gets the + /// " (borderpoi)" suffix. + #[arg(long)] + pub name: Option, } impl Args { diff --git a/src/main.rs b/src/main.rs index ede4b0d..5d0a55e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ mod gpx_io; mod report; use anyhow::Result; +use std::path::Path; use cli::Args; use county::load_counties; @@ -13,6 +14,39 @@ use crossings::find_crossings; use gpx_io::{append_crossing_waypoints, read_gpx, write_gpx}; use report::print_report; +fn basename(path: Option<&Path>) -> Option { + path.filter(|path| path.as_os_str() != "-") + .and_then(Path::file_name) + .and_then(|name| name.to_str()) + .map(|name| { + Path::new(name) + .file_stem() + .and_then(|stem| stem.to_str()) + .unwrap_or(name) + .to_owned() + }) +} + +fn output_name( + explicit_name: Option<&str>, + input_metadata_name: Option<&str>, + output: Option<&Path>, + input: Option<&Path>, +) -> String { + if let Some(name) = explicit_name { + return name.to_owned(); + } + + let base_name = input_metadata_name + .filter(|name| !name.trim().is_empty()) + .map(str::to_owned) + .or_else(|| basename(output)) + .or_else(|| basename(input)) + .unwrap_or_else(|| "track".to_owned()); + + format!("{base_name} (borderpoi)") +} + fn main() -> Result<()> { let args = Args::parse_args(); @@ -22,7 +56,8 @@ fn main() -> Result<()> { eprintln!("Track points: {}", track.len()); - let counties = load_counties(&args.boundaries, &args.name_field, &args.id_field)?; + let counties = + load_counties(&args.boundaries, &args.name_field, &args.id_field)?; eprintln!("Loaded counties: {}", counties.len()); @@ -34,11 +69,34 @@ fn main() -> Result<()> { print_report(&crossings); + let metadata_name = gpx + .metadata + .as_ref() + .and_then(|metadata| metadata.name.as_deref()); + + let name = output_name( + args.name.as_deref(), + metadata_name, + args.output.as_deref(), + args.track.as_deref(), + ); + let mut output_gpx = gpx; - append_crossing_waypoints(&mut output_gpx, &crossings); + output_gpx + .metadata + .get_or_insert_with(Default::default) + .name = Some(name); - write_gpx(&output_gpx, args.output.as_deref())?; + append_crossing_waypoints( + &mut output_gpx, + &crossings, + ); + + write_gpx( + &output_gpx, + args.output.as_deref(), + )?; Ok(()) }