pub struct Keybinds<A> { /* private fields */ }Expand description
A dispatcher that takes key inputs and dispatches the corresponding key bindings’ actions.
The Keybinds::dispatch method dispatches an action for the given key input. The dispatcher receives key inputs
as a key sequence. When the sequence matches to one of the defined key bindings, it returns the corresponding
action.
When some key binding matches to a key sequence, the dispatcher dispatches the corresponding action even if some other key bindings are ongoing. For example, if “a b” and “a b c” are defined, the sequence “a” → “b” matches to the binding “a b” ignoring matching to “a b c” is ongoing hence “a b c” will never be triggered.
If the interval of key inputs exceeds the timeout (default to 1 second), the key sequence breaks there. For example,
when “b” input follows “a” input after 2 seconds, each inputs “a” and “b” are treated as single key inputs, not a
key sequence “a b”. Please see Keybinds::set_timeout for the code example.
use keybinds::{Keybinds, KeyInput, Key, Mods};
#[derive(PartialEq, Eq, Debug)]
enum Action {
Foo,
Bar,
}
let mut keybinds = Keybinds::default();
// Key sequence "f" → "o" → "o"
keybinds.bind("f o o", Action::Foo).unwrap();
// Sequence of key combinations
keybinds.bind("Ctrl+b Ctrl+a", Action::Bar).unwrap();
assert_eq!(keybinds.dispatch('f'), None);
assert_eq!(keybinds.dispatch('o'), None);
assert_eq!(keybinds.dispatch('o'), Some(&Action::Foo));
assert_eq!(keybinds.dispatch(KeyInput::new('b', Mods::CTRL)), None);
assert_eq!(keybinds.dispatch(KeyInput::new('a', Mods::CTRL)), Some(&Action::Bar));Implementations§
Source§impl<A> Keybinds<A>
impl<A> Keybinds<A>
Sourcepub fn new(binds: Vec<Keybind<A>>) -> Self
pub fn new(binds: Vec<Keybind<A>>) -> Self
Create a Keybinds instance from the array of key bindings.
If you want to collect a Keybinds instance from an iterator, Keybinds::from_iter is also useful.
use keybinds::{Keybind, Keybinds, Key, Mods, KeyInput};
enum Action {
Foo,
Bar,
Piyo,
}
let binds = vec![
Keybind::new('a', Action::Foo),
Keybind::new(Key::Enter, Action::Bar),
Keybind::new(KeyInput::new(Key::Up, Mods::CTRL), Action::Piyo),
];
let keybinds = Keybinds::new(binds);
assert_eq!(keybinds.as_slice().len(), 3);Sourcepub fn push(&mut self, bind: Keybind<A>)
pub fn push(&mut self, bind: Keybind<A>)
Push a new Keybind instance. If this method is called while some key binding matching is ongoing, the
matching is reset.
use keybinds::{Keybinds, Keybind};
struct Action;
let mut keybinds = Keybinds::default();
keybinds.push(Keybind::new('x', Action));
assert_eq!(keybinds.as_slice().len(), 1);Sourcepub fn bind(&mut self, key_sequence: &str, action: A) -> Result<()>
pub fn bind(&mut self, key_sequence: &str, action: A) -> Result<()>
Define a new key binding. If the key sequence does not follow the syntax, this method returns an error.
use keybinds::{Keybinds, Keybind, KeyInput, Mods};
#[derive(PartialEq, Eq, Debug)]
struct Action;
let mut keybinds = Keybinds::default();
keybinds.bind("Ctrl+x Ctrl+y", Action).unwrap();
keybinds.bind("Foo+x", Action).unwrap_err(); // Unknown modifier "Foo"
assert_eq!(keybinds.as_slice().len(), 1);
// Dispatch the action
assert_eq!(keybinds.dispatch(KeyInput::new('x', Mods::CTRL)), None); // Matching is ongoing
assert_eq!(keybinds.dispatch(KeyInput::new('y', Mods::CTRL)), Some(&Action)); // DispatchedExamples found in repository?
24 fn default() -> Self {
25 // Create a key bindings dispatcher to dispatch actions for upcoming key inputs
26 let mut keybinds = Keybinds::default();
27
28 // Key bindings to dispatch the actions
29 keybinds.bind("h i", Action::SayHi).unwrap();
30 keybinds.bind("Mod+m", Action::ToggleMaximized).unwrap();
31 keybinds.bind("Mod+Alt+t", Action::ToggleTheme).unwrap();
32 keybinds.bind("Mod+x Mod+c", Action::Exit).unwrap();
33
34 Self {
35 window: None,
36 keybinds,
37 converter: WinitEventConverter::default(),
38 }
39 }More examples
35 fn default() -> Self {
36 // Create a key bindings dispatcher to dispatch actions for upcoming key inputs
37 let mut keybinds = Keybinds::default();
38
39 // Define the key bindings
40 keybinds.bind("Mod+m", Action::ToggleMaximize).unwrap();
41 keybinds.bind("H e l l o", Action::SayHello).unwrap();
42 keybinds.bind("Mod+T", Action::ToggleTheme).unwrap();
43 keybinds.bind("Mod+x Mod+c", Action::Exit).unwrap();
44
45 Self {
46 window_id: window::Id::unique(),
47 ongoing_input: "".to_string(),
48 last_action: "".to_string(),
49 maximized: false,
50 theme: Theme::Dark,
51 help: keybinds
52 .as_slice()
53 .iter()
54 .map(|b| (format!("{}", b.seq), b.action))
55 .collect(),
56 keybinds,
57 }
58 }11fn main() -> io::Result<()> {
12 // Create a key bindings dispatcher to dispatch actions for upcoming key inputs
13 let mut keybinds = Keybinds::default();
14
15 // Register key bindings to dispatch the actions
16 keybinds.bind("h e l l o", Action::SayHello).unwrap();
17 keybinds.bind("Esc", Action::ExitApp).unwrap();
18
19 println!("Type inputs and send it by hitting Enter key. Send Esc to exit");
20 for b in io::stdin().lock().bytes() {
21 // Convert your key input into `KeyInput` struct
22 let input = match b? {
23 b'\x1b' => KeyInput::from(Key::Esc),
24 b => KeyInput::from(b as char),
25 };
26 println!("Key input: {input:?}");
27
28 // Try to dispatch action by `dispatch` method
29 if let Some(action) = keybinds.dispatch(input) {
30 println!("Dispatched action: {action:?}");
31 match action {
32 Action::SayHello => println!("Hello!"),
33 Action::ExitApp => break,
34 }
35 }
36 }
37
38 Ok(())
39}19fn main() -> Result<(), Error> {
20 // Create a key bindings dispatcher to dispatch actions for upcoming key inputs
21 let mut keybinds = Keybinds::default();
22
23 // Key bindings to dispatch the actions
24 keybinds.bind("h i", Action::SayHi).unwrap();
25 keybinds.bind("Left", Action::MoveLeft).unwrap();
26 keybinds.bind("Ctrl+p", Action::Paste).unwrap();
27 keybinds.bind("Ctrl+x Ctrl+c", Action::ExitApp).unwrap();
28
29 let caps = Capabilities::new_from_env()?;
30 let terminal = new_terminal(caps)?;
31
32 let mut buf = BufferedTerminal::new(terminal)?;
33 buf.add_change("Type Ctrl+x Ctrl+c to exit");
34 buf.add_change(Change::CursorPosition {
35 x: Position::Absolute(0),
36 y: Position::Absolute(2),
37 });
38 buf.flush()?;
39 buf.terminal().set_raw_mode()?;
40
41 loop {
42 let Some(input) = buf.terminal().poll_input(None)? else {
43 continue;
44 };
45
46 // Dispatch action by directly passing `InputEvent` to `dispatch` method.
47 let action = keybinds.dispatch(&input);
48
49 buf.add_change(Change::CursorPosition {
50 x: Position::Absolute(0),
51 y: Position::Absolute(0),
52 });
53 buf.add_change(Change::ClearToEndOfLine(ColorAttribute::Default));
54 if let Some(action) = action {
55 buf.add_change(Change::Attribute(AttributeChange::Foreground(
56 AnsiColor::Red.into(),
57 )));
58 buf.add_change(format!("Action: {action:?}"));
59 }
60
61 buf.add_change(Change::CursorPosition {
62 x: Position::Absolute(0),
63 y: Position::Absolute(2),
64 });
65 buf.add_change(Change::ClearToEndOfLine(ColorAttribute::Default));
66 buf.add_change(format!("KeyInput: {:?}", KeyInput::from(input)));
67
68 buf.flush()?;
69
70 if action == Some(&Action::ExitApp) {
71 return Ok(());
72 }
73 }
74}Sourcepub fn dispatch<I: Into<KeyInput>>(&mut self, input: I) -> Option<&A>
pub fn dispatch<I: Into<KeyInput>>(&mut self, input: I) -> Option<&A>
Dispatch an action for the given key input.
This method accepts various values which implement Into<KeyInput>. For example, char value is converted
into a single-character key input with no modifiers. Conversions from key event types in several frameworks
are supported by enabling the optional features.
use keybinds::{Keybinds, KeyInput, Key, Mods};
#[derive(PartialEq, Eq, Debug)]
enum Action {
Foo,
}
let mut keybinds = Keybinds::default();
keybinds.bind("f Ctrl+o Enter", Action::Foo).unwrap();
// Input "f" key with no modifiers
assert_eq!(keybinds.dispatch('f'), None);
// Input "o" key with Ctrl modifier
assert_eq!(keybinds.dispatch(KeyInput::new('o', Mods::CTRL)), None);
// Input "Enter" key with no modifiers
assert_eq!(keybinds.dispatch(Key::Enter), Some(&Action::Foo));Examples found in repository?
More examples
11fn main() -> io::Result<()> {
12 // Create a key bindings dispatcher to dispatch actions for upcoming key inputs
13 let mut keybinds = Keybinds::default();
14
15 // Register key bindings to dispatch the actions
16 keybinds.bind("h e l l o", Action::SayHello).unwrap();
17 keybinds.bind("Esc", Action::ExitApp).unwrap();
18
19 println!("Type inputs and send it by hitting Enter key. Send Esc to exit");
20 for b in io::stdin().lock().bytes() {
21 // Convert your key input into `KeyInput` struct
22 let input = match b? {
23 b'\x1b' => KeyInput::from(Key::Esc),
24 b => KeyInput::from(b as char),
25 };
26 println!("Key input: {input:?}");
27
28 // Try to dispatch action by `dispatch` method
29 if let Some(action) = keybinds.dispatch(input) {
30 println!("Dispatched action: {action:?}");
31 match action {
32 Action::SayHello => println!("Hello!"),
33 Action::ExitApp => break,
34 }
35 }
36 }
37
38 Ok(())
39}49 fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
50 // Convert the window event into key input
51 let input = self.converter.convert(&event);
52 if input.key() != Key::Ignored {
53 println!("Key input: {input:?}");
54 }
55
56 // Check if the converted key input dispatches some action
57 if let Some(action) = self.keybinds.dispatch(input) {
58 println!("Action: {action:?}");
59
60 match action {
61 Action::SayHi => println!("Hi!"),
62 Action::ToggleMaximized => {
63 let window = self.window.as_ref().unwrap();
64 window.set_maximized(!window.is_maximized());
65 }
66 Action::ToggleTheme => {
67 let window = self.window.as_ref().unwrap();
68 let theme = match window.theme() {
69 Some(Theme::Dark) => Theme::Light,
70 _ => Theme::Dark,
71 };
72 window.set_theme(Some(theme));
73 }
74 Action::Exit => event_loop.exit(),
75 }
76 }
77
78 if let WindowEvent::CloseRequested = event {
79 event_loop.exit();
80 }
81 }64fn main() -> io::Result<()> {
65 // Parse the configuration from the file content
66 let config: Config = toml::from_str(CONFIG_FILE_CONTENT).unwrap();
67
68 // `Keybinds` instance is a key bindings dispatcher that receives key inputs and
69 // dispatches the corresponding actions.
70 let mut keybinds = config.keyboard;
71
72 enable_raw_mode()?;
73 let mut stdout = io::stdout();
74
75 // Read the crossterm's key events and pass it to `Keybinds::dispatch` directly.
76 while let Ok(event) = event::read() {
77 // If the event triggered some action, handle it using `match`
78 if let Some(action) = keybinds.dispatch(&event) {
79 match action {
80 Action::Exit => break,
81 Action::Up => execute!(stdout, cursor::MoveUp(1))?,
82 Action::Down => execute!(stdout, cursor::MoveDown(1))?,
83 Action::Left => execute!(stdout, cursor::MoveLeft(1))?,
84 Action::Right => execute!(stdout, cursor::MoveRight(1))?,
85 Action::Top => execute!(stdout, cursor::MoveUp(9999))?,
86 Action::Bottom => execute!(stdout, cursor::MoveDown(9999))?,
87 Action::Home => execute!(stdout, cursor::MoveLeft(9999))?,
88 Action::End => execute!(stdout, cursor::MoveRight(9999))?,
89 }
90 }
91 }
92
93 disable_raw_mode()
94}62 fn update(&mut self, message: Message) -> Task<Message> {
63 match message {
64 Message::WindowOpen(id) => self.window_id = id,
65 Message::KeyEvent(event) => {
66 let input = KeyInput::from(&event);
67 if input.key() != Key::Ignored {
68 println!("Key input: {input:?}");
69 if !self.keybinds.is_ongoing() {
70 self.last_action.clear();
71 self.ongoing_input.clear();
72 }
73 if !self.ongoing_input.is_empty() {
74 self.ongoing_input.push_str(" → ");
75 }
76 write!(self.ongoing_input, "{input:}").unwrap();
77 }
78
79 if let Some(action) = self.keybinds.dispatch(event) {
80 self.last_action = format!("{action:?}");
81
82 // Handle the dispatched action
83 match action {
84 Action::SayHello => println!("Hello!"),
85 Action::ToggleMaximize => {
86 self.maximized = !self.maximized;
87 return window::maximize(self.window_id, self.maximized);
88 }
89 Action::ToggleTheme => {
90 self.theme = match self.theme {
91 Theme::Dark => Theme::Light,
92 _ => Theme::Dark,
93 };
94 }
95 Action::Exit => return iced::exit(),
96 }
97 }
98 }
99 Message::Reset => {
100 self.keybinds.reset();
101 self.ongoing_input.clear();
102 self.last_action.clear();
103 }
104 }
105 Task::none()
106 }19fn main() -> Result<(), Error> {
20 // Create a key bindings dispatcher to dispatch actions for upcoming key inputs
21 let mut keybinds = Keybinds::default();
22
23 // Key bindings to dispatch the actions
24 keybinds.bind("h i", Action::SayHi).unwrap();
25 keybinds.bind("Left", Action::MoveLeft).unwrap();
26 keybinds.bind("Ctrl+p", Action::Paste).unwrap();
27 keybinds.bind("Ctrl+x Ctrl+c", Action::ExitApp).unwrap();
28
29 let caps = Capabilities::new_from_env()?;
30 let terminal = new_terminal(caps)?;
31
32 let mut buf = BufferedTerminal::new(terminal)?;
33 buf.add_change("Type Ctrl+x Ctrl+c to exit");
34 buf.add_change(Change::CursorPosition {
35 x: Position::Absolute(0),
36 y: Position::Absolute(2),
37 });
38 buf.flush()?;
39 buf.terminal().set_raw_mode()?;
40
41 loop {
42 let Some(input) = buf.terminal().poll_input(None)? else {
43 continue;
44 };
45
46 // Dispatch action by directly passing `InputEvent` to `dispatch` method.
47 let action = keybinds.dispatch(&input);
48
49 buf.add_change(Change::CursorPosition {
50 x: Position::Absolute(0),
51 y: Position::Absolute(0),
52 });
53 buf.add_change(Change::ClearToEndOfLine(ColorAttribute::Default));
54 if let Some(action) = action {
55 buf.add_change(Change::Attribute(AttributeChange::Foreground(
56 AnsiColor::Red.into(),
57 )));
58 buf.add_change(format!("Action: {action:?}"));
59 }
60
61 buf.add_change(Change::CursorPosition {
62 x: Position::Absolute(0),
63 y: Position::Absolute(2),
64 });
65 buf.add_change(Change::ClearToEndOfLine(ColorAttribute::Default));
66 buf.add_change(format!("KeyInput: {:?}", KeyInput::from(input)));
67
68 buf.flush()?;
69
70 if action == Some(&Action::ExitApp) {
71 return Ok(());
72 }
73 }
74}Sourcepub fn set_timeout(&mut self, timeout: Duration)
pub fn set_timeout(&mut self, timeout: Duration)
Set the timeout to wait for the next key input while matching to key bindings is ongoing. For the default
timeout value, see DEFAULT_TIMEOUT.
use std::time::Duration;
use std::thread::sleep;
use keybinds::Keybinds;
struct Action;
let mut keybinds = Keybinds::default();
keybinds.bind("a b", Action).unwrap();
// Set the timeout to very small value to demonstrate the usage.
keybinds.set_timeout(Duration::from_millis(10));
// Input the first key input of key sequence "a b"
assert!(keybinds.dispatch('a').is_none());
// Make the ongoing match expire (50ms > 10ms)
sleep(Duration::from_millis(50));
// Input the second key input of key sequence "a b". However it does not dispatch the action
// because the matching expired.
assert!(keybinds.dispatch('b').is_none());Examples found in repository?
27fn main() {
28 let configuration = r#"
29[keyboard]
30timeout = 500
31
32[keyboard.bindings]
33"Ctrl+Alt+Enter" = "OpenFile"
34"Ctrl+x Ctrl+c" = "ExitApp"
35"#;
36
37 // Parse the TOML input into the `Config` instance
38 let config: Config = toml::from_str(configuration).unwrap();
39 let mut keybinds = config.keyboard.bindings;
40
41 // Set the key sequence matching timeout if needed
42 if let Some(ms) = config.keyboard.timeout {
43 keybinds.set_timeout(Duration::from_millis(ms));
44 }
45
46 dbg!(keybinds.as_slice());
47 dbg!(keybinds.timeout());
48}Sourcepub fn reset(&mut self)
pub fn reset(&mut self)
Reset the state of the dispatcher. This resets the ongoing matching state of key binding.
use keybinds::Keybinds;
struct Action;
let mut keybinds = Keybinds::default();
keybinds.bind("a b", Action).unwrap();
assert!(keybinds.dispatch('a').is_none());
// Abandon the ongoing matching for "a b"
keybinds.reset();
assert!(keybinds.dispatch('b').is_none());Examples found in repository?
62 fn update(&mut self, message: Message) -> Task<Message> {
63 match message {
64 Message::WindowOpen(id) => self.window_id = id,
65 Message::KeyEvent(event) => {
66 let input = KeyInput::from(&event);
67 if input.key() != Key::Ignored {
68 println!("Key input: {input:?}");
69 if !self.keybinds.is_ongoing() {
70 self.last_action.clear();
71 self.ongoing_input.clear();
72 }
73 if !self.ongoing_input.is_empty() {
74 self.ongoing_input.push_str(" → ");
75 }
76 write!(self.ongoing_input, "{input:}").unwrap();
77 }
78
79 if let Some(action) = self.keybinds.dispatch(event) {
80 self.last_action = format!("{action:?}");
81
82 // Handle the dispatched action
83 match action {
84 Action::SayHello => println!("Hello!"),
85 Action::ToggleMaximize => {
86 self.maximized = !self.maximized;
87 return window::maximize(self.window_id, self.maximized);
88 }
89 Action::ToggleTheme => {
90 self.theme = match self.theme {
91 Theme::Dark => Theme::Light,
92 _ => Theme::Dark,
93 };
94 }
95 Action::Exit => return iced::exit(),
96 }
97 }
98 }
99 Message::Reset => {
100 self.keybinds.reset();
101 self.ongoing_input.clear();
102 self.last_action.clear();
103 }
104 }
105 Task::none()
106 }Sourcepub fn timeout(&self) -> Duration
pub fn timeout(&self) -> Duration
Get the timeout of key binding matching. See Keybinds::set_timeout to know the details of the
timeout.
use std::time::Duration;
use keybinds::{Keybinds, DEFAULT_TIMEOUT};
struct Action;
let mut keybinds = Keybinds::<Action>::default();
assert_eq!(keybinds.timeout(), DEFAULT_TIMEOUT);
let duration = Duration::from_millis(500);
keybinds.set_timeout(duration);
assert_eq!(keybinds.timeout(), duration);Examples found in repository?
27fn main() {
28 let configuration = r#"
29[keyboard]
30timeout = 500
31
32[keyboard.bindings]
33"Ctrl+Alt+Enter" = "OpenFile"
34"Ctrl+x Ctrl+c" = "ExitApp"
35"#;
36
37 // Parse the TOML input into the `Config` instance
38 let config: Config = toml::from_str(configuration).unwrap();
39 let mut keybinds = config.keyboard.bindings;
40
41 // Set the key sequence matching timeout if needed
42 if let Some(ms) = config.keyboard.timeout {
43 keybinds.set_timeout(Duration::from_millis(ms));
44 }
45
46 dbg!(keybinds.as_slice());
47 dbg!(keybinds.timeout());
48}Sourcepub fn as_slice(&self) -> &[Keybind<A>]
pub fn as_slice(&self) -> &[Keybind<A>]
Get the reference to the inner slice of Keybind instances.
use keybinds::{Keybinds, Keybind};
#[derive(Clone, PartialEq, Eq, Debug)]
struct Action;
let mut keybinds = Keybinds::default();
keybinds.bind("a", Action).unwrap();
assert_eq!(keybinds.as_slice(), &[Keybind::new('a', Action)]);Examples found in repository?
27fn main() {
28 let configuration = r#"
29[keyboard]
30timeout = 500
31
32[keyboard.bindings]
33"Ctrl+Alt+Enter" = "OpenFile"
34"Ctrl+x Ctrl+c" = "ExitApp"
35"#;
36
37 // Parse the TOML input into the `Config` instance
38 let config: Config = toml::from_str(configuration).unwrap();
39 let mut keybinds = config.keyboard.bindings;
40
41 // Set the key sequence matching timeout if needed
42 if let Some(ms) = config.keyboard.timeout {
43 keybinds.set_timeout(Duration::from_millis(ms));
44 }
45
46 dbg!(keybinds.as_slice());
47 dbg!(keybinds.timeout());
48}More examples
35 fn default() -> Self {
36 // Create a key bindings dispatcher to dispatch actions for upcoming key inputs
37 let mut keybinds = Keybinds::default();
38
39 // Define the key bindings
40 keybinds.bind("Mod+m", Action::ToggleMaximize).unwrap();
41 keybinds.bind("H e l l o", Action::SayHello).unwrap();
42 keybinds.bind("Mod+T", Action::ToggleTheme).unwrap();
43 keybinds.bind("Mod+x Mod+c", Action::Exit).unwrap();
44
45 Self {
46 window_id: window::Id::unique(),
47 ongoing_input: "".to_string(),
48 last_action: "".to_string(),
49 maximized: false,
50 theme: Theme::Dark,
51 help: keybinds
52 .as_slice()
53 .iter()
54 .map(|b| (format!("{}", b.seq), b.action))
55 .collect(),
56 keybinds,
57 }
58 }Sourcepub fn is_ongoing(&self) -> bool
pub fn is_ongoing(&self) -> bool
Return whether the matching for key bindings is ongoing.
use keybinds::Keybinds;
struct Action;
let mut keybinds = Keybinds::default();
keybinds.bind("a b", Action).unwrap();
assert!(!keybinds.is_ongoing());
keybinds.dispatch('a');
assert!(keybinds.is_ongoing());
keybinds.dispatch('b');
assert!(!keybinds.is_ongoing());Examples found in repository?
62 fn update(&mut self, message: Message) -> Task<Message> {
63 match message {
64 Message::WindowOpen(id) => self.window_id = id,
65 Message::KeyEvent(event) => {
66 let input = KeyInput::from(&event);
67 if input.key() != Key::Ignored {
68 println!("Key input: {input:?}");
69 if !self.keybinds.is_ongoing() {
70 self.last_action.clear();
71 self.ongoing_input.clear();
72 }
73 if !self.ongoing_input.is_empty() {
74 self.ongoing_input.push_str(" → ");
75 }
76 write!(self.ongoing_input, "{input:}").unwrap();
77 }
78
79 if let Some(action) = self.keybinds.dispatch(event) {
80 self.last_action = format!("{action:?}");
81
82 // Handle the dispatched action
83 match action {
84 Action::SayHello => println!("Hello!"),
85 Action::ToggleMaximize => {
86 self.maximized = !self.maximized;
87 return window::maximize(self.window_id, self.maximized);
88 }
89 Action::ToggleTheme => {
90 self.theme = match self.theme {
91 Theme::Dark => Theme::Light,
92 _ => Theme::Dark,
93 };
94 }
95 Action::Exit => return iced::exit(),
96 }
97 }
98 }
99 Message::Reset => {
100 self.keybinds.reset();
101 self.ongoing_input.clear();
102 self.last_action.clear();
103 }
104 }
105 Task::none()
106 }Sourcepub fn ongoing_inputs(&self) -> &[KeyInput]
pub fn ongoing_inputs(&self) -> &[KeyInput]
Get the ongoing key inputs being matched to some key sequence in the key bindings.
use keybinds::{Keybinds, KeyInput};
struct Action;
let mut keybinds = Keybinds::default();
keybinds.bind("a b c", Action).unwrap();
// Initially there is no ongoing sequence.
assert_eq!(keybinds.ongoing_inputs(), &[]);
// Matching to the key sequence "a b c" is ongoing.
keybinds.dispatch('a');
keybinds.dispatch('b');
assert_eq!(keybinds.ongoing_inputs(), &['a'.into(), 'b'.into()]);
// The inputs matches to "a b c" and dispatches the action.
keybinds.dispatch('c');
assert_eq!(keybinds.ongoing_inputs(), &[]);
// This input matches nothing so there is no ongoing match.
keybinds.dispatch('d');
assert_eq!(keybinds.ongoing_inputs(), &[]);Sourcepub fn into_vec(self) -> Vec<Keybind<A>>
pub fn into_vec(self) -> Vec<Keybind<A>>
Convert to the inner Vec of Keybind instances. This method is useful when you need to modify the key
bindings.
use keybinds::{Keybinds, Keybind};
#[derive(Clone, PartialEq, Eq, Debug)]
struct Action;
let mut keybinds = Keybinds::new(vec![Keybind::new('a', Action)]);
let mut config = keybinds.into_vec();
config[0] = Keybind::new('b', Action);
// Recreate the `Keybinds` instance
let mut keybinds = Keybinds::new(config);
assert_eq!(keybinds.dispatch('a'), None);
assert_eq!(keybinds.dispatch('b'), Some(&Action));Trait Implementations§
Source§impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Keybinds<A>
Available on crate feature arbitrary only.
impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Keybinds<A>
arbitrary only.Source§fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self>
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self>
Self from the given unstructured data. Read moreSource§fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self, Error>
fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self, Error>
Self from the entirety of the given
unstructured data. Read moreSource§fn size_hint(depth: usize) -> (usize, Option<usize>)
fn size_hint(depth: usize) -> (usize, Option<usize>)
Unstructured this type
needs to construct itself. Read moreSource§fn try_size_hint(
depth: usize,
) -> Result<(usize, Option<usize>), MaxRecursionReached>
fn try_size_hint( depth: usize, ) -> Result<(usize, Option<usize>), MaxRecursionReached>
Unstructured this type
needs to construct itself. Read moreSource§impl<'de, A: Deserialize<'de>> Deserialize<'de> for Keybinds<A>
Available on crate feature serde only.
impl<'de, A: Deserialize<'de>> Deserialize<'de> for Keybinds<A>
serde only.Source§fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>
Source§impl<A> Extend<Keybind<A>> for Keybinds<A>
impl<A> Extend<Keybind<A>> for Keybinds<A>
Source§fn extend<I>(&mut self, iter: I)where
I: IntoIterator<Item = Keybind<A>>,
fn extend<I>(&mut self, iter: I)where
I: IntoIterator<Item = Keybind<A>>,
Extend the key bindings with the iterator of Keybind instances. When some key binding matching is ongoing,
it will be reset.
use keybinds::{Keybinds, Keybind};
struct Action;
let mut keybinds = Keybinds::new(vec![Keybind::new(['a', 'b'], Action)]);
keybinds.dispatch('a');
assert!(keybinds.is_ongoing());
keybinds.extend([Keybind::new('c', Action), Keybind::new('d', Action)]);
assert_eq!(keybinds.as_slice().len(), 3);
// The matching state was reset
assert!(!keybinds.is_ongoing());Source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one)Source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one)Source§impl<A> FromIterator<Keybind<A>> for Keybinds<A>
impl<A> FromIterator<Keybind<A>> for Keybinds<A>
Source§fn from_iter<T: IntoIterator<Item = Keybind<A>>>(iter: T) -> Self
fn from_iter<T: IntoIterator<Item = Keybind<A>>>(iter: T) -> Self
Collect Keybinds instance from an iterator of Keybind.
use keybinds::{Keybinds, Keybind, KeySeq};
enum Action {
Foo,
Bar,
Piyo,
}
let config = [
("f o o", Action::Foo),
("Ctrl+b Ctrl+a", Action::Bar),
("Enter", Action::Piyo),
];
let binds: Keybinds<_> = config
.into_iter()
.map(|(k, a)| k.parse().map(|k: KeySeq| Keybind::new(k, a)))
.collect::<Result<_, _>>()
.unwrap();
assert_eq!(binds.as_slice().len(), 3);impl<A: Eq> Eq for Keybinds<A>
impl<A> StructuralPartialEq for Keybinds<A>
Auto Trait Implementations§
impl<A> Freeze for Keybinds<A>
impl<A> RefUnwindSafe for Keybinds<A>where
A: RefUnwindSafe,
impl<A> Send for Keybinds<A>where
A: Send,
impl<A> Sync for Keybinds<A>where
A: Sync,
impl<A> Unpin for Keybinds<A>where
A: Unpin,
impl<A> UnwindSafe for Keybinds<A>where
A: UnwindSafe,
Blanket Implementations§
Source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
D: AdaptFrom<S, Swp, Dwp, T>,
impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
D: AdaptFrom<S, Swp, Dwp, T>,
Source§fn adapt_into_using<M>(self, method: M) -> Dwhere
M: TransformMatrix<T>,
fn adapt_into_using<M>(self, method: M) -> Dwhere
M: TransformMatrix<T>,
Source§fn adapt_into(self) -> D
fn adapt_into(self) -> D
Source§impl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
impl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
Source§fn arrays_from(colors: C) -> T
fn arrays_from(colors: C) -> T
Source§impl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
impl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
Source§fn arrays_into(self) -> C
fn arrays_into(self) -> C
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
Source§type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
parameters when converting.Source§fn cam16_into_unclamped(
self,
parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>,
) -> T
fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T
self into C, using the provided parameters.Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
Source§fn components_from(colors: C) -> T
fn components_from(colors: C) -> T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<T> FromAngle<T> for T
impl<T> FromAngle<T> for T
Source§fn from_angle(angle: T) -> T
fn from_angle(angle: T) -> T
angle.Source§impl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
impl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
Source§fn from_stimulus(other: U) -> T
fn from_stimulus(other: U) -> T
other into Self, while performing the appropriate scaling,
rounding and clamping.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
impl<T, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
Source§fn into_angle(self) -> U
fn into_angle(self) -> U
T.Source§impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
Source§type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
parameters when converting.Source§fn into_cam16_unclamped(
self,
parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>,
) -> T
fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T
self into C, using the provided parameters.Source§impl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
impl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
Source§fn into_color(self) -> U
fn into_color(self) -> U
Source§impl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
impl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
Source§fn into_color_unclamped(self) -> U
fn into_color_unclamped(self) -> U
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoStimulus<T> for T
impl<T> IntoStimulus<T> for T
Source§fn into_stimulus(self) -> T
fn into_stimulus(self) -> T
self into T, while performing the appropriate scaling,
rounding and clamping.Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
impl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
Source§type Error = <C as TryFromComponents<T>>::Error
type Error = <C as TryFromComponents<T>>::Error
try_into_colors fails to cast.Source§fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
Source§impl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
impl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
Source§fn try_into_color(self) -> Result<U, OutOfBounds<U>>
fn try_into_color(self) -> Result<U, OutOfBounds<U>>
OutOfBounds error is returned which contains
the unclamped color. Read more