normalize key hints (#4586)
render key hints the same everywhere. | Before | After | |--------|-------| | <img width="816" height="172" alt="Screenshot 2025-10-01 at 5 15 42 PM" src="https://github.com/user-attachments/assets/f88d5db4-04bb-4e89-b571-568222c41e4b" /> | <img width="672" height="137" alt="Screenshot 2025-10-01 at 5 13 56 PM" src="https://github.com/user-attachments/assets/1fee6a71-f313-4620-8d9a-10766dc4e195" /> | | <img width="816" height="172" alt="Screenshot 2025-10-01 at 5 17 01 PM" src="https://github.com/user-attachments/assets/5170ab35-88b7-4131-b485-ecebea9f0835" /> | <img width="816" height="174" alt="Screenshot 2025-10-01 at 5 14 24 PM" src="https://github.com/user-attachments/assets/6b6bc64c-25b9-4824-b2d7-56f60370870a" /> | | <img width="816" height="172" alt="Screenshot 2025-10-01 at 5 17 29 PM" src="https://github.com/user-attachments/assets/2313b36a-e0a8-4cd2-82be-7d0fe7793c19" /> | <img width="816" height="134" alt="Screenshot 2025-10-01 at 5 14 37 PM" src="https://github.com/user-attachments/assets/e18934e8-8e9d-4f46-9809-39c8cb6ee893" /> | | <img width="816" height="172" alt="Screenshot 2025-10-01 at 5 17 40 PM" src="https://github.com/user-attachments/assets/0cc69e4e-8cce-420a-b3e4-be75a7e2c8f5" /> | <img width="816" height="134" alt="Screenshot 2025-10-01 at 5 14 56 PM" src="https://github.com/user-attachments/assets/329a5121-ae4a-4829-86e5-4c813543770c" /> |
This commit is contained in:
@@ -1,23 +1,86 @@
|
||||
use crossterm::event::KeyCode;
|
||||
use crossterm::event::KeyEvent;
|
||||
use crossterm::event::KeyEventKind;
|
||||
use crossterm::event::KeyModifiers;
|
||||
use ratatui::style::Style;
|
||||
use ratatui::style::Stylize;
|
||||
use ratatui::text::Span;
|
||||
use std::fmt::Display;
|
||||
|
||||
#[cfg(test)]
|
||||
const ALT_PREFIX: &str = "⌥";
|
||||
#[cfg(all(not(test), target_os = "macos"))]
|
||||
const ALT_PREFIX: &str = "⌥";
|
||||
#[cfg(all(not(test), not(target_os = "macos")))]
|
||||
const ALT_PREFIX: &str = "Alt+";
|
||||
const ALT_PREFIX: &str = "alt + ";
|
||||
const CTRL_PREFIX: &str = "ctrl + ";
|
||||
const SHIFT_PREFIX: &str = "shift + ";
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub(crate) struct KeyBinding {
|
||||
key: KeyCode,
|
||||
modifiers: KeyModifiers,
|
||||
}
|
||||
|
||||
impl KeyBinding {
|
||||
pub(crate) const fn new(key: KeyCode, modifiers: KeyModifiers) -> Self {
|
||||
Self { key, modifiers }
|
||||
}
|
||||
|
||||
pub fn is_press(&self, event: KeyEvent) -> bool {
|
||||
self.key == event.code
|
||||
&& self.modifiers == event.modifiers
|
||||
&& (event.kind == KeyEventKind::Press || event.kind == KeyEventKind::Repeat)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) const fn plain(key: KeyCode) -> KeyBinding {
|
||||
KeyBinding::new(key, KeyModifiers::NONE)
|
||||
}
|
||||
|
||||
pub(crate) const fn alt(key: KeyCode) -> KeyBinding {
|
||||
KeyBinding::new(key, KeyModifiers::ALT)
|
||||
}
|
||||
|
||||
pub(crate) const fn shift(key: KeyCode) -> KeyBinding {
|
||||
KeyBinding::new(key, KeyModifiers::SHIFT)
|
||||
}
|
||||
|
||||
pub(crate) const fn ctrl(key: KeyCode) -> KeyBinding {
|
||||
KeyBinding::new(key, KeyModifiers::CONTROL)
|
||||
}
|
||||
|
||||
fn modifiers_to_string(modifiers: KeyModifiers) -> String {
|
||||
let mut result = String::new();
|
||||
if modifiers.contains(KeyModifiers::CONTROL) {
|
||||
result.push_str(CTRL_PREFIX);
|
||||
}
|
||||
if modifiers.contains(KeyModifiers::SHIFT) {
|
||||
result.push_str(SHIFT_PREFIX);
|
||||
}
|
||||
if modifiers.contains(KeyModifiers::ALT) {
|
||||
result.push_str(ALT_PREFIX);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
impl From<KeyBinding> for Span<'static> {
|
||||
fn from(binding: KeyBinding) -> Self {
|
||||
(&binding).into()
|
||||
}
|
||||
}
|
||||
impl From<&KeyBinding> for Span<'static> {
|
||||
fn from(binding: &KeyBinding) -> Self {
|
||||
let KeyBinding { key, modifiers } = binding;
|
||||
let modifiers = modifiers_to_string(*modifiers);
|
||||
let key = match key {
|
||||
KeyCode::Enter => "enter".to_string(),
|
||||
KeyCode::Up => "↑".to_string(),
|
||||
KeyCode::Down => "↓".to_string(),
|
||||
KeyCode::Left => "←".to_string(),
|
||||
KeyCode::Right => "→".to_string(),
|
||||
KeyCode::PageUp => "pgup".to_string(),
|
||||
KeyCode::PageDown => "pgdn".to_string(),
|
||||
_ => format!("{key}").to_ascii_lowercase(),
|
||||
};
|
||||
Span::styled(format!("{modifiers}{key}"), key_hint_style())
|
||||
}
|
||||
}
|
||||
|
||||
fn key_hint_style() -> Style {
|
||||
Style::default().bold()
|
||||
}
|
||||
|
||||
fn modifier_span(prefix: &str, key: impl Display) -> Span<'static> {
|
||||
Span::styled(format!("{prefix}{key}"), key_hint_style())
|
||||
}
|
||||
|
||||
pub(crate) fn alt(key: impl Display) -> Span<'static> {
|
||||
modifier_span(ALT_PREFIX, key)
|
||||
Style::default().dim()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user