1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! # Keybind
//!
//! Wrapper around [device_query](https://github.com/ostrosco/device_query) providing a nicer API, allowing you to trigger
//! your logic on specific keybind.
//!
//! # Example
//!
//! ```ignore
//! use keybind::{Keybind, Keycode};
//!
//!fn main() {
//!    let mut keybind = Keybind::new(&[Keycode::LControl, Keycode::G]);
//!
//!    keybind.on_trigger(|| {
//!        println!("This will be printed when you press CTRL+G");
//!    });
//!
//!    keybind.wait();
//!}
//! ```
//!

use device_query::{DeviceQuery, DeviceState};
use std::mem;

pub use device_query::Keycode;

pub struct Keybind {
    device_state: DeviceState,
    pressed_keys: Vec<Keycode>,
    key_binds: Vec<Keycode>,
    on_trigger: Box<Fn()>,
}

impl Keybind {
    /// Constructs a new `Keybind`.
    ///
    /// # Example
    ///
    /// ```ignore
    /// use keybind::{Keybind, Keycode};
    ///
    /// let mut keybind = Keybind::new(&[Keycode::LControl, Keycode::G]);
    /// ```
    pub fn new(keys: &[Keycode]) -> Keybind {
        Keybind {
            device_state: DeviceState::new(),
            pressed_keys: Vec::new(),
            key_binds: keys.to_vec(),
            on_trigger: Box::new(||{})
        }
    }

    /// Returns bool if the specific keybind has been triggered
    ///
    /// # Example
    ///
    /// ```ignore
    /// use keybind::{Keybind, Keycode};
    ///
    /// let mut keybind = Keybind::new(&[Keycode::LControl, Keycode::G]);
    ///
    /// loop {
    ///     if self.triggered() {
    ///         println!("triggered");
    ///     }
    /// }
    /// ```
    pub fn triggered(&mut self) -> bool {
        let previous_pressed_keys = mem::replace(
            &mut self.pressed_keys,
            self.device_state.get_keys()
        );

        self.pressed_keys.len() == self.key_binds.len()
            && previous_pressed_keys != self.pressed_keys
            && self.pressed_keys == self.key_binds
    }

    /// Sets provided callback that will be executed on trigger.
    ///
    /// # Example
    ///
    /// ```ignore
    /// use keybind::{Keybind, Keycode};
    ///
    /// let mut keybind = Keybind::new(&[Keycode::LControl, Keycode::G]);
    ///
    /// keybind.on_trigger(|| {
    ///     println!("This will be printed when you press CTRL+G");
    /// });
    /// ```
    pub fn on_trigger<C: Fn() + 'static>(&mut self, callback: C) {
        self.on_trigger = Box::new(callback);
    }

    /// Starts an infinite loop and calls provided callback when the keybind is triggered.
    ///
    /// # Example
    ///
    /// ```ignore
    /// use keybind::{Keybind, Keycode};
    ///
    ///fn main() {
    ///    let mut keybind = Keybind::new(&[Keycode::LControl, Keycode::G]);
    ///
    ///    keybind.on_trigger(|| {
    ///        println!("This will be printed when you press CTRL+G");
    ///    });
    ///
    ///    keybind.wait();
    ///}
    /// ```
    pub fn wait(&mut self) {
        loop {
            if self.triggered() {
                (self.on_trigger)();
            }
        }
    }
}