7 个版本
0.3.0 | 2024年7月5日 |
---|---|
0.2.3 | 2024年4月8日 |
0.2.2 | 2024年3月6日 |
0.2.1 | 2024年2月20日 |
0.1.1 | 2024年2月20日 |
#127 在 GUI
43KB
201 行
keyseq
使用 ctrl-A
简写指定按键组合,支持 bevy 和 winit。
目标
-
在代码中指定按键组合的方式与文档中指定的方式相同。
-
为了在代码中找到按键组合,建议使用一种描述键的方式,例如,接受 "ctrl-A";不接受 "control-A" 或 "C-A" 或 "Ctrl+A"。
安装
cargo add keyseq --features bevy; # OR --features winit
主要宏
pkey!
宏指定物理按键组合,例如,pkey! { ctrl-A }
。pkeyseq!
宏指定物理按键组合序列,例如,pkeyseq! { ctrl-A alt-B C }
。lkey!
宏指定逻辑按键组合,例如,lkey! { ctrl-a }
。lkeyseq!
宏指定逻辑按键组合序列,例如,lkeyseq! { ctrl-a alt-b c }
。
概念
- 物理按键表示键盘上的特定按键。它发出的键码不会因按下什么修饰键而改变。例如,有一个物理的 'Q' 键,通常位于制表键的右侧。没有物理的 lowercase 'q' 键。
- 逻辑按键是由按键产生的。如果按下一个键产生一个 'q' 字符,那么它逻辑上就是一个 'q' 键。
用法
Winit
使用 "winit" 功能,keyseq::winit::pkey!
宏返回一个 (Modifiers, KeyCode)
元组。
物理按键
use keyseq::{Modifiers, winit::pkey};
use winit::keyboard::KeyCode;
assert_eq!(pkey! { A }, (Modifiers::NONE, KeyCode::KeyA));
assert_eq!(pkey! { ctrl-A }, (Modifiers::CONTROL, KeyCode::KeyA));
assert_eq!(pkey! { alt-A }, (Modifiers::ALT, KeyCode::KeyA));
assert_eq!(pkey! { shift-A }, (Modifiers::SHIFT, KeyCode::KeyA));
assert_eq!(pkey! { super-A }, (Modifiers::SUPER, KeyCode::KeyA));
assert_eq!(pkey! { ctrl-alt-; }, (Modifiers::ALT |
Modifiers::CONTROL, KeyCode::Semicolon));
物理按键序列
# use keyseq::Modifiers;
# use winit::keyboard::KeyCode;
use keyseq::winit::pkeyseq;
assert_eq!(pkeyseq! { A ctrl-B }, [(Modifiers::NONE, KeyCode::KeyA),
(Modifiers::CONTROL, KeyCode::KeyB)]);
逻辑按键
使用 "winit" 功能,宏 keyseq::winit::lkey!
返回一个 (Modifiers, Key)
元组。
use keyseq::{Modifiers, winit::lkey};
use winit::keyboard::Key;
assert_eq!(lkey! { a }, (Modifiers::NONE, Key::Character('a')));
assert_eq!(lkey! { ctrl-a }, (Modifiers::CONTROL, Key::Character('a')));
assert_eq!(lkey! { alt-a }, (Modifiers::ALT, Key::Character('a')));
assert_eq!(lkey! { shift-a }, (Modifiers::SHIFT, Key::Character('a')));
assert_eq!(lkey! { super-a }, (Modifiers::SUPER, Key::Character('a')));
assert_eq!(lkey! { ctrl-alt-; }, (Modifiers::ALT |
Modifiers::CONTROL, Key::Character(';')));
逻辑按键序列
# use keyseq::Modifiers;
# use winit::keyboard::Key;
use keyseq::winit::lkeyseq;
assert_eq!(lkeyseq! { a ctrl-b }, [(Modifiers::NONE, Key::Character('a')),
(Modifiers::CONTROL, Key::Character('b'))]);
没有小写物理按键
以下代码将无法编译。它坚持使用大写 'A' 来指定 A 键。
# use keyseq::winit::pkey;
let (mods, key) = pkey! { a }; // error: Use uppercase key names for physical keys
严格的修饰符顺序
默认启用 "strict-order" 功能,修饰符顺序错误将产生编译错误。如果没有该功能,它将发出警告。
# use keyseq::winit::pkey;
let _ = pkey! { alt-ctrl-A }; // error: Modifiers must occur in this order: control, alt, shift, super.
为什么不使用 winit::keyboard::ModifiersState
?
为什么返回 keyseq::Modifiers
而不是 winit
的自身 ModifiersState
?keyseq::Modifiers
和 winit::keyboard::ModifiersState
都是通过 bitflags 包生成的。最初,这个包返回 winit
的本地修饰符结构,因为它反编译成几乎相同的东西
// keyseq::winit::pkey! { ctrl-alt-A } desugared to
( ModifiersState::CONTROL
| ModifiersState::ALT
| ModifiersState::empty(), winit::keyboard::KeyCode::KeyA)
// keyseq::bevy::pkey! { ctrl-alt-A } desugars to
( Modifiers::CONTROL
| Modifiers::ALT
| Modifiers::empty(), bevy::prelude::KeyCode::KeyA)
然而,这些位标志与位或管道结合在一起时存在一个问题。
let modifiers: ModifiersState = ...;
match (modifiers.into(), key_code) {
// pkey! { ctrl-alt-A } => println!("Just pressed ctrl-alt-A!"),
// desugared to
(ModifiersState::CONTROL |
ModifiersState::ALT |
ModifiersState::empty(),
KeyCode::KeyA) => println!("Just pressed ctrl-alt-A!"),
反编译后,位或 |
现在被解释为匹配或 |
,它不匹配 ctrl-alt
;它只匹配 ctrl
或 alt
或没有修饰符。(这实际上对 bitflags
生成的结构体来说似乎是一个相当大的表达能力缺陷。)
为了避免这个问题,keyseq::Modifiers
被定义为 Modifiers(pub u8)
,并且位标志在宏中计算。这允许以下匹配表达式按预期工作。
match (modifiers.into(), key_code) {
// pkey! { ctrl-alt-A } => println!("Just pressed ctrl-alt-A!"),
// now desugars to
(Modifiers(3), KeyCode::KeyA) => println!("Just pressed ctrl-alt-A!"),
// And we can use the match-or to match multiple keychords.
pkey! { ctrl-A } | pkey! { super-A } => println!("Just pressed ctrl-A or super-A!"),
此外 keyseq::Modifiers
实现 keyseq::ModifiersState
和反之亦然。
Bevy
启用 "bevy" 功能,宏 keyseq::keyseq::bevy::pkey!
返回一个 (keyseqModifiers, KeyCode)
元组。
Bevy 没有逻辑键表示,因此没有 lkey!
和 lkeyseq!
宏。
use bevy::prelude::KeyCode;
use keyseq::{Modifiers, bevy::pkey};
assert_eq!(pkey! { ctrl-A }, (Modifiers::CONTROL, KeyCode::KeyA));
assert_eq!(pkey! { alt-A }, (Modifiers::ALT, KeyCode::KeyA));
assert_eq!(pkey! { shift-A }, (Modifiers::SHIFT, KeyCode::KeyA));
assert_eq!(pkey! { super-A }, (Modifiers::SUPER, KeyCode::KeyA));
assert_eq!(pkey! { ctrl-shift-A },
(Modifiers::SHIFT |
Modifiers::CONTROL, KeyCode::KeyA));
功能
- Winit,包括对 winit 的支持
- Bevy,包括对 bevy 的支持
- Poor,内部测试的瘦表示
- Strict-order,使用严格的修饰符顺序:ctrl、alt、shift、super(默认启用)
示例
对于这两个示例,按 A
并带有修饰符,将打印出匹配的键序列。
Winit 示例
cargo run --example winit --features winit
Bevy 示例
cargo run --example bevy --features bevy
注意
宏表示法
虽然使用括号也可以工作 pkey!(ctrl-alt-A)
,但 rustfmt 会自动在破折号周围添加空格,将其变为 pkey!(ctrl - alt - A)
。因此,建议使用花括号 pkey! { ctrl-alt-A }
,这样就不会被重新格式化。
兼容性
keyseq | bevy | winit |
---|---|---|
0.1.0 | 0.12.* | 0.29.* |
0.2.0 | 0.13.* | 0.29.* |
许可
此软件包受 MIT 许可证或 Apache 许可证 2.0 的许可。
依赖项
~0.2–37MB
~584K SLoC