]> git.donarmstrong.com Git - qmk_firmware.git/blob - users/talljoe/tapdance.c
Keymap: Talljoe's keymap for oddball keyboards (#3910)
[qmk_firmware.git] / users / talljoe / tapdance.c
1 //Tap Dance
2 #include "talljoe.h"
3
4 enum {
5   SINGLE_TAP = 1,
6   SINGLE_HOLD = 2,
7   DOUBLE_TAP = 3,
8   DOUBLE_HOLD = 4,
9   DOUBLE_SINGLE_TAP = 5, //send two single taps
10   TRIPLE_TAP = 6,
11   TRIPLE_HOLD = 7,
12   SPECIAL = 8
13 };
14
15 static struct {
16   int quote;
17   int semicolon;
18 } tap_state = {0};
19
20 int cur_dance (qk_tap_dance_state_t *state) {
21   if (state->count == 1) {
22     //If count = 1, and it has been interrupted - it doesn't matter if it is pressed or not: Send SINGLE_TAP
23     if (state->interrupted) {
24       //     if (!state->pressed) return SINGLE_TAP;
25       //need "permissive hold" here.
26       //     else return SINGLE_HOLD;
27       //If the interrupting key is released before the tap-dance key, then it is a single HOLD
28       //However, if the tap-dance key is released first, then it is a single TAP
29       //But how to get access to the state of the interrupting key????
30       return SINGLE_TAP;
31     }
32     else {
33       if (!state->pressed) return SINGLE_TAP;
34       else return SINGLE_HOLD;
35     }
36   }
37   //If count = 2, and it has been interrupted - assume that user is trying to type the letter associated
38   //with single tap.
39   else if (state->count == 2) {
40     if (state->interrupted) return DOUBLE_SINGLE_TAP;
41     else if (state->pressed) return DOUBLE_HOLD;
42     else return DOUBLE_TAP;
43   }
44   else if ((state->count == 3) && ((state->interrupted) || (!state->pressed))) return TRIPLE_TAP;
45   else if (state->count == 3) return TRIPLE_HOLD;
46   else return SPECIAL;
47 }
48
49 int hold_cur_dance (qk_tap_dance_state_t *state) {
50   if (state->count == 1) {
51     if (state->interrupted) {
52       if (!state->pressed) return SINGLE_TAP;
53       else return SINGLE_HOLD;
54     }
55     else {
56       if (!state->pressed) return SINGLE_TAP;
57       else return SINGLE_HOLD;
58     }
59   }
60   //If count = 2, and it has been interrupted - assume that user is trying to type the letter associated
61   //with single tap.
62   else if (state->count == 2) {
63     if (state->pressed) return DOUBLE_HOLD;
64     else return DOUBLE_TAP;
65   }
66   else if (state->count == 3) {
67     if (!state->pressed) return TRIPLE_TAP;
68     else return TRIPLE_HOLD;
69   }
70   else return SPECIAL;
71 }
72
73 // Send semi-colon + enter on two taps
74 void tap_dance_semicolon_finished(qk_tap_dance_state_t *state, void *user_data) {
75   tap_state.semicolon = hold_cur_dance(state);
76   switch (tap_state.semicolon) {
77     case SINGLE_TAP: case DOUBLE_HOLD: register_code(KC_SCLN); break;
78     case SINGLE_HOLD: layer_on(_NUM); break;
79   }
80 }
81
82 void tap_dance_semicolon_reset(qk_tap_dance_state_t *state, void *user_data) {
83   switch (tap_state.semicolon) {
84     case SINGLE_TAP: case DOUBLE_HOLD: unregister_code(KC_SCLN); break;
85     case DOUBLE_TAP: {
86       if (get_mods()) {
87         SEND_STRING(";;"); // send normal when mods are pressed
88       }
89       else {
90         SEND_STRING(";\n");
91       }
92       break;
93     }
94     case TRIPLE_TAP: {
95       SEND_STRING(";\n\n");
96     }
97     case SPECIAL: layer_invert(_NUM); break;
98     case SINGLE_HOLD: layer_off(_NUM); break;
99   }
100   tap_state.semicolon = 0;
101 }
102
103 // Send `. ~. ```
104 void tap_dance_grave_finished(qk_tap_dance_state_t *state, void *user_data) {
105   switch(state->count) {
106     case 1:
107       SEND_STRING("`");
108       break;
109     case 2:
110       SEND_STRING("~");
111       break;
112   }
113 }
114
115 void tap_dance_grave_each(qk_tap_dance_state_t *state, void *user_data) {
116   if(state->count == 3) {
117     SEND_STRING("```");
118   } else if (state->count > 3) {
119     SEND_STRING("`");
120   }
121 }
122
123
124 void tap_dance_quote_finished(qk_tap_dance_state_t *state, void *user_data) {
125   tap_state.quote = hold_cur_dance(state);
126   switch (tap_state.quote) {
127     case SINGLE_TAP: case DOUBLE_HOLD: register_code(KC_QUOT); break;
128     case SINGLE_HOLD: layer_on(_NAV); break;
129   }
130 }
131
132 void tap_dance_quote_reset(qk_tap_dance_state_t *state, void *user_data) {
133   switch (tap_state.quote) {
134     case SINGLE_TAP: case DOUBLE_HOLD: unregister_code(KC_QUOTE); break;
135     case DOUBLE_TAP: SEND_STRING("\""); break;
136     case TRIPLE_TAP: layer_invert(_NAV); break;
137     case SINGLE_HOLD: layer_off(_NAV); break;
138   }
139   tap_state.quote = 0;
140 }
141
142 qk_tap_dance_action_t tap_dance_actions[] = {
143   [TD_SEMICOLON] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, tap_dance_semicolon_finished, tap_dance_semicolon_reset),
144   [TD_GRAVE]     = ACTION_TAP_DANCE_FN_ADVANCED(tap_dance_grave_each, tap_dance_grave_finished, NULL),
145   [TD_QUOTE]     = ACTION_TAP_DANCE_FN_ADVANCED(NULL, tap_dance_quote_finished, tap_dance_quote_reset),
146 };