Skip to content

Commit 15c0a24

Browse files
committed
add first readme document
1 parent 61721c4 commit 15c0a24

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed

README.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
keybinds-rs
2+
===========
3+
4+
> [!CAUTION]
5+
> This crate is work in progress yet.
6+
7+
[keybinds-rs][crates-io] is a small Rust crate to define/parse/match key bindings.
8+
9+
- Provide a syntax to easily define key bindings in a configuration file like `Ctrl+A`
10+
- Support key sequences like `Ctrl+X CtrolS`
11+
- Parse/Generate the key bindings configuration using [serde][]
12+
- Platform-agnostic core API with minimal dependencies
13+
- **TODO:** Support several platforms as optional features
14+
15+
## Usage
16+
17+
This crate is platform-agnostic. Define key bindings by `KeyBinds` and build `KeyBindMatcher` instance with it.
18+
Pass each key input to the `trigger` method and it returns a triggered action. Key sequence and key combination
19+
can be parsed using `FromStr` trait.
20+
21+
```rust
22+
use keybinds::{KeyBind, KeyBinds, KeyBindMatcher, KeyInput, Key, Mods};
23+
24+
// Actions triggered by key bindings
25+
#[derive(PartialEq, Eq, Debug)]
26+
enum Action {
27+
SayHello,
28+
OpenFile,
29+
ExitApp,
30+
}
31+
32+
// Key bindings to trigger the actions
33+
let keybinds = KeyBinds::new(vec![
34+
// Key sequence "hello"
35+
KeyBind::multiple("h e l l o".parse().unwrap(), Action::SayHello),
36+
// Key combination "Ctrl + Shift + Enter"
37+
KeyBind::single("Ctrl+Shift+Enter".parse().unwrap(), Action::OpenFile),
38+
// Sequence of key combinations
39+
KeyBind::multiple("Ctrl+x Ctrl+c".parse().unwrap(), Action::ExitApp),
40+
]);
41+
42+
let mut matcher = KeyBindMatcher::new(keybinds);
43+
44+
// Trigger `SayHello` action
45+
assert_eq!(matcher.trigger(KeyInput::from('h')), None);
46+
assert_eq!(matcher.trigger(KeyInput::from('e')), None);
47+
assert_eq!(matcher.trigger(KeyInput::from('l')), None);
48+
assert_eq!(matcher.trigger(KeyInput::from('l')), None);
49+
assert_eq!(matcher.trigger(KeyInput::from('o')), Some(&Action::SayHello));
50+
51+
// Trigger `OpenFile` action
52+
let action = matcher.trigger(KeyInput::new(Key::Enter, Mods::CTRL | Mods::SHIFT));
53+
assert_eq!(action, Some(&Action::OpenFile));
54+
55+
// Trigger `ExitApp` action
56+
assert_eq!(matcher.trigger(KeyInput::new('x', Mods::CTRL)), None);
57+
assert_eq!(matcher.trigger(KeyInput::new('c', Mods::CTRL)), Some(&Action::ExitApp));
58+
```
59+
60+
## Syntax for key sequence and combination
61+
62+
Keys are joint with `+` as a key combination like `Ctrl+a`. The last key must be a normal key and others must be modifier
63+
keys.
64+
65+
Normal keys are a single character (e.g. `a`, `X`, ``) or a special key name (e.g. `Up`, `Enter`, `Tab`). Note that
66+
upper case characters like `A` are equivalent to the lower case ones like `a`. For representing `A` key, explicitly
67+
specify `Shift` modifier key.
68+
69+
The following modifier keys are available:
70+
71+
- `Ctrl`: Ctrl key
72+
- `Cmd`: Command key
73+
- `Mod`: Command key on macOS, Ctrl key on other platforms
74+
- `Shift`: Shift key
75+
- `Alt`: Alt key
76+
- `Option`: An alias to Alt key
77+
78+
here are some examples of key combinations:
79+
80+
```ignore
81+
a
82+
Enter
83+
Mod+x
84+
Ctrl+Shift+Left
85+
```
86+
87+
Key combinations are joint with whitespaces as a key sequence. When key combinations are input in the order, they
88+
trigger the action.
89+
90+
Here are some examples of key sequences:
91+
92+
```ignore
93+
h e l l o
94+
Ctrl+x Ctrl+c
95+
```
96+
97+
## [serde][] support
98+
99+
### Parsing key bindings configurations
100+
101+
`KeyBinds` implements serde's `Deserialize` trait. This is an example to parse key bindings as TOML.
102+
103+
```rust
104+
use serde::Deserialize;
105+
use keybinds::{KeyBinds, KeyBindMatcher, Key, Mods, KeyInput};
106+
107+
// Actions triggered by key bindings
108+
#[derive(Deserialize, PartialEq, Eq, Debug)]
109+
enum Action {
110+
OpenFile,
111+
ExitApp,
112+
}
113+
114+
// Configuration file format of your application
115+
#[derive(Deserialize)]
116+
pub struct Config {
117+
pub bindings: KeyBinds<Action>,
118+
}
119+
120+
let configuration = r#"
121+
[bindings]
122+
"Ctrl+Shift+Enter" = "OpenFile"
123+
"Ctrl+x Ctrl+c" = "ExitApp"
124+
"#;
125+
126+
// Parse the TOML input
127+
let config: Config = toml::from_str(configuration).unwrap();
128+
129+
// Use the key bindings parsed from the TOML input
130+
let mut matcher = KeyBindMatcher::new(config.bindings);
131+
let action = matcher.trigger(KeyInput::new(Key::Enter, Mods::CTRL | Mods::SHIFT));
132+
assert_eq!(action, Some(&Action::OpenFile));
133+
```
134+
135+
## License
136+
137+
This crate is licensed under [the MIT license](./LICENSE.txt).
138+
139+
[crates-io]: https://crates.io/crates/keybinds
140+
[serde]: https://serde.rs/

0 commit comments

Comments
 (0)