Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.z3bra.org/qmk.git
Log | Files | Refs | Submodules | LICENSE

commit 6d4f6f3f4965e3e71d878c36da71b745cc18e345
parent ba11a1c8072fd5d2f2d2914e76e9416be9ca1e11
Author: Dusty Pomerleau <dustypomerleau@users.noreply.github.com>
Date:   Fri,  8 Mar 2019 07:30:02 +1100

[Docs] Add Tap Dance example to the docs (#5326)

* add a tapdance example for creating advanced mod-tap and layer-tap keys

* add optional curly braces to match QMK conventions

* change example to use `register_code16()` and tapdance keycodes more closely matching QMK variants

docs/contributing.md | 14++++++++++++++
docs/feature_advanced_keycodes.md | 2+-
docs/feature_tap_dance.md | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 98 insertions(+), 1 deletion(-)

diff --git a/docs/contributing.md b/docs/contributing.md @@ -129,6 +129,20 @@ Documentation is one of the easiest ways to get started contributing to QMK. Fin You'll find all our documentation in the `qmk_firmware/docs` directory, or if you'd rather use a web based workflow you can click "Suggest An Edit" at the top of each page on http://docs.qmk.fm/. +When providing code examples in your documentation, try to observe naming conventions used elsewhere in the docs. For example, standardizing enums as `my_layers` or `my_keycodes` for consistency: + +```c +enum my_layers { + _FIRST_LAYER, + _SECOND_LAYER +}; + +enum my_keycodes { + FIRST_LAYER = SAFE_RANGE, + SECOND_LAYER +}; +``` + ## Keymaps Most first-time QMK contributors start with their personal keymaps. We try to keep keymap standards pretty casual (keymaps, after all, reflect the personality of their creators) but we do ask that you follow these guidelines to make it easier for others to discover and learn from your keymap. diff --git a/docs/feature_advanced_keycodes.md b/docs/feature_advanced_keycodes.md @@ -15,7 +15,7 @@ This will allow you to use `FN_CAPS` and `ALT_TAB` in your keymap, keeping it mo ## Caveats -Currently, `LT()` and `MT()` are limited to the [Basic Keycode set](keycodes_basic.md), meaning you can't use keycodes like `LCTL()`, `KC_TILD`, or anything greater than `0xFF`. Modifiers specified as part of a Layer Tap or Mod Tap's keycode will be ignored. +Currently, `LT()` and `MT()` are limited to the [Basic Keycode set](keycodes_basic.md), meaning you can't use keycodes like `LCTL()`, `KC_TILD`, or anything greater than `0xFF`. Modifiers specified as part of a Layer Tap or Mod Tap's keycode will be ignored. If you need to apply modifiers to your tapped keycode, [Tap Dance](https://github.com/qmk/qmk_firmware/blob/master/docs/feature_tap_dance.md#example-5-using-tap-dance-for-advanced-mod-tap-and-layer-tap-keys) can be used to accomplish this. Additionally, if at least one right-handed modifier is specified in a Mod Tap or Layer Tap, it will cause all modifiers specified to become right-handed, so it is not possible to mix and match the two. diff --git a/docs/feature_tap_dance.md b/docs/feature_tap_dance.md @@ -314,3 +314,86 @@ qk_tap_dance_action_t tap_dance_actions[] = { And then simply use `TD(X_CTL)` anywhere in your keymap. If you want to implement this in your userspace, then you may want to check out how [DanielGGordon](https://github.com/qmk/qmk_firmware/tree/master/users/gordon) has implemented this in their userspace. + +### Example 5: Using tap dance for advanced mod-tap and layer-tap keys + +Tap dance can be used to emulate `MT()` and `LT()` behavior when the tapped code is not a basic keycode. This is useful to send tapped keycodes that normally require `Shift`, such as parentheses or curly braces—or other modified keycodes, such as `Control + X`. + +Below your layers and custom keycodes, add the following: + +```c +// tapdance keycodes +enum td_keycodes { + ALT_LP // Our example key: `LALT` when held, `(` when tapped. Add additional keycodes for each tapdance. +}; + +// define a type containing as many tapdance states as you need +typedef enum { + SINGLE_TAP, + SINGLE_HOLD, + DOUBLE_SINGLE_TAP +} td_state_t; + +// create a global instance of the tapdance state type +static td_state_t td_state; + +// declare your tapdance functions: + +// function to determine the current tapdance state +int cur_dance (qk_tap_dance_state_t *state); + +// `finished` and `reset` functions for each tapdance keycode +void altlp_finished (qk_tap_dance_state_t *state, void *user_data); +void altlp_reset (qk_tap_dance_state_t *state, void *user_data); +``` + +Below your `LAYOUT`, define each of the tapdance functions: + +```c +// determine the tapdance state to return +int cur_dance (qk_tap_dance_state_t *state) { + if (state->count == 1) { + if (state->interrupted || !state->pressed) { return SINGLE_TAP; } + else { return SINGLE_HOLD; } + } + if (state->count == 2) { return DOUBLE_SINGLE_TAP; } + else { return 3; } // any number higher than the maximum state value you return above +} + +// handle the possible states for each tapdance keycode you define: + +void altlp_finished (qk_tap_dance_state_t *state, void *user_data) { + td_state = cur_dance(state); + switch (td_state) { + case SINGLE_TAP: + register_code16(KC_LPRN); + break; + case SINGLE_HOLD: + register_mods(MOD_BIT(KC_LALT)); // for a layer-tap key, use `layer_on(_MY_LAYER)` here + break; + case DOUBLE_SINGLE_TAP: // allow nesting of 2 parens `((` within tapping term + tap_code16(KC_LPRN); + register_code16(KC_LPRN); + } +} + +void altlp_reset (qk_tap_dance_state_t *state, void *user_data) { + switch (td_state) { + case SINGLE_TAP: + unregister_code16(KC_LPRN); + break; + case SINGLE_HOLD: + unregister_mods(MOD_BIT(KC_LALT)); // for a layer-tap key, use `layer_off(_MY_LAYER)` here + break; + case DOUBLE_SINGLE_TAP: + unregister_code16(KC_LPRN); + } +} + +// define `ACTION_TAP_DANCE_FN_ADVANCED()` for each tapdance keycode, passing in `finished` and `reset` functions +qk_tap_dance_action_t tap_dance_actions[] = { + [ALT_LP] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, altlp_finished, altlp_reset) +}; +``` + +Wrap each tapdance keycode in `TD()` when including it in your keymap, e.g. `TD(ALT_LP)`.