use gpui::{Action, KeyContext, KeybindingKeystroke, Modifiers, SharedString, Window};
pub fn shortcut(action: &dyn Action, window: &Window) -> Option<SharedString> {
let binding = window.highest_precedence_binding_for_action(action)?;
Some(format(binding.keystrokes()))
}
pub fn shortcut_in(action: &dyn Action, context: &str, window: &Window) -> Option<SharedString> {
let mut key_context = KeyContext::new_with_defaults();
key_context.add(context.to_owned());
let binding = window.highest_precedence_binding_for_action_in_context(action, key_context)?;
Some(format(binding.keystrokes()))
}
pub fn format(keystrokes: &[KeybindingKeystroke]) -> SharedString {
let mut out = String::new();
for keystroke in keystrokes {
if !out.is_empty() {
out.push(' ');
}
modifiers(keystroke.modifiers(), &mut out);
out.push_str(&key(keystroke.key()));
}
SharedString::from(out)
}
#[cfg(target_os = "macos")]
fn modifiers(modifiers: &Modifiers, out: &mut String) {
if modifiers.function {
out.push_str("fn");
}
if modifiers.control {
out.push('⌃');
}
if modifiers.alt {
out.push('⌥');
}
if modifiers.shift {
out.push('⇧');
}
if modifiers.platform {
out.push('⌘');
}
}
#[cfg(not(target_os = "macos"))]
fn modifiers(modifiers: &Modifiers, out: &mut String) {
if modifiers.platform {
out.push_str(PLATFORM_MODIFIER);
}
if modifiers.control {
out.push_str("Ctrl+");
}
if modifiers.alt {
out.push_str("Alt+");
}
if modifiers.shift {
out.push_str("Shift+");
}
}
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
const PLATFORM_MODIFIER: &str = "Super+";
#[cfg(target_os = "windows")]
const PLATFORM_MODIFIER: &str = "Win+";
#[cfg(not(any(
target_os = "macos",
target_os = "linux",
target_os = "freebsd",
target_os = "windows"
)))]
const PLATFORM_MODIFIER: &str = "Super+";
#[cfg(target_os = "macos")]
fn key(key: &str) -> String {
let glyph = match key {
"backspace" => "⌫",
"delete" => "⌦",
"enter" => "↩",
"tab" => "⇥",
"escape" => "⎋",
"up" => "↑",
"down" => "↓",
"left" => "←",
"right" => "→",
"pageup" => "⇞",
"pagedown" => "⇟",
"home" => "↖",
"end" => "↘",
"space" => "Space",
key if key.chars().count() == 1 => return key.to_uppercase(),
key => return title_case(key),
};
glyph.to_owned()
}
#[cfg(not(target_os = "macos"))]
fn key(key: &str) -> String {
match key {
key if key.chars().count() == 1 => key.to_uppercase(),
key => title_case(key),
}
}
fn title_case(key: &str) -> String {
let mut chars = key.chars();
match chars.next() {
Some(first) => first.to_uppercase().chain(chars).collect(),
None => String::new(),
}
}