20 个版本 (3 个稳定版)
1.1.0 | 2024年8月12日 |
---|---|
1.0.1 | 2024年6月18日 |
1.0.0 | 2024年4月24日 |
0.6.4 | 2024年3月30日 |
0.4.0 | 2022年2月7日 |
#58 in 命令行界面
17,750 个月下载量
在 35 个库中使用 (13 个直接使用)
47KB
807 行
Crokey
Crokey 通过提供函数帮助在基于 crossterm 的终端应用程序中集成可配置的快捷键
- 解析字符串中的键组合
- 在字符串中描述键组合
- 编译时解析键组合
- 将 Crossterm 键事件组合成键组合
键组合
KeyCombination
由 1 到 3 个 "普通" 键和一些可选修饰符(alt、shift、ctrl)组成。
它可以被解析,通过 key!
宏以用户友好的方式构建,并从键事件中获取。
组合器
使用 Combiner
,您可以改变原始 Crossterm 键事件为键组合。
当终端足够现代并支持 Kitty 协议时,可以形成包含最多三个非修饰键的复杂组合,例如 Ctrl-Alt-Shift-g-y
或 Space-!
。
对于标准 ANSI 终端,仅提供常规组合,如 Shift-o
、Ctrl-Alt-Shift-g
或 i
。
组合器在这两种情况下都起作用:如果您同时按下 ctrl
、i
和 u
键,在兼容 kitty 的终端上它将产生一个组合(ctrl-i-u
),在其他终端中则假设您先按下 i
然后再按下 u
,它将作为两个键组合的序列(ctrl-i
然后 ctrl-u
)。
print_key
示例展示了如何处理这种情况
let fmt = KeyCombinationFormat::default();
let mut combiner = Combiner::default();
let combines = combiner.enable_combining().unwrap();
if combines {
println!("Your terminal supports combining keys");
} else {
println!("Your terminal doesn't support combining non-modifier keys");
}
println!("Type any key combination");
loop {
terminal::enable_raw_mode().unwrap();
let e = read();
terminal::disable_raw_mode().unwrap();
match e {
Ok(Event::Key(key_event)) => {
if let Some(key_combination) = combiner.transform(key_event) {
match key_combination {
key!(ctrl-c) | key!(ctrl-q) => {
println!("quitting");
break;
}
_ => {
println!("You typed {}", fmt.to_string(key_combination));
}
}
}
},
...
}
}
解析字符串
这些字符串通常由配置文件提供。
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
assert_eq!(
crokey::parse("alt-enter").unwrap(),
KeyEvent::new(KeyCode::Enter, KeyModifiers::ALT),
);
assert_eq!(
crokey::parse("shift-F6").unwrap(),
KeyEvent::new(KeyCode::F(6), KeyModifiers::SHIFT),
);
使用过程宏通过键组合 "字面量"
这些键组合在编译时解析,且运行时成本为零。
它们效率高且方便,用于匹配事件或定义硬编码的快捷键。
match key_event.into() {
key!(ctrl-c) => {
println!("Arg! You savagely killed me with a {}", fmt.to_string(key_event).red());
break;
}
key!(ctrl-q) => {
println!("You typed {} which gracefully quits", fmt.to_string(key_event).green());
break;
}
_ => {
println!("You typed {}", fmt.to_string(key_event).blue());
}
}
完整示例在 /examples/print_key
可以在常量上下文中调用 key!
宏
const quit: KeyCombination = key!(ctrl-q);
以可配置的格式显示字符串
use crokey::*;
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
// The default format
let format = KeyCombinationFormat::default();
assert_eq!(format.to_string(key!(shift-a)), "Shift-a");
assert_eq!(format.to_string(key!(ctrl-c)), "Ctrl-c");
// A more compact format
let format = KeyCombinationFormat::default()
.with_implicit_shift()
.with_control("^");
assert_eq!(format.to_string(key!(shift-a)), "A");
assert_eq!(format.to_string(key!(ctrl-c)), "^c");
使用 Serde 反序列化快捷键绑定
启用 "serde" 功能后,您可以以直接方式读取配置文件
use {
crokey::*,
crossterm::event::KeyEvent,
serde::Deserialize,
std::collections::HashMap,
};
#[derive(Debug, Deserialize)]
struct Config {
keybindings: HashMap<KeyCombination, String>,
}
static CONFIG_HJSON: &str = r#"
{
keybindings: {
a: aardvark
shift-b: babirussa
ctrl-k: koala
alt-j: jaguar
}
}
"#;
let config: Config = deser_hjson::from_str(CONFIG_HJSON).unwrap();
let key: KeyCombination = key!(shift-b);
assert_eq!(
config.keybindings.get(&key).unwrap(),
"babirussa",
);
您可以使用任何 Serde 兼容的格式,例如 JSON 或 TOML。
Crossterm 兼容性
Crokey 包含并重新导出 Crossterm,因此您无需导入它,以避免冲突。
依赖关系
~4–12MB
~165K SLoC