1use crate::dispatch::{gen_dispatch_str, DispatchType};
4use crate::keyword::Keyword;
5
6pub mod binds {
8 use super::*;
9
10 trait Join: IntoIterator {
11 fn join(&self) -> String;
12 }
13
14 #[derive(Debug, Clone)]
16 pub enum Key<'a> {
17 Mod(
19 Vec<Mod>,
21 &'a str,
23 ),
24 Key(&'a str),
26 }
27
28 impl std::fmt::Display for Key<'_> {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 write!(
31 f,
32 "{}",
33 match self {
34 Key::Mod(m, s) => format!("{}_{s}", m.join()),
35 Key::Key(s) => s.to_string(),
36 }
37 )
38 }
39 }
40
41 #[derive(Debug, Clone, Copy)]
42 #[allow(missing_docs)]
43 pub enum Mod {
45 SUPER,
46 SHIFT,
47 ALT,
48 CTRL,
49 NONE,
50 }
51
52 impl ToString for Mod {
53 fn to_string(&self) -> String {
54 match self {
55 Mod::NONE => "",
56 Mod::SUPER => "SUPER",
57 Mod::SHIFT => "SHIFT",
58 Mod::ALT => "ALT",
59 Mod::CTRL => "CTRL",
60 }
61 .to_string()
62 }
63 }
64
65 impl Join for Vec<Mod> {
66 fn join(&self) -> String {
67 let mut buf = String::new();
68 for i in self {
69 buf.push_str(&i.to_string());
70 }
71 buf
72 }
73 }
74
75 #[derive(Debug, Clone, Copy)]
76 #[allow(non_camel_case_types)]
77 pub enum Flag {
79 l,
81 m,
83 e,
85 r,
87 }
88
89 impl ToString for Flag {
90 fn to_string(&self) -> String {
91 match self {
92 Flag::l => "l",
93 Flag::m => "m",
94 Flag::e => "e",
95 Flag::r => "r",
96 }
97 .to_string()
98 }
99 }
100
101 impl Join for Vec<Flag> {
102 fn join(&self) -> String {
103 let mut buf = String::new();
104 for i in self {
105 buf.push_str(&i.to_string());
106 }
107 buf
108 }
109 }
110
111 #[derive(Debug, Clone)]
113 pub struct Binding<'a> {
114 pub mods: Vec<Mod>,
116 pub key: Key<'a>,
118 pub flags: Vec<Flag>,
120 pub dispatcher: DispatchType<'a>,
122 }
123
124 pub struct Binder;
126
127 impl Binder {
128 pub(crate) fn gen_str(binding: Binding) -> crate::Result<String> {
129 Ok(format!(
130 "{mods},{key},{dispatcher}",
131 mods = binding.mods.join(),
132 key = binding.key,
133 dispatcher = gen_dispatch_str(binding.dispatcher, false)?
134 ))
135 }
136 pub fn bind(binding: Binding) -> crate::Result<()> {
138 Keyword::set(
139 format!("bind{}", binding.flags.join()),
140 Self::gen_str(binding)?,
141 )?;
142 Ok(())
143 }
144 pub async fn bind_async(binding: Binding<'_>) -> crate::Result<()> {
146 Keyword::set_async(
147 format!("bind{}", binding.flags.join()),
148 Self::gen_str(binding)?,
149 )
150 .await?;
151 Ok(())
152 }
153 }
154 #[macro_export]
156 #[doc(hidden)]
157 macro_rules! bind_raw {
158 (sync $mods:expr,$key:expr,$flags:expr,$dis:expr ) => {{
159 use $crate::config::binds::*;
160 let binding = Binding {
161 mods: $mods,
162 key: $key,
163 flags: $flags,
164 dispatcher: $dis,
165 };
166 Binder::bind(binding)
167 }};
168 ($mods:expr,$key:expr,$flags:expr,$dis:expr ) => {{
169 use $crate::config::binds::*;
170 let binding = Binding {
171 mods: $mods,
172 key: $key,
173 flags: $flags,
174 dispatcher: $dis,
175 };
176 Binder::bind_async(binding)
177 }};
178 }
179
180 #[macro_export]
182 macro_rules! bind {
183 ($( $flag:ident ) *|$( $mod:ident ) *,$keyt:ident, $( $key:expr ), * => $dis:ident, $( $arg:expr ), *) => {
184 $crate::bind_raw!(
185 sync
186 vec![$(Mod::$mod), *],
187 Key::$keyt( $( $key ), * ),
188 vec![$(Flag::$flag), *],
189 DispatchType::$dis( $($arg),* )
190 )
191 };
192 ($( $flag:ident ) *|$( $mod:ident ) *,$keyt:ident,$( $key:expr ), * => $dis:ident ) => {
193 $crate::bind_raw!(
194 sync
195 vec![$(Mod::$mod), *],
196 Key::$keyt( $( $key ), * ),
197 vec![$(Flag::$flag), *],
198 DispatchType::$dis
199 )
200 };
201 ($( $mod:ident ) *,$keyt:ident,$( $key:expr ), * => $dis:ident, $( $arg:expr ), *) => {
202 $crate::bind_raw!(
203 sync
204 vec![$(Mod::$mod), *],
205 Key::$keyt( $( $key ), * ),
206 vec![],
207 DispatchType::$dis( $($arg),* )
208 )
209 };
210 ($( $mod:ident ) *,$keyt:ident,$( $key:expr ), * => $dis:ident ) => {
211 $crate::bind_raw!(
212 sync
213 vec![$(Mod::$mod), *],
214 Key::$keyt( $( $key ), * ),
215 vec![],
216 DispatchType::$dis
217 )
218 };
219 (async ; $( $flag:ident ) *|$( $mod:ident ) *,$keyt:ident, $( $key:expr ), * => $dis:ident, $( $arg:expr ), *) => {
220 $crate::bind_raw!(
221 vec![$(Mod::$mod), *],
222 Key::$keyt( $( $key ), * ),
223 vec![$(Flag::$flag), *],
224 DispatchType::$dis( $($arg),* )
225 )
226 };
227 (async ; $( $flag:ident ) *|$( $mod:ident ) *,$keyt:ident,$( $key:expr ), * => $dis:ident ) => {
228 $crate::bind_raw!(
229 vec![$(Mod::$mod), *],
230 Key::$keyt( $( $key ), * ),
231 vec![$(Flag::$flag), *],
232 DispatchType::$dis
233 )
234 };
235 (async ; $( $mod:ident ) *,$keyt:ident,$( $key:expr ), * => $dis:ident, $( $arg:expr ), *) => {
236 $crate::bind_raw!(
237 vec![$(Mod::$mod), *],
238 Key::$keyt( $( $key ), * ),
239 vec![],
240 DispatchType::$dis( $($arg),* )
241 )
242 };
243 (async ; $( $mod:ident ) *,$keyt:ident,$( $key:expr ), * => $dis:ident ) => {
244 $crate::bind_raw!(
245 vec![$(Mod::$mod), *],
246 Key::$keyt( $( $key ), * ),
247 vec![],
248 DispatchType::$dis
249 )
250 };
251 }
252}
253
254#[test]
255fn test_binds() {
256 use binds::*;
257 let binding = Binding {
258 mods: vec![Mod::SUPER],
259 key: Key::Key("v"),
260 flags: vec![],
261 dispatcher: DispatchType::ToggleFloating(None),
262 };
263 let built_bind = match Binder::gen_str(binding) {
264 Ok(v) => v,
265 Err(e) => panic!("Error occured: {e}"),
266 };
267 assert_eq!(built_bind, "SUPER,v,/togglefloating");
268}