diff options
Diffstat (limited to 'packages/cli/src/main.rs')
-rw-r--r-- | packages/cli/src/main.rs | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/packages/cli/src/main.rs b/packages/cli/src/main.rs new file mode 100644 index 0000000..0773354 --- /dev/null +++ b/packages/cli/src/main.rs @@ -0,0 +1,251 @@ +#![deny(warnings)] +#[macro_use] +extern crate clap; + +extern crate svgbob; + +use svgbob::Settings; + +use clap::ArgMatches; +use std::error::Error; +use std::fs::{self, File}; +use std::io::Read; +use std::path::{Path, PathBuf}; +use std::process::exit; +use std::str::FromStr; + +fn main() { + use clap::{App, Arg, SubCommand}; + + let args = App::new("svgbob") + .version(crate_version!()) + .about("SvgBobRus is an ascii to svg converter") + .arg(Arg::with_name("background") + .long("background") + .takes_value(true) + .help("backdrop background will be filled with this color (default: 'white')")) + .arg(Arg::with_name("inline").short("s").help("parse an inline string")) + .arg(Arg::with_name("input").index(1).help("svgbob text file or inline string to parse [default: STDIN]")) + .arg(Arg::with_name("output") + .short("o") + .long("output") + .takes_value(true) + .help("where to write svg output [default: STDOUT]")) + .arg(Arg::with_name("fill-color") + .long("fill-color") + .takes_value(true) + .help("solid shapes will be filled with this color (default: 'black')")) + .arg(Arg::with_name("font-family") + .long("font-family") + .takes_value(true) + .help("text will be rendered with this font (default: 'arial')")) + .arg(Arg::with_name("font-size") + .long("font-size") + .takes_value(true) + .help("text will be rendered with this font size (default: 14)")) + .arg(Arg::with_name("stroke-width") + .long("stroke-width") + .takes_value(true) + .help("stroke width for all lines (default: 2)")) + .arg(Arg::with_name("scale") + .long("scale") + .takes_value(true) + .help("scale the entire svg (dimensions, font size, stroke width) by this factor (default: 1)")) + .subcommand(SubCommand::with_name("build") + .about("Batch convert files to svg.") + .version("0.0.1") + .arg(Arg::with_name("input") + .short("i") + .long("input") + .takes_value(true) + .help("set input file pattern like: *.bob or dir/*.bob")) + .arg(Arg::with_name("outdir") + .short("o") + .long("outdir") + .takes_value(true) + .help("set dir of svg files"))) + .get_matches(); + + if let Some(sub_build) = args.subcommand_matches("build") { + match build(sub_build) { + Ok(_) => {} + Err(e) => println!("{}", e), + }; + exit(1); + } + + let mut bob = String::new(); + + if args.is_present("inline") { + bob = args + .value_of("input") + .unwrap() + .replace("\\n", "\n") + .to_string(); + } else { + if let Some(file) = args.value_of("input") { + match File::open(file) { + Ok(mut f) => { + f.read_to_string(&mut bob).unwrap(); + } + Err(e) => { + use std::io::Write; + + writeln!( + &mut std::io::stderr(), + "Failed to open input file {}: {}", + file, + e + ) + .unwrap(); + exit(1); + } + } + } else { + use std::io; + io::stdin().read_to_string(&mut bob).unwrap(); + } + } + + let mut settings = Settings::default(); + + if let Some(background) = args.value_of("background") { + settings.background = background.to_string(); + } + + if let Some(fill_color) = args.value_of("fill-color") { + settings.fill_color = fill_color.to_string(); + } + + if let Some(font_family) = args.value_of("font-family") { + settings.font_family = font_family.to_string(); + } + + if let Some(font_size) = parse_value_of(&args, "font-size") { + settings.font_size = font_size; + } + + if let Some(stroke_width) = parse_value_of(&args, "stroke-width") { + settings.stroke_width = stroke_width; + } + + let scale : Option<f32> = parse_value_of(&args, "scale"); + match scale { + Some(s) => { settings.scale *= s; }, + _ => {} + } + + let svg = svgbob::to_svg_with_settings(&*bob, &settings); + + if let Some(file) = args.value_of("output") { + if let Err(e) = fs::write(file, &svg) { + use std::io::Write; + + writeln!( + &mut std::io::stderr(), + "Failed to write to output file {}: {}", + file, + e + ) + .unwrap(); + exit(2); + } + } else { + println!("{}", svg); + } +} + +fn parse_value_of<T: FromStr>(args: &ArgMatches, arg_name: &str) -> Option<T> +where + <T as std::str::FromStr>::Err: std::fmt::Display, +{ + return args + .value_of(arg_name) + .and_then(|arg| match arg.parse::<T>() { + Ok(a) => Some(a), + Err(e) => { + use std::io::Write; + + writeln!( + &mut std::io::stderr(), + "Illegal value for argument {}: {}", + arg_name, + e + ) + .unwrap(); + exit(1); + } + }); +} + +// Batch convert files to svg +// use svgbob build -i inputdir/*.bob -o outdir/ +fn build(args: &ArgMatches) -> Result<(), Box<dyn Error>> { + let files_pattern = args.value_of("input").unwrap_or("*.bob"); + let outdir = args.value_of("outdir").unwrap_or(""); + let input_path = Path::new(files_pattern); + let ext = input_path + .extension() + .unwrap_or(&"bob".as_ref()) + .to_str() + .unwrap(); + + let input_dir = if input_path.is_dir() { + input_path.clone() + } else { + input_path.parent().unwrap() + }; + + if !input_dir.is_dir() { + return Err(Box::from(format!( + "[Error]: No such dir name is {} !", + input_dir.to_string_lossy() + ))); + } + + let mut out_path = PathBuf::new(); + if outdir == "" { + out_path = input_dir.to_path_buf(); + } else { + out_path.push(outdir) + } + + if !out_path.is_dir() { + fs::create_dir_all(out_path.clone())?; + } + + let paths = fs::read_dir(input_dir).unwrap(); + for path in paths { + let tmp_path = path.unwrap().path(); + if tmp_path.is_file() { + let tmp_ext = tmp_path + .extension() + .unwrap_or(&"".as_ref()) + .to_str() + .unwrap(); + if tmp_ext == ext { + let name = tmp_path.file_stem().unwrap().to_str().unwrap(); + let mut tmp = out_path.clone(); + tmp.push(format!("{}.svg", name)); + println!("{} => {}", tmp_path.display(), tmp.display()); + match convert_file(tmp_path.clone(), tmp) { + Ok(_) => {} + Err(e) => { + println!("{}", e); + } + } + } + } + } + + Ok(()) +} + +fn convert_file(input: PathBuf, output: PathBuf) -> Result<(), Box<dyn Error>> { + let mut bob = String::new(); + let mut f = File::open(&input)?; + f.read_to_string(&mut bob).unwrap(); + let svg = svgbob::to_svg_with_settings(&*bob, &Settings::default()); + fs::write(&output, &svg)?; + Ok(()) +} |