coliru

A minimal, flexible, dotfile installer
git clone https://git.ashermorgan.net/coliru/
Log | Files | Refs | README

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 }