Accept positional input/output args in the CLI

`vtracer in.png out.svg` now works alongside the `-i/--input` and
`-o/--output` flags. Input/output become optional positionals plus the
existing flags; an explicit flag wins over the positional, and a clear error
is shown if neither is given.
This commit is contained in:
Chris Tsang
2026-07-24 11:18:21 +01:00
parent 35b4b6f846
commit 837fde8aa4
+28 -6
View File
@@ -15,13 +15,21 @@ use vtracer::{ColorMode, Config, FitMode, Hierarchical, Preset};
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(name = "vtracer", version, about, rename_all = "kebab-case")] #[command(name = "vtracer", version, about, rename_all = "kebab-case")]
struct Args { struct Args {
/// Input raster image (positional; or use --input).
#[arg(value_name = "INPUT")]
input_pos: Option<PathBuf>,
/// Output SVG (positional; or use --output).
#[arg(value_name = "OUTPUT")]
output_pos: Option<PathBuf>,
/// Path to the input raster image. /// Path to the input raster image.
#[arg(short, long)] #[arg(short = 'i', long = "input", value_name = "INPUT")]
input: PathBuf, input: Option<PathBuf>,
/// Path to the output SVG. /// Path to the output SVG.
#[arg(short, long)] #[arg(short = 'o', long = "output", value_name = "OUTPUT")]
output: PathBuf, output: Option<PathBuf>,
/// Start from a preset: bw, poster, photo. /// Start from a preset: bw, poster, photo.
#[arg(long)] #[arg(long)]
@@ -187,11 +195,25 @@ fn read_image(path: &std::path::Path) -> Result<ColorImage, String> {
fn run() -> Result<(), String> { fn run() -> Result<(), String> {
let args = Args::parse(); let args = Args::parse();
// Accept input/output as positionals (`vtracer in.png out.svg`) or as
// named flags; an explicit flag takes precedence over the positional.
let input = args
.input
.as_ref()
.or(args.input_pos.as_ref())
.ok_or("no input path given (positional or --input)")?;
let output = args
.output
.as_ref()
.or(args.output_pos.as_ref())
.ok_or("no output path given (positional or --output)")?;
let config = build_config(&args)?; let config = build_config(&args)?;
let pipeline = config.build().map_err(|e| e.to_string())?; let pipeline = config.build().map_err(|e| e.to_string())?;
let img = read_image(&args.input)?; let img = read_image(input)?;
let svg = pipeline.to_svg(&img).map_err(|e| e.to_string())?; let svg = pipeline.to_svg(&img).map_err(|e| e.to_string())?;
std::fs::write(&args.output, svg).map_err(|e| format!("cannot write output file: {e}"))?; std::fs::write(output, svg).map_err(|e| format!("cannot write output file: {e}"))?;
Ok(()) Ok(())
} }