Skip to content

Instantly share code, notes, and snippets.

@dustypomerleau
Last active March 5, 2019 08:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dustypomerleau/9c1dab59721bb59c195c5e8f80083450 to your computer and use it in GitHub Desktop.
Save dustypomerleau/9c1dab59721bb59c195c5e8f80083450 to your computer and use it in GitHub Desktop.
tapdance example

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:

// tapdance keycodes
enum td_keycodes {
  ALT_OP // 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 altop_finished (qk_tap_dance_state_t *state, void *user_data);
void altop_reset (qk_tap_dance_state_t *state, void *user_data);

Below your LAYOUT, define each of the tapdance functions:

// 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 altop_finished (qk_tap_dance_state_t *state, void *user_data) {
  td_state = cur_dance(state);
  switch (td_state) {
    case SINGLE_TAP:
      register_mods(MOD_BIT(KC_LSFT));
      register_code(KC_9);
      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
      register_mods(MOD_BIT(KC_LSFT));
      tap_code(KC_9);
      register_code(KC_9);
  }
}

void altop_reset (qk_tap_dance_state_t *state, void *user_data) {
  switch (td_state) {
    case SINGLE_TAP:
      unregister_code(KC_9);
      unregister_mods(MOD_BIT(KC_LSFT));
      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_code(KC_9);
      unregister_mods(MOD_BIT(KC_LSFT));
  }
}

// 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_OP] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, altop_finished, altop_reset)
};

Wrap each tapdance keycode in TD() when including it in your keymap, e.g. TD(ALT_OP).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment