1use anyhow::{Result, anyhow};
7use core::fmt;
8use kanata_keyberon::key_code::KeyCode;
9
10use crate::{cfg::SimpleSExpr, keys::OsCode};
11
12#[derive(Debug, Clone, PartialEq, Eq, Hash)]
18pub enum CustomAction {
19 Cmd(Vec<String>),
20 CmdLog(LogLevel, LogLevel, Vec<String>),
21 CmdOutputKeys(Vec<String>),
22 PushMessage(Vec<SimpleSExpr>),
23 Unicode(char),
24 Mouse(Btn),
25 MouseTap(Btn),
26 FakeKey {
27 coord: Coord,
28 action: FakeKeyAction,
29 },
30 FakeKeyOnRelease {
31 coord: Coord,
32 action: FakeKeyAction,
33 },
34 FakeKeyOnIdle(FakeKeyOnIdle),
35 FakeKeyOnPhysicalIdle(FakeKeyOnIdle),
36 FakeKeyHoldForDuration(FakeKeyHoldForDuration),
37 Delay(u16),
38 DelayOnRelease(u16),
39 MWheel {
40 direction: MWheelDirection,
41 interval: u16,
42 distance: u16,
43 inertial_scroll_params: Option<Box<MWheelInertial>>,
44 },
45 MWheelNotch {
46 direction: MWheelDirection,
47 },
48 MoveMouse {
49 direction: MoveDirection,
50 interval: u16,
51 distance: u16,
52 },
53 MoveMouseAccel {
54 direction: MoveDirection,
55 interval: u16,
56 accel_time: u16,
57 min_distance: u16,
58 max_distance: u16,
59 },
60 MoveMouseSpeed {
61 speed: u16,
62 },
63 SequenceCancel,
64 SequenceLeader(u16, SequenceInputMode),
65 SequenceNoerase(u16),
71 LiveReload,
72 LiveReloadNext,
73 LiveReloadPrev,
74 LiveReloadNum(u16),
78 LiveReloadFile(String),
79 Repeat,
80 CancelMacroOnRelease,
81 CancelMacroOnNextPress(u32),
82 DynamicMacroRecord(u16),
83 DynamicMacroRecordStop(u16),
84 DynamicMacroPlay(u16),
85 SendArbitraryCode(u16),
86 CapsWord(CapsWordCfg),
87 SetMouse {
88 x: u16,
89 y: u16,
90 },
91 Unmodded {
92 keys: Box<[KeyCode]>,
93 mods: UnmodMods,
94 },
95 Unshifted {
96 keys: Box<[KeyCode]>,
97 },
98 ReverseReleaseOrder,
99 ClipboardSet(String),
100 ClipboardCmdSet(Vec<String>),
101 ClipboardSave(u16),
102 ClipboardRestore(u16),
103 ClipboardSaveSet(u16, String),
104 ClipboardSaveCmdSet(u16, Vec<String>),
105 ClipboardSaveSwap(u16, u16),
106}
107
108#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
109pub enum Btn {
110 Left,
111 Right,
112 Mid,
113 Forward,
114 Backward,
115}
116
117impl fmt::Display for Btn {
118 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119 match self {
120 Btn::Left => write!(f, "‹🖰"),
121 Btn::Right => write!(f, "🖰›"),
122 Btn::Mid => write!(f, "🖱"),
123 Btn::Backward => write!(f, "⎌🖰"),
124 Btn::Forward => write!(f, "🖰↷"),
125 }
126 }
127}
128
129#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
130pub struct Coord {
131 pub x: u8,
132 pub y: u16,
133}
134
135#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
136pub enum FakeKeyAction {
137 Press,
138 Release,
139 Tap,
140 Toggle,
141}
142
143#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
145pub struct FakeKeyOnIdle {
146 pub coord: Coord,
147 pub action: FakeKeyAction,
148 pub idle_duration: u16,
149}
150
151#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
154pub struct FakeKeyHoldForDuration {
155 pub coord: Coord,
156 pub hold_duration: u16,
157}
158
159#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
160pub enum MWheelDirection {
161 Up,
162 Down,
163 Left,
164 Right,
165}
166impl fmt::Display for MWheelDirection {
167 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
168 match self {
169 MWheelDirection::Up => write!(f, "🖱↑"),
170 MWheelDirection::Down => write!(f, "🖱↓"),
171 MWheelDirection::Left => write!(f, "🖱←"),
172 MWheelDirection::Right => write!(f, "🖱→"),
173 }
174 }
175}
176
177impl TryFrom<OsCode> for MWheelDirection {
178 type Error = ();
179 fn try_from(value: OsCode) -> Result<Self, Self::Error> {
180 use OsCode::*;
181 Ok(match value {
182 MouseWheelUp => MWheelDirection::Up,
183 MouseWheelDown => MWheelDirection::Down,
184 MouseWheelLeft => MWheelDirection::Left,
185 MouseWheelRight => MWheelDirection::Right,
186 _ => return Err(()),
187 })
188 }
189}
190
191#[derive(Debug, Copy, Clone, PartialEq, Hash, Eq)]
192pub struct MWheelInertial {
193 pub initial_velocity: ordered_float::OrderedFloat<f32>,
194 pub maximum_velocity: ordered_float::OrderedFloat<f32>,
195 pub acceleration_multiplier: ordered_float::OrderedFloat<f32>,
196 pub deceleration_multiplier: ordered_float::OrderedFloat<f32>,
197}
198
199#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
200pub enum MoveDirection {
201 Up,
202 Down,
203 Left,
204 Right,
205}
206impl fmt::Display for MoveDirection {
207 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
208 match self {
209 MoveDirection::Up => write!(f, "↑"),
210 MoveDirection::Down => write!(f, "↓"),
211 MoveDirection::Left => write!(f, "←"),
212 MoveDirection::Right => write!(f, "→"),
213 }
214 }
215}
216
217#[derive(Debug, Clone, PartialEq, Eq, Hash)]
218pub struct CapsWordCfg {
219 pub keys_to_capitalize: &'static [KeyCode],
220 pub keys_nonterminal: &'static [KeyCode],
221 pub timeout: u16,
222 pub repress_behaviour: CapsWordRepressBehaviour,
223}
224
225#[derive(Debug, Clone, PartialEq, Eq, Hash)]
226pub enum CapsWordRepressBehaviour {
227 Overwrite,
228 Toggle,
229}
230
231#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
242pub enum SequenceInputMode {
243 HiddenSuppressed,
244 HiddenDelayType,
245 VisibleBackspaced,
246}
247
248const SEQ_VISIBLE_BACKSPACED: &str = "visible-backspaced";
249const SEQ_HIDDEN_SUPPRESSED: &str = "hidden-suppressed";
250const SEQ_HIDDEN_DELAY_TYPE: &str = "hidden-delay-type";
251
252impl SequenceInputMode {
253 pub fn try_from_str(s: &str) -> Result<Self> {
254 match s {
255 SEQ_VISIBLE_BACKSPACED => Ok(SequenceInputMode::VisibleBackspaced),
256 SEQ_HIDDEN_SUPPRESSED => Ok(SequenceInputMode::HiddenSuppressed),
257 SEQ_HIDDEN_DELAY_TYPE => Ok(SequenceInputMode::HiddenDelayType),
258 _ => Err(anyhow!(SequenceInputMode::err_msg())),
259 }
260 }
261
262 pub fn err_msg() -> String {
263 format!(
264 "sequence input mode must be one of: {SEQ_VISIBLE_BACKSPACED}, {SEQ_HIDDEN_SUPPRESSED}, {SEQ_HIDDEN_DELAY_TYPE}"
265 )
266 }
267}
268
269const LOG_LEVEL_DEBUG: &str = "debug";
270const LOG_LEVEL_INFO: &str = "info";
271const LOG_LEVEL_WARN: &str = "warn";
272const LOG_LEVEL_ERROR: &str = "error";
273const LOG_LEVEL_NONE: &str = "none";
274
275#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
276pub enum LogLevel {
277 Debug,
279 Info,
280 Warn,
281 Error,
282 None,
283}
284
285impl LogLevel {
286 pub fn try_from_str(s: &str) -> Result<Self> {
287 match s {
288 LOG_LEVEL_DEBUG => Ok(LogLevel::Debug),
289 LOG_LEVEL_INFO => Ok(LogLevel::Info),
290 LOG_LEVEL_WARN => Ok(LogLevel::Warn),
291 LOG_LEVEL_ERROR => Ok(LogLevel::Error),
292 LOG_LEVEL_NONE => Ok(LogLevel::None),
293 _ => Err(anyhow!(LogLevel::err_msg())),
294 }
295 }
296
297 pub fn get_level(&self) -> Option<log::Level> {
298 match self {
299 LogLevel::Debug => Some(log::Level::Debug),
300 LogLevel::Info => Some(log::Level::Info),
301 LogLevel::Warn => Some(log::Level::Warn),
302 LogLevel::Error => Some(log::Level::Error),
303 LogLevel::None => None,
304 }
305 }
306
307 pub fn err_msg() -> String {
308 format!(
309 "log level must be one of: {LOG_LEVEL_DEBUG}, {LOG_LEVEL_INFO}, {LOG_LEVEL_WARN}, {LOG_LEVEL_ERROR}, {LOG_LEVEL_NONE}"
310 )
311 }
312}
313
314#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
315pub struct UnmodMods(u8);
316
317bitflags::bitflags! {
318 impl UnmodMods: u8 {
319 const LSft = 0b00000001;
320 const RSft = 0b00000010;
321 const LAlt = 0b00000100;
322 const RAlt = 0b00001000;
323 const LCtl = 0b00010000;
324 const RCtl = 0b00100000;
325 const LMet = 0b01000000;
326 const RMet = 0b10000000;
327 }
328}