cli.rs (2727B)
1 //! The coliru command line interface 2 3 use anyhow::{Context, Result}; 4 use colored::{Colorize, control::set_override}; 5 use clap::{Parser, ColorChoice}; 6 use std::path::Path; 7 use super::core::{install_manifest, list_tags}; 8 use super::manifest::parse_manifest_file; 9 10 /// CLI about description 11 const HELP_ABOUT: &str = "A minimal, flexible, dotfile installer"; 12 13 /// CLI examples to be appended to help output 14 const HELP_EXAMPLES: &str = "\ 15 Examples: 16 # List tags in manifest 17 coliru manifest.yml --list-tags 18 19 # Preview installation steps with tags matching A && (B || C) && !D 20 coliru manifest.yml --tag-rules A B,C ^D --dry-run 21 22 # Install dotfiles on local machine 23 coliru manifest.yml --tag-rules A B,C ^D 24 25 # Install dotfiles to user@hostname over SSH 26 coliru manifest.yml --tag-rules A B,C ^D --host user@hostname"; 27 28 /// Arguments to the coliru CLI 29 #[derive(Parser, Debug)] 30 #[command(version, color=ColorChoice::Never, arg_required_else_help=true, 31 about=HELP_ABOUT, after_help=HELP_EXAMPLES)] 32 struct Args { 33 /// The path to the coliru manifest file 34 pub manifest: String, 35 36 /// The set of tag rules to enforce 37 #[arg(short, long, value_name="RULE", num_args=0..)] 38 pub tag_rules: Vec<String>, 39 40 /// List available tags and quit without installing 41 #[arg(short, long)] 42 pub list_tags: bool, 43 44 /// Do a trial run without any permanent changes 45 #[arg(short = 'n', long)] 46 pub dry_run: bool, 47 48 /// Install dotfiles on another machine over SSH 49 #[arg(long, default_value="", hide_default_value=true)] 50 pub host: String, 51 52 /// Interpret link commands as copy commands 53 #[arg(long)] 54 pub copy: bool, 55 56 /// Disable color output 57 #[arg(long)] 58 pub no_color: bool, 59 } 60 61 /// Runs the coliru CLI 62 pub fn run() { 63 let args = Args::parse(); 64 65 match run_args(args) { 66 Err(why) => { 67 eprintln!("{} {:#}", "Error:".bold().red(), why); 68 std::process::exit(2); 69 }, 70 Ok(minor_errors) => { 71 std::process::exit(if minor_errors { 1 } else { 0 }); 72 }, 73 } 74 } 75 76 /// Runs the coliru CLI according to a set of arguments 77 /// 78 /// Returns an Err if a critical occurs, Ok(true) if minor errors occurred, and 79 /// Ok(false) if no errors occurred. 80 fn run_args(args: Args) -> Result<bool> { 81 if args.no_color { 82 set_override(false); 83 } 84 85 let manifest = parse_manifest_file(Path::new(&args.manifest)) 86 .with_context(|| { 87 format!("Failed to parse {}", args.manifest) 88 })?; 89 90 if args.list_tags { 91 list_tags(manifest); 92 Ok(false) 93 } else { 94 install_manifest(manifest, args.tag_rules, &args.host, args.dry_run, 95 args.copy) 96 } 97 }