patchy/flags.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
use std::{env, fmt::Display};
use colored::Colorize;
use once_cell::sync::Lazy;
use crate::{commands::help::format_description, types::CommandArgs};
pub struct Flag<'a> {
pub short: &'a str,
pub long: &'a str,
pub description: &'a str,
}
/// Extracts value out of a `flag` which can have an assignment
///
/// # Examples
///
/// ```rust
/// use patchy::flags::Flag;
///
/// let my_flag = Flag {
/// short: "-r=",
/// long: "--remote-name=",
/// description: "some flag",
/// };
///
/// let long_version = my_flag.extract_from_arg("--remote-name=abc");
/// let short_version = my_flag.extract_from_arg("-r=abcdefg");
/// let invalid = my_flag.extract_from_arg("-m=abcdefg");
///
/// assert_eq!(long_version, Some("abc".into()));
/// assert_eq!(short_version, Some("abcdefg".into()));
/// assert_eq!(invalid, None);
/// ```
impl Flag<'_> {
pub fn is_in_args(&self, args: &CommandArgs) -> bool {
args.contains(self.short) || args.contains(self.long)
}
pub fn extract_from_arg(&self, arg: &str) -> Option<String> {
if arg.starts_with(self.short) {
arg.get(self.short.len()..).map(|value| value.into())
} else if arg.starts_with(self.long) {
arg.get(self.long.len()..).map(|value| value.into())
} else {
None
}
}
}
impl Display for Flag<'_> {
/// Formats a flag into a colored format with a description, printable to the terminal
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}{}{}\n {}",
self.short.bright_magenta(),
", ".bright_black(),
self.long.bright_magenta(),
format_description(self.description)
)
}
}
/// Checks whether an input argument is a valid flag
pub fn is_valid_flag(arg: &str, available_flags: &[&Flag]) -> bool {
// TODO: flags that don't end in "=" should be compared fully, not just the beginning
available_flags
.iter()
.flat_map(|flag| [flag.short, flag.long])
.any(|flag| arg.starts_with(flag))
}
/// Makes the program output more detailed information
pub static IS_VERBOSE: Lazy<bool> = Lazy::new(|| {
let args: CommandArgs = env::args().collect();
args.contains("--verbose")
});