use {
crossterm::event::{KeyCode::*, KeyEvent, KeyModifiers},
std::fmt,
};
#[derive(Debug, Clone)]
pub struct KeyEventFormat {
pub control: String,
pub alt: String,
pub shift: String,
pub enter: String,
pub uppercase_shift: bool,
}
impl Default for KeyEventFormat {
fn default() -> Self {
Self {
control: "Ctrl-".to_string(),
alt: "Alt-".to_string(),
shift: "Shift-".to_string(),
enter: "Enter".to_string(),
uppercase_shift: false,
}
}
}
impl KeyEventFormat {
pub fn with_lowercase_modifiers(mut self) -> Self {
self.control = self.control.to_lowercase();
self.alt = self.alt.to_lowercase();
self.shift = self.shift.to_lowercase();
self
}
pub fn with_control<S: Into<String>>(mut self, s: S) -> Self {
self.control = s.into();
self
}
pub fn with_alt<S: Into<String>>(mut self, s: S) -> Self {
self.alt = s.into();
self
}
pub fn with_shift<S: Into<String>>(mut self, s: S) -> Self {
self.shift = s.into();
self
}
pub fn with_implicit_shift(mut self) -> Self {
self.shift = "".to_string();
self.uppercase_shift = true;
self
}
pub fn format(&self, key: KeyEvent) -> FormattedKeyEvent {
FormattedKeyEvent { format: self, key }
}
pub fn to_string(&self, key: KeyEvent) -> String {
self.format(key).to_string()
}
}
pub struct FormattedKeyEvent<'s> {
format: &'s KeyEventFormat,
key: KeyEvent,
}
impl<'s> fmt::Display for FormattedKeyEvent<'s> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let format = &self.format;
let key = &self.key;
if key.modifiers.contains(KeyModifiers::CONTROL) {
write!(f, "{}", format.control)?;
}
if key.modifiers.contains(KeyModifiers::ALT) {
write!(f, "{}", format.alt)?;
}
if key.modifiers.contains(KeyModifiers::SHIFT) {
write!(f, "{}", format.shift)?;
}
match key.code {
Char(' ') => {
write!(f, "Space")?;
}
Char('-') => {
write!(f, "Hyphen")?;
}
Char('\r') | Char('\n') | Enter => {
write!(f, "{}", format.enter)?;
}
Char(c) if key.modifiers.contains(KeyModifiers::SHIFT) && format.uppercase_shift => {
write!(f, "{}", c.to_ascii_uppercase())?;
}
Char(c) => {
write!(f, "{}", c.to_ascii_lowercase())?;
}
F(u) => {
write!(f, "F{u}")?;
}
_ => {
write!(f, "{:?}", key.code)?;
}
}
Ok(())
}
}