hlctl/src/add/mod.rs

82 lines
2.1 KiB
Rust

use clap::Subcommand;
use rustyline::{error::ReadlineError, DefaultEditor};
use thiserror::Error;
use crate::hlwm::{
command::{CommandParseError, HlwmCommand},
key::Key,
parser::{FromCommandArgs, ParseError},
};
#[derive(Subcommand, Debug, Clone)]
pub enum Add {
/// Add a new keybind to the existing hlctl config
#[clap(arg_required_else_help = true)]
Keybind {
#[arg(short, long)]
interactive: bool,
},
}
#[derive(Debug, Clone, Error)]
pub enum Error {
#[error("readline error: [{0}]")]
ReadlineError(String),
#[error("parse error: [{0}]")]
KeyParseError(#[from] ParseError),
#[error("could not parse command: [{0}]")]
CommandParseError(#[from] CommandParseError),
}
impl From<ReadlineError> for Error {
fn from(value: ReadlineError) -> Self {
Self::ReadlineError(value.to_string())
}
}
impl Add {
pub fn run(self) -> Result<(), Error> {
match self {
Add::Keybind { interactive } => {
if interactive {
keybind_interactive()
} else {
todo!()
}
}
}
}
}
fn keybind_interactive() -> Result<(), Error> {
let mut read = DefaultEditor::new()?;
let keys = read
.readline("Keys (Separated by spaces, tabs, +, or -): ")?
.trim()
.split([' ', '\t', '+', '-'])
.map(|l| l.trim())
.filter(|l| !l.is_empty())
.map(|k| Key::from_str_case_insensitive(k))
.collect::<Result<Vec<_>, _>>()?;
let command = {
let read = read.readline("Command (Arguments separated by tabs or spaces): ")?;
let mut args = read
.trim()
.split([' ', '\t'])
.map(|a| a.trim())
.filter(|a| !a.is_empty())
.map(|a| a.to_string());
match args.next() {
Some(cmd) => HlwmCommand::from_command_args(&cmd, args)?,
None => {
println!("No command provided");
std::process::exit(1);
}
}
};
println!("{keys:?} -> {command:?}");
Ok(())
}