This commit is contained in:
Drew Whitney 2025-06-15 16:03:47 -06:00
commit 896e722a65
42 changed files with 1620 additions and 32 deletions

View file

@ -1,30 +1,18 @@
---
BasedOnStyle: Google
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: 'true'
AlignConsecutiveDeclarations: 'true'
AlignOperands: 'true'
AllowAllParametersOfDeclarationOnNextLine: 'false'
AllowShortCaseLabelsOnASingleLine: 'false'
AllowShortFunctionsOnASingleLine: Empty
AllowShortLoopsOnASingleLine: 'false'
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: 'false'
BinPackArguments: 'true'
BinPackParameters: 'true'
ColumnLimit: '1000'
IndentCaseLabels: 'true'
IndentPPDirectives: AfterHash
IndentWidth: '4'
MaxEmptyLinesToKeep: '1'
PointerAlignment: Right
SortIncludes: 'false'
SpaceBeforeAssignmentOperators: 'true'
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: 'false'
SpacesBeforeTrailingComments: 1
TabWidth: '4'
UseTab: Never
...
BasedOnStyle: LLVM
IndentWidth: 4
Language: Cpp
AlignConsecutiveMacros:
PadOperators: True
ReferenceAlignment: Left
SpacesInParens: Custom
ColumnLimit: 100
IndentCaseLabels: true
PointerAlignment: Left
AllowShortBlocksOnASingleLine: Empty
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AlignAfterOpenBracket: BlockIndent
AlignArrayOfStructures: None
AlignTrailingComments:
Kind: Leave
AllowShortEnumsOnASingleLine: false

1
TODO.md Normal file
View file

@ -0,0 +1 @@
Remove all tap-dance keys.

View file

@ -0,0 +1,26 @@
#include QMK_KEYBOARD_H
#include "caps_word.h"
bool caps_word_press_user(uint16_t keycode) {
switch (keycode) {
// Keycodes that continue Caps Word, with shift applied
case KC_A ... KC_Z:
add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to next key
return true;
break;
// Keycodes that continue Caps Word, without shifting
case KC_1 ... KC_0:
case KC_BSPC:
case KC_DEL:
case KC_LEFT:
case KC_RGHT:
case KC_MINS:
case KC_UNDS:
// custom keycodes
return true;
break;
default:
return false; // Deactivate Caps Word
break;
}
}

View file

@ -0,0 +1,4 @@
#pragma once
#include "../custom_keys/mapping.h"
bool caps_word_press_user(uint16_t keycode);

View file

@ -0,0 +1,4 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>

View file

@ -0,0 +1,49 @@
// Copyright 2023 Danny Nguyen (danny@keeb.io)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#define SPLIT_HAND_PIN GP23
#define USB_VBUS_PIN GP18
#define SERIAL_USART_FULL_DUPLEX
#define SERIAL_USART_TX_PIN GP8
#define SERIAL_USART_RX_PIN GP9
#define SERIAL_USART_PIN_SWAP
#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET
#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_TIMEOUT 1000U
#define I2C_DRIVER I2CD0
#define I2C0_SDA_PIN GP4
#define I2C0_SCL_PIN GP5m
// -------------------------------------------------------------------------------------------------
// #define DYNAMIC_KEYMAP_LAYER_COUNT 5
// stuff I added
#define MAX_REMAPS_PER_CUSTOM_KEY 2
// end stuff I added
#define SPLIT_USB_TIMEOUT 20000
#define TAPPING_TERM 200
#define QUICK_TAP_TERM_PER_KEY
#define HOLD_ON_OTHER_KEY_PRESS_PER_KEY
#define PERMISSIVE_HOLD_PER_KEY
#define TAPPING_TERM_PER_KEY
#define CAPS_WORD_IDLE_TIMEOUT 0
#define DUMMY_MOD_NEUTRALIZER_KEYCODE KC_RCTL
#define MODS_TO_NEUTRALIZE {MOD_BIT(KC_LALT), MOD_BIT(KC_RALT), MOD_BIT(KC_LGUI), MOD_BIT(KC_RGUI)}
// disable some features to make the code smaller
#define NO_ACTION_ONESHOT
// delete later; tap dance
#define TAPPING_TERM_PER_KEY

View file

@ -0,0 +1,22 @@
#pragma once
#include QMK_KEYBOARD_H
#include "../common.h"
#define TAB_FORWARD C(KC_TAB)
#define TAB_BACKWARD (C(S(KC_TAB)))
#define LAUNCH A(KC_SPC)
#define MENU S(KC_F10)
#define GUI_LAUNCH GUI_T(NK(TH_LAUNCH))
#define ALT_DEL ALT_T(NK(TH_DEL))
#define ALT_COMP ALT_T(NK(TH_RALT))
#define SFT_TILD SFT_T(NK(TH_TILD))
#define SFT_SFT SFT_T(NK(TH_LSFT))
#define SFT_COMM SFT_T(NK(TH_COMM))
#define CTL_COLN CTL_T(NK(TH_COLN))
// non-custom
#define NUM_SPC LT(_NUM, TH_SPC)
#define NAV_ENT LT(_NAV, KC_ENT)
#define CAD C(A(KC_DEL))
#define LOCK G(KC_L)

View file

@ -0,0 +1,120 @@
#include "custom_keys.h"
#include "../caps_word/caps_word.h"
#include "mapping.h"
void suppress_flashing_mods_needed(uint8_t mods_to_check, uint8_t active_mods) {
if (mods_to_check & MOD_MASK_AG) {
suppress_flashing_mods(active_mods);
}
}
void update_held_keycode(custom_key_t* custom_key, uint16_t keycode) {
custom_key->held_keycode = keycode;
}
void handle_caps_word(uint16_t keycode) {
if (is_caps_word_on()) {
if (!caps_word_press_user(keycode)) {
caps_word_off();
}
}
}
void do_keycode(uint16_t keycode, custom_key_t* custom_key) {
handle_caps_word(keycode);
register_code16(keycode);
update_held_keycode(custom_key, keycode);
}
void do_action(key_remap_t* remap, custom_key_t* custom_key) {
// handle the dynamic typing of replacement_action
if (remap->options.action_is_function) {
void (*action)(custom_key_t*) = remap->replacement_action;
action(custom_key);
} else {
uint16_t* keycode = remap->replacement_action;
do_keycode(*keycode, custom_key);
}
}
void register_default_keycode(custom_key_t* custom_key) {
uint16_t* keycode = custom_key->default_action;
do_keycode(*keycode, custom_key);
}
void run_default_fn(custom_key_t* custom_key) {
void (*action)(custom_key_t*) = custom_key->default_action;
action(custom_key);
}
void process_remaps(
custom_key_t* custom_key, keyrecord_t* record, void (*default_fn)(custom_key_t*)
) {
if (record->event.pressed) { // key down
for (uint8_t i = 0; i < custom_key->num_remaps; i++) {
key_remap_t* remap = &(custom_key->remaps)[i];
key_remap_options_t* options = &remap->options;
// determine whether there is a mod match
bool match;
uint8_t mods = get_mods();
if (options->exact_match) {
match = (mods == remap->trigger_mods);
} else {
match = (mods & remap->trigger_mods);
}
// if any of the trigger_mods are active AND none of the negative mods are active
if (match && !(mods & remap->negative_mods)) {
// determine if we need to remove any mods
switch (options->mod_removal_mode) {
case REMOVE_TRIGGER:
// if Alt or GUI are in the trigger mods, suppress them
suppress_flashing_mods_needed(remap->trigger_mods, mods);
del_mods(remap->trigger_mods);
break;
case REMOVE_ALL:
// if Alt or GUI are active, suppress them
suppress_flashing_mods_needed(mods, mods);
clear_mods();
break;
}
// register the replacement/perform the function
do_action(remap, custom_key);
set_mods(mods);
return; // do not process more remaps
}
}
// if none of the remaps trigger, register the default keycode/run the default function
default_fn(custom_key);
} else { // key up
unregister_code16(custom_key->held_keycode);
neutralize_mods_on_release(); // necessary for flashing mods
}
}
bool process_custom_taphold(uint16_t custom_keycode, keyrecord_t* record) {
// only trigger a remap on a tap, not a hold
if (record->tap.count) {
// get the index from the tap-hold keycode
uint8_t index = (custom_keycode & 0b11111111) - ((SAFE_RANGE) & 0b11111111);
custom_key_t* custom_key = &custom_keys[index];
switch (index) {
case KEYCODE_RANGE:
process_remaps(custom_key, record, register_default_keycode);
break;
case FUNCTION_RANGE:
process_remaps(custom_key, record, run_default_fn);
break;
}
return false;
}
return true;
}
void process_custom_key(uint16_t custom_keycode, keyrecord_t* record) {
// subtract SAFE_RANGE to get an index that starts at 0
custom_key_t* custom_key = &custom_keys[custom_keycode - SAFE_RANGE];
process_remaps(custom_key, record, register_default_keycode);
}

