// Copyright 2022 Artjoms Rizihs (@artjomsR) // SPDX-License-Identifier: GPL-2.0-or-later #include "art.h" #include "custom_definitions.h" #include "secr.h" #include "funcs/led_funcs.h" #include "funcs/string_funcs.h" static const int COPY_DELAY = 50; static const int INCOGNITO_DELAY = 500; static const int LMB_SPAM_INTERVAL = 30; static const uint8_t OS_MOD_KEYS[2] = {MOD_LALT, MOD_LCTL}; bool mac_ctrl_on = false; //for switching tabs bool mac_gui_on = false; //for switching languages bool mac_alt_window_switching_on = false; //for switching windows int char_to_bspace = 1; int char_to_del = 0; static bool sarcasm_on = false; static bool sarcasm_key = false; static bool full_caps_mode = false; bool hw_caps_on; static bool is_lmb_timer_active = false; static uint16_t lmb_timer = 0; __attribute__ ((weak)) bool process_record_keymap(uint16_t keycode, keyrecord_t *record) { return true; } void keyboard_post_init_user(void) { led_show_variable_status(is_win); layer_state_set_user(layer_state); } void matrix_scan_user(void) { if (is_lmb_timer_active) { if (timer_elapsed(lmb_timer) > LMB_SPAM_INTERVAL) { SEND_STRING(SS_TAP(X_BTN1)); //do stuff that needs spamming lmb_timer = timer_read(); } } } bool caps_word_on(void) { return hw_caps_on && !full_caps_mode; } bool process_record_user(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { if (sarcasm_on) { sarcasm_key = ! sarcasm_key; del_mods(MOD_LSFT); if (sarcasm_key) { add_mods(MOD_LSFT); } } //Checking all other non-backspace keys to clear the backspace buffer. This is to prevent the bug of deleting N chars sometime after using a macro switch (keycode) { case LT(COMBOS,KC_BSPC): case KC_BACKSPACE: case KC_DEL: case KC_LSFT: case KC_RSFT: case XXXXXXX: break; default: char_to_bspace = 1; char_to_del = 0; break; } } switch (keycode) { case XXXXXXX: if (record->event.pressed && !layer_state_is(BASE)) { blink_leds(NUM_SCROLL_LED_ON); return true; } break; case KC_TAB: if (record->event.pressed && is_mac_with_base_layer_off()) { uint8_t mod_state = get_mods() & MOD_MASK_CTRL; if (get_mods() & mod_state && !mac_alt_window_switching_on) { del_mods(mod_state); add_mods(MOD_LGUI); mac_ctrl_on = true; } } case KC_GRAVE: if (record->event.pressed && is_mac_with_base_layer_off()) { uint8_t mod_state = get_mods() & MOD_MASK_ALT; if (get_mods() & mod_state) { del_mods(mod_state); add_mods(MOD_LCTL); mac_alt_window_switching_on = true; } } break; case KC_LSFT: if (record->event.pressed && is_mac_with_base_layer_off() && !mac_ctrl_on) { uint8_t mod_state = get_mods() & MOD_MASK_AG; if (get_mods() & mod_state) { del_mods(mod_state); add_mods(MOD_LGUI); mac_gui_on = true; send_string(lang_switch_combo); return false; } else { return true; } } break; case KC_LEFT: case KC_RIGHT: if (record->event.pressed && is_mac_with_base_layer_off()) { /* && !mac_ctrl_on/!mac_alt_tab_on are required since setting the state while holding the key changes the modifier from OS's perspective. As a result, just the pressed key cannot be the single source of truth to determine which state we're in, and a separate bool is required */ uint8_t alt_state = get_mods() & MOD_MASK_ALT; uint8_t ctrl_state = get_mods() & MOD_MASK_CTRL; //Allows Ctrl <-/-> on Mac if Ctrl Tab is already pressed if (get_mods() & alt_state && mac_alt_window_switching_on && !mac_ctrl_on) { del_mods(alt_state); add_mods(MOD_LCTL); } if (get_mods() & ctrl_state && !mac_alt_window_switching_on && !mac_gui_on) { del_mods(ctrl_state); add_mods(MOD_LALT); mac_ctrl_on = true; } } break; case KC_LALT: if (!record->event.pressed && is_mac_with_base_layer_off()) { if (mac_alt_window_switching_on) { unregister_mods(MOD_LCTL); mac_alt_window_switching_on = false; return false; } else if (mac_gui_on) { unregister_mods(MOD_LGUI); mac_gui_on = false; return false; } return true; } break; case KC_RALT: if (!record->event.pressed && mac_alt_window_switching_on && is_mac_with_base_layer_off()) { unregister_mods(MOD_LCTL); mac_alt_window_switching_on = false; return false; } break; case KC_LCTL: case KC_RCTL: if (!record->event.pressed && mac_ctrl_on && is_mac_with_base_layer_off()) { // Need to remove only previously set mods (e.g. WIN & ALT) to preserve Shift, etc unregister_mods(MOD_LGUI); unregister_mods(MOD_LALT); mac_ctrl_on = false; return false; } break; case KC_HOME: if (record->event.pressed && is_mac_with_base_layer_off()) { SEND_STRING(SS_LCTL(SS_TAP(X_LEFT))); return false; } break; case KC_END: if (record->event.pressed && is_mac_with_base_layer_off()) { SEND_STRING(SS_LCTL(SS_TAP(X_RIGHT))); return false; } break; case KC_DEL: case KC_BSPC: if (record->event.pressed) { return handle_del_bspace(); } break; case LT(COMBOS, KC_BSPC): if (record->event.pressed && record->tap.count == 1) { return handle_del_bspace(); } break; case LT(NAV,KC_APP): if (!record->event.pressed && !is_win) { mac_ctrl_on = false; mac_gui_on = false; mac_alt_window_switching_on = false; clear_mods(); SEND_STRING(SS_TAP(X_LCTL) SS_TAP(X_LGUI) SS_TAP(X_LALT) SS_TAP(X_LSFT)); return true; } break; /* ------------------------------------------------------------------------- * CAPS WORD * ------------------------------------------------------------------------ */ case KC_CAPS: if (record->event.pressed && !layer_state_is(BASE)) { if (get_mods() & MOD_MASK_SHIFT) { full_caps_mode = true; led_show_variable_status(full_caps_mode); if (hw_caps_on) { SEND_STRING(SS_TAP(X_CAPS)); } } else if (hw_caps_on) { full_caps_mode = false; } } break; // case KC_SPACE: case LT(MEDIA,KC_SPC): case LT(NAV,KC_SPC): if (record->event.pressed && caps_word_on() && !layer_state_is(BASE) && record->tap.count == 1) { SEND_STRING(SS_TAP(X_CAPS)); } break; case KC_MINS: if (record->event.pressed && caps_word_on() && !layer_state_is(BASE)) { SEND_STRING("_"); return false; } break; /* ------------------------------------------------------------------------- * CUSTOM MACROS * ------------------------------------------------------------------------ */ case CTRL_CTV: if (record->event.pressed) { bool shifted = get_mods() & MOD_MASK_SHIFT; clear_mods(); SEND_STRING(SS_LCTL("c")); wait_ms(COPY_DELAY); SEND_STRING(SS_LCTL("tv")); if (!shifted) { SEND_STRING(SS_TAP(X_ENTER)); } } break; case BEAT_BROWSER: if (record->event.pressed) { SEND_STRING(SS_LCTL("c")); wait_ms(COPY_DELAY); SEND_STRING(SS_LGUI("1") SS_LCTL("tv") SS_TAP(X_ENTER)); } break; case CTRL_LCTV: if (record->event.pressed) { if (get_mods() & MOD_MASK_SHIFT) { //Firefox clear_mods(); SEND_STRING(SS_LCTL("lc")); wait_ms(COPY_DELAY); SEND_STRING(SS_LCTL("P")); wait_ms(INCOGNITO_DELAY); SEND_STRING(SS_LCTL("v") SS_TAP(X_ENTER)); } else if (get_mods() & MOD_MASK_CTRL) { //Chrome clear_mods(); SEND_STRING(SS_LCTL("lc")); wait_ms(COPY_DELAY); SEND_STRING(SS_LCTL("Nv") SS_TAP(X_ENTER)); } else { SEND_STRING(SS_LCTL("lc")); wait_ms(COPY_DELAY); SEND_STRING(SS_LCTL("tv")); } } break; case CTRL_CAV: if (record->event.pressed) { SEND_STRING(SS_LCTL("c" SS_TAP(X_TAB))); wait_ms(COPY_DELAY); SEND_STRING(SS_LCTL("av")); } break; case NEUTRAL_COPY: if (record->event.pressed && is_win) { uint8_t shifted = get_mods() & MOD_MASK_SHIFT; if (shifted) { del_mods(shifted); SEND_STRING(SS_LCTL("z")); } SEND_STRING(SS_LCTL("c")); wait_ms(COPY_DELAY); SEND_STRING(SS_LGUI("r") SS_LCTL("vac") SS_TAP(X_ESC)); } break; case SARCASM: if (record->event.pressed) { del_mods(MOD_LSFT); sarcasm_on = !sarcasm_on; led_show_variable_status(sarcasm_on); } break; case LMB_SPAM: if (record->event.pressed) { is_lmb_timer_active = ! is_lmb_timer_active; lmb_timer = timer_read(); } break; /* ------------------------------------------------------------------------- * OS TOGGLING * ------------------------------------------------------------------------ */ case TOG_OS: if (record->event.pressed) { is_win = ! is_win; led_show_variable_status(is_win); } break; case CTR_ALT: if (record->event.pressed) { add_mods(OS_MOD_KEYS[is_win]); } else { unregister_mods(OS_MOD_KEYS[is_win]); } break; case CTR_ALT_SHIFT: if (record->event.pressed) { add_mods(OS_MOD_KEYS[is_win]); add_mods(MOD_RSFT); } else { unregister_mods(OS_MOD_KEYS[is_win]); unregister_mods(MOD_RSFT); } break; case OS_CTRL: if (is_win) { if (record->event.pressed) { SEND_STRING(SS_DOWN(X_LCTL)); } else { SEND_STRING(SS_UP(X_LCTL)); } } else { if (record->event.pressed) { SEND_STRING(SS_DOWN(X_LGUI)); } else { SEND_STRING(SS_UP(X_LGUI)); } } break; case OS_WIN: if (is_win) { if (record->event.pressed) { SEND_STRING(SS_DOWN(X_LGUI)); } else { SEND_STRING(SS_UP(X_LGUI)); } } else { if (record->event.pressed) { SEND_STRING(SS_DOWN(X_LCTL)); } else { SEND_STRING(SS_UP(X_LCTL)); } } break; /* ------------------------------------------------------------------------- * STRING MACROS * ------------------------------------------------------------------------ */ // case : // if (record->event.pressed) { // send_string_remembering_length(""); // } // break; // case : // if (record->event.pressed) { // send_shifted_strings("", ""); // } // break; case TILD_BLOCK: if (record->event.pressed) { uint8_t alted = get_mods() & MOD_MASK_ALT; uint8_t switch_lang_state = get_mods() & MOD_MASK_CTRL; if (switch_lang_state) { del_mods(switch_lang_state); switch_lang(); } if (alted) { del_mods(alted); SEND_STRING(SS_TAP(X_ESC) "```" SS_LSFT(SS_TAP(X_ENTER) SS_TAP(X_ENTER)) "```" SS_TAP(X_UP)); char_to_bspace = 4; char_to_del = 4; } else { SEND_STRING("`` "); uint8_t shifted = get_mods() & MOD_MASK_SHIFT; del_mods(shifted); SEND_STRING(SS_TAP(X_LEFT) SS_TAP(X_LEFT)); add_mods(shifted); char_to_bspace = 1; char_to_del = 2; } if (switch_lang_state) { switch_lang(); } } break; case ALL_BEST: if (record->event.pressed) { send_shifted_strings_add("All the best,\nArt", "joms"); } break; case AT_EMAIL: if (record->event.pressed) { send_string_remembering_length("@gmail.com"); } break; case BRACES: if (record->event.pressed) { uint8_t shifted = get_mods() & MOD_MASK_SHIFT; uint8_t switch_lang_state = get_mods() & MOD_MASK_CTRL; if (switch_lang_state) { del_mods(switch_lang_state); switch_lang(); } add_mods(shifted); SEND_STRING("[]"); del_mods(shifted); SEND_STRING(SS_TAP(X_LEFT)); add_mods(shifted); if (switch_lang_state) { switch_lang(); } char_to_bspace = 1; char_to_del = 1; } break; case DASHES: if (record->event.pressed) { SEND_STRING("--"); uint8_t shifted = get_mods() & MOD_MASK_SHIFT; del_mods(shifted); SEND_STRING(" " SS_TAP(X_LEFT) SS_TAP(X_LEFT)); add_mods(shifted); char_to_bspace = 1; char_to_del = 2; } break; case PARENTHS: if (record->event.pressed) { clear_mods(); SEND_STRING("() " SS_TAP(X_LEFT) SS_TAP(X_LEFT)); char_to_bspace = 1; char_to_del = 2; } break; case QUOTES: if (record->event.pressed) { uint8_t shifted = get_mods() & MOD_MASK_SHIFT; uint8_t switch_lang_state = get_mods() & MOD_MASK_CTRL; if (switch_lang_state) { del_mods(switch_lang_state); switch_lang(); } add_mods(shifted); SEND_STRING("''"); del_mods(shifted); wait_ms(LONG_TYPING_INTERVAL); SEND_STRING(" " SS_TAP(X_LEFT) SS_TAP(X_LEFT)); add_mods(shifted); if (switch_lang_state) { switch_lang(); } char_to_bspace = 1; char_to_del = 2; } break; case QUOTES_RU: if (record->event.pressed) { clear_mods(); SEND_STRING("@@ "); wait_ms(LONG_TYPING_INTERVAL); SEND_STRING(SS_TAP(X_LEFT) SS_TAP(X_LEFT)); char_to_bspace = 1; char_to_del = 2; } break; case STARS: if (record->event.pressed) { clear_mods(); SEND_STRING("** " SS_TAP(X_LEFT) SS_TAP(X_LEFT)); char_to_bspace = 1; char_to_del = 2; } break; case ADMINS: if (record->event.pressed) { send_string_remembering_length("admin"); } break; case G_ADD: if (record->event.pressed) { send_string_remembering_length("git add "); } break; case G_BRCH: if (record->event.pressed) { send_shifted_strings_add("git branch ", "-d "); } break; case G_C: if (record->event.pressed) { send_string_remembering_length("git c[Heckout/Ommit]"); layer_on(GIT_C); } break; case G_CHEC: if (!record->event.pressed) { bool shifted = get_mods() & MOD_MASK_SHIFT; clear_mods(); press_n_times(15, KC_BACKSPACE); send_string_with_translation("heckout "); char_to_bspace = 13; if (shifted) { send_string_with_translation("-b "); char_to_bspace = 16; } layer_off(GIT_C); } break; case G_COMM: if (!record->event.pressed) { bool ctrled = get_mods() & MOD_MASK_CTRL; bool shifted = get_mods() & MOD_MASK_SHIFT; clear_mods(); press_n_times(15, KC_BACKSPACE); send_string_with_translation("ommit "); char_to_bspace = 11; layer_off(GIT_C); if (ctrled) { return false; } SEND_STRING("-"); char_to_bspace = 15; if (shifted) { send_string_with_translation("a"); char_to_bspace = 16; } send_string_with_translation("m"); SEND_STRING(" \"\"" SS_TAP(X_LEFT)); char_to_del = 1; } break; case G_DEV: if (record->event.pressed) { send_shifted_strings("develop", "master"); } break; case G_DIFF: if (record->event.pressed) { send_string_remembering_length("git diff "); } break; case G_FTCH: if (record->event.pressed) { send_string_remembering_length("git fetch "); } break; case G_LOG: if (record->event.pressed) { send_string_remembering_length("git log "); } break; case G_MERG: if (record->event.pressed) { send_string_remembering_length("git merge "); } break; case G_PULL: if (record->event.pressed) { send_string_remembering_length("git pull "); } break; case G_PUSH: if (record->event.pressed) { send_string_remembering_length("git push -u "); } break; case G_R: if (!record->event.pressed) { send_string_remembering_length("git re[Set/Vert/Base -i]"); layer_on(GIT_R); } break; case G_RBASE: if (!record->event.pressed) { press_n_times(18, KC_BACKSPACE); send_string_with_translation("base -i "); char_to_bspace = 14; layer_off(GIT_R); } break; case G_RVERT: if (!record->event.pressed) { press_n_times(18, KC_BACKSPACE); send_string_with_translation("vert "); char_to_bspace = 11; layer_off(GIT_R); } break; case G_RST: if (!record->event.pressed) { bool shifted = get_mods() & MOD_MASK_SHIFT; clear_mods(); press_n_times(18, KC_BACKSPACE); send_string_with_translation("set "); char_to_bspace = 10; if (shifted) { send_string_with_translation("--hard "); char_to_bspace = 17; } layer_off(GIT_R); } break; case G_S: if (!record->event.pressed) { send_string_remembering_length("git s[taSh/How/taTus]"); layer_on(GIT_S); } break; case G_SHOW: if (!record->event.pressed) { press_n_times(16, KC_BACKSPACE); send_string_with_translation("how "); char_to_bspace = 9; layer_off(GIT_S); } break; case G_STSH: if (!record->event.pressed) { bool shifted = get_mods() & MOD_MASK_SHIFT; clear_mods(); press_n_times(16, KC_BACKSPACE); send_string_with_translation("tash "); char_to_bspace = 10; if (shifted) { clear_mods(); send_string_with_translation("apply "); char_to_bspace = 16; } layer_off(GIT_S); } break; case G_STAT: if (!record->event.pressed) { press_n_times(16, KC_BACKSPACE); send_string_with_translation("tatus "); char_to_bspace = 11; layer_off(GIT_S); } break; case K_CUST1 ... K_CUST3: // custom strings not stored in source control if (!record->event.pressed) { send_string_remembering_length(custom[keycode - K_CUST1]); blink_leds(NUM_SCROLL_LED_ON); } break; case K_SECR1 ... K_SECR4: // Secrets! Externally defined strings, not stored in repo if (!record->event.pressed) { send_string_remembering_length(secrets[keycode - K_SECR1]); blink_leds(NUM_SCROLL_LED_ON); } break; case CTL_ALT_START ... CTL_ALT_END: if (record->event.pressed) { if (is_win) { register_code16(LCTL(keycode - CTL_ALT_START)); } else { register_code16(LALT(keycode - CTL_ALT_START)); } } else { if (is_win) { unregister_code16(LCTL(keycode - CTL_ALT_START)); } else { unregister_code16(LALT(keycode - CTL_ALT_START)); } } break; } return process_record_keymap(keycode, record); }