streampager/
keymap_macro.rs

1//! Keymap macro
2
3// Keymap macro implementation.
4//
5// Token-tree muncher: { rest } ( visible ) ( modifiers ) ( keys ) [ data ]
6//
7// Consumes definition from 'rest'.  Modifiers are accumulated in 'modifiers'.  Key definitions are
8// accumulated in 'keys'.  Bindings are accumulated in 'data'.
9macro_rules! keymap_impl {
10    // Base case: generate keymap data.
11    ( {} ( $visible:literal ) () () $data:tt ) => {
12        pub(crate) static KEYMAP: $crate::keymaps::KeymapData = &$data;
13    };
14
15    // , (consume comma between keys)
16    (
17        { , $( $rest:tt )* }
18        ( $visible:literal )
19        ( )
20        ( $( $keys:tt )* )
21        [ $( $data:tt )* ]
22    ) => {
23        keymap_impl! {
24            { $( $rest )* }
25            ( $visible )
26            ( )
27            ( $( $keys )* )
28            [ $( $data )* ]
29        }
30    };
31
32    // => Binding (termination)
33    (
34        {
35            => $action:ident $( ( $( $action_params:tt )* ) )? ;
36            $( $rest:tt )*
37        }
38        ( $visible:literal )
39        ( )
40        ( )
41        [ $( $data:tt )* ]
42    ) => {
43        keymap_impl! {
44            { $( $rest )* }
45            ( $visible )
46            ( )
47            ( )
48            [ $( $data )* ]
49        }
50    };
51
52    // => Binding (assign key)
53    (
54        {
55            => $action:ident $( ( $( $action_params:tt )* ) )? ;
56            $( $rest:tt )*
57        }
58        ( $visible:literal )
59        ( )
60        ( $key:tt $key_visible:literal $( $keys:tt )* )
61        [ $( $data:tt )* ]
62    ) => {
63        keymap_impl! {
64            {
65                => $action $( ( $( $action_params )* ) )? ;
66                $( $rest )*
67            }
68            ( $visible )
69            ( )
70            ( $( $keys )* )
71            [
72                $( $data )*
73                (
74                    $key,
75                    $crate::bindings::BindingConfig {
76                        binding: $crate::bindings::Binding::Action(
77                            $crate::action::Action::$action $( ( $( $action_params )* ) )?
78                        ),
79                        visible: $key_visible,
80                    },
81                ),
82            ]
83        }
84    };
85
86    // CTRL
87    (
88        { CTRL $( $rest:tt )* }
89        ( $visible:literal )
90        ( $( $modifier:ident )* )
91        ( $( $keys:tt )* )
92        [ $( $data:tt )* ]
93    ) => {
94        keymap_impl! {
95            { $( $rest )* }
96            ( $visible )
97            ( $( $modifier )* CTRL )
98            ( $( $keys )* )
99            [ $( $data )* ]
100        }
101    };
102
103    // SHIFT
104    (
105        { SHIFT $( $rest:tt )* }
106        ( $visible:literal )
107        ( $( $modifier:ident )* )
108        ( $( $keys:tt )* )
109        [ $( $data:tt )* ]
110    ) => {
111        keymap_impl! {
112            { $( $rest )* }
113            ( $visible )
114            ( $( $modifier )* SHIFT )
115            ( $( $keys )* )
116            [ $( $data )* ]
117        }
118    };
119
120    // ALT
121    (
122        { ALT $( $rest:tt )* }
123        ( $visible:literal )
124        ( $( $modifier:ident )* )
125        ( $( $keys:tt )* )
126        [ $( $data:tt )* ]
127    ) => {
128        keymap_impl! {
129            { $( $rest )* }
130            ( $visible )
131            ( $( $modifier )* ALT )
132            ( $( $keys )* )
133            [ $( $data )* ]
134        }
135    };
136
137    // SUPER
138    (
139        { SUPER $( $rest:tt )* }
140        ( $visible:literal )
141        ( $( $modifier:ident )* )
142        ( $( $keys:tt )* )
143        [ $( $data:tt )* ]
144    ) => {
145        keymap_impl! {
146            { $( $rest )* }
147            ( $visible )
148            ( $( $modifier )* SUPER )
149            ( $( $keys )* )
150            [ $( $data )* ]
151        }
152    };
153
154    // Character key (e.g. 'c')
155    (
156        { $key:literal $( $rest:tt )* }
157        ( $visible:literal )
158        ( $( $modifier:ident )* )
159        ( $( $keys:tt )* )
160        [ $( $data:tt )* ]
161    ) => {
162        keymap_impl! {
163            { $( $rest )* }
164            ( true )
165            ( )
166            (
167                $( $keys )*
168                (
169                    termwiz::input::Modifiers::from_bits_truncate(
170                        $( termwiz::input::Modifiers::$modifier.bits() | )*
171                        termwiz::input::Modifiers::NONE.bits()
172                    ),
173                    termwiz::input::KeyCode::Char($key),
174                )
175                $visible
176            )
177            [ $( $data )* ]
178        }
179    };
180
181    // F <number>
182    (
183        { F $num:literal $( $rest:tt )* }
184        ( $visible:literal )
185        ( $( $modifier:ident )* )
186        ( $( $keys:tt )* )
187        [ $( $data:tt )* ]
188    ) => {
189        keymap_impl! {
190            { $( $rest )* }
191            ( true )
192            ( )
193            (
194                $( $keys )*
195                (
196                    termwiz::input::Modifiers::from_bits_truncate(
197                        $( termwiz::input::Modifiers::$modifier.bits() | )*
198                        termwiz::input::Modifiers::NONE.bits()
199                    ),
200                    termwiz::input::KeyCode::Function($num),
201                )
202                $visible
203            )
204            [ $( $data )* ]
205        }
206    };
207
208    // KeyCode
209    (
210        { $key:ident $( $rest:tt )* }
211        ( $visible:literal )
212        ( $( $modifier:ident )* )
213        ( $( $keys:tt )* )
214        [ $( $data:tt )* ]
215    ) => {
216        keymap_impl! {
217            { $( $rest )* }
218            ( true )
219            ( )
220            (
221                $( $keys )*
222                (
223                    termwiz::input::Modifiers::from_bits_truncate(
224                        $( termwiz::input::Modifiers::$modifier.bits() | )*
225                        termwiz::input::Modifiers::NONE.bits()
226                    ),
227                    termwiz::input::KeyCode::$key,
228                )
229                $visible
230            )
231            [ $( $data )* ]
232        }
233    };
234
235    // ( hidden binding )
236    (
237        { ( $( $bind:tt )* ) $( $rest:tt )* }
238        ( $visible:literal )
239        ( $( $modifier:ident )* )
240        ( $( $keys:tt )* )
241        [ $( $data:tt )* ]
242    ) => {
243        keymap_impl! {
244            { $( $bind )* $( $rest )* }
245            ( false )
246            ( $( $modifier )* )
247            ( $( $keys )* )
248            [ $( $data )* ]
249        }
250    };
251}
252
253macro_rules! keymap {
254    ( $( $all:tt )* ) => {
255        keymap_impl! { { $( $all )* } (true) () () [] }
256    };
257}