From 7749a73fe462f23c55e9f68f4359f25f8b7fef9b Mon Sep 17 00:00:00 2001 From: Sadek Baroudi Date: Tue, 8 Jun 2021 15:19:37 -0700 Subject: [PATCH] renabled macros and added casemodes, which includes capsword, very cool --- .../pteron38/keymaps/sadekbaroudi/keymap.c | 4 +- users/sadekbaroudi/casemodes.c | 263 ++++++++++++++++++ users/sadekbaroudi/casemodes.h | 47 ++++ users/sadekbaroudi/process_records.c | 211 +++++++------- users/sadekbaroudi/process_records.h | 23 +- users/sadekbaroudi/rules.mk | 9 +- users/sadekbaroudi/wrappers.h | 18 +- 7 files changed, 452 insertions(+), 123 deletions(-) create mode 100755 users/sadekbaroudi/casemodes.c create mode 100755 users/sadekbaroudi/casemodes.h diff --git a/keyboards/handwired/pteron38/keymaps/sadekbaroudi/keymap.c b/keyboards/handwired/pteron38/keymaps/sadekbaroudi/keymap.c index 57cc5ecf96..33ce95b7b4 100644 --- a/keyboards/handwired/pteron38/keymaps/sadekbaroudi/keymap.c +++ b/keyboards/handwired/pteron38/keymaps/sadekbaroudi/keymap.c @@ -39,8 +39,8 @@ LAYOUT_wrapper( \ K01, K02, K03, K04, K05, K06, K07, LT(_WINNAV,K08), K09, K0A, \ LCTL_T(K11), LGUI_T(K12), LALT_T(K13), LSFT_T(K14), K15, K16, RSFT_T(K17), RALT_T(K18), RGUI_T(K19), RCTL_T(K1A), \ - LSFT_T(K21), K22, K23, K24, K25, K26, K27, K28, K29, RSFT_T(K2A), \ - KC_DEL, LT(_NAVIGATION,KC_ENT), LT(_FUNCTION,KC_TAB), _______, _______, LT(_FUNCTION,KC_BSPC), LT(_SYMBOLS,KC_SPACE), LT(_MOUSE,KC_QUOT) \ + K21, K22, K23, K24, K25, K26, K27, K28, K29, LT(_MOUSE,K2A), \ + KC_DEL, LT(_NAVIGATION,KC_ENT), LT(_FUNCTION,KC_TAB), _______, _______, LT(_FUNCTION,KC_BSPC), LT(_SYMBOLS,KC_SPACE), KC_QUOT \ ) /* Re-pass though to allow templates to be used */ diff --git a/users/sadekbaroudi/casemodes.c b/users/sadekbaroudi/casemodes.c new file mode 100755 index 0000000000..937b9669d0 --- /dev/null +++ b/users/sadekbaroudi/casemodes.c @@ -0,0 +1,263 @@ +/* Copyright 2021 Andrew Rae ajrae.nv@gmail.com @andrewjrae + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "casemodes.h" + +/* The caps word concept started with me @iaap on splitkb.com discord. + * However it has been implemented and extended by many splitkb.com users: + * - @theol0403 made many improvements to initial implementation + * - @precondition used caps lock rather than shifting + * - @dnaq his own implementation which also used caps lock + * - @sevanteri added underscores on spaces + * - @metheon extended on @sevanteri's work and added specific modes for + * snake_case and SCREAMING_SNAKE_CASE + * - @baffalop came up with the idea for xcase, which he implements in his own + * repo, however this is implemented by @iaap with support also for one-shot-shift. + * - @sevanteri + * - fixed xcase waiting mode to allow more modified keys and keys from other layers. + * - Added @baffalop's separator defaulting on first keypress, with a + * configurable default separator and overrideable function to determine + * if the default should be used. + */ + + +#ifndef DEFAULT_XCASE_SEPARATOR +#define DEFAULT_XCASE_SEPARATOR KC_UNDS +#endif + +#define IS_OSM(keycode) (keycode >= QK_ONE_SHOT_MOD && keycode <= QK_ONE_SHOT_MOD_MAX) + +// bool to keep track of the caps word state +static bool caps_word_on = false; + +// enum to keep track of the xcase state +static enum xcase_state xcase_state = XCASE_OFF; +// the keycode of the xcase delimiter +static uint16_t xcase_delimiter; +// the number of keys to the last delimiter +static int8_t distance_to_last_delim = -1; + +// Check whether caps word is on +bool caps_word_enabled(void) { + return caps_word_on; +} + +// Enable caps word +void enable_caps_word(void) { + caps_word_on = true; +#ifndef CAPSWORD_USE_SHIFT + if (!host_keyboard_led_state().caps_lock) { + tap_code(KC_CAPS); + } +#endif +} + +// Disable caps word +void disable_caps_word(void) { + caps_word_on = false; +#ifndef CAPSWORD_USE_SHIFT + if (host_keyboard_led_state().caps_lock) { + tap_code(KC_CAPS); + } +#else + unregister_mods(MOD_LSFT); +#endif +} + +// Toggle caps word +void toggle_caps_word(void) { + if (caps_word_on) { + disable_caps_word(); + } + else { + enable_caps_word(); + } +} + +// Get xcase state +enum xcase_state get_xcase_state(void) { + return xcase_state; +} + +// Enable xcase and pickup the next keystroke as the delimiter +void enable_xcase(void) { + xcase_state = XCASE_WAIT; +} + +// Enable xcase with the specified delimiter +void enable_xcase_with(uint16_t delimiter) { + xcase_state = XCASE_ON; + xcase_delimiter = delimiter; + distance_to_last_delim = -1; +} + +// Disable xcase +void disable_xcase(void) { + xcase_state = XCASE_OFF; +} + +// Place the current xcase delimiter +static void place_delimiter(void) { + if (IS_OSM(xcase_delimiter)) { + // apparently set_oneshot_mods() is dumb and doesn't deal with handedness for you + uint8_t mods = xcase_delimiter & 0x10 ? (xcase_delimiter & 0x0F) << 4 : xcase_delimiter & 0xFF; + set_oneshot_mods(mods); + } else { + tap_code16(xcase_delimiter); + } +} + +// Removes a delimiter, used for double tap space exit +static void remove_delimiter(void) { + if (IS_OSM(xcase_delimiter)) { + clear_oneshot_mods(); + } else { + tap_code(KC_BSPC); + } +} + +// overrideable function to determine whether the case mode should stop +__attribute__ ((weak)) +bool terminate_case_modes(uint16_t keycode, const keyrecord_t *record) { + switch (keycode) { + // Keycodes to ignore (don't disable caps word) + case KC_A ... KC_Z: + case KC_1 ... KC_0: + case KC_MINS: + case KC_UNDS: + case KC_BSPC: + // If mod chording disable the mods + if (record->event.pressed && (get_mods() != 0)) { + return true; + } + break; + default: + if (record->event.pressed) { + return true; + } + break; + } + return false; +} + +/* overrideable function to determine whether to use the default separator on + * first keypress when waiting for the separator. */ +__attribute__ ((weak)) +bool use_default_xcase_separator(uint16_t keycode, const keyrecord_t *record) { + // for example: + /* switch (keycode) { */ + /* case KC_A ... KC_Z: */ + /* case KC_1 ... KC_0: */ + /* return true; */ + /* } */ + return false; +} + +bool process_case_modes(uint16_t keycode, const keyrecord_t *record) { + if (caps_word_on || xcase_state) { + if ((QK_MOD_TAP <= keycode && keycode <= QK_MOD_TAP_MAX) + || (QK_LAYER_TAP <= keycode && keycode <= QK_LAYER_TAP_MAX)) { + // Earlier return if this has not been considered tapped yet + if (record->tap.count == 0) + return true; + keycode = keycode & 0xFF; + } + + if (keycode >= QK_LAYER_TAP && keycode <= QK_ONE_SHOT_LAYER_MAX) { + // let special keys and normal modifiers go through + return true; + } + + if (xcase_state == XCASE_WAIT) { + // grab the next input to be the delimiter + if (use_default_xcase_separator(keycode, record)) { + enable_xcase_with(DEFAULT_XCASE_SEPARATOR); + } + else if (record->event.pressed) { + // factor in mods + if (get_mods() & MOD_MASK_SHIFT) { + keycode = LSFT(keycode); + } + else if (get_mods() & MOD_BIT(KC_RALT)) { + keycode = RALT(keycode); + } + enable_xcase_with(keycode); + return false; + } + else { + if (IS_OSM(keycode)) { + // this catches the OSM release if no other key was pressed + set_oneshot_mods(0); + enable_xcase_with(keycode); + return false; + } + // let other special keys go through + return true; + } + } + + if (record->event.pressed) { + // handle xcase mode + if (xcase_state == XCASE_ON) { + // place the delimiter if space is tapped + if (keycode == KC_SPACE) { + if (distance_to_last_delim != 0) { + place_delimiter(); + distance_to_last_delim = 0; + return false; + } + // remove the delimiter and disable modes + else { + remove_delimiter(); + disable_xcase(); + disable_caps_word(); + return true; + } + } + // decrement distance to delimiter on back space + else if (keycode == KC_BSPC) { + --distance_to_last_delim; + } + // don't increment distance to last delim if negative + else if (distance_to_last_delim >= 0) { + // puts back a one shot delimiter if you we're back to the delimiter pos + if (distance_to_last_delim == 0 && (IS_OSM(xcase_delimiter))) { + place_delimiter(); + } + ++distance_to_last_delim; + } + + } // end XCASE_ON + + // check if the case modes have been terminated + if (terminate_case_modes(keycode, record)) { + disable_caps_word(); + disable_xcase(); + } + +#ifdef CAPSWORD_USE_SHIFT + else if (keycode >= KC_A && keycode <= KC_Z){ + tap_code16(LSFT(keycode)); + return false; + } +#endif + + } // end if event.pressed + + return true; + } + return true; +} diff --git a/users/sadekbaroudi/casemodes.h b/users/sadekbaroudi/casemodes.h new file mode 100755 index 0000000000..4a8c00b3d2 --- /dev/null +++ b/users/sadekbaroudi/casemodes.h @@ -0,0 +1,47 @@ +/* Copyright 2021 Andrew Rae ajrae.nv@gmail.com @andrewjrae + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include QMK_KEYBOARD_H + +// Check whether caps word is on +bool caps_word_enabled(void); +// Enable caps word +void enable_caps_word(void); +// Disable caps word +void disable_caps_word(void); +// Toggle caps word +void toggle_caps_word(void); + +// enum for the xcase states +enum xcase_state { + XCASE_OFF = 0, // xcase is off + XCASE_ON, // xcase is actively on + XCASE_WAIT, // xcase is waiting for the delimiter input +}; + +// Get xcase state +enum xcase_state get_xcase_state(void); +// Enable xcase and pickup the next keystroke as the delimiter +void enable_xcase(void); +// Enable xcase with the specified delimiter +void enable_xcase_with(uint16_t delimiter); +// Disable xcase +void disable_xcase(void); + +// Function to be put in process user +bool process_case_modes(uint16_t keycode, const keyrecord_t *record); diff --git a/users/sadekbaroudi/process_records.c b/users/sadekbaroudi/process_records.c index af4f3f4cf6..8932e16bd3 100755 --- a/users/sadekbaroudi/process_records.c +++ b/users/sadekbaroudi/process_records.c @@ -1,4 +1,5 @@ #include "sadekbaroudi.h" +#include "casemodes.h" #if defined(RGBLIGHT_ENABLE) #include "rgb_stuff.h" #endif @@ -10,6 +11,10 @@ __attribute__((weak)) bool process_record_secrets(uint16_t keycode, keyrecord_t // Defines actions tor my global custom keycodes. Defined in sadekbaroudi.h file // Then runs the _keymap's record handler if not processed here bool process_record_user(uint16_t keycode, keyrecord_t *record) { + // Process case modes + if (!process_case_modes(keycode, record)) { + return false; + } // If console is enabled, it will print the matrix position and status of each key pressed #ifdef KEYLOGGER_ENABLE # if defined(KEYBOARD_ergodox_ez) || defined(KEYBOARD_keebio_iris_rev2) @@ -40,43 +45,43 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { } } break; - // UNCOMMENT TO REENABLE MACROS -// case KC_MAKE: // Compiles the firmware, and adds the flash command based on keyboard bootloader -// if (!record->event.pressed) { -// #ifndef MAKE_BOOTLOADER -// uint8_t temp_mod = mod_config(get_mods()); -// uint8_t temp_osm = mod_config(get_oneshot_mods()); -// clear_mods(); -// clear_oneshot_mods(); -// #endif -// send_string_with_delay_P(PSTR("qmk"), TAP_CODE_DELAY); -// #ifndef MAKE_BOOTLOADER -// if ((temp_mod | temp_osm) & MOD_MASK_SHIFT) -// #endif -// { -// send_string_with_delay_P(PSTR(" flash "), TAP_CODE_DELAY); -// #ifndef MAKE_BOOTLOADER -// } else { -// send_string_with_delay_P(PSTR(" compile "), TAP_CODE_DELAY); -// #endif -// } -// send_string_with_delay_P(PSTR("-kb " QMK_KEYBOARD " -km " QMK_KEYMAP), TAP_CODE_DELAY); -// #ifdef RGB_MATRIX_SPLIT_RIGHT -// send_string_with_delay_P(PSTR(" RGB_MATRIX_SPLIT_RIGHT=yes"), TAP_CODE_DELAY); -// # ifndef OLED_DRIVER_ENABLE -// send_string_with_delay_P(PSTR(" OLED_DRIVER_ENABLE=no"), TAP_CODE_DELAY); -// # endif -// #endif -// send_string_with_delay_P(PSTR(SS_TAP(X_ENTER)), TAP_CODE_DELAY); -// } + // COMMENT TO DISABLE MACROS + case KC_MAKE: // Compiles the firmware, and adds the flash command based on keyboard bootloader + if (!record->event.pressed) { +#ifndef MAKE_BOOTLOADER + uint8_t temp_mod = mod_config(get_mods()); + uint8_t temp_osm = mod_config(get_oneshot_mods()); + clear_mods(); + clear_oneshot_mods(); +#endif + send_string_with_delay_P(PSTR("qmk"), TAP_CODE_DELAY); +#ifndef MAKE_BOOTLOADER + if ((temp_mod | temp_osm) & MOD_MASK_SHIFT) +#endif + { + send_string_with_delay_P(PSTR(" flash "), TAP_CODE_DELAY); +#ifndef MAKE_BOOTLOADER + } else { + send_string_with_delay_P(PSTR(" compile "), TAP_CODE_DELAY); +#endif + } + send_string_with_delay_P(PSTR("-kb " QMK_KEYBOARD " -km " QMK_KEYMAP), TAP_CODE_DELAY); +#ifdef RGB_MATRIX_SPLIT_RIGHT + send_string_with_delay_P(PSTR(" RGB_MATRIX_SPLIT_RIGHT=yes"), TAP_CODE_DELAY); +# ifndef OLED_DRIVER_ENABLE + send_string_with_delay_P(PSTR(" OLED_DRIVER_ENABLE=no"), TAP_CODE_DELAY); +# endif +#endif + send_string_with_delay_P(PSTR(SS_TAP(X_ENTER)), TAP_CODE_DELAY); + } -// break; - -// case VRSN: // Prints firmware version -// if (record->event.pressed) { -// send_string_with_delay_P(PSTR(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION ", Built on: " QMK_BUILDDATE), TAP_CODE_DELAY); -// } -// break; + break; + // COMMENT TO DISABLE MACROS + case VRSN: // Prints firmware version + if (record->event.pressed) { + send_string_with_delay_P(PSTR(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION ", Built on: " QMK_BUILDDATE), TAP_CODE_DELAY); + } + break; case KC_RGB_T: // This allows me to use underglow as layer indication, or as normal #if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE) @@ -174,70 +179,76 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { } break; #endif - // UNCOMMENT TO REENABLE MACROS - // case L_GREP: - // if (record->event.pressed) { - // SEND_STRING("grep -rn \""); - // } else { - // // when keycode is released - // } - // break; - // case L_FIND: - // if (record->event.pressed) { - // SEND_STRING("find . -name \""); - // } else { - // // when keycode is released - // } - // break; - // case L_GITCOMMIT: - // if (record->event.pressed) { - // SEND_STRING("git commit -a -m \"\""SS_TAP(X_LEFT)); - // } else { - // // when keycode is released - // } - // break; - // case P_ANGBRKT: - // if (record->event.pressed) { - // SEND_STRING("<>"SS_TAP(X_LEFT)); - // } else { - // // when keycode is released - // } - // break; - // case P_PAREN: - // if (record->event.pressed) { - // SEND_STRING("()"SS_TAP(X_LEFT)); - // } else { - // // when keycode is released - // } - // break; - // case P_CURLY: - // if (record->event.pressed) { - // SEND_STRING("{}"SS_TAP(X_LEFT)); - // } else { - // // when keycode is released - // } - // break; - // case P_BRKT: - // if (record->event.pressed) { - // SEND_STRING("[]"SS_TAP(X_LEFT)); - // } else { - // // when keycode is released - // } - // break; - // case E_ROBOT: - // if (record->event.pressed) { - // SEND_STRING("d[o_0]b"); - // } else { - // // when keycode is released - // } - // break; - // case E_CAT: - // if (record->event.pressed) { - // SEND_STRING("=^..^="); - // } else { - // // when keycode is released - // } - // break; + case CAPSWORD: + if (record->event.pressed) { + enable_caps_word(); + } + break; + // COMMENT TO DISABLE MACROS + case L_GREP: + if (record->event.pressed) { + SEND_STRING("grep -rn \""); + } else { + // when keycode is released + } + break; + case L_FIND: + if (record->event.pressed) { + SEND_STRING("find . -name \""); + } else { + // when keycode is released + } + break; + case L_GITCOMMIT: + if (record->event.pressed) { + SEND_STRING("git commit -a -m \"\""SS_TAP(X_LEFT)); + } else { + // when keycode is released + } + break; + case P_ANGBRKT: + if (record->event.pressed) { + SEND_STRING("<>"SS_TAP(X_LEFT)); + } else { + // when keycode is released + } + break; + case P_PAREN: + if (record->event.pressed) { + SEND_STRING("()"SS_TAP(X_LEFT)); + } else { + // when keycode is released + } + break; + case P_CURLY: + if (record->event.pressed) { + SEND_STRING("{}"SS_TAP(X_LEFT)); + } else { + // when keycode is released + } + break; + case P_BRKT: + if (record->event.pressed) { + SEND_STRING("[]"SS_TAP(X_LEFT)); + } else { + // when keycode is released + } + break; + case E_ROBOT: + if (record->event.pressed) { + SEND_STRING("d[o_0]b"); + } else { + // when keycode is released + } + break; + case E_CAT: + if (record->event.pressed) { + SEND_STRING("=^..^="); + } else { + // when keycode is released + } + break; + // COMMENT TO DISABLE MACROS } return true; } diff --git a/users/sadekbaroudi/process_records.h b/users/sadekbaroudi/process_records.h index 4614077c99..a9a9762ea7 100755 --- a/users/sadekbaroudi/process_records.h +++ b/users/sadekbaroudi/process_records.h @@ -12,17 +12,18 @@ enum userspace_custom_keycodes { KC_RGB_T, // Toggles RGB Layer Indication mode KC_RGB_BLT, // Toggles RGB Base Layer Override mode RGB_IDL, // RGB Idling animations - // UNCOMMENT TO REENABLE MACROS - // KC_MAKE, // Run keyboard's customized make command - // L_GREP, - // L_FIND, - // L_GITCOMMIT, - // P_ANGBRKT, - // P_PAREN, - // P_CURLY, - // P_BRKT, - // E_ROBOT, - // E_CAT, + // COMMENT TO DISABLE MACROS + KC_MAKE, // Run keyboard's customized make command + L_GREP, + L_FIND, + L_GITCOMMIT, + P_ANGBRKT, + P_PAREN, + P_CURLY, + P_BRKT, + E_ROBOT, + E_CAT, + CAPSWORD, NEW_SAFE_RANGE // use "NEWPLACEHOLDER for keymap specific codes }; diff --git a/users/sadekbaroudi/rules.mk b/users/sadekbaroudi/rules.mk index 190be86541..658d531089 100755 --- a/users/sadekbaroudi/rules.mk +++ b/users/sadekbaroudi/rules.mk @@ -9,8 +9,11 @@ MOUSEKEY_ENABLE = yes BACKLIGHT_ENABLE = no NKRO_ENABLE = no RAW_ENABLE = yes +CASEMODES_ENABLE = yes -EXTRAFLAGS += -flto +# UNCOMMENT TO DISABLE MACROS +# EXTRAFLAGS += -flto +# UNCOMMENT TO DISABLE MACROS SPACE_CADET_ENABLE = no GRAVE_ESC_ENABLE = no @@ -46,3 +49,7 @@ endif ifeq ($(strip $(RAW_ENABLE)), yes) SRC += hid.c endif + +ifeq ($(strip $(CASEMODES_ENABLE)), yes) + SRC += casemodes.c +endif diff --git a/users/sadekbaroudi/wrappers.h b/users/sadekbaroudi/wrappers.h index 760accbf5b..a412df26cb 100755 --- a/users/sadekbaroudi/wrappers.h +++ b/users/sadekbaroudi/wrappers.h @@ -72,7 +72,7 @@ NOTE: These are all the same length. If you do a search/replace #define _________________META_NAV_1________________ KC_ESC, KC_PGUP, KC_UP, KC_PGDN, _______ #define _________________META_NAV_2________________ KC_HOME, KC_LEFT, KC_DOWN, KC_RGHT, KC_END -#define _________________META_NAV_L1_______________ KC_CAPS, KC_GRV, LCTL(LSFT(KC_TAB)), LCTL(LGUI(KC_LEFT)), _______ +#define _________________META_NAV_L1_______________ KC_CAPS, KC_GRV, LCTL(LSFT(KC_TAB)), LCTL(LGUI(KC_LEFT)), CAPSWORD #define _________________META_NAV_R1_______________ _______, LCTL(LGUI(KC_RIGHT)), LCTL(KC_TAB), _______, KC_BSLS #define __________________WIN_NAV_1________________ _______, _______, LGUI(KC_UP), _______, _______ @@ -145,14 +145,14 @@ NOTE: These are all the same length. If you do a search/replace #define __________________MOUSE_3__________________ KC_MS_ACCEL0, KC_MS_ACCEL1, KC_MS_ACCEL2, _______, _______ -// COMMENT TO REENABLE MACROS -#define _________________MACROS_1__________________ ___________________BLANK___________________ -#define _________________MACROS_2__________________ ___________________BLANK___________________ -#define _________________MACROS_3__________________ ___________________BLANK___________________ +// // UNCOMMENT TO DISABLE MACROS +// #define _________________MACROS_1__________________ ___________________BLANK___________________ +// #define _________________MACROS_2__________________ ___________________BLANK___________________ +// #define _________________MACROS_3__________________ ___________________BLANK___________________ -// UNCOMMENT TO REENABLE MACROS -// #define _________________MACROS_1__________________ VRSN, L_FIND, L_GITCOMMIT, _______, E_ROBOT -// #define _________________MACROS_2__________________ P_ANGBRKT, P_PAREN, P_CURLY, P_BRKT, _______ -// #define _________________MACROS_3__________________ KC_MAKE, L_GREP, _______, _______, E_CAT +// COMMENT TO DISABLE MACROS +#define _________________MACROS_1__________________ VRSN, L_FIND, L_GITCOMMIT, _______, E_ROBOT +#define _________________MACROS_2__________________ P_ANGBRKT, P_PAREN, P_CURLY, P_BRKT, _______ +#define _________________MACROS_3__________________ KC_MAKE, L_GREP, _______, _______, E_CAT // clang-format on