summaryrefslogtreecommitdiff
path: root/users/kuchosauronad0
diff options
context:
space:
mode:
authorkuchosauronad0 <22005492+kuchosauronad0@users.noreply.github.com>2019-08-17 08:19:35 -0700
committerMechMerlin <30334081+mechmerlin@users.noreply.github.com>2019-08-17 08:19:35 -0700
commit683605a9dc285c5e8f6328ec81a29505892287b7 (patch)
tree82254e30a4aa0c0774aec22a6c7f69a1045b83d0 /users/kuchosauronad0
parentc178bbf2e50424ee54fbd3a43609089470129c34 (diff)
Userspace kuchosauronad0 (#6541)
* initial commit * Update layout. Tweak rules.mk * initial userspace configuration for kuchosauronad0 * modified userspace for kuchosauronad0 * added OSL_UNI * clean up * clean up * style * style * added more unicode * fixed representation * fixed representation * added comments * added comments, restructure * accidently one line * restructure * restructure * added git_lazy(void) * fixed indenting and added missing symbols * fixed indent * fixed indent * update * change tapping_term to 150 * added UNICODEMAP_ENABLE block * replace register with tap_code where possible * formatting * rearrange sequences * clean up * clean up * added unicode layer * disabled tap dance * add files for encoder * removed unnecessary include * removed unnecessary stuff
Diffstat (limited to 'users/kuchosauronad0')
-rw-r--r--users/kuchosauronad0/.gitignore3
-rw-r--r--users/kuchosauronad0/config.h93
-rw-r--r--users/kuchosauronad0/encoder.c10
-rw-r--r--users/kuchosauronad0/encoder.h3
-rw-r--r--users/kuchosauronad0/kuchosauronad0.c196
-rw-r--r--users/kuchosauronad0/kuchosauronad0.h111
-rw-r--r--users/kuchosauronad0/leader.c84
-rw-r--r--users/kuchosauronad0/leader.h6
-rw-r--r--users/kuchosauronad0/process_records.c244
-rw-r--r--users/kuchosauronad0/process_records.h94
-rw-r--r--users/kuchosauronad0/readme.md145
-rw-r--r--users/kuchosauronad0/rules.mk44
-rw-r--r--users/kuchosauronad0/tap_dances.c57
-rw-r--r--users/kuchosauronad0/tap_dances.h26
-rw-r--r--users/kuchosauronad0/template.c125
-rw-r--r--users/kuchosauronad0/template.h18
-rw-r--r--users/kuchosauronad0/unicode.c62
-rw-r--r--users/kuchosauronad0/unicode.h67
-rw-r--r--users/kuchosauronad0/wrappers.h206
19 files changed, 1594 insertions, 0 deletions
diff --git a/users/kuchosauronad0/.gitignore b/users/kuchosauronad0/.gitignore
new file mode 100644
index 0000000000..6878d13e7c
--- /dev/null
+++ b/users/kuchosauronad0/.gitignore
@@ -0,0 +1,3 @@
+secrets.c
+secrets.h
+kuchosauronad0_song_list.h
diff --git a/users/kuchosauronad0/config.h b/users/kuchosauronad0/config.h
new file mode 100644
index 0000000000..f543a4fd25
--- /dev/null
+++ b/users/kuchosauronad0/config.h
@@ -0,0 +1,93 @@
+#pragma once
+
+
+#ifdef AUDIO_ENABLE
+ #define AUDIO_CLICKY
+ #define STARTUP_SONG SONG(RICK_ROLL)
+ #define GOODBYE_SONG SONG(SONIC_RING)
+ #define DEFAULT_LAYER_SONGS { SONG(QWERTY_SOUND), \
+ SONG(COLEMAK_SOUND), \
+ SONG(DVORAK_SOUND), \
+ SONG(OVERWATCH_THEME) \
+ }
+
+ #define AUDIO_CLICKY_FREQ_RANDOMNESS 1.5f
+ // #ifdef RGBLIGHT_ENABLE
+ // #define NO_MUSIC_MODE
+ // #endif //RGBLIGHT_ENABLE/
+ // #ifndef __arm__
+ // #undef NOTE_REST
+ // #define NOTE_REST 1.00f
+ // #endif // !__arm__
+
+#define UNICODE_SONG_OSX SONG(RICK_ROLL)
+#define UNICODE_SONG_LNX SONG(RICK_ROLL)
+#define UNICODE_SONG_WIN SONG(RICK_ROLL)
+#define UNICODE_SONG_BSD SONG(RICK_ROLL)
+#define UNICODE_SONG_WINC SONG(RICK_ROLL)
+
+#endif // !AUDIO_ENABLE
+
+#ifdef RGBLIGHT_ENABLE
+ #define RGBLIGHT_SLEEP
+ #undef RGBLIGHT_ANIMATIONS
+ #define RGBLIGHT_EFFECT_BREATHING
+ #define RGBLIGHT_EFFECT_SNAKE
+ #define RGBLIGHT_EFFECT_KNIGHT
+#endif // !RGBLIGHT_ENABLE
+
+#ifndef ONESHOT_TAP_TOGGLE
+ #define ONESHOT_TAP_TOGGLE 2
+#endif // !ONESHOT_TAP_TOGGLE
+
+#ifndef ONESHOT_TIMEOUT
+ #define ONESHOT_TIMEOUT 3000
+#endif// !ONESHOT_TIMEOUT
+
+#ifndef QMK_KEYS_PER_SCAN
+ #define QMK_KEYS_PER_SCAN 4
+#endif // !QMK_KEYS_PER_SCAN
+
+
+
+// this makes it possible to do rolling combos (zx) with keys that
+// convert to other keys on hold (z becomes ctrl when you hold it,
+// and when this option isn't enabled, z rapidly followed by x
+// actually sends Ctrl-x. That's bad.)
+#define IGNORE_MOD_TAP_INTERRUPT
+#undef PERMISSIVE_HOLD
+//#define TAPPING_FORCE_HOLD
+//#define RETRO_TAPPING
+
+#define FORCE_NKRO
+
+#ifndef TAPPING_TOGGLE
+ #define TAPPING_TOGGLE 1
+#endif
+
+#ifdef TAPPING_TERM
+ #undef TAPPING_TERM
+#endif // !TAPPING_TERM
+#if defined(KEYBOARD_ergodox_ez)
+ #define TAPPING_TERM 185
+#elif defined(KEYBOARD_crkbd)
+ #define TAPPING_TERM 200
+#else
+ #define TAPPING_TERM 150
+#endif
+
+
+// Disable action_get_macro and fn_actions, since we don't use these
+// and it saves on space in the firmware.
+#define NO_ACTION_MACRO
+#define NO_ACTION_FUNCTION
+
+#define TAP_CODE_DELAY 5
+
+// Enable Leader key
+#if defined(LEADER_ENABLE)
+ #define LEADER_PER_KEY_TIMING
+ #define LEADER_TIMEOUT 250
+#endif // !LEADER_ENABLE
+
+#define MACRO_TIMER 5
diff --git a/users/kuchosauronad0/encoder.c b/users/kuchosauronad0/encoder.c
new file mode 100644
index 0000000000..1b9b2cb12f
--- /dev/null
+++ b/users/kuchosauronad0/encoder.c
@@ -0,0 +1,10 @@
+#include "encoder.h"
+
+void encoder_update_user(uint8_t index, bool clockwise) {
+ if (clockwise) {
+ tap_code(KC_1);
+ } else {
+ tap_code(KC_0);
+ }
+}
+
diff --git a/users/kuchosauronad0/encoder.h b/users/kuchosauronad0/encoder.h
new file mode 100644
index 0000000000..078989d52d
--- /dev/null
+++ b/users/kuchosauronad0/encoder.h
@@ -0,0 +1,3 @@
+#pragma once
+#include "quantum.h"
+void encoder_update_user(uint8_t index, bool clockwise);
diff --git a/users/kuchosauronad0/kuchosauronad0.c b/users/kuchosauronad0/kuchosauronad0.c
new file mode 100644
index 0000000000..21e74a0fae
--- /dev/null
+++ b/users/kuchosauronad0/kuchosauronad0.c
@@ -0,0 +1,196 @@
+/*
+Copyright 2019 Andre Poley <andre.poley@mailbox.org>
+
+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 <http://www.gnu.org/licenses/>.
+*/
+#include "quantum.h"
+#include "kuchosauronad0.h"
+
+userspace_config_t userspace_config;
+#if (defined(UNICODE_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_ENABLE))
+ #define KUCHOSAURONAD0_UNICODE_MODE UC_WINC
+#else
+ // set to 2 for UC_WIN, set to 4 for UC_WINC
+ #define KUCHOSAURONAD0_UNICODE_MODE 2
+#endif
+
+
+// Add reconfigurable functions here, for keymap customization
+// This allows for a global, userspace functions, and continued
+// customization of the keymap. Use _keymap instead of _user
+// functions in the keymaps
+__attribute__ ((weak))
+void matrix_init_keymap(void) {}
+
+// Call user matrix init, set default RGB colors and then
+// call the keymap's init function
+void matrix_init_user(void) {
+ userspace_config.raw = eeconfig_read_user();
+
+ #ifdef BOOTLOADER_CATERINA
+ DDRD &= ~(1<<5);
+ PORTD &= ~(1<<5);
+
+ DDRB &= ~(1<<0);
+ PORTB &= ~(1<<0);
+ #endif
+
+ #if (defined(UNICODE_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_ENABLE))
+ set_unicode_input_mode(KUCHOSAURONAD0_UNICODE_MODE);
+ get_unicode_input_mode();
+ #endif //UNICODE_ENABLE
+ matrix_init_keymap();
+}
+
+__attribute__((weak))
+void keyboard_post_init_keymap(void){ }
+
+void keyboard_post_init_user(void){
+#ifdef RGBLIGHT_ENABLE
+ keyboard_post_init_rgb();
+#endif
+ keyboard_post_init_keymap();
+}
+
+__attribute__ ((weak))
+void shutdown_keymap(void) {}
+
+void shutdown_user (void) {
+ #ifdef RGBLIGHT_ENABLE
+ rgblight_enable_noeeprom();
+ rgblight_mode_noeeprom(1);
+ rgblight_setrgb_red();
+ #endif // RGBLIGHT_ENABLE
+ #ifdef RGB_MATRIX_ENABLE
+ // uint16_t timer_start = timer_read();
+ // rgb_matrix_set_color_all( 0xFF, 0x00, 0x00 );
+ // while(timer_elapsed(timer_start) < 250) { wait_ms(1); }
+ #endif //RGB_MATRIX_ENABLE
+ shutdown_keymap();
+}
+
+__attribute__ ((weak))
+void suspend_power_down_keymap(void) {}
+
+void suspend_power_down_user(void) {
+ suspend_power_down_keymap();
+}
+
+__attribute__ ((weak))
+void suspend_wakeup_init_keymap(void) {}
+
+void suspend_wakeup_init_user(void) {
+ suspend_wakeup_init_keymap();
+}
+
+
+__attribute__ ((weak))
+void matrix_scan_keymap(void) {}
+
+__attribute__ ((weak))
+void matrix_scan_user(void){
+ static bool has_ran_yet;
+ if (!has_ran_yet) {
+ has_ran_yet = true;
+ startup_user();
+ }
+
+#ifdef TAP_DANCE_ENABLE // Run Diablo 3 macro checking code.
+// run_diablo_macro_check();
+#endif // TAP_DANCE_ENABLE
+
+#ifdef RGBLIGHT_ENABLE
+ matrix_scan_rgb();
+#endif // RGBLIGHT_ENABLE
+
+ matrix_scan_keymap();
+}
+
+__attribute__ ((weak))
+uint32_t layer_state_set_keymap (uint32_t state) {
+ return state;
+}
+
+// on layer change, no matter where the change was initiated
+// Then runs keymap's layer change check
+uint32_t layer_state_set_user(uint32_t state) {
+ state = update_tri_layer_state(state, _RAISE, _LOWER, _ADJUST);
+#ifdef RGBLIGHT_ENABLE
+ state = layer_state_set_rgb(state);
+#endif // RGBLIGHT_ENABLE
+ return layer_state_set_keymap (state);
+}
+
+
+__attribute__ ((weak))
+uint32_t default_layer_state_set_keymap (uint32_t state) {
+ return state;
+}
+
+// Runs state check and changes underglow color and animation
+uint32_t default_layer_state_set_user(uint32_t state) {
+ state = default_layer_state_set_keymap(state);
+#if 0
+#ifdef RGBLIGHT_ENABLE
+ state = default_layer_state_set_rgb(state);
+#endif // RGBLIGHT_ENABLE
+#endif
+ return state;
+}
+
+__attribute__ ((weak))
+void led_set_keymap(uint8_t usb_led) {}
+
+// Any custom LED code goes here.
+// So far, I only have keyboard specific code,
+// So nothing goes here.
+void led_set_user(uint8_t usb_led) {
+ led_set_keymap(usb_led);
+}
+__attribute__ ((weak))
+void eeconfig_init_keymap(void) {}
+
+void eeconfig_init_user(void) {
+ userspace_config.raw = 0;
+ userspace_config.rgb_layer_change = true;
+ eeconfig_update_user(userspace_config.raw);
+ #if (defined(UNICODE_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_ENABLE))
+ set_unicode_input_mode(KUCHOSAURONAD0_UNICODE_MODE);
+ get_unicode_input_mode();
+ #else
+ eeprom_update_byte(EECONFIG_UNICODEMODE, KUCHOSAURONAD0_UNICODE_MODE);
+ #endif
+}
+
+// TMUX stuff
+void tmux_prefix(void) {
+ register_code(KC_LCTL);
+ tap_code(KC_B);
+ unregister_code(KC_LCTL);
+}
+
+
+void tmux_pane_last(void) {
+ tmux_prefix();
+ tap_code(KC_SCLN);
+}
+
+void tmux_pane_switch_repeat(void) {
+ tmux_pane_last();
+ tap_code(KC_UP);
+ tap_code(KC_ENT);
+ tmux_pane_last();
+}
+
+/* vi: ft=c:tw=80:sw=2:ts=2:sts=2:et */
diff --git a/users/kuchosauronad0/kuchosauronad0.h b/users/kuchosauronad0/kuchosauronad0.h
new file mode 100644
index 0000000000..9ea2673dab
--- /dev/null
+++ b/users/kuchosauronad0/kuchosauronad0.h
@@ -0,0 +1,111 @@
+#ifndef USERSPACE
+#define USERSPACE
+
+//#pragma once
+
+#include "quantum.h"
+
+#include "version.h"
+#include "eeprom.h"
+#include "wrappers.h"
+#include "process_records.h"
+
+#ifdef TAP_DANCE_ENABLE
+ #include "tap_dances.h"
+ #define KC_TMX TD(TD_TMX) // tap1: 't' tap2: <CTL>+b
+ #define KC_EOL TD(TD_EOL) // tap1: 'e' tap2: <CTL>+e
+ #define KC_BOL TD(TD_BOL) // tap1: 'a' tap2: <CTL>+a
+ #define KC_NW TD(TD_NW) // tap1: 'f' tap2: <ALT>+f
+ #define KC_PW TD(TD_PW) // tap1: 'b' tap2: <ALT>+b
+ #define KC_DW TD(TD_DW) // tap1: 'w' tap2: <CTL>+w
+#endif //!TAP_DANCE_ENABLE
+#if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
+ #include "rgb_stuff.h"
+#endif
+#if defined(UNICODEMAP_ENABLE) || defined(UNICODE_ENABLE)
+ #include "unicode.h"
+#endif //!UNICODE_ENABLE
+
+// Keycode aliases
+#define TM_X LCTL(KC_B) // Tmux control sequence
+// Unix QoL macros
+#define MC_BOL LCTL(KC_A) // jump to beginning of line
+#define MC_EOL LCTL(KC_E) // jump to end of line
+#define MC_NW LALT(KC_F) // next word
+#define MC_PW LALT(KC_B) // previous word
+#define MC_DW LCTL(KC_W) // delete word
+
+// Define layer names
+enum userspace_layers {
+ _QWERTY = 0,
+ _NUMLOCK = 0,
+ _COLEMAK,
+ _DVORAK,
+ _WORKMAN,
+ _NORMAN,
+ _MALTRON,
+ _EUCALYN,
+ _CARPLAX,
+ _UNICODE,
+ _MODS, /* layer 8 now 9*/
+ _GAMEPAD,
+ _DIABLO,
+ _MACROS,
+ _MEDIA,
+ _LOWER,
+ _RAISE,
+ _ADJUST,
+};
+
+bool mod_key_press_timer (uint16_t code, uint16_t mod_code, bool pressed);
+bool mod_key_press (uint16_t code, uint16_t mod_code, bool pressed, uint16_t this_timer);
+bool send_game_macro(const char *str, keyrecord_t *record, bool override);
+void matrix_init_keymap(void);
+void shutdown_keymap(void);
+void suspend_power_down_keymap(void);
+void suspend_wakeup_init_keymap(void);
+void matrix_scan_keymap(void);
+uint32_t layer_state_set_keymap (uint32_t state);
+uint32_t default_layer_state_set_keymap (uint32_t state);
+void led_set_keymap(uint8_t usb_led);
+void eeconfig_init_keymap(void);
+
+void tmux_prefix(void);
+void tmux_pane_zoom(void);
+void tmux_pane_last(void);
+void tmux_pane_switch_repeat(void);
+void tmux_pane_switch(uint16_t keycode);
+
+typedef union {
+ uint32_t raw;
+ struct {
+ bool rgb_layer_change :1;
+ bool is_overwatch :1;
+ bool nuke_switch :1;
+ uint8_t unicode_mod :4;
+ bool swapped_numbers :1;
+ };
+} userspace_config_t;
+
+extern userspace_config_t userspace_config;
+
+/*
+Custom Keycodes for Diablo 3 layer
+But since TD() doesn't work when tap dance is disabled
+We use custom codes here, so we can substitute the right stuff
+*/
+#ifdef TAP_DANCE_ENABLE
+#define KC_D3_1 TD(TD_D3_1)
+#define KC_D3_2 TD(TD_D3_2)
+#define KC_D3_3 TD(TD_D3_3)
+#define KC_D3_4 TD(TD_D3_4)
+#else // TAP_DANCE_ENABLE
+#define KC_D3_1 KC_1
+#define KC_D3_2 KC_2
+#define KC_D3_3 KC_3
+#define KC_D3_4 KC_4
+#endif // TAP_DANCE_ENABLE
+
+#endif // !USERSPACE
+
+/* vi: ft=c:tw=80:sw=2:ts=2:sts=2:et */
diff --git a/users/kuchosauronad0/leader.c b/users/kuchosauronad0/leader.c
new file mode 100644
index 0000000000..611b70074c
--- /dev/null
+++ b/users/kuchosauronad0/leader.c
@@ -0,0 +1,84 @@
+#include "leader.h"
+
+LEADER_EXTERNS();
+
+void matrix_scan_user(void){
+ static bool has_ran_yet;
+ if (!has_ran_yet) {
+ has_ran_yet = true;
+ startup_user();
+ }
+
+#ifdef TAP_DANCE_ENABLE // Run Diablo 3 macro checking code.
+// run_diablo_macro_check();
+#endif // TAP_DANCE_ENABLE
+
+#ifdef RGBLIGHT_ENABLE
+ matrix_scan_rgb();
+#endif // RGBLIGHT_ENABLE
+
+ LEADER_DICTIONARY() {
+ leading = false;
+ leader_end();
+ // Q is for TMUX
+ // Z is for OS related things
+ // other single key sequences are mostly for terminals and vim
+
+ SEQ_ONE_KEY(KC_W) {
+ // Vim + Tmux Macro, when in command mode in vim: write to file, change to the other pane in the current session and repeat the last command
+ SEND_STRING(":w" SS_TAP(X_ENTER));
+ tmux_pane_switch_repeat();
+ }
+
+ SEQ_ONE_KEY(KC_T) {
+ // Send the Tmux Prefix
+ tmux_prefix();
+ }
+
+ SEQ_ONE_KEY(KC_A) {
+ // Send the Tmux Prefix and press 'right' arrow
+ tmux_prefix();
+ tap_code(KC_RIGHT);
+ }
+
+ SEQ_TWO_KEYS(KC_T, KC_T) {
+ // Send the Tmux Prefix to a nested session
+ tmux_prefix();
+ tmux_prefix();
+ }
+ SEQ_TWO_KEYS(KC_Q, KC_A) {
+ // Switch pane and repeat last action
+ tmux_pane_switch_repeat();
+ }
+
+ SEQ_TWO_KEYS(KC_Z, KC_P){
+ // Press windows key, send string 'plex' and press enter
+ register_code(KC_LGUI);
+ register_code(KC_S);
+ unregister_code(KC_S);
+
+ unregister_code(KC_LGUI);
+ SEND_STRING("plex");
+ tap_code(KC_ENTER);
+ }
+
+ SEQ_TWO_KEYS(KC_Z, KC_F) {
+ // Open a search
+ register_code(KC_LGUI);
+ register_code(KC_S);
+ unregister_code(KC_S);
+ unregister_code(KC_LGUI);
+ }
+
+ SEQ_TWO_KEYS(KC_Z, KC_Z) {
+ SEND_STRING("https://start.duckduckgo.com"SS_TAP(X_ENTER));
+ }
+
+ SEQ_THREE_KEYS(KC_BSPC, KC_BSPC, KC_BSPC){
+ // Reset the keyboard
+ reset_keyboard();
+ }
+ }
+
+ matrix_scan_keymap();
+}
diff --git a/users/kuchosauronad0/leader.h b/users/kuchosauronad0/leader.h
new file mode 100644
index 0000000000..ed904f3063
--- /dev/null
+++ b/users/kuchosauronad0/leader.h
@@ -0,0 +1,6 @@
+#pragma once
+#include "kuchosauronad0.h"
+
+#include "leader.h"
+
+void matrix_scan_user(void);
diff --git a/users/kuchosauronad0/process_records.c b/users/kuchosauronad0/process_records.c
new file mode 100644
index 0000000000..1eb3043b1c
--- /dev/null
+++ b/users/kuchosauronad0/process_records.c
@@ -0,0 +1,244 @@
+#include "kuchosauronad0.h"
+
+uint16_t copy_paste_timer;
+
+__attribute__ ((weak))
+bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
+ return true;
+}
+
+__attribute__ ((weak))
+bool process_record_secrets(uint16_t keycode, keyrecord_t *record) {
+ return true;
+}
+
+// Defines actions for my global custom keycodes. Defined in kuchosauronad0.h file
+// Then runs the _keymap's record handier if not processed here
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ // 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)
+ xprintf("KL: kc: %u, col: %u, row: %u, pressed: %u\n", keycode, record->event.key.row, record->event.key.col, record->event.pressed);
+ #else
+ xprintf("KL: kc: %u, col: %u, row: %u, pressed: %u\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed);
+ #endif
+#endif //KEYLOGGER_ENABLE
+
+ switch (keycode) {
+ case KC_QWERTY ... KC_UNICODE:
+ if (record->event.pressed) {
+ set_single_persistent_default_layer(keycode - KC_QWERTY);
+ }
+ break;
+
+ case KC_MAKE: // Compiles the firmware, and adds the flash command based on keyboard bootloader
+ if (!record->event.pressed) {
+ uint8_t temp_mod = get_mods();
+ uint8_t temp_osm = get_oneshot_mods();
+ clear_mods(); clear_oneshot_mods();
+ send_string_with_delay_P(PSTR("make " QMK_KEYBOARD ":" QMK_KEYMAP), TAP_CODE_DELAY);
+#ifndef MAKE_BOOTLOADER
+ if ( ( temp_mod | temp_osm ) & MOD_MASK_SHIFT )
+#endif
+ {
+ #if defined(__arm__)
+ send_string_with_delay_P(PSTR(":dfu-util"), TAP_CODE_DELAY);
+ #elif defined(BOOTLOADER_DFU)
+ send_string_with_delay_P(PSTR(":dfu"), TAP_CODE_DELAY);
+ #elif defined(BOOTLOADER_HALFKAY)
+ send_string_with_delay_P(PSTR(":teensy"), TAP_CODE_DELAY);
+ #elif defined(BOOTLOADER_CATERINA)
+ send_string_with_delay_P(PSTR(":avrdude"), TAP_CODE_DELAY);
+ #endif // bootloader options
+ }
+ if ( ( temp_mod | temp_osm ) & MOD_MASK_CTRL) { send_string_with_delay_P(PSTR(" -j8 --output-sync"), TAP_CODE_DELAY); }
+ send_string_with_delay_P(PSTR(SS_TAP(X_ENTER)), TAP_CODE_DELAY);
+ }
+ break;
+// FLEDERMAUSLAND
+ case MC_QT1: // ""
+ if(record->event.pressed){
+ SEND_STRING("\"\"");
+ tap_code(KC_LEFT);
+ }
+ break;
+ case MC_QT2: // ''
+ if(record->event.pressed){
+ SEND_STRING("''");
+ tap_code(KC_LEFT);
+ }
+ break;
+ case MC_QT3: // `'
+ if(record->event.pressed){
+ SEND_STRING("`'");
+ tap_code(KC_LEFT);
+ }
+ break;
+ case MC_PAR: // Parenthesis
+ if(record->event.pressed){
+ SEND_STRING("()");
+ tap_code(KC_LEFT);
+ }
+ break;
+ case MC_CUR: // Curly bracket
+ if(record->event.pressed){
+ SEND_STRING("{}");
+ tap_code(KC_LEFT);
+ }
+ break;
+ case MC_SQR: // Square bracket
+ if(record->event.pressed){
+ SEND_STRING("[]");
+ tap_code(KC_LEFT);
+ }
+ break;
+ case MC_ABR: // Angle bracket
+ if(record->event.pressed){
+ SEND_STRING("<>");
+ tap_code(KC_LEFT);
+ }
+ break;
+ case MCT_NEW: // New Tmux Session
+ if(record->event.pressed){
+ tmux_prefix();
+ SEND_STRING(":neww");
+ tap_code(KC_ENT);
+ }
+ break;
+ case MCT_SH: // Tmux horizontal split
+ if(record->event.pressed){
+ tmux_prefix();
+ SEND_STRING("%");
+ }
+ break;
+ case MCT_SV: // Tmux vertical split
+ if(record->event.pressed){
+ tmux_prefix();
+ SEND_STRING("\"");
+ }
+ break;
+ case MCT_ZM: // Tmux zoom
+ if(record->event.pressed){
+ tmux_prefix();
+ tap_code(KC_Z);
+ }
+ break;
+ case MCT_SCR: // Tmux scroll mode
+ if(record->event.pressed){
+ tmux_prefix();
+ tap_code(KC_PGUP);
+ }
+ break;
+ case MCT_UP: // Tmux up
+ break;
+ case MCT_DW: // Tmux down
+ break;
+ case MCT_LFT: // Tmux left
+ break;
+ case MCT_RGT: // Tmux right
+ tmux_prefix();
+ tap_code(KC_RIGHT);
+ break;
+ case MCV_B: // Vim begin of line
+ if(record->event.pressed){
+ tap_code(KC_0);
+ }
+ break;
+ case MCV_E: // Vim end of line
+ if(record->event.pressed){
+ SEND_STRING(":vsplit");
+ tap_code(KC_ENT);
+ }
+ break;
+ case MCT_F: // Vim for loop
+ if(record->event.pressed){
+ SEND_STRING(":help");
+ tap_code(KC_ENT);
+ }
+ 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;
+// These are a series of gaming macros.
+// Only enables for the viterbi, basically,
+// to save on firmware space, since it's limited.
+#ifdef MACROS_ENABLED
+ case KC_OVERWATCH: // Toggle's if we hit "ENTER" or "BACKSPACE" to input macros
+ if (record->event.pressed) { userspace_config.is_overwatch ^= 1; eeconfig_update_user(userspace_config.raw); }
+#ifdef RGBLIGHT_ENABLE
+ userspace_config.is_overwatch ? rgblight_mode_noeeprom(17) : rgblight_mode_noeeprom(18);
+#endif //RGBLIGHT_ENABLE
+ break;
+ case KC_SALT:
+ return send_game_macro("Salt, salt, salt...", record, false);
+ case KC_MORESALT:
+ return send_game_macro("Please sir, can I have some more salt?!", record, false);
+ case KC_SALTHARD:
+ return send_game_macro("Your salt only makes me harder, and even more aggressive!", record, false);
+ case KC_GOODGAME:
+ return send_game_macro("Good game, everyone!", record, false);
+ case KC_GLHF:
+ return send_game_macro("Good luck, have fun!!!", record, false);
+ case KC_SYMM:
+ return send_game_macro("Left click to win!", record, false);
+ case KC_JUSTGAME:
+ return send_game_macro("It may be a game, but if you don't want to actually try, please go play AI, so that people that actually want to take the game seriously and \"get good\" have a place to do so without trolls like you throwing games.", record, false);
+ case KC_TORB:
+ return send_game_macro("That was positively riveting!", record, false);
+ case KC_AIM:
+ send_game_macro("That aim is absolutely amazing. It's almost like you're a machine!", record, true);
+ return send_game_macro("Wait! That aim is TOO good! You're clearly using an aim hack! CHEATER!", record, false);
+ case KC_C9:
+ return send_game_macro("OMG!!! C9!!!", record, false);
+ case KC_GGEZ:
+ return send_game_macro("That was a fantastic game, though it was a bit easy. Try harder next time!", record, false);
+#endif // MACROS_ENABLED
+
+ case KC_CCCV: // One key copy/paste
+ if(record->event.pressed){
+ copy_paste_timer = timer_read();
+ } else {
+ if (timer_elapsed(copy_paste_timer) > TAPPING_TERM) { // Hold, copy
+ register_code(KC_LCTL);
+ tap_code(KC_C);
+ unregister_code(KC_LCTL);
+ } else { // Tap, paste
+ register_code(KC_LCTL);
+ tap_code(KC_V);
+ unregister_code(KC_LCTL);
+ }
+ }
+ break;
+
+// Unicode
+#ifdef UNICODE_ENABLE
+ case UC_FLIP: // (ノಠ痊ಠ)ノ彡┻━┻
+ if (record->event.pressed) {
+ send_unicode_hex_string("0028 30CE 0CA0 75CA 0CA0 0029 30CE 5F61 253B 2501 253B");
+ }
+ break;
+ case UC_TABL: // ┬┬ノ( º _ ºノ)
+ if (record->event.pressed) {
+ send_unicode_hex_string("252C 2500 252C 30CE 0028 0020 00BA 0020 005F 0020 00BA 30CE 0029");
+ }
+ break;
+ case UC_SHRG: // ¯\_(ツ)_/¯
+ if (record->event.pressed) {
+ send_unicode_hex_string("00AF 005C 005F 0028 30C4 0029 005F 002F 00AF");
+ }
+ break;
+ case UC_DISA: // ಠ_ಠ
+ if (record->event.pressed) {
+ send_unicode_hex_string("0CA0 005F 0CA0");
+ }
+ break;
+#endif //!Unicode
+}
+ return process_record_keymap(keycode, record) &&
+#if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
+ process_record_user_rgb(keycode, record) &&
+#endif // RGBLIGHT_ENABLE
+ process_record_secrets(keycode, record);
+}
diff --git a/users/kuchosauronad0/process_records.h b/users/kuchosauronad0/process_records.h
new file mode 100644
index 0000000000..1a66beaa77
--- /dev/null
+++ b/users/kuchosauronad0/process_records.h
@@ -0,0 +1,94 @@
+#pragma once
+#include "kuchosauronad0.h"
+
+#if defined(KEYMAP_SAFE_RANGE)
+#define PLACEHOLDER_SAFE_RANGE KEYMAP_SAFE_RANGE
+#else
+#define PLACEHOLDER_SAFE_RANGE SAFE_RANGE
+#endif
+
+enum userspace_custom_keycodes{
+ VRSN = PLACEHOLDER_SAFE_RANGE, // Prints QMK Firmware and board info
+ KC_QWERTY, // Sets default layer to QWERTY
+ KC_COLEMAK, // Sets default layer to COLEMAK
+ KC_DVORAK, // Sets default layer to DVORAK
+ KC_WORKMAN, // Sets default layer to WORKMAN
+ KC_NORMAN, // Sets default layer to NORMAN
+ KC_MALTRON, // Sets default layer to MALTRON
+ KC_EUCALYN, // Sets default layer to EUCALYN
+ KC_CARPLAX, // Sets default layer to CARPLAX
+ KC_UNICODE, // Sets default layer to UNICODE
+
+ KC_MAKE, // Run keyboard's customized make command
+ KC_RGB_T, // Toggles RGB Layer Indication mode
+ KC_SECRET_1,
+ KC_SECRET_2,
+ KC_SECRET_3,
+ KC_SECRET_4,
+ KC_SECRET_5,
+ KC_CCCV, // Hold to copy, tap to paste
+ KC_NUKE, // NUCLEAR LAUNCH DETECTED!!!
+ UC_FLIP, // (ಠ痊ಠ)┻━┻
+ UC_TABL, // ┬┬ノ( º _ ºノ)
+ UC_SHRG, // ¯\_(ツ)_/¯
+ UC_DISA, // ಠ_ಠ
+
+ MC_QT1, // ""
+ MC_QT2, // ''
+ MC_QT3, // `'
+ MC_PAR, // Parenthesis
+ MC_CUR, // Curly bracket
+ MC_SQR, // Square bracket
+ MC_ABR, // Angle bracket
+ MCT_NEW, // New Tmux Session
+ MCT_SH, // Tmux horizontal split
+ MCT_SV, // Tmux vertical split
+ MCT_ZM, // Tmux zoom
+ MCT_SCR, // Tmux scroll mode
+ MCT_UP, // Tmux up
+ MCT_DW, // Tmux down
+ MCT_LFT, // Tmux left
+ MCT_RGT, // Tmux right
+ MCV_B, // Vim begin of line
+ MCV_E, // Vim end of line
+ MCT_F, // Vim for loop
+ MCG_A, // Git add
+ MCG_C, // Git commit
+ MCG_P, // Git push
+ MCG_R, // Git revert
+ MCG_L, // Git log
+ MCG_S, // Git status
+
+ NEW_SAFE_RANGE //use "NEWPLACEHOLDER for keymap specific codes
+ };
+
+bool process_record_secrets(uint16_t keycode, keyrecord_t *record);
+bool process_record_keymap(uint16_t keycode, keyrecord_t *record);
+
+#define LOWER MO(_LOWER)
+#define RAISE MO(_RAISE)
+#define ADJUST MO(_ADJUST)
+#define TG_MODS TG(_MODS)
+#define TG_GAME TG(_GAMEPAD)
+#define OS_LWR OSL(_LOWER)
+#define OS_RSE OSL(_RAISE)
+#define OS_UNI OSL(_UNICODE)
+
+#define KC_SEC1 KC_SECRET_1
+#define KC_SEC2 KC_SECRET_2
+#define KC_SEC3 KC_SECRET_3
+#define KC_SEC4 KC_SECRET_4
+#define KC_SEC5 KC_SECRET_5
+#define KC_SEC6 KC_SECRET_6
+
+#define QWERTY KC_QWERTY
+#define DVORAK KC_DVORAK
+#define COLEMAK KC_COLEMAK
+#define WORKMAN KC_WORKMAN
+#define UNICODE KC_UNICODE
+
+#define KC_RESET RESET
+#define KC_RST KC_RESET
+
+#define UC_IRNY UC(0x2E2E)
+#define UC_CLUE UC(0x203D)
diff --git a/users/kuchosauronad0/readme.md b/users/kuchosauronad0/readme.md
new file mode 100644
index 0000000000..8211dc189a
--- /dev/null
+++ b/users/kuchosauronad0/readme.md
@@ -0,0 +1,145 @@
+# qmk userspace for kuchosauronad0
+Thanks to drashna and everyone else in the qmk_firmware/users/ directory :)
+
+# Overview
+
+## Keyboard Layout Templates
+This borrows from @jola5's "Not quite neo" code. This allows me to maintain blocks of keymaps in the userspace, so that I can modify the userspace, and this is reflected in all of the keyboards that use it, at once.
+
+This makes adding tap/hold mods, or other special keycodes or functions to all keyboards super easy, as it's done to all of them at once.
+
+The caveat here is that the keymap needs a processor/wrapper, as it doesn't like the substitutions. However, this is as simple as just pushing it through a define. For instance:
+
+`#define LAYOUT_ergodox_wrapper(...) LAYOUT_ergodox(__VA_ARGS__)`
+
+Once that's been done and you've switched the keymaps to use the "wrapper", it will read the substitution blocks just fine.
+
+Credit goes to @jola5 for first implementing this awesome idea.
+
+## Custom Keycodes
+Declared in `process_records.h` and `template.h` and defined in `process_record_user` in template.c
+
+## Tap Dances
+Set `TAP_DANCE_ENABLE = yes` in rules.mk. See file tap_dances.{c,h}
+
+## Leader Key
+Set `LEADER_ENABLE = yes` in rules.mk.
+TODO: document tmux / vim / os
+
+## Unicode
+TODO: Set `idk` in `idc`
+
+## Diablo Layer
+Currently not in use.
+
+# Secret Macros
+Set `NO_SECRETS = yes` in rules.mk.
+
+With help from gitter and Colinta, this adds the ability to add hidden macros from other users.
+
+First, I have several files that are hidden/excluded from Git/GitHub. These contain everything needed for the macros. To hide these files, open `.git/info/exclude` and add `secrets.c` and `secrets.h` to that file, below the comments.
+
+And this requires `KC_SECRET_1` through `KC_SECRET_5` to be defined in your `<name>.h` file to define the keycodes for the new macros.
+
+
+### .git/info/exclude
+
+```
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
+/users/kuchosauronad0/secrets.c
+/users/kuchosauronad0/secrets.h
+```
+
+Then you can create these files:
+
+### secrets.c
+
+```c
+#include "kuchosauronad0.h" // replace with your keymap's "h" file, or whatever file stores the keycodes
+
+#if (__has_include("secrets.h") && !defined(NO_SECRETS))
+#include "secrets.h"
+#else
+// `PROGMEM const char secret[][x]` may work better, but it takes up more space in the firmware
+// And I'm not familiar enough to know which is better or why...
+static const char * const secret[] = {
+ "test1",
+ "test2",
+ "test3",
+ "test4",
+ "test5"
+};
+#endif
+
+bool process_record_secrets(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case KC_SECRET_1 ... KC_SECRET_5: // Secrets! Externally defined strings, not stored in repo
+ if (!record->event.pressed) {
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+ send_string_with_delay(secret[keycode - KC_SECRET_1], MACRO_TIMER);
+ }
+ return false;
+ break;
+ }
+ return true;
+}
+```
+
+### secrets.h
+
+```c
+static const char * const secrets[] = {
+ "secret1",
+ "secret2",
+ "secret3",
+ "secret4",
+ "secret5"
+};
+```
+
+Replacing the strings with the codes that you need.
+
+### name.c
+
+In the `<name>.c` file, you will want to add this to the top:
+
+```c
+__attribute__ ((weak))
+bool process_record_secrets(uint16_t keycode, keyrecord_t *record) {
+ return true;
+}
+```
+
+This is so that the function can be called here, and replaced in the `secrets.c` file, and so it won't error out if it doesn't exist.
+
+And then, in the `process_record_user` function, assuming you have `return process_record_keymap(keycode, record)` here, you'll want to replace the "final" return with the following. Otherwise, you want to replace the `return true;` with `return process_record_secrets(keycode, record);`
+
+```c
+ return process_record_keymap(keycode, record) && process_record_secrets(keycode, record);
+}
+```
+
+### rules.mk
+
+Here, you want your `/users/<name>/rules.mk` file to "detect" the existence of the `secrets.c` file, and only add it if the file exists. To do so, add this block:
+
+```make
+ifneq ("$(wildcard $(USER_PATH)/secrets.c)","")
+ SRC += secrets.c
+endif
+```
+
+Additionally, if you want to make sure that you can disable the function without messing with the file, you need to add this to your `/users/<name>/rules.mk`, so that it catches the flag:
+
+```make
+ifeq ($(strip $(NO_SECRETS)), yes)
+ OPT_DEFS += -DNO_SECRETS
+endif
+```
+
+Then, if you run `make keyboard:name NO_SECRETS=yes`, it will default to the test strings in your `<name>.c` file, rather than reading from your file.
diff --git a/users/kuchosauronad0/rules.mk b/users/kuchosauronad0/rules.mk
new file mode 100644
index 0000000000..8610a9b7a1
--- /dev/null
+++ b/users/kuchosauronad0/rules.mk
@@ -0,0 +1,44 @@
+SRC += kuchosauronad0.c \
+ process_records.c
+
+LINK_TIME_OPTIMIZATION_ENABLE = yes
+
+#ifneq ("$(wildcard $(USER_PATH)/secrets.c)","")
+# SRC += secrets.c
+#endif
+
+ifeq ($(strip $(TAP_DANCE_ENABLE)), yes)
+ SRC += tap_dances.c
+endif
+
+ifeq ($(strip $(ENCODER_ENABLE)), yes)
+ SRC += encoder.c
+endif
+
+ifeq ($(strip $(LEADER_ENABLE)), yes)
+ SRC += leader.c
+endif
+
+ifneq ("$(wildcard $(USER_PATH)/secrets.c)","")
+ SRC += secrets.c
+endif
+ifeq ($(strip $(NO_SECRETS)), yes)
+ OPT_DEFS += -DNO_SECRETS
+endif
+ifeq ($(strip $(UNICODEMAP_ENABLE)), yes)
+ SRC += unicode.c
+endif
+
+ifeq ($(strip $(MACROS_ENABLED)), yes)
+ OPT_DEFS += -DMACROS_ENABLED
+endif
+
+ifdef CONSOLE_ENABLE
+ ifeq ($(strip $(KEYLOGGER_ENABLE)), yes)
+ OPT_DEFS += -DKEYLOGGER_ENABLE
+ endif
+endif
+
+ifeq ($(strip $(MAKE_BOOTLOADER)), yes)
+ OPT_DEFS += -DMAKE_BOOTLOADER
+endif
diff --git a/users/kuchosauronad0/tap_dances.c b/users/kuchosauronad0/tap_dances.c
new file mode 100644
index 0000000000..4ebb5dc739
--- /dev/null
+++ b/users/kuchosauronad0/tap_dances.c
@@ -0,0 +1,57 @@
+#include "tap_dances.h"
+void td_parenthesis (qk_tap_dance_state_t *state, void *user_data) {
+ if (state->count == 1) {
+ SEND_STRING ("\(");
+ reset_tap_dance (state);
+ }
+ else if (state->count == 2) {
+ SEND_STRING("()" SS_TAP(X_LEFT));
+ //tap_code(KC_2);
+ //tap_code(KC_3);
+ //tap_code(KC_LEFT);
+ reset_tap_dance (state);
+ }
+ else if (state->count == 3) {
+ SEND_STRING("[]" SS_TAP(X_LEFT));
+ reset_tap_dance (state);
+ }
+ else if (state->count == 4) {
+ SEND_STRING("{}" SS_TAP(X_LEFT));
+ reset_tap_dance (state);
+ }
+ else if (state->count >= 5) {
+ SEND_STRING("<>" SS_TAP(X_LEFT));
+ reset_tap_dance (state);
+ }
+}
+
+void safe_reset(qk_tap_dance_state_t *state, void *user_data) {
+ if (state->count >= 3) {
+ // Reset the keyboard if you tap the key more than three times
+ reset_keyboard();
+ reset_tap_dance(state);
+ }
+}
+
+qk_tap_dance_action_t tap_dance_actions[] = {
+ [TD_RESET] = ACTION_TAP_DANCE_FN(safe_reset),
+ [TD_NUM1] = ACTION_TAP_DANCE_DOUBLE(KC_1, KC_4),
+ [TD_NUM2] = ACTION_TAP_DANCE_DOUBLE(KC_2, KC_5),
+ [TD_NUM3] = ACTION_TAP_DANCE_DOUBLE(KC_3, KC_6),
+ [TD_QT1] = ACTION_TAP_DANCE_DOUBLE(KC_QUOT, MC_QT1),
+ [TD_QT2] = ACTION_TAP_DANCE_DOUBLE(LSFT(KC_QUOT), MC_QT2),
+ [TD_QT3] = ACTION_TAP_DANCE_DOUBLE(KC_GRV, MC_QT3),
+
+ [TD_TMX] = ACTION_TAP_DANCE_DOUBLE(KC_T, TM_X),
+ [TD_EOL] = ACTION_TAP_DANCE_DOUBLE(KC_E, MC_EOL), // end of line
+ [TD_BOL] = ACTION_TAP_DANCE_DOUBLE(KC_A, MC_BOL), // beginning of line
+ [TD_NW] = ACTION_TAP_DANCE_DOUBLE(KC_F, MC_NW), // next word
+ [TD_PW] = ACTION_TAP_DANCE_DOUBLE(KC_B, MC_PW), // pevious word
+ [TD_DW] = ACTION_TAP_DANCE_DOUBLE(KC_W, MC_DW), // pevious word
+
+ [TD_SPC] = ACTION_TAP_DANCE_FN(td_parenthesis), // \(, (), [], {}, <>
+ [TD_PAR] = ACTION_TAP_DANCE_DOUBLE(KC_LPRN, MC_PAR), // ()
+ [TD_SQR] = ACTION_TAP_DANCE_DOUBLE(KC_LBRC, MC_SQR), // []
+ [TD_CUR] = ACTION_TAP_DANCE_DOUBLE(LSFT(KC_LCBR), MC_CUR),// {}
+ [TD_ABR] = ACTION_TAP_DANCE_DOUBLE(LSFT(KC_COMM), MC_ABR),//
+};
diff --git a/users/kuchosauronad0/tap_dances.h b/users/kuchosauronad0/tap_dances.h
new file mode 100644
index 0000000000..19da8d69dc
--- /dev/null
+++ b/users/kuchosauronad0/tap_dances.h
@@ -0,0 +1,26 @@
+#pragma once
+#include "kuchosauronad0.h"
+
+#ifdef TAP_DANCE_ENABLE
+enum {
+ TD_RESET = 0,
+ TD_SPC, // for special function td_parenthesis testing
+ TD_NUM1, // compact gaming numpad
+ TD_NUM2, //
+ TD_NUM3, //
+ TD_TMX, // tmux control sequence
+ TD_EOL, // end of line
+ TD_BOL, // beginning of line
+ TD_NW, // next word
+ TD_PW, // pevious word
+ TD_DW, // delete word
+ TD_QT1, // single double quote for '
+ TD_QT2, // single double quote for "
+ TD_QT3, // single double quote for `
+ TD_PAR, // single double parenthesis
+ TD_CUR, // single double curly braces
+ TD_SQR, // single double square brackets
+ TD_ABR // single double angle brackets
+};
+#endif // TAP_DANCE_ENABLE
+void td_parenthesis (qk_tap_dance_state_t *state, void *user_data);
diff --git a/users/kuchosauronad0/template.c b/users/kuchosauronad0/template.c
new file mode 100644
index 0000000000..475e45d391
--- /dev/null
+++ b/users/kuchosauronad0/template.c
@@ -0,0 +1,125 @@
+#include "template.h"
+
+
+// Add reconfigurable functions here, for keymap customization
+// This allows for a global, userspace functions, and continued
+// customization of the keymap. Use _keymap instead of _user
+// functions in the keymaps
+__attribute__ ((weak))
+void matrix_init_keymap(void) {}
+
+// Call user matrix init, then call the keymap's init function
+void matrix_init_user(void) {
+ matrix_init_keymap();
+}
+
+
+__attribute__ ((weak))
+void matrix_scan_keymap(void) {}
+
+// No global matrix scan code, so just run keymap's matix
+// scan function
+__attribute__ ((weak))
+void matrix_scan_user(void) {
+ matrix_scan_keymap();
+}
+
+
+__attribute__ ((weak))
+bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
+ return true;
+}
+
+// Defines actions tor my global custom keycodes. Defined in drashna.h file
+// Then runs the _keymap's recod handier if not processed here,
+// And use "NEWPLACEHOLDER" for new safe range
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+
+ switch (keycode) {
+ case KC_MAKE:
+ if (!record->event.pressed) {
+ SEND_STRING("make " QMK_KEYBOARD ":" QMK_KEYMAP
+#if (defined(BOOTLOADER_DFU) || defined(BOOTLOADER_LUFA_DFU) || defined(BOOTLOADER_QMK_DFU))
+ ":dfu"
+#elif defined(BOOTLOADER_HALFKAY)
+ ":teensy"
+#elif defined(BOOTLOADER_CATERINA)
+ ":avrdude"
+#endif
+ SS_TAP(X_ENTER));
+ }
+ return false;
+ break;
+
+ case VRSN:
+ if (record->event.pressed) {
+ SEND_STRING(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION);
+ }
+ return false;
+ break;
+ }
+ return process_record_keymap(keycode, record);
+}
+
+
+__attribute__ ((weak))
+uint32_t layer_state_set_keymap (uint32_t state) {
+ return state;
+}
+
+uint32_t layer_state_set_user (uint32_t state) {
+ return layer_state_set_keymap (state);
+}
+
+
+
+__attribute__ ((weak))
+void led_set_keymap(uint8_t usb_led) {}
+
+void led_set_user(uint8_t usb_led) {
+ led_set_keymap(usb_led);
+}
+
+
+
+__attribute__ ((weak))
+void suspend_power_down_keymap(void) {}
+
+void suspend_power_down_user(void)
+{
+ suspend_power_down_keymap();
+}
+
+
+
+__attribute__ ((weak))
+void suspend_wakeup_init_keymap(void) {}
+
+void suspend_wakeup_init_user(void)
+{
+ suspend_wakeup_init_keymap();
+ #ifdef KEYBOARD_ergodox_ez
+ wait_ms(10);
+ #endif
+}
+
+
+
+__attribute__ ((weak))
+void startup_keymap(void) {}
+
+void startup_user (void) {
+ #ifdef RGBLIGHT_ENABLE
+ matrix_init_rgb();
+ #endif //RGBLIGHT_ENABLE
+ startup_keymap();
+}
+
+
+
+__attribute__ ((weak))
+void shutdown_keymap(void) {}
+
+void shutdown_user (void) {
+ shutdown_keymap();
+}
diff --git a/users/kuchosauronad0/template.h b/users/kuchosauronad0/template.h
new file mode 100644
index 0000000000..dd1c487604
--- /dev/null
+++ b/users/kuchosauronad0/template.h
@@ -0,0 +1,18 @@
+#ifndef USERSPACE
+#define USERSPACE
+
+#include "quantum.h"
+#include "version.h"
+#include "eeprom.h"
+
+// Define layer names
+#define BASE 0
+
+enum custom_keycodes {
+ VRSN = SAFE_RANGE, // can always be here
+ KC_MAKE,
+ KC_RESET,
+ NEWPLACEHOLDER //use "NEWPLACEHOLDER for keymap specific codes
+};
+
+#endif
diff --git a/users/kuchosauronad0/unicode.c b/users/kuchosauronad0/unicode.c
new file mode 100644
index 0000000000..8b312deb66
--- /dev/null
+++ b/users/kuchosauronad0/unicode.c
@@ -0,0 +1,62 @@
+#include "unicode.h"
+
+//#ifdef UNICODEMAP_ENABLE
+const uint32_t PROGMEM unicode_map[] = {
+ [BANG] = 0x0203D,// ‽
+ [IRONY] = 0x02E2E,// ⸮
+ [DEGREE] = 0x000B0,// °
+ [THINK] = 0x1F914,// 🤔
+ [GRIN] = 0x1F600,// �
+ [MONOCL] = 0x1F9D0,// 🧐
+ [DRUG0] = 0x1F92A,// 🤪
+ [DRUG1] = 0x1F974,// 🥴
+ [CLOWN] = 0x1F921,// 🤡
+ [MNDBLWN] = 0x1F92F,// 🤯
+ [MONEY] = 0x1F911,// 🤑
+ [SHTUP] = 0x1F910,// 🤐
+ [PARTY] = 0x1F973,// 🥳
+ [SMRK] = 0x1F60F,// 😏
+ [WEARY] = 0x1F629,// 😩
+ [UNAMU] = 0x1F612,// 😒
+ [SPY] = 0x1F575,//🕵
+ [DAFUQ] = 0x1F47A,// 👺
+ [FIST0] = 0x1F91B,// 🤛
+ [FIST1] = 0x1F91C,// 🤜
+ [FIST2] = 0x270A, // ✊
+ [FIST3] = 0x1F44A,// 👊
+ [WIFIHAND] = 0x1F44B,// 👋
+ [OKOK] = 0x1F44C,// 👌
+ [EFFU] = 0x1F595,// 🖕
+ [SPOCK] = 0x1F596,// 🖖
+ [INUP] = 0x1F446,// 👆
+ [THDN] = 0x1F44E,// 👎
+ [THUP] = 0x1F44D,// 👍
+ [TUMBLER] = 0x1F943,// 🥃
+ [DRAGON0] = 0x1F409,// 🐉
+ [DRAGON1] = 0x1F432,// 🐲
+ [TIGER0] = 0x1F405,// 🐅
+ [TIGER1] = 0x1F42F,// 🐯
+ [COOL] = 0x1F192,// 🆒
+ [UCHART] = 0x1F4C8,// 📈
+ [DCHART] = 0x1F4C9,// 📉
+ [BCHART] = 0x1F4CA,// 📊
+ [NOPRCY] = 0x1F572,// 🕲
+ [PRCY] = 0x1F571,// 🕱
+ [BBB] = 0x1F171,// 🅱
+ [POO] = 0x1F4A9,// 💩
+ [HUNDR] = 0x1F4AF,// 💯
+ [EGGPL] = 0x1F346,// 🍆
+ [WATER] = 0x1F4A6,// 💦
+ [LIT] = 0x1F525,// 🔥
+ [SNEK] = 0x1F40D,// 🐍
+ [PENGUIN] = 0x1F427,// 🐧
+ [BOAR] = 0x1F417,// 🐗
+ [MONKEY] = 0x1F412,// 🐒
+ [CHICK] = 0x1F425,// 🐥
+ [DASH] = 0x1F4A8,// 💨
+ [DIZZY] = 0x1F4AB,// 💫
+ [KEEB] = 0x1F5AE,// 🖮
+ [HOLE] = 0x1F573,// 🕳
+ [SAUCER] = 0x1F6F8// 🛸
+ };
+//#endif // UNICODEMAP_ENABLE
diff --git a/users/kuchosauronad0/unicode.h b/users/kuchosauronad0/unicode.h
new file mode 100644
index 0000000000..cb550243ee
--- /dev/null
+++ b/users/kuchosauronad0/unicode.h
@@ -0,0 +1,67 @@
+#pragma once
+
+#include "quantum.h"
+
+void send_unicode_hex_string(const char* str);
+
+/* use X(n) to call the */
+#ifdef UNICODEMAP_ENABLE
+enum unicode_name {
+OKOK, //
+BANG, // ‽
+IRONY, // ⸮
+DEGREE, // °
+THINK, // 🤔
+GRIN, // �
+MONOCL, // 🧐
+DRUG0, // 🤪
+DRUG1, // 🥴
+CLOWN, // 🤡
+MNDBLWN, // 🤯
+MONEY, // 🤑
+SHTUP, // 🤐
+PARTY, // 🥳
+SMRK, // 😏
+WEARY, // 😩
+UNAMU, // 😒
+SPY, // 🕵
+DAFUQ, // 👺
+FIST0, // 🤛
+FIST1, // 🤜
+FIST2, // ✊
+FIST3, // 👊
+WIFIHAND, // 👌
+EFFU, // 🖕
+SPOCK, // 🖖
+INUP, // 👆
+THDN, // 👎
+THUP, // 👍
+TUMBLER, // 🥃
+DRAGON0, // 🐉
+DRAGON1, // 🐅
+TIGER0, // 🐅
+TIGER1, // 🐯
+COOL, // 🆒
+UCHART, // 📈
+DCHART, // 📉
+BCHART, // 📊
+NOPRCY, // 🕲
+PRCY, // 🕱
+BBB, // 🅱
+POO, // 💩
+HUNDR, // 💯
+EGGPL, // 🍆
+WATER, // 💦
+LIT, // 🔥
+SNEK, // 🐍
+PENGUIN, // 🐧
+BOAR, // 🐗
+MONKEY, // 🐒
+CHICK, // 🐥
+DASH, // 💨
+DIZZY, // 💫
+KEEB, // 🖮
+HOLE, // 🕳
+SAUCER // 🛸
+};
+#endif
diff --git a/users/kuchosauronad0/wrappers.h b/users/kuchosauronad0/wrappers.h
new file mode 100644
index 0000000000..3172c8a6d3
--- /dev/null
+++ b/users/kuchosauronad0/wrappers.h
@@ -0,0 +1,206 @@
+#pragma once
+#include "kuchosauronad0.h"
+/*
+Since our quirky block definitions are basically a list of comma separated
+arguments, we need a wrapper in order for these definitions to be
+expanded before being used as arguments to the LAYOUT_xxx macro.
+*/
+#if (!defined(LAYOUT) && defined(KEYMAP))
+#define LAYOUT KEYMAP
+#endif
+
+#define LAYOUT_ergodox_wrapper(...) LAYOUT_ergodox(__VA_ARGS__)
+#define LAYOUT_ergodox_pretty_wrapper(...) LAYOUT_ergodox_pretty(__VA_ARGS__)
+#define KEYMAP_wrapper(...) LAYOUT(__VA_ARGS__)
+#define LAYOUT_wrapper(...) LAYOUT(__VA_ARGS__)
+#define LAYOUT_ortho_4x12_wrapper(...) LAYOUT_ortho_4x12(__VA_ARGS__)
+#define LAYOUT_ortho_5x12_wrapper(...) LAYOUT_ortho_5x12(__VA_ARGS__)
+
+/*
+Blocks for each of the four major keyboard layouts
+Organized so we can quickly adapt and modify all of them
+at once, rather than for each keyboard, one at a time.
+And this allows for much cleaner blocks in the keymaps.
+For instance Tap/Hold for Control on all of the layouts
+NOTE: These are all the same length. If you do a search/replace
+ then you need to add/remove underscores to keep the
+ lengths consistent.
+*/
+#ifdef TAP_DANCE_ENABLE
+ #define _________________QWERTY_L1_________________ KC_Q, KC_DW, KC_EOL, KC_R, KC_TMX
+ #define _________________QWERTY_L2_________________ KC_BOL, KC_S, KC_D, KC_NW, KC_G
+ #define _________________QWERTY_L3_________________ KC_Z, KC_X, KC_C, KC_V, KC_PW
+#else
+ #define _________________QWERTY_L1_________________ KC_Q, KC_W, KC_E, KC_R, KC_T
+ #define _________________QWERTY_L2_________________ KC_A, KC_S, KC_D, KC_F, KC_G
+ #define _________________QWERTY_L3_________________ KC_Z, KC_X, KC_C, KC_V, KC_B
+#endif
+
+#define _________________QWERTY_R1_________________ KC_Y, KC_U, KC_I, KC_O, KC_P
+#define _________________QWERTY_R2_________________ KC_H, KC_J, KC_K, KC_L, KC_SCLN
+#define _________________QWERTY_R3_________________ KC_N, KC_M, KC_COMM, KC_DOT, KC_SLASH
+
+
+#define _________________COLEMAK_L1________________ KC_Q, KC_W, KC_F, KC_P, KC_G
+#define _________________COLEMAK_L2________________ KC_A, KC_R, KC_S, KC_T, KC_D
+#define _________________COLEMAK_L3________________ KC_Z, KC_X, KC_C, KC_V, KC_B
+
+#define _________________COLEMAK_R1________________ KC_J, KC_L, KC_U, KC_Y, KC_SCLN
+#define _________________COLEMAK_R2________________ KC_H, KC_N, KC_E, KC_I, KC_O
+#define _________________COLEMAK_R3________________ KC_K, KC_M, KC_COMM, KC_DOT, KC_SLASH
+
+#define ______________COLEMAK_MOD_DH_L1____________ KC_Q, KC_W, KC_F, KC_P, KC_B
+#define ______________COLEMAK_MOD_DH_L2____________ KC_A, KC_R, KC_S, KC_T, KC_G
+#define ______________COLEMAK_MOD_DH_L3____________ KC_Z, KC_X, KC_C, KC_D, KC_V
+
+#define ______________COLEMAK_MOD_DH_R1____________ KC_J, KC_L, KC_U, KC_Y, KC_SCLN
+#define ______________COLEMAK_MOD_DH_R2____________ KC_M, KC_N, KC_E, KC_I, KC_O
+#define ______________COLEMAK_MOD_DH_R3____________ KC_K, KC_H, KC_COMM, KC_DOT, KC_SLASH
+
+
+#define _________________DVORAK_L1_________________ KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y
+#define _________________DVORAK_L2_________________ KC_A, KC_O, KC_E, KC_U, KC_I
+#define _________________DVORAK_L3_________________ KC_SCLN, KC_Q, KC_J, KC_K, KC_X
+
+#define _________________DVORAK_R1_________________ KC_F, KC_G, KC_C, KC_R, KC_L
+#define _________________DVORAK_R2_________________ KC_D, KC_H, KC_T, KC_N, KC_S
+#define _________________DVORAK_R3_________________ KC_B, KC_M, KC_W, KC_V, KC_Z
+
+#define ________________DVORAK_AU_L1_______________ KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y
+#define ________________DVORAK_AU_L2_______________ KC_O, KC_A, KC_E, KC_I, KC_U
+#define ________________DVORAK_AU_L3_______________ KC_SCLN, KC_Q, KC_J, KC_K, KC_X
+
+#define ________________DVORAK_AU_R1_______________ KC_F, KC_G, KC_C, KC_R, KC_L
+#define ________________DVORAK_AU_R2_______________ KC_D, KC_H, KC_T, KC_N, KC_S
+#define ________________DVORAK_AU_R3_______________ KC_B, KC_M, KC_W, KC_V, KC_Z
+
+
+#define _________________WORKMAN_L1________________ KC_Q, KC_D, KC_R, KC_W, KC_B
+#define _________________WORKMAN_L2________________ KC_A, KC_S, KC_H, KC_T, KC_G
+#define _________________WORKMAN_L3________________ KC_Z, KC_X, KC_M, KC_C, KC_V
+
+#define _________________WORKMAN_R1________________ KC_J, KC_F, KC_U, KC_P, KC_SCLN
+#define _________________WORKMAN_R2________________ KC_Y, KC_N, KC_E, KC_O, KC_I
+#define _________________WORKMAN_R3________________ KC_K, KC_L, KC_COMM, KC_DOT, KC_SLASH
+
+
+#define _________________NORMAN_L1_________________ KC_Q, KC_W, KC_D, KC_F, KC_K
+#define _________________NORMAN_L2_________________ KC_A, KC_S, KC_E, KC_T, KC_G
+#define _________________NORMAN_L3_________________ KC_Z, KC_X, KC_C, KC_V, KC_B
+
+#define _________________NORMAN_R1_________________ KC_J, KC_U, KC_R, KC_L, KC_SCLN
+#define _________________NORMAN_R2_________________ KC_Y, KC_N, KC_I, KC_O, KC_U
+#define _________________NORMAN_R3_________________ KC_P, KC_M, KC_COMM, KC_DOT, KC_SLASH
+
+
+#define _________________MALTRON_L1________________ KC_Q, KC_P, KC_Y, KC_C, KC_B
+#define _________________MALTRON_L2________________ KC_A, KC_N, KC_I, KC_S, KC_F
+#define _________________MALTRON_L3________________ KC_SCLN, KC_SLSH, KC_J, KC_G, KC_COMM
+
+#define _________________MALTRON_R1________________ KC_V, KC_M, KC_U, KC_Z, KC_L
+#define _________________MALTRON_R2________________ KC_D, KC_T, KC_D, KC_O, KC_R
+#define _________________MALTRON_R3________________ KC_DOT, KC_W, KC_K, KC_MINS, KC_X
+
+
+#define _________________EUCALYN_L1________________ KC_SLSH, KC_COMM, KC_DOT, KC_F, KC_Q
+#define _________________EUCALYN_L2________________ KC_A, KC_O, KC_E, KC_I, KC_U
+#define _________________EUCALYN_L3________________ KC_Z, KC_X, KC_C, KC_V, KC_W
+
+#define _________________EUCALYN_R1________________ KC_M, KC_R, KC_D, KC_Y, KC_P
+#define _________________EUCALYN_R2________________ KC_G, KC_T, KC_K, KC_S, KC_N
+#define _________________EUCALYN_R3________________ KC_B, KC_H, KC_J, KC_L, KC_SCLN
+
+
+#define _____________CARPLAX_QFMLWY_L1_____________ KC_Q, KC_F, KC_M, KC_L, KC_W
+#define _____________CARPLAX_QFMLWY_L2_____________ KC_D, KC_S, KC_T, KC_N, KC_R
+#define _____________CARPLAX_QFMLWY_L3_____________ KC_Z, KC_V, KC_G, KC_C, KC_X
+
+#define _____________CARPLAX_QFMLWY_R1_____________ KC_Y, KC_U, KC_O, KC_B, KC_J
+#define _____________CARPLAX_QFMLWY_R2_____________ KC_I, KC_A, KC_E, KC_H, KC_SCLN
+#define _____________CARPLAX_QFMLWY_R3_____________ KC_P, KC_K, KC_COMM, KC_DOT, KC_SLSH
+
+
+#define _____________CARPLAX_QGMLWB_L1_____________ KC_Q, KC_G, KC_M, KC_L, KC_W
+#define _____________CARPLAX_QGMLWB_L2_____________ KC_D, KC_S, KC_T, KC_N, KC_R
+#define _____________CARPLAX_QGMLWB_L3_____________ KC_Z, KC_X, KC_C, KC_F, KC_J
+
+#define _____________CARPLAX_QGMLWB_R1_____________ KC_B, KC_Y, KC_U, KC_V, KC_SCLN
+#define _____________CARPLAX_QGMLWB_R2_____________ KC_I, KC_A, KC_E, KC_O, KC_H
+#define _____________CARPLAX_QGMLWB_R3_____________ KC_K, KC_P, KC_COMM, KC_DOT, KC_SLSH
+
+
+#define _____________CARPLAX_QGMLWY_L1_____________ KC_Q, KC_G, KC_M, KC_L, KC_W
+#define _____________CARPLAX_QGMLWY_L2_____________ KC_D, KC_S, KC_T, KC_N, KC_R
+#define _____________CARPLAX_QGMLWY_L3_____________ KC_Z, KC_X, KC_C, KC_V, KC_J
+
+#define _____________CARPLAX_QGMLWY_R1_____________ KC_Y, KC_F, KC_U, KC_B, KC_SCLN
+#define _____________CARPLAX_QGMLWY_R2_____________ KC_I, KC_A, KC_E, KC_O, KC_H
+#define _____________CARPLAX_QGMLWY_R3_____________ KC_K, KC_P, KC_COMM, KC_DOT, KC_SLSH
+
+#ifdef UNICODE_ENABLE
+#define _______________UNICODE_L1__________________ UC_DISA,UC_DISA, UC_DISA, UC_DISA, UC_DISA
+#define _______________UNICODE_L2__________________ UC_DISA,UC_DISA, UC_DISA, UC_DISA, UC_DISA
+#define _______________UNICODE_L3__________________ UC_DISA,UC_DISA, UC_DISA, UC_DISA, UC_DISA
+
+#define _______________UNICODE_R1__________________ UC_SHRG, UC_SHRG, UC_SHRG, UC_SHRG, UC_SHRG
+#define _______________UNICODE_R2__________________ UC_SHRG, UC_SHRG, UC_SHRG, UC_SHRG, UC_SHRG
+#define _______________UNICODE_R3__________________ UC_SHRG, UC_SHRG, UC_SHRG, UC_SHRG, UC_SHRG
+#endif
+
+#ifdef UNICODEMAP_ENABLE
+#define _______________UNICODE_L1__________________ X(SMRK), X(THINK), X(CLOWN), X(HUNDR), X(BANG)
+#define _______________UNICODE_L2__________________ X(GRIN), X(MONKEY), X(OKOK), X(EGGPL), X(LIT)
+#define _______________UNICODE_L3__________________ X(WEARY), X(UNAMU), X(EFFU), X(MONOCL), X(IRONY)
+
+#define _______________UNICODE_R1__________________ X(DRUG0), X(THUP), X(INUP), X(DIZZY), X(COOL)
+#define _______________UNICODE_R2__________________ X(FIST0), X(FIST2),X(FIST3),X(FIST1), X(OKOK)
+#define _______________UNICODE_R3__________________ X(MNDBLWN), X(THDN), X(SPOCK),X(HOLE), X(DASH)
+#endif
+
+#define ________________NUMBER_LEFT________________ KC_1, KC_2, KC_3, KC_4, KC_5
+#define ________________NUMBER_RIGHT_______________ KC_6, KC_7, KC_8, KC_9, KC_0
+#define _________________FUNC_LEFT_________________ KC_F1, KC_F2, KC_F3, KC_F4, KC_F5
+#define _________________FUNC_RIGHT________________ KC_F6, KC_F7, KC_F8, KC_F9, KC_F10
+
+#define ___________________BLANK___________________ _______, _______, _______, _______, _______
+
+
+#define _________________LOWER_L1__________________ KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC
+#define _________________LOWER_L2__________________ ___________________BLANK___________________
+#define _________________LOWER_L3__________________ ___________________BLANK___________________
+
+#define _________________LOWER_R1__________________ KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN
+#define _________________LOWER_R2__________________ OS_UNI, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR
+#define _________________LOWER_R3__________________ TM_X, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT
+
+
+
+#define _________________RAISE_L1__________________ ________________NUMBER_LEFT________________
+#define _________________RAISE_L2__________________ ___________________BLANK___________________
+#define _________________RAISE_L3__________________ ___________________BLANK___________________
+
+#define _________________RAISE_R1__________________ ________________NUMBER_RIGHT_______________
+#define _________________RAISE_R2__________________ _______, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC
+#define _________________RAISE_R3__________________ _______, KC_HOME, KC_PGDN, KC_PGUP, KC_END
+
+
+
+#define _________________ADJUST_L1_________________ ___________________BLANK___________________
+#define _________________ADJUST_L2_________________ _________________FUNC_LEFT_________________
+#define _________________ADJUST_L3_________________ AG_SWAP, QWERTY, COLEMAK, DVORAK, WORKMAN
+
+#define _________________ADJUST_R1_________________ KC_SEC1, KC_SEC2, KC_SEC3, KC_SEC4, KC_SEC5
+#define _________________ADJUST_R2_________________ _________________FUNC_RIGHT________________
+#define _________________ADJUST_R3_________________ KC_MUTE, KC_MUTE, KC_VOLD, KC_VOLU, KC_MNXT
+
+
+/*
+#define _________________RGB_L1____________________ RGB_MOD, RGB_HUI, RGB_SAI, RGB_VAI, RGB_TOG
+#define _________________RGB_L2____________________ MU_TOG , CK_TOGG, AU_ON, AU_OFF, AG_NORM
+#define _________________RGB_L3____________________ RGB_RMOD,RGB_HUD,RGB_SAD, RGB_VAD, KC_RGB_T
+#define _________________RGB_R1____________________ RGB_MOD, RGB_HUI, RGB_SAI, RGB_VAI, RGB_TOG
+#define _________________RGB_R2____________________ MU_TOG , CK_TOGG, AU_ON, AU_OFF, AG_NORM
+#define _________________RGB_R3____________________ RGB_RMOD,RGB_HUD,RGB_SAD, RGB_VAD, KC_RGB_T
+*/
+/* vi: ft=c:tw=80:sw=2:ts=2:sts=2:et
+ */