aboutsummaryrefslogtreecommitdiff
path: root/docs/feature_macros.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/feature_macros.md')
-rw-r--r--docs/feature_macros.md164
1 files changed, 94 insertions, 70 deletions
diff --git a/docs/feature_macros.md b/docs/feature_macros.md
index 673153081..aa13fb97f 100644
--- a/docs/feature_macros.md
+++ b/docs/feature_macros.md
@@ -12,24 +12,28 @@ Here is an example `keymap.c` for a two-key keyboard:
12 12
13```c 13```c
14enum custom_keycodes { 14enum custom_keycodes {
15 MY_CUSTOM_MACRO = SAFE_RANGE 15 QMKBEST = SAFE_RANGE,
16}; 16};
17 17
18bool process_record_user(uint16_t keycode, keyrecord_t *record) { 18bool process_record_user(uint16_t keycode, keyrecord_t *record) {
19 if (record->event.pressed) { 19 switch (keycode) {
20 switch(keycode) { 20 case QMKBEST:
21 case MY_CUSTOM_MACRO: 21 if (record->event.pressed) {
22 SEND_STRING("QMK is the best thing ever!"); // this is our macro! 22 // when keycode QMKBEST is pressed
23 return false; 23 SEND_STRING("QMK is the best thing ever!");
24 } 24 } else {
25 } 25 // when keycode QMKBEST is released
26 return true; 26 }
27 break;
28
29 }
30 return true;
27}; 31};
28 32
29const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { 33const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
30 [0] = { 34 [0] = {
31 {MY_CUSTOM_MACRO, KC_ESC} 35 {QMKBEST, KC_ESC}
32 } 36 }
33}; 37};
34``` 38```
35 39
@@ -37,7 +41,7 @@ What happens here is this:
37We first define a new custom keycode in the range not occupied by any other keycodes. 41We first define a new custom keycode in the range not occupied by any other keycodes.
38Then we use the `process_record_user` function, which is called whenever a key is pressed or released, to check if our custom keycode has been activated. 42Then we use the `process_record_user` function, which is called whenever a key is pressed or released, to check if our custom keycode has been activated.
39If yes, we send the string `"QMK is the best thing ever!"` to the computer via the `SEND_STRING` macro (this is a C preprocessor macro, not to be confused with QMK macros). 43If yes, we send the string `"QMK is the best thing ever!"` to the computer via the `SEND_STRING` macro (this is a C preprocessor macro, not to be confused with QMK macros).
40We return `false` to indicate to the caller that the key press we just processed need not be processed any further. 44We return `true` to indicate to the caller that the key press we just processed should continue to be processed as normal (as we didn't replace or alter the functionality).
41Finally, we define the keymap so that the first button activates our macro and the second button is just an escape button. 45Finally, we define the keymap so that the first button activates our macro and the second button is just an escape button.
42 46
43You might want to add more than one macro. 47You might want to add more than one macro.
@@ -45,28 +49,42 @@ You can do that by adding another keycode and adding another case to the switch
45 49
46```c 50```c
47enum custom_keycodes { 51enum custom_keycodes {
48 MY_CUSTOM_MACRO = SAFE_RANGE, 52 QMKBEST = SAFE_RANGE,
49 MY_OTHER_MACRO 53 QMKURL,
54 MY_OTHER_MACRO
50}; 55};
51 56
52bool process_record_user(uint16_t keycode, keyrecord_t *record) { 57bool process_record_user(uint16_t keycode, keyrecord_t *record) {
53 if (record->event.pressed) { 58 switch (keycode) {
54 switch(keycode) { 59 case QMKBEST:
55 case MY_CUSTOM_MACRO: 60 if (record->event.pressed) {
56 SEND_STRING("QMK is the best thing ever!"); 61 // when keycode QMKBEST is pressed
57 return false; 62 SEND_STRING("QMK is the best thing ever!");
58 case MY_OTHER_MACRO: 63 } else {
59 SEND_STRING(SS_LCTRL("ac")); // selects all and copies 64 // when keycode QMKBEST is released
60 return false; 65 }
61 } 66 break;
62 } 67 case QMKURL:
63 return true; 68 if (record->event.pressed) {
69 // when keycode QMKURL is pressed
70 SEND_STRING("https://qmk.fm/" SS_TAP(X_ENTER));
71 } else {
72 // when keycode QMKURL is released
73 }
74 break;
75 case MY_OTHER_MACRO:
76 if (record->event.pressed) {
77 SEND_STRING(SS_LCTRL("ac")); // selects all and copies
78 }
79 break;
80 }
81 return true;
64}; 82};
65 83
66const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { 84const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
67 [0] = { 85 [0] = {
68 {MY_CUSTOM_MACRO, MY_OTHER_MACRO} 86 {MY_CUSTOM_MACRO, MY_OTHER_MACRO}
69 } 87 }
70}; 88};
71``` 89```
72 90
@@ -136,21 +154,21 @@ By default QMK assumes you don't have any macros. To define your macros you crea
136 154
137```c 155```c
138const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { 156const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
139 if (record->event.pressed) { 157 if (record->event.pressed) {
140 switch(id) { 158 switch(id) {
141 case 0: 159 case 0:
142 return MACRO(D(LSFT), T(H), U(LSFT), T(I), D(LSFT), T(1), U(LSFT), END); 160 return MACRO(D(LSFT), T(H), U(LSFT), T(I), D(LSFT), T(1), U(LSFT), END);
143 case 1: 161 case 1:
144 return MACRO(D(LSFT), T(B), U(LSFT), T(Y), T(E), D(LSFT), T(1), U(LSFT), END); 162 return MACRO(D(LSFT), T(B), U(LSFT), T(Y), T(E), D(LSFT), T(1), U(LSFT), END);
145 } 163 }
146 } 164 }
147 return MACRO_NONE; 165 return MACRO_NONE;
148}; 166};
149``` 167```
150 168
151This defines two macros which will be run when the key they are assigned to is pressed. If instead you'd like them to run when the key is released you can change the if statement: 169This defines two macros which will be run when the key they are assigned to is pressed. If instead you'd like them to run when the key is released you can change the if statement:
152 170
153 if (!record->event.pressed) { 171 if (!record->event.pressed) {
154 172
155### Macro Commands 173### Macro Commands
156 174
@@ -169,21 +187,21 @@ Use the `M()` function within your `KEYMAP()` to call a macro. For example, here
169 187
170```c 188```c
171const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { 189const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
172 [0] = KEYMAP( 190 [0] = KEYMAP(
173 M(0), M(1) 191 M(0), M(1)
174 ), 192 ),
175}; 193};
176 194
177const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { 195const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
178 if (record->event.pressed) { 196 if (record->event.pressed) {
179 switch(id) { 197 switch(id) {
180 case 0: 198 case 0:
181 return MACRO(D(LSFT), T(H), U(LSFT), T(I), D(LSFT), T(1), U(LSFT), END); 199 return MACRO(D(LSFT), T(H), U(LSFT), T(I), D(LSFT), T(1), U(LSFT), END);
182 case 1: 200 case 1:
183 return MACRO(D(LSFT), T(B), U(LSFT), T(Y), T(E), D(LSFT), T(1), U(LSFT), END); 201 return MACRO(D(LSFT), T(B), U(LSFT), T(Y), T(E), D(LSFT), T(1), U(LSFT), END);
184 } 202 }
185 } 203 }
186 return MACRO_NONE; 204 return MACRO_NONE;
187}; 205};
188``` 206```
189 207
@@ -198,9 +216,9 @@ If you have a bunch of macros you want to refer to from your keymap while keepin
198#define M_BYE M(1) 216#define M_BYE M(1)
199 217
200const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { 218const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
201 [0] = KEYMAP( 219 [0] = KEYMAP(
202 M_HI, M_BYE 220 M_HI, M_BYE
203 ), 221 ),
204}; 222};
205``` 223```
206 224
@@ -213,11 +231,11 @@ There are some functions you may find useful in macro-writing. Keep in mind that
213This is a boolean value that can be tested to see if the switch is being pressed or released. An example of this is 231This is a boolean value that can be tested to see if the switch is being pressed or released. An example of this is
214 232
215```c 233```c
216 if (record->event.pressed) { 234 if (record->event.pressed) {
217 // on keydown 235 // on keydown
218 } else { 236 } else {
219 // on keyup 237 // on keyup
220 } 238 }
221``` 239```
222 240
223### `register_code(<kc>);` 241### `register_code(<kc>);`
@@ -228,6 +246,12 @@ This sends the `<kc>` keydown event to the computer. Some examples would be `KC_
228 246
229Parallel to `register_code` function, this sends the `<kc>` keyup event to the computer. If you don't use this, the key will be held down until it's sent. 247Parallel to `register_code` function, this sends the `<kc>` keyup event to the computer. If you don't use this, the key will be held down until it's sent.
230 248
249### `tap_code(<kc>);`
250
251This will send `register_code(<kc>)` and then `unregister_code(<kc>)`. This is useful if you want to send both the press and release events ("tap" the key, rather than hold it).
252
253If you're having issues with taps (un)registering, you can add a delay between the register and unregister events by setting `#define TAP_CODE_DELAY 100` in your `config.h` file. The value is in milliseconds.
254
231### `clear_keyboard();` 255### `clear_keyboard();`
232 256
233This will clear all mods and keys currently pressed. 257This will clear all mods and keys currently pressed.
@@ -246,16 +270,16 @@ This example defines a macro which sends `Ctrl-C` when pressed down, and `Ctrl-V
246 270
247```c 271```c
248const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { 272const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
249 switch(id) { 273 switch(id) {
250 case 0: { 274 case 0: {
251 if (record->event.pressed) { 275 if (record->event.pressed) {
252 return MACRO( D(LCTL), T(C), U(LCTL), END ); 276 return MACRO( D(LCTL), T(C), U(LCTL), END );
253 } else { 277 } else {
254 return MACRO( D(LCTL), T(V), U(LCTL), END ); 278 return MACRO( D(LCTL), T(V), U(LCTL), END );
255 } 279 }
256 break; 280 break;
257 } 281 }
258 } 282 }
259 return MACRO_NONE; 283 return MACRO_NONE;
260}; 284};
261``` 285```