use anyhow::Result;
use clap::Parser;
use std::path::PathBuf;
use draw_core::document::Document;
#[derive(Parser, Debug)]
#[command(name = "draw")]
#[command(about = "Local-first drawing tool")]
#[command(version)]
pub struct Args {
#[cfg(feature = "app")]
#[arg(short = 'a', long)]
pub app: bool,
#[cfg(feature = "webapp")]
#[arg(short = 'w', long)]
pub webapp: bool,
#[command(subcommand)]
pub command: Option<Command>,
}
#[derive(clap::Subcommand, Debug)]
pub enum Command {
New {
#[arg(default_value = "untitled")]
name: String,
},
Open {
file: PathBuf,
},
List,
ExportSvg {
file: PathBuf,
#[arg(short, long)]
output: Option<PathBuf>,
},
ExportPng {
file: PathBuf,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(short, long, default_value_t = 2.0)]
scale: f32,
},
}
pub fn run_cli(argv: impl IntoIterator<Item = impl Into<String>>) -> Result<()> {
let argv: Vec<String> = argv.into_iter().map(Into::into).collect();
if argv.len() <= 1 {
Args::parse_from(["draw", "--help"]);
}
let args = Args::parse_from(&argv);
#[cfg(feature = "app")]
if args.app {
return draw_app::run_app(None);
}
#[cfg(feature = "webapp")]
if args.webapp {
return draw_webapp::run_webapp(None);
}
match args.command {
Some(Command::New { name }) => {
let doc = Document::new(name);
let path = draw_core::storage::save_to_storage(&doc)?;
println!("Created: {} ({})", doc.name, path.display());
#[cfg(feature = "webapp")]
return draw_webapp::run_webapp(Some(doc.id));
#[cfg(not(feature = "webapp"))]
{
println!("Run with --webapp to open in browser");
Ok(())
}
}
Some(Command::Open { file }) => {
let doc = draw_core::storage::load(&file)?;
println!("Loaded: {} ({} elements)", doc.name, doc.elements.len());
#[cfg(feature = "webapp")]
return draw_webapp::run_webapp(Some(doc.id));
#[cfg(not(feature = "webapp"))]
{
println!("Run with --webapp to open in browser");
Ok(())
}
}
Some(Command::List) => {
let drawings = draw_core::storage::list_drawings()?;
if drawings.is_empty() {
println!("No saved drawings.");
} else {
for (name, path) in drawings {
println!(" {} ({})", name, path.display());
}
}
Ok(())
}
Some(Command::ExportSvg { file, output }) => {
let doc = draw_core::storage::load(&file)?;
let svg = draw_core::export_svg(&doc);
let out_path = output.unwrap_or_else(|| file.with_extension("svg"));
std::fs::write(&out_path, &svg)?;
println!("Exported SVG to {}", out_path.display());
Ok(())
}
Some(Command::ExportPng {
file,
output,
scale,
}) => {
let doc = draw_core::storage::load(&file)?;
let png = draw_core::export_png_with_scale(&doc, scale)?;
let out_path = output.unwrap_or_else(|| file.with_extension("png"));
std::fs::write(&out_path, &png)?;
println!("Exported PNG to {}", out_path.display());
Ok(())
}
None => {
Args::parse_from(["draw", "--help"]);
unreachable!()
}
}
}