1#[macro_use]
2extern crate log;
3
4pub mod cargo_manifest;
5pub mod commands;
6pub mod error;
7
8use clap::Clap;
9use colored::Colorize;
10use commands::*;
11use creator_tools::utils::{Config, Shell, Verbosity};
12use std::path::PathBuf;
13
14#[derive(Clap, Clone, Debug)]
15#[clap(author, about, version)]
16pub struct Opts {
17 #[clap(short, long)]
19 pub current_dir: Option<PathBuf>,
20 #[clap(short, long, parse(from_occurrences))]
22 pub verbose: u32,
23 #[clap(short, long)]
25 pub quiet: bool,
26
27 #[clap(subcommand)]
28 pub cmd: Commands,
29}
30
31impl Opts {
32 pub fn get_verbosity(&self) -> Verbosity {
33 if self.quiet {
34 Verbosity::Quiet
35 } else {
36 match self.verbose {
39 0 => Verbosity::Normal,
40 1 => Verbosity::Verbose,
41 _ => {
42 pretty_env_logger::formatted_builder()
43 .filter_level(log::LevelFilter::Trace)
44 .init();
45 Verbosity::Verbose
46 }
47 }
48 }
49 }
50
51 pub fn get_current_dir(&self) -> PathBuf {
52 self.current_dir
53 .clone()
54 .unwrap_or_else(|| std::env::current_dir().unwrap())
55 }
56}
57
58pub fn run() -> std::result::Result<(), Box<dyn std::error::Error>> {
59 let opts = Opts::parse();
60 let mut shell = Shell::new();
61 shell.set_verbosity(opts.get_verbosity());
62 let config = Config::new(shell, opts.get_current_dir());
63 opts.cmd.handle_command(&config)?;
64 Ok(())
65}
66
67pub fn handle_errors(run: impl FnOnce() -> std::result::Result<(), Box<dyn std::error::Error>>) {
68 if let Err(error) = run() {
69 eprintln!("{}: {}", "error".red().bold(), error);
70 handle_error_source(error.source());
71 std::process::exit(1);
72 };
73}
74
75fn handle_error_source(source: Option<&(dyn std::error::Error + 'static)>) {
76 if let Some(error) = source {
77 eprintln!("{}: {}", "caused by".red().bold(), error);
78 handle_error_source(error.source());
79 }
80}