Files
codex/codex-rs/tui/src/key_hint.rs
T
Josh McKinney e258f0f044 Use Option symbol for mac key hints (#5582)
## Summary
- show the Option (⌥) symbol in key hints when the TUI is built for
macOS so the shortcut text matches the platform terminology

## Testing
- cargo test -p codex-tui

------
https://chatgpt.com/codex/tasks/task_i_68fab7505530832992780a9e13fb707b
2025-10-23 20:04:15 -07:00

90 lines
2.6 KiB
Rust

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;
#[cfg(target_os = "macos")]
const ALT_PREFIX: &str = "⌥ + ";
#[cfg(not(target_os = "macos"))]
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().dim()
}