-
Notifications
You must be signed in to change notification settings - Fork 0
/
helper.h
165 lines (145 loc) · 5.95 KB
/
helper.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
* helper.h
*
* Convenience macros simplifying ZMK's keymap configuration.
* See https://github.com/urob/zmk-nodefree-config for documentation.
*/
#pragma once
#define ZMK_HELPER_STRINGIFY(x) #x
// Preprocessor mechanism to overload macros, cf. https://stackoverflow.com/a/27051616/6114651
#define VARGS_(_10, _9, _8, _7, _6, _5, _4, _3, _2, _1, N, ...) N
#define VARGS(...) VARGS_(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define CONCAT_(a, b) a##b
#define CONCAT(a, b) CONCAT_(a, b)
/* ZMK_BEHAVIOR */
#define ZMK_BEHAVIOR_CORE_caps_word compatible = "zmk,behavior-caps-word"; #binding-cells = <0>
#define ZMK_BEHAVIOR_CORE_dynamic_macro compatible = "zmk,behavior-dynamic-macro"; #binding-cells = <1>
#define ZMK_BEHAVIOR_CORE_hold_tap compatible = "zmk,behavior-hold-tap"; #binding-cells = <2>
#define ZMK_BEHAVIOR_CORE_key_repeat compatible = "zmk,behavior-key-repeat"; #binding-cells = <0>
#define ZMK_BEHAVIOR_CORE_macro compatible = "zmk,behavior-macro"; #binding-cells = <0>
#define ZMK_BEHAVIOR_CORE_macro_one_param compatible = "zmk,behavior-macro-one-param"; #binding-cells = <1>
#define ZMK_BEHAVIOR_CORE_macro_two_param compatible = "zmk,behavior-macro-two-param"; #binding-cells = <2>
#define ZMK_BEHAVIOR_CORE_mod_morph compatible = "zmk,behavior-mod-morph"; #binding-cells = <0>
#define ZMK_BEHAVIOR_CORE_sticky_key compatible = "zmk,behavior-sticky-key"; #binding-cells = <1>
#define ZMK_BEHAVIOR_CORE_tap_dance compatible = "zmk,behavior-tap-dance"; #binding-cells = <0>
#define ZMK_BEHAVIOR_CORE_tri_state compatible = "zmk,behavior-tri-state"; #binding-cells = <0>
#define ZMK_BEHAVIOR(name, type, ...) \
/ { \
behaviors { \
name: name { \
ZMK_BEHAVIOR_CORE_ ## type; \
__VA_ARGS__ \
}; \
}; \
};
/* ZMK_LAYER */
#define ZMK_LAYER(...) CONCAT(ZMK_LAYER_, VARGS(__VA_ARGS__))(__VA_ARGS__)
#define ZMK_LAYER_2(_name, layout) \
/ { \
keymap { \
compatible = "zmk,keymap"; \
layer_ ## _name { \
display-name = ZMK_HELPER_STRINGIFY(_name); \
bindings = <layout>; \
}; \
}; \
};
#define ZMK_LAYER_3(_name, layout, sensors) \
/ { \
keymap { \
compatible = "zmk,keymap"; \
layer_ ## _name { \
display-name = ZMK_HELPER_STRINGIFY(_name); \
bindings = <layout>; \
sensor-bindings = <sensors>; \
}; \
}; \
};
/* ZMK_COMBOS */
#define ALL 0xff
#if !defined COMBO_TERM
#define COMBO_TERM 30
#endif
#define ZMK_COMBO(...) CONCAT(ZMK_COMBO_, VARGS(__VA_ARGS__))(__VA_ARGS__)
#define ZMK_COMBO_3(name, combo_bindings, keypos) \
ZMK_COMBO_4(name, combo_bindings, keypos, ALL)
#define ZMK_COMBO_4(name, combo_bindings, keypos, combo_layers) \
ZMK_COMBO_5(name, combo_bindings, keypos, combo_layers, COMBO_TERM)
#define ZMK_COMBO_5(name, combo_bindings, keypos, combo_layers, combo_timeout) \
ZMK_COMBO_6(name, combo_bindings, keypos, combo_layers, combo_timeout, 0)
#define ZMK_COMBO_6(name, combo_bindings, keypos, combo_layers, combo_timeout, combo_idle) \
ZMK_COMBO_7(name, combo_bindings, keypos, combo_layers, combo_timeout, combo_idle, )
#define ZMK_COMBO_7(name, combo_bindings, keypos, combo_layers, combo_timeout, combo_idle, combo_vaargs) \
/ { \
combos { \
compatible = "zmk,combos"; \
combo_ ## name { \
timeout-ms = <combo_timeout>; \
bindings = <combo_bindings>; \
key-positions = <keypos>; \
layers = <combo_layers>; \
require-prior-idle-ms = <combo_idle>; \
combo_vaargs \
}; \
}; \
};
/* ZMK_CONDITIONAL_LAYER */
#define ZMK_CONDITIONAL_LAYER(if_layers, then_layer) \
/ { \
conditional_layers { \
compatible = "zmk,conditional-layers"; \
tri_layer { \
if-layers = <if_layers>; \
then-layer = <then_layer>; \
}; \
}; \
};
/* ZMK_UNICODE */
#if !defined OS_UNICODE_LEAD
#if HOST_OS == 2
#define OS_UNICODE_LEAD ¯o_press &kp LALT // macOS/Windows-Alt-Codes
#elif HOST_OS == 1
#define OS_UNICODE_LEAD ¯o_tap &kp LS(LC(U)) // Linux
#else
#define OS_UNICODE_LEAD ¯o_tap &kp RALT &kp U // Windows + WinCompose (default)
#endif
#endif
#if !defined OS_UNICODE_TRAIL
#if HOST_OS == 2
#define OS_UNICODE_TRAIL ¯o_release &kp LALT // macOS/Windows-Alt-Codes
#elif HOST_OS == 1
#define OS_UNICODE_TRAIL ¯o_tap &kp SPACE // Linux
#else
#define OS_UNICODE_TRAIL ¯o_tap &kp RET // Windows + WinCompose (default)
#endif
#endif
#define UC_MACRO(name, unicode_bindings) \
/ { \
macros { \
name: name { \
compatible = "zmk,behavior-macro"; \
wait-ms = <0>; \
tap-ms = <0>; \
#binding-cells = <0>; \
bindings = <OS_UNICODE_LEAD>, <¯o_tap unicode_bindings>, <OS_UNICODE_TRAIL>; \
}; \
}; \
};
#define UC_MODMORPH(name, uc_binding, shifted_uc_binding) \
/ { \
behaviors { \
name: name { \
compatible = "zmk,behavior-mod-morph"; \
#binding-cells = <0>; \
bindings = <uc_binding>, <shifted_uc_binding>; \
mods = <(MOD_LSFT|MOD_RSFT)>; \
}; \
}; \
};
#define ZMK_UNICODE_SINGLE(name, L0, L1, L2, L3) \
UC_MACRO(name ## _lower, &kp L0 &kp L1 &kp L2 &kp L3) \
UC_MODMORPH(name, &name ## _lower, &none)
#define ZMK_UNICODE_PAIR(name, L0, L1, L2, L3, U0, U1, U2, U3) \
UC_MACRO(name ## _lower, &kp L0 &kp L1 &kp L2 &kp L3) \
UC_MACRO(name ## _upper, &kp U0 &kp U1 &kp U2 &kp U3) \
UC_MODMORPH(name, &name ## _lower, &name ## _upper)