A cli program to easily handle .gitignore files
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

82 lines
3.0 KiB

/*! TODO: Application description here
This file provided by [rust-cli-boilerplate](https://github.com/ssokolow/rust-cli-boilerplate)
*/
// Copyright 2017-2019, Stephan Sokolow
// `error_chain` recursion adjustment
#![recursion_limit = "1024"]
// Make rustc's built-in lints more strict and set clippy into a whitelist-based configuration so
// we see new lints as they get written (We'll opt back out selectively)
#![warn(warnings, rust_2018_idioms, clippy::all, clippy::complexity, clippy::correctness,
clippy::pedantic, clippy::perf, clippy::style, clippy::restriction)]
// Opt out of the lints I've seen and don't want
#![allow(clippy::float_arithmetic, clippy::implicit_return)]
// stdlib imports
use std::io;
use std::convert::TryInto;
// 3rd-party imports
mod errors;
use structopt::{clap, StructOpt};
use log::error;
// Local imports
mod app;
mod helpers;
mod validators;
/// Boilerplate to parse command-line arguments, set up logging, and handle bubbled-up `Error`s.
///
/// Based on the `StructOpt` example from stderrlog and the suggested error-chain harness from
/// [quickstart.rs](https://github.com/brson/error-chain/blob/master/examples/quickstart.rs).
///
/// See `app::main` for the application-specific logic.
///
/// **TODO:** Consider switching to Failure and look into `impl Termination` as a way to avoid
/// having to put the error message pretty-printing inside main()
fn main() {
// Parse command-line arguments (exiting on parse error, --version, or --help)
let opts = app::CliOpts::from_args();
// Configure logging output so that -q is "decrease verbosity" rather than instant silence
let verbosity = opts.boilerplate.verbose
.saturating_add(app::DEFAULT_VERBOSITY)
.saturating_sub(opts.boilerplate.quiet);
stderrlog::new()
.module(module_path!())
.quiet(verbosity == 0)
.verbosity(verbosity.saturating_sub(1).try_into().expect("should never even come close"))
.timestamp(opts.boilerplate.timestamp.unwrap_or(stderrlog::Timestamp::Off))
.init()
.expect("initializing logging output");
// If requested, generate shell completions and then exit with status of "success"
if let Some(shell) = opts.boilerplate.dump_completions {
app::CliOpts::clap().gen_completions_to(
app::CliOpts::clap().get_bin_name().unwrap_or_else(|| clap::crate_name!()),
shell,
&mut io::stdout());
std::process::exit(0);
};
if let Err(ref e) = app::main(opts) {
// Write the top-level error message, then chained errors, then backtrace if available
error!("error: {}", e);
for e in e.iter().skip(1) {
error!("caused by: {}", e);
}
if let Some(backtrace) = e.backtrace() {
error!("backtrace: {:?}", backtrace);
}
// Exit with a nonzero exit code
// TODO: Decide how to allow code to set this to something other than 1
std::process::exit(1);
}
}
// vim: set sw=4 sts=4 expandtab :