View file

@ -0,0 +1,104 @@
#pragma once
#include QMK_KEYBOARD_H
#include "../common.h"
#include "../utils/mod_suppression.h"
#include "alias.h"
// -------------------------------------------------------------------------------------------------
#define CUSTOM_KEY_RANGE NK(NK_Q)... NK(NK_LAST)
#define KEYCODE_RANGE TH_DEL... TH_COLN
#define FUNCTION_RANGE TH_LAUNCH
#define NK(keycode) keycode + SAFE_RANGE
// -------------------------------------------------------------------------------------------------
typedef struct {
// 0 = do not change current mods, 1 = remove just trigger mods, 2 = remove all mods
uint8_t mod_removal_mode;
// true = mods must match exactly, false = only one match is required
bool exact_match;
// whether replacement_action is a function or a keycode
bool action_is_function;
} key_remap_options_t;
typedef struct {
void* replacement_action;
uint8_t trigger_mods;
uint8_t negative_mods;
key_remap_options_t options;
} key_remap_t;
typedef struct {
void* default_action; // the action to perform if none of the remaps trigger
uint16_t held_keycode; // the currently held keycode
uint8_t num_remaps; // how many entries are in remaps[]
// an array containing remaps that dictate how the key is handles based on the mod state
key_remap_t remaps[MAX_REMAPS_PER_CUSTOM_KEY];
} custom_key_t;
// -------------------------------------------------------------------------------------------------
void update_held_keycode(custom_key_t* custom_key, uint16_t keycode);
void process_custom_key(uint16_t custom_keycode, keyrecord_t* record);
bool process_custom_taphold(uint16_t custom_keycode, keyrecord_t* record);
// -------------------------------------------------------------------------------------------------
enum {
NO_CHANGE,
REMOVE_TRIGGER,
REMOVE_ALL
};
// -------------------------------------------------------------------------------------------------
typedef void (*remap_fn)(custom_key_t*);
#define REMAP_OPTIONS(mod_removal_mode, exact_match, action_is_function) \
{mod_removal_mode, exact_match, action_is_function}
#define REMAP_WITH_NEGATIVE_MODS_AND_OPTIONS_FN( \
replacement_action, trigger_mods, negative_mods, mod_removal_mode, exact_match \
) \
{(remap_fn)replacement_action, trigger_mods, negative_mods, \
REMAP_OPTIONS(mod_removal_mode, exact_match, true)}
#define REMAP_WITH_NEGATIVE_MODS_AND_OPTIONS( \
replacement_keycode, trigger_mods, negative_mods, mod_removal_mode, exact_match \
) \
{&(uint16_t){replacement_keycode}, trigger_mods, negative_mods, \
REMAP_OPTIONS(mod_removal_mode, exact_match, false)}
#define REMAP_WITH_NEGATIVE_MODS(replacement_keycode, trigger_mods, negative_mods) \
REMAP_WITH_NEGATIVE_MODS_AND_OPTIONS( \
replacement_keycode, trigger_mods, negative_mods, NO_CHANGE, false \
)
#define REMAP_WITH_OPTIONS(replacement_keycode, trigger_mods, mod_removal_mode, exact_match) \
REMAP_WITH_NEGATIVE_MODS_AND_OPTIONS( \
replacement_keycode, trigger_mods, 0, mod_removal_mode, exact_match \
)
#define REMAP(replacement_keycode, trigger_mods) \
REMAP_WITH_NEGATIVE_MODS(replacement_keycode, trigger_mods, 0)
#define CUSTOM_KEY(default_keycode, num_remaps, ...) \
{ \
&(uint16_t){default_keycode}, KC_NO, num_remaps, { \
__VA_ARGS__ \
} \
}
#define CUSTOM_KEY_NO_REMAP(default_keycode) {&(uint16_t){default_keycode}, 0}
#define CUSTOM_KEY_FN(default_action, num_remaps, ...) \
{ \
(void)(*)(custom_key_t*){default_action}, num_remaps, { \
__VA_ARGS__ \
} \
}
#define CUSTOM_KEY_FN_NO_REMAP(default_action) {(remap_fn)default_action, 0}
// -------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,148 @@
#include "mapping.h"
void obliterate_line_backwards(custom_key_t* custom_key) {
obliterate_line(KC_BSPC);
update_held_keycode(custom_key, KC_BSPC);
}
void obliterate_line_forwards(custom_key_t* custom_key) {
obliterate_line(KC_DEL);
update_held_keycode(custom_key, KC_DEL);
}
void launch(custom_key_t* custom_key) {
tap_code16(LAUNCH);
update_held_keycode(custom_key, KC_NO);
}
void turn_on_caps_word(custom_key_t* custom_key) {
caps_word_on();
update_held_keycode(custom_key, KC_NO);
}
custom_key_t custom_keys[] = {
// _BASE layer
[NK_Q] = CUSTOM_KEY(KC_Q, 1, REMAP_WITH_OPTIONS(A(KC_F4), MOD_MASK_GUI, REMOVE_TRIGGER, false)),
[NK_R] = CUSTOM_KEY(KC_R, 1, REMAP(KC_Y, MOD_MASK_CTRL)),
// _NUM layer
[NK_COLN] = CUSTOM_KEY(KC_COLN, 1, REMAP(KC_M, MOD_MASK_CTRL)),
[NK_MINS_NUM] = CUSTOM_KEY(KC_MINS, 1, REMAP(KC_Y, MOD_MASK_CTRL)),
[NK_1] = CUSTOM_KEY(
KC_1, 2, REMAP(KC_A, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_1, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_2] = CUSTOM_KEY(
KC_2, 2, REMAP(KC_S, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_2, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_3] = CUSTOM_KEY(KC_3, 1, REMAP_WITH_OPTIONS(KC_3, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)),
[NK_4] = CUSTOM_KEY(
KC_4, 2, REMAP(KC_F, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_4, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_5] = CUSTOM_KEY(KC_5, 1, REMAP_WITH_OPTIONS(KC_5, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)),
[NK_6] = CUSTOM_KEY(
KC_6, 2, REMAP(KC_H, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_6, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_7] = CUSTOM_KEY(
KC_7, 2, REMAP(KC_J, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_7, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_8] = CUSTOM_KEY(KC_8, 1, REMAP_WITH_OPTIONS(KC_8, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)),
[NK_9] = CUSTOM_KEY(KC_9, 1, REMAP_WITH_OPTIONS(KC_9, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)),
[NK_0] = CUSTOM_KEY(KC_0, 1, REMAP_WITH_OPTIONS(KC_0, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)),
[NK_6_LOW] = CUSTOM_KEY(
KC_6, 2, REMAP(KC_Z, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_6, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_7_LOW] = CUSTOM_KEY(
KC_7, 2, REMAP(KC_X, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_7, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_8_LOW] = CUSTOM_KEY(
KC_8, 2, REMAP(KC_C, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_8, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_9_LOW] = CUSTOM_KEY(
KC_9, 2, REMAP(KC_V, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_9, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_0_LOW] = CUSTOM_KEY(
KC_0, 2, REMAP(KC_B, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_0, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
// _NAV layer
[NK_BSLS] = CUSTOM_KEY(
KC_BSLS, 2, REMAP(KC_A, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_BSLS, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_LBRC] = CUSTOM_KEY(
KC_LBRC, 2, REMAP(KC_S, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_LBRC, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_RBRC] =
CUSTOM_KEY(KC_RBRC, 1, REMAP_WITH_OPTIONS(KC_RBRC, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)),
[NK_MINS_NAV] = CUSTOM_KEY(
KC_MINS, 2, REMAP(KC_F, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_MINS, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_EQL] =
CUSTOM_KEY(KC_EQL, 1, REMAP_WITH_OPTIONS(KC_EQL, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)),
[NK_GRV] = CUSTOM_KEY(
KC_GRV, 2, REMAP_WITH_OPTIONS(TAB_FORWARD, MOD_MASK_ALT, REMOVE_ALL, false),
REMAP_WITH_OPTIONS(KC_GRV, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_PIPE] = CUSTOM_KEY(KC_PIPE, 1, REMAP(KC_Z, MOD_MASK_CTRL)),
[NK_LCBR] = CUSTOM_KEY(KC_LCBR, 1, REMAP(KC_X, MOD_MASK_CTRL)),
[NK_RCBR] = CUSTOM_KEY(KC_RCBR, 1, REMAP(KC_C, MOD_MASK_CTRL)),
[NK_UNDS] = CUSTOM_KEY(KC_UNDS, 1, REMAP(KC_V, MOD_MASK_CTRL)),
[NK_PLUS] = CUSTOM_KEY(KC_PLUS, 1, REMAP(KC_B, MOD_MASK_CTRL)),
[NK_F2] = CUSTOM_KEY(KC_F2, 1, REMAP(KC_M, MOD_MASK_CTRL)),
[NK_DLR] = CUSTOM_KEY(KC_DLR, 1, REMAP(KC_Y, MOD_MASK_CTRL)),
[NK_HOME] = CUSTOM_KEY(
KC_HOME, 2, REMAP_WITH_OPTIONS(C(KC_HOME), MOD_MASK_GUI, REMOVE_TRIGGER, false),
REMAP_WITH_OPTIONS(KC_HOME, MOD_MASK_CTRL, REMOVE_TRIGGER, false)
),
[NK_END] = CUSTOM_KEY(
KC_END, 2, REMAP_WITH_OPTIONS(C(KC_END), MOD_MASK_GUI, REMOVE_TRIGGER, false),
REMAP_WITH_OPTIONS(KC_END, MOD_MASK_CTRL, REMOVE_TRIGGER, false)
),
// multiple layers
[NK_CIRC] = CUSTOM_KEY(KC_CIRC, 1, REMAP(KC_Y, MOD_MASK_CTRL)),
[NK_AMPR] = CUSTOM_KEY(KC_AMPR, 1, REMAP(KC_U, MOD_MASK_CTRL)),
[NK_ASTR] = CUSTOM_KEY(KC_ASTR, 1, REMAP(KC_I, MOD_MASK_CTRL)),
[NK_RPRN] = CUSTOM_KEY(KC_RPRN, 1, REMAP(KC_P, MOD_MASK_CTRL)),
[NK_ESC] =
CUSTOM_KEY(KC_ESC, 1, REMAP_WITH_OPTIONS(TAB_FORWARD, MOD_MASK_ALT, REMOVE_ALL, false)),
[NK_UP] = CUSTOM_KEY(KC_UP, 1, REMAP(C(KC_EQL), MOD_MASK_CTRL)),
[NK_DOWN] = CUSTOM_KEY(KC_DOWN, 1, REMAP(C(KC_MINS), MOD_MASK_CTRL)),
[NK_BSPC] = CUSTOM_KEY(
KC_BSPC, 1,
REMAP_WITH_NEGATIVE_MODS_AND_OPTIONS_FN(
obliterate_line_backwards, MOD_MASK_GUI, 0, REMOVE_TRIGGER, false
)
),
// tap-hold
[TH_LAUNCH] = CUSTOM_KEY_FN_NO_REMAP(launch),
[TH_DEL] = CUSTOM_KEY(
KC_DEL, 2,
REMAP_WITH_NEGATIVE_MODS_AND_OPTIONS_FN(
turn_on_caps_word, MOD_MASK_SHIFT, 0, NO_CHANGE, false
),
REMAP_WITH_NEGATIVE_MODS_AND_OPTIONS_FN(
obliterate_line_forwards, MOD_MASK_GUI, 0, REMOVE_TRIGGER, false
),
),
[TH_RALT] = CUSTOM_KEY(KC_RALT, 1, REMAP(KC_CAPS, MOD_MASK_SHIFT)),
[TH_TILD] =
CUSTOM_KEY(KC_TILD, 1, REMAP_WITH_OPTIONS(TAB_BACKWARD, MOD_MASK_ALT, REMOVE_ALL, false)),
[TH_LSFT] =
CUSTOM_KEY(KC_LSFT, 1, REMAP_WITH_OPTIONS(TAB_BACKWARD, MOD_MASK_ALT, REMOVE_ALL, false)),
[TH_COMM] =
CUSTOM_KEY(KC_COMM, 1, REMAP_WITH_OPTIONS(TAB_BACKWARD, MOD_MASK_ALT, REMOVE_ALL, false)),
[TH_COLN] = CUSTOM_KEY_NO_REMAP(KC_COLN),
[TH_SPC] =
CUSTOM_KEY(KC_SPC, 1, REMAP_WITH_OPTIONS(MENU, MOD_MASK_CTRL, REMOVE_TRIGGER, false)),
};

View file

@ -0,0 +1,85 @@
#pragma once
#include QMK_KEYBOARD_H
#include "../common.h"
#include "../layers.h"
#include "../utils/deletion.h"
#include "alias.h"
#include "custom_keys.h"
// -------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------
// clang-format off
// NK stands for "new key"
enum custom_keycodes {
// _BASE layer
NK_Q,
NK_R,
// _NUM layer
NK_COLN,
NK_MINS_NUM,
NK_1,
NK_2,
NK_3,
NK_4,
NK_5,
NK_6,
NK_7,
NK_8,
NK_9,
NK_0,
NK_6_LOW,
NK_7_LOW,
NK_8_LOW,
NK_9_LOW,
NK_0_LOW,
// _NAV layer
NK_BSLS, // backslash
NK_LBRC, // [
NK_RBRC, // ]
NK_MINS_NAV, // -
NK_EQL, // =
NK_GRV, // `
NK_PIPE,
NK_LCBR,
NK_RCBR,
NK_UNDS,
NK_PLUS,
NK_F2,
NK_DLR,
NK_HOME,
NK_END,
// multiple layers
NK_CIRC,
NK_AMPR,
NK_ASTR,
NK_RPRN,
NK_ESC,
NK_UP,
NK_DOWN,
NK_BSPC,
// tap-hold
// default function
TH_LAUNCH,
// default keycode
TH_DEL,
TH_RALT,
TH_TILD,
TH_LSFT,
TH_COMM,
TH_COLN,
TH_SPC,
// this is always last
NK_LAST,
};
// clang-format on
// -------------------------------------------------------------------------------------------------
extern custom_key_t custom_keys[];
// -------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,85 @@
#include QMK_KEYBOARD_H
#include "caps_word/caps_word.h"
#include "common.h"
#include "custom_keys/custom_keys.h"
#include "custom_keys/mapping.h"
#include "layers.h"
#include "tap_dance/tap_dance.h"
#include "taphold/taphold_options.h"
bool NAV_enabled = false;
// clang-format off
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// base
[_BASE] = LAYOUT_ortho_4x12(
NK(NK_ESC), NK(NK_Q), KC_W, KC_E, NK(NK_R), KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, NK(NK_BSPC),
CTL_T(KC_TAB), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
SFT_SFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, ALT_DEL,
KC_RCTL, LT(_FUNC, KC_MPLY), ALT_T(KC_LALT), TD(TD_CAD_LOCK), GUI_LAUNCH, NUM_SPC, NAV_ENT, ALT_COMP, KC_LEFT, NK(NK_DOWN), NK(NK_UP), KC_RGHT
),
// gamer
[_GAME] = LAYOUT_ortho_4x12(
KC_TRNS, KC_Q, KC_TRNS, KC_TRNS, KC_R, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TAB, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_LSFT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_PGDN, KC_PGUP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
),
// special characters
// numbers
[_NUM] = LAYOUT_ortho_4x12(
KC_TRNS, KC_SLSH, KC_AT, KC_ASTR, NK(NK_MINS_NUM), KC_PLUS, NK(NK_CIRC), NK(NK_AMPR), NK(NK_ASTR), KC_LPRN, NK(NK_RPRN), KC_TRNS,
CTL_T(KC_DOT), NK(NK_1), NK(NK_2), NK(NK_3), NK(NK_4), NK(NK_5), NK(NK_6), NK(NK_7), NK(NK_8), NK(NK_9), NK(NK_0), KC_TRNS,
SFT_COMM, NK(NK_6_LOW), NK(NK_7_LOW), NK(NK_8_LOW), NK(NK_9_LOW), NK(NK_0_LOW), KC_SCLN, NK(NK_COLN), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
CTL_COLN, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
),
[_NAV] = LAYOUT_ortho_4x12(
NK(NK_GRV), KC_EXLM, KC_AT, KC_HASH, NK(NK_DLR), KC_PERC, NK(NK_CIRC), NK(NK_AMPR), NK(NK_ASTR), KC_LPRN, NK(NK_RPRN), KC_TRNS,
KC_TRNS, NK(NK_BSLS), NK(NK_LBRC), NK(NK_RBRC), NK(NK_MINS_NAV), NK(NK_EQL), NK(NK_HOME), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, NK(NK_END),
SFT_TILD, NK(NK_PIPE), NK(NK_LCBR), NK(NK_RCBR), NK(NK_UNDS), NK(NK_PLUS), KC_NO, NK(NK_F2), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
),
// function
[_FUNC] = LAYOUT_ortho_4x12(
KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,
KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_TRNS, KC_MUTE, KC_MPRV, KC_VOLD, KC_VOLU, KC_MNXT, KC_NO, KC_NO, KC_NO, KC_NO, TG(_GAME), QK_BOOT,
KC_TRNS, KC_NO, KC_BRID, KC_BRIU, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, QK_RBT
),
};
// clang-format on
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
// make it possible to go from layer 3 to layer 2
case NUM_SPC:
if (!record->tap.count) {
if (NAV_enabled) {
record->event.pressed ? layer_off(_NAV) : layer_on(_NAV);
}
} else {
process_custom_key(NK(TH_SPC), record);
return false;
}
break;
case NAV_ENT:
if (!record->tap.count) {
NAV_enabled = record->event.pressed;
}
break;
case CUSTOM_KEY_RANGE:
process_custom_key(keycode, record);
return false;
break;
case GUI_LAUNCH:
case ALT_DEL:
case ALT_COMP:
case SFT_TILD:
case SFT_SFT:
case SFT_COMM:
case CTL_COLN:
return process_custom_taphold(keycode, record);
break;
}
return true;
}

View file

@ -0,0 +1,9 @@
#pragma once
enum layers {
_BASE,
_GAME,
_NUM,
_NAV,
_FUNC,
};

View file

@ -0,0 +1,16 @@
SRC += caps_word/caps_word.c
SRC += taphold/taphold_options.c
SRC += utils/mod_suppression.c
SRC += utils/deletion.c
SRC += custom_keys/custom_keys.c
SRC += custom_keys/mapping.c
# VIA_ENABLE = yes
LTO_ENABLE = yes
CAPS_WORD_ENABLE = yes
# CONSOLE_ENABLE = yes
TAP_DANCE_ENABLE = yes
SEND_STRING_ENABLE = yes

View file

@ -0,0 +1,5 @@
#include "tap_dance.h"
tap_dance_action_t tap_dance_actions[] = {
[TD_CAD_LOCK] = ACTION_TAP_DANCE_DOUBLE(CAD, LOCK),
};

View file

@ -0,0 +1,9 @@
#pragma once
#include "../common.h"
enum {
TD_CAD_LOCK,
};
extern tap_dance_action_t tap_dance_actions[];

View file

@ -0,0 +1,48 @@
#include "taphold_options.h"
uint16_t get_quick_tap_term(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
case CTL_T(KC_TAB):
case NUM_SPC:
case NAV_ENT:
case GUI_LAUNCH: // no repeat tapping when tapped and then held for these keys
return 0;
break;
default:
return QUICK_TAP_TERM;
break;
}
}
bool get_permissive_hold(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
case NUM_SPC: // permissive hold for layer tap space
return true;
break;
default:
return false;
break;
}
}
bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
case NUM_SPC: // no hold on other key press for layer tap space
return false;
break;
default:
return true;
break;
}
}
uint16_t get_tapping_term(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
case GUI_LAUNCH:
return 500;
break;
default:
return TAPPING_TERM;
break;
}
}

View file

@ -0,0 +1,13 @@
#pragma once
#include QMK_KEYBOARD_H
#include "../common.h"
#include "../custom_keys/alias.h"
#include "../custom_keys/mapping.h"
#include "../layers.h"
#include "../tap_dance.h"
uint16_t get_quick_tap_term(uint16_t keycode, keyrecord_t* record);
bool get_permissive_hold(uint16_t keycode, keyrecord_t* record);
bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t* record);
uint16_t get_tapping_term(uint16_t keycode, keyrecord_t* record);

View file

@ -0,0 +1,18 @@
#include "deletion.h"
void obliterate_line(uint8_t deletion_keycode) {
uint8_t movement_keycode;
switch (deletion_keycode) {
case KC_BSPC:
movement_keycode = KC_HOME;
break;
case KC_DEL:
movement_keycode = KC_END;
break;
default: // this should never run
return;
break;
}
tap_code16(S(movement_keycode));
register_code(deletion_keycode);
}

View file

@ -0,0 +1,4 @@
#pragma once
#include QMK_KEYBOARD_H
void obliterate_line(uint8_t deletion_keycode);

View file

@ -0,0 +1,31 @@
#include "mod_suppression.h"
void trigger_dummy_key(uint8_t mods) {
if (mods & MOD_BIT(DUMMY_MOD_NEUTRALIZER_KEYCODE)) {
unregister_mods(MOD_BIT(DUMMY_MOD_NEUTRALIZER_KEYCODE));
register_mods(MOD_BIT(DUMMY_MOD_NEUTRALIZER_KEYCODE));
} else {
tap_code(DUMMY_MOD_NEUTRALIZER_KEYCODE);
}
}
void suppress_flashing_mods(uint8_t mods) {
trigger_dummy_key(mods);
del_mods(MOD_MASK_AG);
}
void neutralize_mods_on_release(void) {
uint8_t mods = get_mods();
if (mods & (MOD_MASK_AG)) {
send_keyboard_report();
trigger_dummy_key(mods);
}
}
// void tap_code16_suppress(uint16_t keycode, uint8_t mods) {
// suppress_flashing_mods(mods);
// tap_code16(keycode);
// set_mods(mods);
// }
// void register_code16_suppress(uint16_t keycode, uint8_t mods) {
// suppress_flashing_mods(mods);
// register_code16(keycode);
// set_mods(mods);
// }

View file

@ -0,0 +1,8 @@
#pragma once
#include QMK_KEYBOARD_H
void trigger_dummy_key(uint8_t mods);
void suppress_flashing_mods(uint8_t mods);
void neutralize_mods_on_release(void);
void tap_code16_suppress(uint16_t keycode, uint8_t mods);
void register_code16_suppress(uint16_t keycode, uint8_t mods);

View file

@ -0,0 +1,26 @@
#include QMK_KEYBOARD_H
#include "caps_word.h"
bool caps_word_press_user(uint16_t keycode) {
switch (keycode) {
// Keycodes that continue Caps Word, with shift applied
case KC_A ... KC_Z:
add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to next key
return true;
break;
// Keycodes that continue Caps Word, without shifting
case KC_1 ... KC_0:
case KC_BSPC:
case KC_DEL:
case KC_LEFT:
case KC_RGHT:
case KC_MINS:
case KC_UNDS:
// custom keycodes
return true;
break;
default:
return false; // Deactivate Caps Word
break;
}
}

View file

@ -0,0 +1,4 @@
#pragma once
#include "../custom_keys/mapping.h"
bool caps_word_press_user(uint16_t keycode);

View file

@ -0,0 +1,25 @@
#pragma once
// stuff I added
#define MAX_REMAPS_PER_CUSTOM_KEY 2
// end stuff I added
#define TAPPING_TERM 200
#define QUICK_TAP_TERM_PER_KEY
#define HOLD_ON_OTHER_KEY_PRESS_PER_KEY
#define PERMISSIVE_HOLD_PER_KEY
#define TAPPING_TERM_PER_KEY
#define CAPS_WORD_IDLE_TIMEOUT 0
#define DUMMY_MOD_NEUTRALIZER_KEYCODE KC_RCTL
#define MODS_TO_NEUTRALIZE {MOD_BIT(KC_LALT), MOD_BIT(KC_RALT), MOD_BIT(KC_LGUI), MOD_BIT(KC_RGUI)}
// disable some features to make the code smaller
#define NO_ACTION_ONESHOT
// delete later; tap dance
#define TAPPING_TERM_PER_KEY
#define DYNAMIC_KEYMAP_LAYER_COUNT 6

View file

@ -0,0 +1,20 @@
#pragma once
#include QMK_KEYBOARD_H
#define TAB_FORWARD C(KC_TAB)
#define TAB_BACKWARD (C(S(KC_TAB)))
#define LAUNCH A(KC_SPC)
#define MENU S(KC_F10)
#define GUI_LAUNCH GUI_T(NK(TH_LAUNCH))
#define ALT_DEL ALT_T(NK(TH_DEL))
#define ALT_COMP ALT_T(NK(TH_RALT))
#define SFT_TILD SFT_T(NK(TH_TILD))
#define SFT_SFT SFT_T(NK(TH_LSFT))
#define SFT_COMM SFT_T(NK(TH_COMM))
#define CTL_COLN CTL_T(NK(TH_COLN))
// non-custom
#define NUM_SPC LT(_NUM, TH_SPC)
#define NAV_ENT LT(_NAV, KC_ENT)
#define CAD C(A(KC_DEL))
#define LOCK G(KC_L)

View file

@ -0,0 +1,120 @@
#include "custom_keys.h"
#include "../caps_word/caps_word.h"
#include "mapping.h"
void suppress_flashing_mods_needed(uint8_t mods_to_check, uint8_t active_mods) {
if (mods_to_check & MOD_MASK_AG) {
suppress_flashing_mods(active_mods);
}
}
void update_held_keycode(custom_key_t* custom_key, uint16_t keycode) {
custom_key->held_keycode = keycode;
}
void handle_caps_word(uint16_t keycode) {
if (is_caps_word_on()) {
if (!caps_word_press_user(keycode)) {
caps_word_off();
}
}
}
void do_keycode(uint16_t keycode, custom_key_t* custom_key) {
handle_caps_word(keycode);
register_code16(keycode);
update_held_keycode(custom_key, keycode);
}
void do_action(key_remap_t* remap, custom_key_t* custom_key) {
// handle the dynamic typing of replacement_action
if (remap->options.action_is_function) {
void (*action)(custom_key_t*) = remap->replacement_action;
action(custom_key);
} else {
uint16_t* keycode = remap->replacement_action;
do_keycode(*keycode, custom_key);
}
}
void register_default_keycode(custom_key_t* custom_key) {
uint16_t* keycode = custom_key->default_action;
do_keycode(*keycode, custom_key);
}
void run_default_fn(custom_key_t* custom_key) {
void (*action)(custom_key_t*) = custom_key->default_action;
action(custom_key);
}
void process_remaps(
custom_key_t* custom_key, keyrecord_t* record, void (*default_fn)(custom_key_t*)
) {
if (record->event.pressed) { // key down
for (uint8_t i = 0; i < custom_key->num_remaps; i++) {
key_remap_t* remap = &(custom_key->remaps)[i];
key_remap_options_t* options = &remap->options;
// determine whether there is a mod match
bool match;
uint8_t mods = get_mods();
if (options->exact_match) {
match = (mods == remap->trigger_mods);
} else {
match = (mods & remap->trigger_mods);
}
// if any of the trigger_mods are active AND none of the negative mods are active
if (match && !(mods & remap->negative_mods)) {
// determine if we need to remove any mods
switch (options->mod_removal_mode) {
case REMOVE_TRIGGER:
// if Alt or GUI are in the trigger mods, suppress them
suppress_flashing_mods_needed(remap->trigger_mods, mods);
del_mods(remap->trigger_mods);
break;
case REMOVE_ALL:
// if Alt or GUI are active, suppress them
suppress_flashing_mods_needed(mods, mods);
clear_mods();
break;
}
// register the replacement/perform the function
do_action(remap, custom_key);
set_mods(mods);
return; // do not process more remaps
}
}
// if none of the remaps trigger, register the default keycode/run the default function
default_fn(custom_key);
} else { // key up
unregister_code16(custom_key->held_keycode);
neutralize_mods_on_release(); // necessary for flashing mods
}
}
bool process_custom_taphold(uint16_t custom_keycode, keyrecord_t* record) {
// only trigger a remap on a tap, not a hold
if (record->tap.count) {
// get the index from the tap-hold keycode
uint8_t index = (custom_keycode & 0b11111111) - ((SAFE_RANGE) & 0b11111111);
custom_key_t* custom_key = &custom_keys[index];
switch (index) {
case KEYCODE_RANGE:
process_remaps(custom_key, record, register_default_keycode);
break;
case FUNCTION_RANGE:
process_remaps(custom_key, record, run_default_fn);
break;
}
return false;
}
return true;
}
void process_custom_key(uint16_t custom_keycode, keyrecord_t* record) {
// subtract SAFE_RANGE to get an index that starts at 0
custom_key_t* custom_key = &custom_keys[custom_keycode - SAFE_RANGE];
process_remaps(custom_key, record, register_default_keycode);
}

View file

@ -0,0 +1,103 @@
#pragma once
#include QMK_KEYBOARD_H
#include "../utils/mod_suppression.h"
#include "alias.h"
// -------------------------------------------------------------------------------------------------
#define CUSTOM_KEY_RANGE NK(NK_Q)... NK(NK_LAST)
#define KEYCODE_RANGE TH_DEL... TH_COLN
#define FUNCTION_RANGE TH_LAUNCH
#define NK(keycode) keycode + SAFE_RANGE
// -------------------------------------------------------------------------------------------------
typedef struct {
// 0 = do not change current mods, 1 = remove just trigger mods, 2 = remove all mods
uint8_t mod_removal_mode;
// true = mods must match exactly, false = only one match is required
bool exact_match;
// whether replacement_action is a function or a keycode
bool action_is_function;
} key_remap_options_t;
typedef struct {
void* replacement_action;
uint8_t trigger_mods;
uint8_t negative_mods;
key_remap_options_t options;
} key_remap_t;
typedef struct {
void* default_action; // the action to perform if none of the remaps trigger
uint16_t held_keycode; // the currently held keycode
uint8_t num_remaps; // how many entries are in remaps[]
// an array containing remaps that dictate how the key is handles based on the mod state
key_remap_t remaps[MAX_REMAPS_PER_CUSTOM_KEY];
} custom_key_t;
// -------------------------------------------------------------------------------------------------
void update_held_keycode(custom_key_t* custom_key, uint16_t keycode);
void process_custom_key(uint16_t custom_keycode, keyrecord_t* record);
bool process_custom_taphold(uint16_t custom_keycode, keyrecord_t* record);
// -------------------------------------------------------------------------------------------------
enum {
NO_CHANGE,
REMOVE_TRIGGER,
REMOVE_ALL
};
// -------------------------------------------------------------------------------------------------
typedef void (*remap_fn)(custom_key_t*);
#define REMAP_OPTIONS(mod_removal_mode, exact_match, action_is_function) \
{mod_removal_mode, exact_match, action_is_function}
#define REMAP_WITH_NEGATIVE_MODS_AND_OPTIONS_FN( \
replacement_action, trigger_mods, negative_mods, mod_removal_mode, exact_match \
) \
{(remap_fn)replacement_action, trigger_mods, negative_mods, \
REMAP_OPTIONS(mod_removal_mode, exact_match, true)}
#define REMAP_WITH_NEGATIVE_MODS_AND_OPTIONS( \
replacement_keycode, trigger_mods, negative_mods, mod_removal_mode, exact_match \
) \
{&(uint16_t){replacement_keycode}, trigger_mods, negative_mods, \
REMAP_OPTIONS(mod_removal_mode, exact_match, false)}
#define REMAP_WITH_NEGATIVE_MODS(replacement_keycode, trigger_mods, negative_mods) \
REMAP_WITH_NEGATIVE_MODS_AND_OPTIONS( \
replacement_keycode, trigger_mods, negative_mods, NO_CHANGE, false \
)
#define REMAP_WITH_OPTIONS(replacement_keycode, trigger_mods, mod_removal_mode, exact_match) \
REMAP_WITH_NEGATIVE_MODS_AND_OPTIONS( \
replacement_keycode, trigger_mods, 0, mod_removal_mode, exact_match \
)
#define REMAP(replacement_keycode, trigger_mods) \
REMAP_WITH_NEGATIVE_MODS(replacement_keycode, trigger_mods, 0)
#define CUSTOM_KEY(default_keycode, num_remaps, ...) \
{ \
&(uint16_t){default_keycode}, KC_NO, num_remaps, { \
__VA_ARGS__ \
} \
}
#define CUSTOM_KEY_NO_REMAP(default_keycode) {&(uint16_t){default_keycode}, 0}
#define CUSTOM_KEY_FN(default_action, num_remaps, ...) \
{ \
(void)(*)(custom_key_t*){default_action}, num_remaps, { \
__VA_ARGS__ \
} \
}
#define CUSTOM_KEY_FN_NO_REMAP(default_action) {(remap_fn)default_action, 0}
// -------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,148 @@
#include "mapping.h"
void obliterate_line_backwards(custom_key_t* custom_key) {
obliterate_line(KC_BSPC);
update_held_keycode(custom_key, KC_BSPC);
}
void obliterate_line_forwards(custom_key_t* custom_key) {
obliterate_line(KC_DEL);
update_held_keycode(custom_key, KC_DEL);
}
void launch(custom_key_t* custom_key) {
tap_code16(LAUNCH);
update_held_keycode(custom_key, KC_NO);
}
void turn_on_caps_word(custom_key_t* custom_key) {
caps_word_on();
update_held_keycode(custom_key, KC_NO);
}
custom_key_t custom_keys[] = {
// _BASE layer
[NK_Q] = CUSTOM_KEY(KC_Q, 1, REMAP_WITH_OPTIONS(A(KC_F4), MOD_MASK_GUI, REMOVE_TRIGGER, false)),
[NK_R] = CUSTOM_KEY(KC_R, 1, REMAP(KC_Y, MOD_MASK_CTRL)),
// _NUM layer
[NK_COLN] = CUSTOM_KEY(KC_COLN, 1, REMAP(KC_M, MOD_MASK_CTRL)),
[NK_MINS_NUM] = CUSTOM_KEY(KC_MINS, 1, REMAP(KC_Y, MOD_MASK_CTRL)),
[NK_1] = CUSTOM_KEY(
KC_1, 2, REMAP(KC_A, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_1, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_2] = CUSTOM_KEY(
KC_2, 2, REMAP(KC_S, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_2, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_3] = CUSTOM_KEY(KC_3, 1, REMAP_WITH_OPTIONS(KC_3, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)),
[NK_4] = CUSTOM_KEY(
KC_4, 2, REMAP(KC_F, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_4, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_5] = CUSTOM_KEY(KC_5, 1, REMAP_WITH_OPTIONS(KC_5, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)),
[NK_6] = CUSTOM_KEY(
KC_6, 2, REMAP(KC_H, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_6, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_7] = CUSTOM_KEY(
KC_7, 2, REMAP(KC_J, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_7, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_8] = CUSTOM_KEY(KC_8, 1, REMAP_WITH_OPTIONS(KC_8, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)),
[NK_9] = CUSTOM_KEY(KC_9, 1, REMAP_WITH_OPTIONS(KC_9, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)),
[NK_0] = CUSTOM_KEY(KC_0, 1, REMAP_WITH_OPTIONS(KC_0, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)),
[NK_6_LOW] = CUSTOM_KEY(
KC_6, 2, REMAP(KC_Z, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_6, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_7_LOW] = CUSTOM_KEY(
KC_7, 2, REMAP(KC_X, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_7, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_8_LOW] = CUSTOM_KEY(
KC_8, 2, REMAP(KC_C, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_8, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_9_LOW] = CUSTOM_KEY(
KC_9, 2, REMAP(KC_V, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_9, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_0_LOW] = CUSTOM_KEY(
KC_0, 2, REMAP(KC_B, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_0, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
// _NAV layer
[NK_BSLS] = CUSTOM_KEY(
KC_BSLS, 2, REMAP(KC_A, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_BSLS, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_LBRC] = CUSTOM_KEY(
KC_LBRC, 2, REMAP(KC_S, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_LBRC, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_RBRC] =
CUSTOM_KEY(KC_RBRC, 1, REMAP_WITH_OPTIONS(KC_RBRC, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)),
[NK_MINS_NAV] = CUSTOM_KEY(
KC_MINS, 2, REMAP(KC_F, MOD_MASK_CTRL),
REMAP_WITH_OPTIONS(KC_MINS, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_EQL] =
CUSTOM_KEY(KC_EQL, 1, REMAP_WITH_OPTIONS(KC_EQL, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)),
[NK_GRV] = CUSTOM_KEY(
KC_GRV, 2, REMAP_WITH_OPTIONS(TAB_FORWARD, MOD_MASK_ALT, REMOVE_ALL, false),
REMAP_WITH_OPTIONS(KC_GRV, MOD_MASK_SHIFT, REMOVE_TRIGGER, false)
),
[NK_PIPE] = CUSTOM_KEY(KC_PIPE, 1, REMAP(KC_Z, MOD_MASK_CTRL)),
[NK_LCBR] = CUSTOM_KEY(KC_LCBR, 1, REMAP(KC_X, MOD_MASK_CTRL)),
[NK_RCBR] = CUSTOM_KEY(KC_RCBR, 1, REMAP(KC_C, MOD_MASK_CTRL)),
[NK_UNDS] = CUSTOM_KEY(KC_UNDS, 1, REMAP(KC_V, MOD_MASK_CTRL)),
[NK_PLUS] = CUSTOM_KEY(KC_PLUS, 1, REMAP(KC_B, MOD_MASK_CTRL)),
[NK_F2] = CUSTOM_KEY(KC_F2, 1, REMAP(KC_M, MOD_MASK_CTRL)),
[NK_DLR] = CUSTOM_KEY(KC_DLR, 1, REMAP(KC_Y, MOD_MASK_CTRL)),
[NK_HOME] = CUSTOM_KEY(
KC_HOME, 2, REMAP_WITH_OPTIONS(C(KC_HOME), MOD_MASK_GUI, REMOVE_TRIGGER, false),
REMAP_WITH_OPTIONS(KC_HOME, MOD_MASK_CTRL, REMOVE_TRIGGER, false)
),
[NK_END] = CUSTOM_KEY(
KC_END, 2, REMAP_WITH_OPTIONS(C(KC_END), MOD_MASK_GUI, REMOVE_TRIGGER, false),
REMAP_WITH_OPTIONS(KC_END, MOD_MASK_CTRL, REMOVE_TRIGGER, false)
),
// multiple layers
[NK_CIRC] = CUSTOM_KEY(KC_CIRC, 1, REMAP(KC_Y, MOD_MASK_CTRL)),
[NK_AMPR] = CUSTOM_KEY(KC_AMPR, 1, REMAP(KC_U, MOD_MASK_CTRL)),
[NK_ASTR] = CUSTOM_KEY(KC_ASTR, 1, REMAP(KC_I, MOD_MASK_CTRL)),
[NK_RPRN] = CUSTOM_KEY(KC_RPRN, 1, REMAP(KC_P, MOD_MASK_CTRL)),
[NK_ESC] =
CUSTOM_KEY(KC_ESC, 1, REMAP_WITH_OPTIONS(TAB_FORWARD, MOD_MASK_ALT, REMOVE_ALL, false)),
[NK_UP] = CUSTOM_KEY(KC_UP, 1, REMAP(C(KC_EQL), MOD_MASK_CTRL)),
[NK_DOWN] = CUSTOM_KEY(KC_DOWN, 1, REMAP(C(KC_MINS), MOD_MASK_CTRL)),
[NK_BSPC] = CUSTOM_KEY(
KC_BSPC, 1,
REMAP_WITH_NEGATIVE_MODS_AND_OPTIONS_FN(
obliterate_line_backwards, MOD_MASK_GUI, 0, REMOVE_TRIGGER, false
)
),
// tap-hold
[TH_LAUNCH] = CUSTOM_KEY_FN_NO_REMAP(launch),
[TH_DEL] = CUSTOM_KEY(
KC_DEL, 2,
REMAP_WITH_NEGATIVE_MODS_AND_OPTIONS_FN(
turn_on_caps_word, MOD_MASK_SHIFT, 0, NO_CHANGE, false
),
REMAP_WITH_NEGATIVE_MODS_AND_OPTIONS_FN(
obliterate_line_forwards, MOD_MASK_GUI, 0, REMOVE_TRIGGER, false
),
),
[TH_RALT] = CUSTOM_KEY(KC_RALT, 1, REMAP(KC_CAPS, MOD_MASK_SHIFT)),
[TH_TILD] =
CUSTOM_KEY(KC_TILD, 1, REMAP_WITH_OPTIONS(TAB_BACKWARD, MOD_MASK_ALT, REMOVE_ALL, false)),
[TH_LSFT] =
CUSTOM_KEY(KC_LSFT, 1, REMAP_WITH_OPTIONS(TAB_BACKWARD, MOD_MASK_ALT, REMOVE_ALL, false)),
[TH_COMM] =
CUSTOM_KEY(KC_COMM, 1, REMAP_WITH_OPTIONS(TAB_BACKWARD, MOD_MASK_ALT, REMOVE_ALL, false)),
[TH_COLN] = CUSTOM_KEY_NO_REMAP(KC_COLN),
[TH_SPC] =
CUSTOM_KEY(KC_SPC, 1, REMAP_WITH_OPTIONS(MENU, MOD_MASK_CTRL, REMOVE_TRIGGER, false)),
};

View file

@ -0,0 +1,84 @@
#pragma once
#include QMK_KEYBOARD_H
#include "../layers.h"
#include "../utils/deletion.h"
#include "alias.h"
#include "custom_keys.h"
// -------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------
// clang-format off
// NK stands for "new key"
enum custom_keycodes {
// _BASE layer
NK_Q,
NK_R,
// _NUM layer
NK_COLN,
NK_MINS_NUM,
NK_1,
NK_2,
NK_3,
NK_4,
NK_5,
NK_6,
NK_7,
NK_8,
NK_9,
NK_0,
NK_6_LOW,
NK_7_LOW,
NK_8_LOW,
NK_9_LOW,
NK_0_LOW,
// _NAV layer
NK_BSLS, // backslash
NK_LBRC, // [
NK_RBRC, // ]
NK_MINS_NAV, // -
NK_EQL, // =
NK_GRV, // `
NK_PIPE,
NK_LCBR,
NK_RCBR,
NK_UNDS,
NK_PLUS,
NK_F2,
NK_DLR,
NK_HOME,
NK_END,
// multiple layers
NK_CIRC,
NK_AMPR,
NK_ASTR,
NK_RPRN,
NK_ESC,
NK_UP,
NK_DOWN,
NK_BSPC,
// tap-hold
// default function
TH_LAUNCH,
// default keycode
TH_DEL,
TH_RALT,
TH_TILD,
TH_LSFT,
TH_COMM,
TH_COLN,
TH_SPC,
// this is always last
NK_LAST,
};
// clang-format on
// -------------------------------------------------------------------------------------------------
extern custom_key_t custom_keys[];
// -------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,84 @@
#include QMK_KEYBOARD_H
#include "caps_word/caps_word.h"
#include "custom_keys/custom_keys.h"
#include "custom_keys/mapping.h"
#include "layers.h"
#include "tap_dance.c"
#include "taphold/taphold_options.h"
bool NAV_enabled = false;
// clang-format off
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// base
[_BASE] = LAYOUT_ortho_4x12(
NK(NK_ESC), NK(NK_Q), KC_W, KC_E, NK(NK_R), KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, NK(NK_BSPC),
CTL_T(KC_TAB), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
SFT_SFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, ALT_DEL,
KC_RCTL, LT(_FUNC, KC_MPLY), ALT_T(KC_LALT), TD(TD_CAD_LOCK), GUI_LAUNCH, NUM_SPC, NAV_ENT, ALT_COMP, KC_LEFT, NK(NK_DOWN), NK(NK_UP), KC_RGHT
),
// gamer
[_GAME] = LAYOUT_ortho_4x12(
KC_TRNS, KC_Q, KC_TRNS, KC_TRNS, KC_R, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TAB, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_LSFT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_PGDN, KC_PGUP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
),
// special characters
// numbers
[_NUM] = LAYOUT_ortho_4x12(
KC_TRNS, KC_SLSH, KC_AT, KC_ASTR, NK(NK_MINS_NUM), KC_PLUS, NK(NK_CIRC), NK(NK_AMPR), NK(NK_ASTR), KC_LPRN, NK(NK_RPRN), KC_TRNS,
CTL_T(KC_DOT), NK(NK_1), NK(NK_2), NK(NK_3), NK(NK_4), NK(NK_5), NK(NK_6), NK(NK_7), NK(NK_8), NK(NK_9), NK(NK_0), KC_TRNS,
SFT_COMM, NK(NK_6_LOW), NK(NK_7_LOW), NK(NK_8_LOW), NK(NK_9_LOW), NK(NK_0_LOW), KC_SCLN, NK(NK_COLN), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
CTL_COLN, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
),
[_NAV] = LAYOUT_ortho_4x12(
NK(NK_GRV), KC_EXLM, KC_AT, KC_HASH, NK(NK_DLR), KC_PERC, NK(NK_CIRC), NK(NK_AMPR), NK(NK_ASTR), KC_LPRN, NK(NK_RPRN), KC_TRNS,
KC_TRNS, NK(NK_BSLS), NK(NK_LBRC), NK(NK_RBRC), NK(NK_MINS_NAV), NK(NK_EQL), NK(NK_HOME), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, NK(NK_END),
SFT_TILD, NK(NK_PIPE), NK(NK_LCBR), NK(NK_RCBR), NK(NK_UNDS), NK(NK_PLUS), KC_NO, NK(NK_F2), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
),
// function
[_FUNC] = LAYOUT_ortho_4x12(
KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,
KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_TRNS, KC_MUTE, KC_MPRV, KC_VOLD, KC_VOLU, KC_MNXT, KC_NO, KC_NO, KC_NO, QK_AUDIO_OFF, TG(_GAME), QK_BOOT,
KC_TRNS, KC_NO, KC_BRID, KC_BRIU, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, QK_RBT
),
};
// clang-format on
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
// make it possible to go from layer 3 to layer 2
case NUM_SPC:
if (!record->tap.count) {
if (NAV_enabled) {
record->event.pressed ? layer_off(_NAV) : layer_on(_NAV);
}
} else {
process_custom_key(NK(TH_SPC), record);
return false;
}
break;
case NAV_ENT:
if (!record->tap.count) {
NAV_enabled = record->event.pressed;
}
break;
case CUSTOM_KEY_RANGE:
process_custom_key(keycode, record);
return false;
break;
case GUI_LAUNCH:
case ALT_DEL:
case ALT_COMP:
case SFT_TILD:
case SFT_SFT:
case SFT_COMM:
case CTL_COLN:
return process_custom_taphold(keycode, record);
break;
}
return true;
}

View file

@ -0,0 +1,9 @@
#pragma once
enum layers {
_BASE,
_GAME,
_NUM,
_NAV,
_FUNC,
};

View file

@ -0,0 +1,16 @@
SRC += caps_word/caps_word.c
SRC += taphold/taphold_options.c
SRC += utils/mod_suppression.c
SRC += utils/deletion.c
SRC += custom_keys/custom_keys.c
SRC += custom_keys/mapping.c
VIA_ENABLE = yes
LTO_ENABLE = yes
CAPS_WORD_ENABLE = yes
# CONSOLE_ENABLE = yes
TAP_DANCE_ENABLE = yes
SEND_STRING_ENABLE = yes

View file

@ -0,0 +1,20 @@
#include "tap_dance.h"
void on_password_tap(tap_dance_state_t* state, void* user_data) {
switch (state->count) {
case 1:
tap_code16(C(A(KC_DEL)));
break;
case 2:
SEND_STRING("240303");
break;
case 3:
tap_code(KC_ENT);
break;
}
}
tap_dance_action_t tap_dance_actions[] = {
[TD_PASSWORD] = ACTION_TAP_DANCE_FN_ADVANCED(on_password_tap, NULL, NULL),
[TD_CAD_LOCK] = ACTION_TAP_DANCE_DOUBLE(CAD, LOCK),
};

View file

@ -0,0 +1,6 @@
#pragma once
enum {
TD_CAD_LOCK,
TD_PASSWORD,
};

View file

@ -0,0 +1,51 @@
#include "taphold_options.h"
uint16_t get_quick_tap_term(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
case CTL_T(KC_TAB):
case NUM_SPC:
case NAV_ENT:
case GUI_LAUNCH: // no repeat tapping when tapped and then held for these keys
return 0;
break;
default:
return QUICK_TAP_TERM;
break;
}
}
bool get_permissive_hold(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
case NUM_SPC: // permissive hold for layer tap space
return true;
break;
default:
return false;
break;
}
}
bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
case NUM_SPC: // no hold on other key press for layer tap space
return false;
break;
default:
return true;
break;
}
}
uint16_t get_tapping_term(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
case GUI_LAUNCH:
return 500;
break;
case TD(TD_PASSWORD):
return 800;
break;
default:
return TAPPING_TERM;
break;
}
}

View file

@ -0,0 +1,11 @@
#pragma once
#include QMK_KEYBOARD_H
#include "../custom_keys/alias.h"
#include "../custom_keys/mapping.h"
#include "../layers.h"
#include "../tap_dance.h"
uint16_t get_quick_tap_term(uint16_t keycode, keyrecord_t* record);
bool get_permissive_hold(uint16_t keycode, keyrecord_t* record);
bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t* record);
uint16_t get_tapping_term(uint16_t keycode, keyrecord_t* record);

View file

@ -0,0 +1,18 @@
#include "deletion.h"
void obliterate_line(uint8_t deletion_keycode) {
uint8_t movement_keycode;
switch (deletion_keycode) {
case KC_BSPC:
movement_keycode = KC_HOME;
break;
case KC_DEL:
movement_keycode = KC_END;
break;
default: // this should never run
return;
break;
}
tap_code16(S(movement_keycode));
register_code(deletion_keycode);
}

View file

@ -0,0 +1,4 @@
#pragma once
#include QMK_KEYBOARD_H
void obliterate_line(uint8_t deletion_keycode);

View file

@ -0,0 +1,31 @@
#include "mod_suppression.h"
void trigger_dummy_key(uint8_t mods) {
if (mods & MOD_BIT(DUMMY_MOD_NEUTRALIZER_KEYCODE)) {
unregister_mods(MOD_BIT(DUMMY_MOD_NEUTRALIZER_KEYCODE));
register_mods(MOD_BIT(DUMMY_MOD_NEUTRALIZER_KEYCODE));
} else {
tap_code(DUMMY_MOD_NEUTRALIZER_KEYCODE);
}
}
void suppress_flashing_mods(uint8_t mods) {
trigger_dummy_key(mods);
del_mods(MOD_MASK_AG);
}
void neutralize_mods_on_release(void) {
uint8_t mods = get_mods();
if (mods & (MOD_MASK_AG)) {
send_keyboard_report();
trigger_dummy_key(mods);
}
}
// void tap_code16_suppress(uint16_t keycode, uint8_t mods) {
// suppress_flashing_mods(mods);
// tap_code16(keycode);
// set_mods(mods);
// }
// void register_code16_suppress(uint16_t keycode, uint8_t mods) {
// suppress_flashing_mods(mods);
// register_code16(keycode);
// set_mods(mods);
// }

View file

@ -0,0 +1,8 @@
#pragma once
#include QMK_KEYBOARD_H
void trigger_dummy_key(uint8_t mods);
void suppress_flashing_mods(uint8_t mods);
void neutralize_mods_on_release(void);
void tap_code16_suppress(uint16_t keycode, uint8_t mods);
void register_code16_suppress(uint16_t keycode, uint8_t mods);

View file

@ -1,4 +1,7 @@
{
"userspace_version": "1.0",
"build_targets": []
"userspace_version": "1.1",
"build_targets": [
["keebio/nyquist/rev4", "drew"],
["planck/rev7", "drew"]
]
}