flake + ci rework

This commit is contained in:
Robin Appelman 2025-06-09 17:07:18 +02:00
commit 6e13b8e412
10 changed files with 178 additions and 165 deletions

View file

@ -11,9 +11,12 @@
//! ```rust,no_run
//! # use std::path::PathBuf;
//! # use glob::GlobError;
//! # use evdev_shortcut::{ShortcutListener, Shortcut, Modifier, Key};
//! # #[cfg(feature = "listener")]
//! # use evdev_shortcut::{ShortcutListener};
//! # use evdev_shortcut::{Shortcut, Modifier, Key};
//! # use tokio::pin;
//! # use futures::stream::StreamExt;
//! # use tokio_stream::StreamExt;
//! # #[cfg(feature = "listener")]
//! # #[tokio::main]
//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let listener = ShortcutListener::new();
@ -30,6 +33,10 @@
//! }
//! # Ok(())
//! # }
//! # #[cfg(not(feature = "listener"))]
//! # fn main() {
//! # // placeholder so we can build the doc example without default features
//! # }
//! ```
pub use keycodes::Key;
@ -134,21 +141,26 @@ pub struct ModifierList(u8);
impl ModifierList {
pub fn new(modifiers: &[Modifier]) -> Self {
ModifierList(modifiers
.iter()
.fold(0, |mask, modifier| mask | modifier.mask()))
ModifierList(
modifiers
.iter()
.fold(0, |mask, modifier| mask | modifier.mask()),
)
}
pub fn mask(&self) -> u8 {
self.0
}
pub fn modifiers(&self) -> impl Iterator<Item=Modifier> {
pub fn modifiers(&self) -> impl Iterator<Item = Modifier> {
let mask = self.mask();
ALL_MODIFIERS.iter().copied().filter(move |modifier| {
for combined in COMBINED_MODIFIERS {
// if <Ctrl> is enabled, don't emit <LeftCtrl> and <RightCtrl>
if combined != modifier && combined.mask() & modifier.mask() == modifier.mask() && combined.mask() & mask == combined.mask() {
if combined != modifier
&& combined.mask() & modifier.mask() == modifier.mask()
&& combined.mask() & mask == combined.mask()
{
return false;
}
}
@ -178,7 +190,8 @@ impl FromStr for ModifierList {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let modifiers = s.split('>')
let modifiers = s
.split('>')
.filter(|part| !part.is_empty())
.map(|part| {
if !part.starts_with('<') {
@ -251,8 +264,8 @@ impl Display for Shortcut {
#[cfg(test)]
mod tests {
use test_case::test_case;
use crate::{Key, Modifier, ModifierList, Shortcut};
use test_case::test_case;
#[test_case("KeyP", Shortcut::new(& [], Key::KeyP))]
#[test_case("<Ctrl>-KeyP", Shortcut::new(& [Modifier::Ctrl], Key::KeyP))]
@ -267,7 +280,10 @@ mod tests {
#[test_case(& [Modifier::LeftAlt, Modifier::LeftCtrl])]
#[test_case(& [Modifier::Shift, Modifier::Meta])]
fn test_modifier_list(modifiers: &[Modifier]) {
assert_eq!(modifiers.to_vec(), ModifierList::new(modifiers).modifiers().collect::<Vec<_>>())
assert_eq!(
modifiers.to_vec(),
ModifierList::new(modifiers).modifiers().collect::<Vec<_>>()
)
}
}
@ -280,9 +296,7 @@ impl Shortcut {
}
pub fn identifier(&self) -> String {
self.to_string()
.replace(['<', '>'], "")
.replace('-', "_")
self.to_string().replace(['<', '>'], "").replace('-', "_")
}
}
@ -322,7 +336,7 @@ mod triggered_tests {
#[test_case("<Ctrl><Alt>-KeyLeft", & [Key::KeyLeftCtrl, Key::KeyRightAlt, Key::KeyLeft] => true)]
fn shortcut_triggered(s: &str, keys: &[Key]) -> bool {
let shortcut: Shortcut = s.parse().unwrap();
shortcut.is_triggered(&keys.into_iter().copied().collect())
shortcut.is_triggered(&keys.iter().copied().collect())
}
}
@ -353,4 +367,4 @@ impl Display for ShortcutState {
pub struct ShortcutEvent {
pub shortcut: Shortcut,
pub state: ShortcutState,
}
}

View file

@ -1,14 +1,14 @@
use crate::{DeviceOpenError, Key, Shortcut, ShortcutEvent, ShortcutState};
use async_stream::stream;
use evdev::Device;
use futures::pin_mut;
use futures::stream::iter;
use futures::{Stream, StreamExt};
use std::collections::HashSet;
use std::convert::TryFrom;
use std::sync::{Arc, Mutex};
use crate::{Shortcut, DeviceOpenError, Key, ShortcutEvent, ShortcutState};
use std::path::Path;
use async_stream::stream;
use futures::pin_mut;
use futures::{Stream, StreamExt};
use futures::stream::{iter};
use tracing::{debug, trace, info};
use std::sync::{Arc, Mutex};
use tracing::{debug, info, trace};
/// A listener for shortcut events
///
@ -42,20 +42,29 @@ impl ShortcutListener {
/// Listen for shortcuts on the provided set of input devices.
///
/// Note that you need to register shortcuts using [add](ShortcutListener::add) to get any events.
pub fn listen<P: AsRef<Path>>(&self, devices: &[P]) -> Result<impl Stream<Item=ShortcutEvent>, DeviceOpenError> {
pub fn listen<P: AsRef<Path>>(
&self,
devices: &[P],
) -> Result<impl Stream<Item = ShortcutEvent>, DeviceOpenError> {
let shortcuts = self.shortcuts.clone();
let devices = devices
.iter()
.map(|path| {
let path = path.as_ref();
let res = Device::open(path).map_err(|_| DeviceOpenError { device: path.into() });
let res = Device::open(path).map_err(|_| DeviceOpenError {
device: path.into(),
});
debug!(device = ?path, success = res.is_ok(), "opening input device");
res
})
.collect::<Result<Vec<Device>, DeviceOpenError>>()?;
let events = iter(devices.into_iter().flat_map(|device| device.into_event_stream()))
.flatten();
let events = iter(
devices
.into_iter()
.flat_map(|device| device.into_event_stream()),
)
.flatten();
Ok(stream! {
let mut active_keys = HashSet::new();