mouse_codes/parser/
mod.rs

1//! Parsing utilities for mouse buttons and events
2
3use crate::{
4    error::MouseParseError,
5    types::{Button, MouseEvent, ScrollDirection},
6};
7
8/// Parse a button with support for common aliases
9pub fn parse_button_with_aliases(s: &str) -> Result<Button, MouseParseError> {
10    let s = s.to_lowercase();
11    match s.as_str() {
12        "left" | "lmb" => Ok(Button::Left),
13        "right" | "rmb" => Ok(Button::Right),
14        "middle" | "mmb" | "wheel" => Ok(Button::Middle),
15        "x1" | "back" => Ok(Button::X1),
16        "x2" | "forward" => Ok(Button::X2),
17        "extra3" => Ok(Button::Extra3),
18        "extra4" => Ok(Button::Extra4),
19        "extra5" => Ok(Button::Extra5),
20        "extra6" => Ok(Button::Extra6),
21        "extra7" => Ok(Button::Extra7),
22        "extra8" => Ok(Button::Extra8),
23        #[cfg(feature = "extended")]
24        "extra9" => Ok(Button::Extra9),
25        #[cfg(feature = "extended")]
26        "extra10" => Ok(Button::Extra10),
27        _ => Err(MouseParseError::UnknownButton(s)),
28    }
29}
30
31/// Parse a scroll direction from a string
32pub fn parse_scroll_direction(s: &str) -> Result<ScrollDirection, MouseParseError> {
33    let s = s.to_lowercase();
34    match s.as_str() {
35        "verticalup" | "up" => Ok(ScrollDirection::VerticalUp),
36        "verticaldown" | "down" => Ok(ScrollDirection::VerticalDown),
37        "horizontalleft" | "left" => Ok(ScrollDirection::HorizontalLeft),
38        "horizontalright" | "right" => Ok(ScrollDirection::HorizontalRight),
39        _ => Err(MouseParseError::UnknownButton(s)),
40    }
41}
42
43/// Parse a mouse event from a string representation
44pub fn parse_mouse_input(s: &str) -> Result<MouseEvent, MouseParseError> {
45    if s.is_empty() {
46        return Err(MouseParseError::EmptyInput);
47    }
48
49    let (event_type, params) = s
50        .split_once('(')
51        .and_then(|(t, p)| p.strip_suffix(')').map(|p| (t, p)))
52        .ok_or_else(|| MouseParseError::UnknownButton(s.to_string()))?;
53
54    match event_type {
55        "Press" => {
56            let button = parse_button_with_aliases(params)?;
57            Ok(MouseEvent::Press(button))
58        }
59        "Release" => {
60            let button = parse_button_with_aliases(params)?;
61            Ok(MouseEvent::Release(button))
62        }
63        "Scroll" => {
64            let parts: Vec<&str> = params.split(',').map(|s| s.trim()).collect();
65            if parts.len() != 2 {
66                return Err(MouseParseError::UnknownButton(s.to_string()));
67            }
68            let dir = parse_scroll_direction(parts[0])?;
69            let amount = parts[1]
70                .parse()
71                .map_err(|_| MouseParseError::UnknownButton(s.to_string()))?;
72            Ok(MouseEvent::Scroll(dir, amount))
73        }
74        "Move" => {
75            let parts: Vec<&str> = params.split(',').map(|s| s.trim()).collect();
76            if parts.len() != 2 {
77                return Err(MouseParseError::UnknownButton(s.to_string()));
78            }
79            let x = parts[0]
80                .parse()
81                .map_err(|_| MouseParseError::UnknownButton(s.to_string()))?;
82            let y = parts[1]
83                .parse()
84                .map_err(|_| MouseParseError::UnknownButton(s.to_string()))?;
85            Ok(MouseEvent::Move(x, y))
86        }
87        "RelativeMove" => {
88            let parts: Vec<&str> = params.split(',').map(|s| s.trim()).collect();
89            if parts.len() != 2 {
90                return Err(MouseParseError::UnknownButton(s.to_string()));
91            }
92            let dx = parts[0]
93                .parse()
94                .map_err(|_| MouseParseError::UnknownButton(s.to_string()))?;
95            let dy = parts[1]
96                .parse()
97                .map_err(|_| MouseParseError::UnknownButton(s.to_string()))?;
98            Ok(MouseEvent::RelativeMove(dx, dy))
99        }
100        _ => Err(MouseParseError::UnknownButton(s.to_string())),
101    }
102}