feat: add clap CLI arg parser, replacing MANDEL_* debug env vars

Prep work for a headless render mode: native debug flags (kind, power,
julia, share, view, de, buddhabrot, export, ...) are now parsed with
clap instead of read from env vars, with proper --help/--version.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018GFBP9qrNg6NGJWzzP36xe
This commit is contained in:
2026-09-19 17:51:03 +02:00
co-authored by Claude Sonnet 5
parent 3797a33230
commit ff5ac0f262
4 changed files with 114 additions and 27 deletions
+84
View File
@@ -0,0 +1,84 @@
// Native command-line arguments. Currently mirrors the old `MANDEL_*` debug
// env vars one-for-one; this is the foundation a future headless (no-window,
// render-to-file) mode will build on.
use clap::{Parser, ValueEnum};
use crate::fractal::FractalKind;
#[derive(Parser, Debug, Default)]
#[command(name = "mandelbrot", about = "Deep-zoom fractal explorer", version)]
pub struct Cli {
/// Fractal formula to render.
#[arg(long, value_enum)]
pub kind: Option<KindArg>,
/// Exponent for the Multibrot kind (z -> z^power + c), clamped to [2, 8].
#[arg(long)]
pub power: Option<u32>,
/// Start in Julia mode with this seed constant.
#[arg(long, value_name = "RE,IM")]
pub julia: Option<String>,
/// Restore a view from a share-link fragment (the part after '#').
#[arg(long, value_name = "FRAGMENT")]
pub share: Option<String>,
/// Jump to a view on startup.
#[arg(long, value_name = "RE,IM,HALF_HEIGHT[,ITERATIONS]")]
pub view: Option<String>,
/// Enable distance-estimation shading.
#[arg(long)]
pub de: bool,
/// Switch to the Buddhabrot renderer.
#[arg(long)]
pub buddhabrot: bool,
/// Buddhabrot tonemap palette index.
#[arg(long, value_name = "INDEX")]
pub buddha_palette: Option<u32>,
/// Render a PNG export on startup.
#[arg(long)]
pub export: bool,
/// Output path for --export (default: fractal-<timestamp>.png).
#[arg(long, value_name = "PATH")]
pub export_path: Option<String>,
}
#[derive(Copy, Clone, Debug, ValueEnum)]
pub enum KindArg {
Mandelbrot,
#[value(alias = "ship")]
BurningShip,
#[value(alias = "mandelbar")]
Tricorn,
#[value(alias = "multi")]
Multibrot,
Celtic,
#[value(alias = "perp")]
Perpendicular,
Buffalo,
Phoenix,
Lambda,
}
impl From<KindArg> for FractalKind {
fn from(k: KindArg) -> Self {
match k {
KindArg::Mandelbrot => FractalKind::Mandelbrot,
KindArg::BurningShip => FractalKind::BurningShip,
KindArg::Tricorn => FractalKind::Tricorn,
KindArg::Multibrot => FractalKind::Multibrot,
KindArg::Celtic => FractalKind::Celtic,
KindArg::Perpendicular => FractalKind::Perpendicular,
KindArg::Buffalo => FractalKind::Buffalo,
KindArg::Phoenix => FractalKind::Phoenix,
KindArg::Lambda => FractalKind::Lambda,
}
}
}