Created
December 30, 2024 05:11
-
-
Save juliancoleman/848a9ab9119b76c0748f3d82a67f116b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include QMK_KEYBOARD_H | |
enum custom_keycodes { | |
REPT = SAFE_RANGE | |
}; | |
// Defines names for use in layer keycodes and the keymap | |
enum layer_names { | |
_COLEMAK, | |
_NUMPAD | |
}; | |
#define L1 TO(_COLEMAK) | |
#define L2 TT(_NUMPAD) | |
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |
/* L1 (Colemak DHm) | |
* By nature of the shift key, it's still possible that | |
* shifting the comma may result in the < key being | |
* printed to the screen. Likewise with the other special | |
* characters. | |
* | |
* ,-----------------------------. ,-----------------------------. | |
* | Q | W | F | P | B | | J | L | U | Y | BSP | | |
* |-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----| | |
* | A | R | S | T | G | | M | N | E | I | O | | |
* |-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----| | |
* | Z | X | C | D | V | | K | H | ,/⌃ | ./⌥ | / | | |
* `-----------------------------' `-----------------------------' | |
* ,--------------------. ,--------------------. | |
* | ⇧/⏎ | RPT | ENC | | ENC | ␣ | ⌘ | | |
* `--------------------' `--------------------. | |
*/ | |
[_COLEMAK] = LAYOUT_sweeeeep( | |
KC_Q, KC_W, KC_F, KC_P , KC_B, KC_J, KC_L, KC_U, KC_Y, KC_BSPC, | |
KC_A, KC_R, KC_S, KC_T , KC_G, KC_M, KC_N, KC_E, KC_I, KC_O, | |
KC_Z, KC_X, KC_C, KC_D , KC_V, KC_K, KC_H, LCTL_T(KC_COMM), LALT_T(KC_DOT), KC_SCLN, | |
SC_SENT, REPT, KC_NO, KC_NO, KC_SPC, KC_LGUI | |
), | |
/* L2 (Numpad & Fn) | |
* Again here, we can utilize the Shift key to access | |
* the remaining special characters. | |
* TODO: explore moving higher-utilized programming chars | |
* to the left hand, (e.g. parens, brackets, etc.) | |
* | |
* ,-----------------------------. ,-----------------------------. | |
* | | | | | | | 7 | 8 | 9 | - | DEL | | |
* |-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----| | |
* | | | | | | | 4 | 5 | 6 | = | \ | | |
* |-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----| | |
* | | | | | | | 1 | 2 | 3 | / | ' | | |
* `-----------------------------' `-----------------------------' | |
* ,--------------------. ,--------------------. | |
* | ⇧ | SPC | ENC | | ENC | 0 | . | | |
* `--------------------' `--------------------. | |
*/ | |
[_NUMPAD] = LAYOUT_sweeeeep( | |
KC_NO, KC_NO, KC_NO, KC_NO , KC_NO , KC_7, KC_8, KC_9, KC_MINS, KC_DEL, | |
KC_NO, KC_NO, KC_NO, KC_NO , KC_NO , KC_4, KC_5, KC_6, KC_EQL , KC_BSLS, | |
L1 , KC_NO, KC_NO, KC_NO , KC_NO , KC_1, KC_2, KC_3, KC_SLSH, KC_QUOT, | |
KC_LSFT, KC_SPC, KC_NO, KC_NO, KC_0, KC_DOT | |
) | |
}; | |
/** | |
* Define combos. I need to update the count, but some of these can be shifted or otherwise | |
* used with a modifier key. | |
*/ | |
const uint16_t PROGMEM gesc_combo[] = {KC_Q, KC_W, COMBO_END}; | |
const uint16_t PROGMEM lprn_combo[] = {KC_T, KC_G, COMBO_END}; | |
const uint16_t PROGMEM rprn_combo[] = {KC_M, KC_N, COMBO_END}; | |
const uint16_t PROGMEM tab_combo[] = {KC_A, KC_R, COMBO_END}; | |
const uint16_t PROGMEM lbrc_combo[] = {KC_S, KC_T, COMBO_END}; | |
const uint16_t PROGMEM rbrc_combo[] = {KC_E, KC_N, COMBO_END}; | |
const uint16_t PROGMEM l2_combo[] = {KC_Z, KC_X, COMBO_END}; | |
combo_t key_combos[] = { | |
// Default layer combos | |
COMBO(gesc_combo, QK_GESC), | |
COMBO(lprn_combo, KC_LPRN), | |
COMBO(rprn_combo, KC_RPRN), | |
COMBO(tab_combo, KC_TAB), | |
COMBO(lbrc_combo, KC_LBRC), | |
COMBO(rbrc_combo, KC_RBRC), | |
// TT from Default to Numpad layer | |
COMBO(l2_combo, TT(L2)) | |
}; | |
/** | |
* Repeat Key Functionality | |
*/ | |
// Used to extract the basic tapping keycode from a dual-role key. | |
// Example: GET_TAP_KC(MT(MOD_RSFT, KC_E)) == KC_E | |
#define GET_TAP_KC(dual_role_key) dual_role_key & 0xFF | |
uint16_t last_keycode = KC_NO; | |
uint8_t last_modifier = 0; | |
// Initialize variables holding the bitfield | |
// representation of active modifiers. | |
uint8_t mod_state; | |
uint8_t oneshot_mod_state; | |
void process_repeat_key(uint16_t keycode, const keyrecord_t *record) { | |
if (keycode != REPT) { | |
// Early return when pressing a pure layer key | |
// to retain modifiers | |
switch (keycode) { | |
case QK_DEF_LAYER ... QK_DEF_LAYER_MAX: | |
case QK_MOMENTARY ... QK_MOMENTARY_MAX: | |
case QK_LAYER_MOD ... QK_LAYER_MOD_MAX: | |
case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX: | |
case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX: | |
case QK_TO ... QK_TO_MAX: | |
case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX: | |
case KC_LSFT: | |
case KC_RSFT: | |
return; | |
} | |
// apply existing modifiers | |
last_modifier = oneshot_mod_state > mod_state ? oneshot_mod_state : mod_state; | |
// process additional keys pressed in different layers | |
switch (keycode) { | |
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: | |
case QK_MOD_TAP ... QK_MOD_TAP_MAX: | |
if (record->event.pressed) { | |
last_keycode = GET_TAP_KC(keycode); | |
} | |
break; | |
default: | |
if (record->event.pressed) { | |
last_keycode = keycode; | |
} | |
break; | |
} | |
} else { // keycode == REPT | |
if (record->event.pressed) { | |
register_mods(last_modifier); | |
register_code16(last_keycode); | |
} else { | |
unregister_code16(last_keycode); | |
unregister_mods(last_modifier); | |
} | |
} | |
} | |
/** | |
* Rotary Encoder Functionality | |
*/ | |
bool encoder_update_user(uint8_t index, bool clockwise) { | |
// left hand; move cursor left or right by one character | |
if (index == 0) { | |
if (clockwise) { | |
tap_code(KC_LEFT); | |
} else { | |
tap_code(KC_RGHT); | |
} | |
} | |
// right hand; move cursor up or down by one character | |
else if (index == 1) { | |
if (clockwise) { | |
tap_code(KC_UP); | |
} else { | |
tap_code(KC_DOWN); | |
} | |
} | |
return false; | |
} | |
// putting it all together | |
bool process_record_user(uint16_t keycode, keyrecord_t *record) { | |
process_repeat_key(keycode, record); | |
// It's important to update the mod variables *after* calling process_repeat_key, or else | |
// only a single modifier from the previous key is repeated (e.g. Ctrl+Shift+T then Repeat produces Shift+T) | |
mod_state = get_mods(); | |
oneshot_mod_state = get_oneshot_mods(); | |
return true; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment