X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=docs%2Ffeature_macros.md;h=ba5d91882fb7e8080ea31ace73fc64bc70969730;hb=a91f439aec39ec8bbcbb2f579a9434c266f09f5c;hp=66d2bc090a84002f717c0f07e44ca37e41a69623;hpb=67cc5cebc0430d15169e2c649ea25112a31bfa31;p=qmk_firmware.git diff --git a/docs/feature_macros.md b/docs/feature_macros.md index 66d2bc090..ba5d91882 100644 --- a/docs/feature_macros.md +++ b/docs/feature_macros.md @@ -1,41 +1,83 @@ # Macros -Macros allow you to send multiple keystrokes when pressing just one key. QMK has a number of ways to define and use macros. These can do anything you want: type common phrases for you, copypasta, repetitive game movements, or even help you code. +Macros allow you to send multiple keystrokes when pressing just one key. QMK has a number of ways to define and use macros. These can do anything you want: type common phrases for you, copypasta, repetitive game movements, or even help you code. -{% hint style='danger' %} -**Security Note**: While it is possible to use macros to send passwords, credit card numbers, and other sensitive information it is a supremely bad idea to do so. Anyone who gets ahold of your keyboard will be able to access that information by opening a text editor. -{% endhint %} +!> **Security Note**: While it is possible to use macros to send passwords, credit card numbers, and other sensitive information it is a supremely bad idea to do so. Anyone who gets a hold of your keyboard will be able to access that information by opening a text editor. -## The new way: `SEND_STRING()` & `process_record_user` +## The New Way: `SEND_STRING()` & `process_record_user` -Sometimes you just want a key to type out words or phrases. For the most common situations we've provided `SEND_STRING()`, which will type out your string for you. All ascii that is easily translated to a keycode is supported (eg `\n\t`). +Sometimes you just want a key to type out words or phrases. For the most common situations we've provided `SEND_STRING()`, which will type out your string (i.e. a sequence of characters) for you. All ASCII characters that are easily translated to a keycode are supported (e.g. `\n\t`). -For example: +Here is an example `keymap.c` for a two-key keyboard: + +```c +enum custom_keycodes { + MY_CUSTOM_MACRO = SAFE_RANGE +}; + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + if (record->event.pressed) { + switch(keycode) { + case MY_CUSTOM_MACRO: + SEND_STRING("QMK is the best thing ever!"); // this is our macro! + return false; + } + } + return true; +}; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [0] = { + {MY_CUSTOM_MACRO, KC_ESC} + } +}; +``` + +What happens here is this: +We first define a new custom keycode in the range not occupied by any other keycodes. +Then 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. +If 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). +We return `false` to indicate to the caller that the key press we just processed need not be processed any further. +Finally, we define the keymap so that the first button activates our macro and the second button is just an escape button. + +You might want to add more than one macro. +You can do that by adding another keycode and adding another case to the switch statement, like so: ```c enum custom_keycodes { - PRINT_TRUTH = SAFE_RANGE + MY_CUSTOM_MACRO = SAFE_RANGE, + MY_OTHER_MACRO }; bool process_record_user(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { switch(keycode) { - case PRINT_TRUTH: + case MY_CUSTOM_MACRO: SEND_STRING("QMK is the best thing ever!"); - return false; break; + return false; + case MY_OTHER_MACRO: + SEND_STRING(SS_LCTRL("ac")); // selects all and copies + return false; } } return true; }; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [0] = { + {MY_CUSTOM_MACRO, MY_OTHER_MACRO} + } +}; ``` -### Tap/down/up +### TAP, DOWN and UP -You can send arbitary keycodes by wrapping them in: +You may want to use keys in your macros that you can't write down, such as `Ctrl` or `Home`. +You can send arbitrary keycodes by wrapping them in: -* `SS_TAP()` -* `SS_DOWN()` -* `SS_UP()` +* `SS_TAP()` presses and releases a key. +* `SS_DOWN()` presses (but does not release) a key. +* `SS_UP()` releases a key. For example: @@ -52,20 +94,23 @@ There's also a couple of mod shortcuts you can use: * `SS_LCTRL(string)` * `SS_LGUI(string)` * `SS_LALT(string)` +* `SS_LSFT(string)` +* `SS_RALT(string)` -That can be used like this: +These press the respective modifier, send the supplied string and then release the modifier. +They can be used like this: SEND_STRING(SS_LCTRL("a")); -Which would send LCTRL+a (LTRL down, a, LTRL up) - notice that they take strings (eg `"k"`), and not the `X_K` keycodes. +Which would send LCTRL+a (LCTRL down, a, LCTRL up) - notice that they take strings (eg `"k"`), and not the `X_K` keycodes. -### Alternative keymaps +### Alternative Keymaps By default, it assumes a US keymap with a QWERTY layout; if you want to change that (e.g. if your OS uses software Colemak), include this somewhere in your keymap: #include -### Strings in memory +### Strings in Memory If for some reason you're manipulating strings and need to print out something you just generated (instead of being a literal, constant string), you can use `send_string()`, like this: @@ -83,11 +128,9 @@ send_string(my_str); SEND_STRING(".."SS_TAP(X_END)); ``` -## The old way: `MACRO()` & `action_get_macro` +## The Old Way: `MACRO()` & `action_get_macro` -{% hint style='info' %} -This is inherited from TMK, and hasn't been updated - it's recommend that you use `SEND_STRING` and `process_record_user` instead. -{% endhint %} +?> This is inherited from TMK, and hasn't been updated - it's recommend that you use `SEND_STRING` and `process_record_user` instead. By default QMK assumes you don't have any macros. To define your macros you create an `action_get_macro()` function. For example: @@ -120,7 +163,7 @@ A macro can include the following commands: * W() wait (milliseconds). * END end mark. -### Mapping a Macro to a key +### Mapping a Macro to a Key Use the `M()` function within your `KEYMAP()` to call a macro. For example, here is the keymap for a 2-key keyboard: @@ -146,7 +189,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { When you press the key on the left it will type "Hi!" and when you press the key on the right it will type "Bye!". -### Naming your macros +### Naming Your Macros If you have a bunch of macros you want to refer to from your keymap while keeping the keymap easily readable you can name them using `#define` at the top of your file. @@ -161,7 +204,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { }; ``` -## Advanced macro functions +## Advanced Macro Functions There are some functions you may find useful in macro-writing. Keep in mind that while you can write some fairly advanced code within a macro if your functionality gets too complex you may want to define a custom keycode instead. Macros are meant to be simple. @@ -185,6 +228,10 @@ This sends the `` keydown event to the computer. Some examples would be `KC_ Parallel to `register_code` function, this sends the `` keyup event to the computer. If you don't use this, the key will be held down until it's sent. +### `tap_code();` + +This will send `register_code()` and then `unregister_code()`. This is useful if you want to send both the press and release events ("tap" the key, rather than hold it). + ### `clear_keyboard();` This will clear all mods and keys currently pressed. @@ -197,9 +244,9 @@ This will clear all mods currently pressed. This will clear all keys besides the mods currently pressed. -## Advanced Example: Single-key copy/paste +## Advanced Example: Single-Key Copy/Paste -This example defines a macro which sends `Ctrl-C` when pressed down, and `Ctrl-V` when released. +This example defines a macro which sends `Ctrl-C` when pressed down, and `Ctrl-V` when released. ```c const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { @@ -216,5 +263,3 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { return MACRO_NONE; }; ``` - -