Skip to main content

indigo_parse_keys/
indigo-parse-keys.rs

1use clap::Parser as _;
2use indigo_core::key::{Key, KeyCode, KeyModifiers, Keys};
3use std::{
4    fmt::{self, Debug, Display},
5    io,
6    process::ExitCode,
7    str::FromStr,
8};
9
10#[derive(clap::ValueEnum, Clone, Default)]
11enum Type {
12    #[default]
13    Keys,
14    Key,
15    KeyModifiers,
16    KeyCode,
17}
18
19impl Display for Type {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
21        match self {
22            Self::Keys => write!(f, "keys")?,
23            Self::Key => write!(f, "key")?,
24            Self::KeyModifiers => write!(f, "key-modifiers")?,
25            Self::KeyCode => write!(f, "key-code")?,
26        }
27        Ok(())
28    }
29}
30
31#[derive(clap::Parser)]
32struct Args {
33    /// Type to parse
34    #[arg(long, default_value_t)]
35    r#type: Type,
36
37    /// Print parsed result with `Debug` instead of `Display`
38    #[arg(long)]
39    debug: bool,
40}
41
42fn main() -> anyhow::Result<ExitCode> {
43    let args = Args::parse();
44
45    let input = io::read_to_string(io::stdin())?;
46
47    let input = if let Type::Keys = args.r#type {
48        &input
49    } else {
50        // Trim whitespace for parsers that can't handle it. Otherwise input on `stdin` that ends in
51        // a newline (e.g. what `echo` outputs by default) will fail with a cryptic error.
52        input.trim()
53    };
54
55    let exit_code = match args.r#type {
56        Type::Keys => run::<Keys>(input, args.debug),
57        Type::Key => run::<Key>(input, args.debug),
58        Type::KeyModifiers => run::<KeyModifiers>(input, args.debug),
59        Type::KeyCode => run::<KeyCode>(input, args.debug),
60    };
61
62    Ok(exit_code)
63}
64
65fn run<T>(input: &str, debug: bool) -> ExitCode
66where
67    T: FromStr + Debug + Display,
68    <T as FromStr>::Err: Display,
69{
70    let result = input.parse::<T>();
71
72    match &result {
73        Ok(keys) if debug => println!("{keys:?}"),
74        Ok(keys) => println!("{keys}"),
75        Err(error) => println!("{error}"),
76    }
77
78    match &result {
79        Ok(_) => ExitCode::SUCCESS,
80        Err(_) => ExitCode::FAILURE,
81    }
82}