diff options
| author | Drashna Jaelre <drashna@live.com> | 2021-12-14 20:53:36 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-12-14 20:53:36 -0800 |
| commit | 3fa592a4024a24a636fa0c562e6761667a94f565 (patch) | |
| tree | 4ce826128e29e36dfe606fa2b5a3d25b3bd0afcc /users/drashna | |
| parent | c10bc9f91e737dd3675b2e4492daa09092655af9 (diff) | |
| download | qmk_firmware-3fa592a4024a24a636fa0c562e6761667a94f565.tar.gz qmk_firmware-3fa592a4024a24a636fa0c562e6761667a94f565.zip | |
[Keymap] Unicode and Pointing Device and Autocorect for drashna keymaps (#15415)
Diffstat (limited to 'users/drashna')
| -rw-r--r-- | users/drashna/config.h | 4 | ||||
| -rw-r--r-- | users/drashna/drashna.c | 10 | ||||
| -rw-r--r-- | users/drashna/drashna.h | 21 | ||||
| -rw-r--r-- | users/drashna/keyrecords/autocorrection/autocorrection.c | 143 | ||||
| -rw-r--r-- | users/drashna/keyrecords/autocorrection/autocorrection.h | 10 | ||||
| -rwxr-xr-x | users/drashna/keyrecords/autocorrection/make_autocorrection_data.py | 273 | ||||
| -rw-r--r-- | users/drashna/keyrecords/caps_word.c | 69 | ||||
| -rw-r--r-- | users/drashna/keyrecords/caps_word.h | 8 | ||||
| -rw-r--r-- | users/drashna/keyrecords/process_records.c (renamed from users/drashna/process_records.c) | 17 | ||||
| -rw-r--r-- | users/drashna/keyrecords/process_records.h (renamed from users/drashna/process_records.h) | 7 | ||||
| -rw-r--r-- | users/drashna/keyrecords/tap_dances.c (renamed from users/drashna/tap_dances.c) | 0 | ||||
| -rw-r--r-- | users/drashna/keyrecords/tap_dances.h (renamed from users/drashna/tap_dances.h) | 0 | ||||
| -rw-r--r-- | users/drashna/keyrecords/unicode.c (renamed from users/drashna/unicoooode.c) | 11 | ||||
| -rw-r--r-- | users/drashna/keyrecords/wrappers.h (renamed from users/drashna/wrappers.h) | 0 | ||||
| -rw-r--r-- | users/drashna/oled/drashna_font.h (renamed from users/drashna/drashna_font.h) | 0 | ||||
| -rw-r--r-- | users/drashna/oled/oled_stuff.c (renamed from users/drashna/oled_stuff.c) | 8 | ||||
| -rw-r--r-- | users/drashna/oled/oled_stuff.h (renamed from users/drashna/oled_stuff.h) | 0 | ||||
| -rw-r--r-- | users/drashna/pointing/pointing.c | 136 | ||||
| -rw-r--r-- | users/drashna/pointing/pointing.h | 23 | ||||
| -rw-r--r-- | users/drashna/readme.md | 12 | ||||
| -rw-r--r-- | users/drashna/readme/handlers.md (renamed from users/drashna/readme_handlers.md) | 0 | ||||
| -rw-r--r-- | users/drashna/readme/keycodes.md (renamed from users/drashna/readme_keycodes.md) | 0 | ||||
| -rw-r--r-- | users/drashna/readme/rgb.md (renamed from users/drashna/readme_rgb.md) | 0 | ||||
| -rw-r--r-- | users/drashna/readme/secrets.md (renamed from users/drashna/readme_secrets.md) | 0 | ||||
| -rw-r--r-- | users/drashna/readme/tap_dance.md (renamed from users/drashna/readme_tap_dance.md) | 0 | ||||
| -rw-r--r-- | users/drashna/readme/wrappers.md (renamed from users/drashna/readme_wrappers.md) | 0 | ||||
| -rw-r--r-- | users/drashna/rgb/rgb_matrix_stuff.c (renamed from users/drashna/rgb_matrix_stuff.c) | 0 | ||||
| -rw-r--r-- | users/drashna/rgb/rgb_matrix_stuff.h (renamed from users/drashna/rgb_matrix_stuff.h) | 0 | ||||
| -rw-r--r-- | users/drashna/rgb/rgb_stuff.c (renamed from users/drashna/rgb_stuff.c) | 0 | ||||
| -rw-r--r-- | users/drashna/rgb/rgb_stuff.h (renamed from users/drashna/rgb_stuff.h) | 0 | ||||
| -rw-r--r-- | users/drashna/rules.mk | 40 | ||||
| -rw-r--r-- | users/drashna/split/transport_sync.c (renamed from users/drashna/transport_sync.c) | 0 | ||||
| -rw-r--r-- | users/drashna/split/transport_sync.h (renamed from users/drashna/transport_sync.h) | 0 |
33 files changed, 751 insertions, 41 deletions
diff --git a/users/drashna/config.h b/users/drashna/config.h index 8b5d5ba93..cc8f9ac83 100644 --- a/users/drashna/config.h +++ b/users/drashna/config.h | |||
| @@ -77,7 +77,7 @@ | |||
| 77 | # endif | 77 | # endif |
| 78 | #endif // !AUDIO_ENABLE | 78 | #endif // !AUDIO_ENABLE |
| 79 | 79 | ||
| 80 | #define UNICODE_SELECTED_MODES UC_WIN, UC_MAC | 80 | #define UNICODE_SELECTED_MODES UC_WINC, UC_MAC |
| 81 | 81 | ||
| 82 | #ifdef RGBLIGHT_ENABLE | 82 | #ifdef RGBLIGHT_ENABLE |
| 83 | # define RGBLIGHT_SLEEP | 83 | # define RGBLIGHT_SLEEP |
| @@ -200,7 +200,7 @@ | |||
| 200 | # ifdef OLED_FONT_H | 200 | # ifdef OLED_FONT_H |
| 201 | # undef OLED_FONT_H | 201 | # undef OLED_FONT_H |
| 202 | # endif | 202 | # endif |
| 203 | # define OLED_FONT_H "drashna_font.h" | 203 | # define OLED_FONT_H "oled/drashna_font.h" |
| 204 | # define OLED_FONT_END 255 | 204 | # define OLED_FONT_END 255 |
| 205 | // # define OLED_FONT_5X5 | 205 | // # define OLED_FONT_5X5 |
| 206 | // # define OLED_FONT_AZTECH | 206 | // # define OLED_FONT_AZTECH |
diff --git a/users/drashna/drashna.c b/users/drashna/drashna.c index 7e07a2c7c..9c1233ed9 100644 --- a/users/drashna/drashna.c +++ b/users/drashna/drashna.c | |||
| @@ -70,7 +70,9 @@ void matrix_init_user(void) { | |||
| 70 | DDRB &= ~(1 << 0); | 70 | DDRB &= ~(1 << 0); |
| 71 | PORTB &= ~(1 << 0); | 71 | PORTB &= ~(1 << 0); |
| 72 | #endif | 72 | #endif |
| 73 | 73 | #ifdef CUSTOM_UNICODE_ENABLE | |
| 74 | matrix_init_unicode(); | ||
| 75 | #endif | ||
| 74 | matrix_init_secret(); | 76 | matrix_init_secret(); |
| 75 | matrix_init_keymap(); | 77 | matrix_init_keymap(); |
| 76 | } | 78 | } |
| @@ -152,6 +154,9 @@ void matrix_scan_user(void) { | |||
| 152 | #if defined(RGB_MATRIX_ENABLE) | 154 | #if defined(RGB_MATRIX_ENABLE) |
| 153 | matrix_scan_rgb_matrix(); | 155 | matrix_scan_rgb_matrix(); |
| 154 | #endif | 156 | #endif |
| 157 | #if defined(POINTING_DEVICE_ENABLE) | ||
| 158 | matrix_scan_pointing(); | ||
| 159 | #endif | ||
| 155 | 160 | ||
| 156 | matrix_scan_secret(); | 161 | matrix_scan_secret(); |
| 157 | 162 | ||
| @@ -171,6 +176,9 @@ layer_state_t layer_state_set_user(layer_state_t state) { | |||
| 171 | } | 176 | } |
| 172 | 177 | ||
| 173 | state = update_tri_layer_state(state, _RAISE, _LOWER, _ADJUST); | 178 | state = update_tri_layer_state(state, _RAISE, _LOWER, _ADJUST); |
| 179 | #if defined(POINTING_DEVICE_ENABLE) | ||
| 180 | state = layer_state_set_pointing(state); | ||
| 181 | #endif | ||
| 174 | #if defined(RGBLIGHT_ENABLE) | 182 | #if defined(RGBLIGHT_ENABLE) |
| 175 | state = layer_state_set_rgb_light(state); | 183 | state = layer_state_set_rgb_light(state); |
| 176 | #endif // RGBLIGHT_ENABLE | 184 | #endif // RGBLIGHT_ENABLE |
diff --git a/users/drashna/drashna.h b/users/drashna/drashna.h index 6a45141d9..7bcae881e 100644 --- a/users/drashna/drashna.h +++ b/users/drashna/drashna.h | |||
| @@ -18,25 +18,25 @@ | |||
| 18 | #include QMK_KEYBOARD_H | 18 | #include QMK_KEYBOARD_H |
| 19 | 19 | ||
| 20 | #include "eeprom.h" | 20 | #include "eeprom.h" |
| 21 | #include "wrappers.h" | 21 | #include "keyrecords/wrappers.h" |
| 22 | #include "process_records.h" | 22 | #include "keyrecords/process_records.h" |
| 23 | #ifdef TAP_DANCE_ENABLE | 23 | #ifdef TAP_DANCE_ENABLE |
| 24 | # include "tap_dances.h" | 24 | # include "keyrecords/tap_dances.h" |
| 25 | #endif // TAP_DANCE_ENABLE | 25 | #endif // TAP_DANCE_ENABLE |
| 26 | #if defined(RGBLIGHT_ENABLE) | 26 | #if defined(RGBLIGHT_ENABLE) |
| 27 | # include "rgb_stuff.h" | 27 | # include "rgb/rgb_stuff.h" |
| 28 | #endif | 28 | #endif |
| 29 | #if defined(RGB_MATRIX_ENABLE) | 29 | #if defined(RGB_MATRIX_ENABLE) |
| 30 | # include "rgb_matrix_stuff.h" | 30 | # include "rgb/rgb_matrix_stuff.h" |
| 31 | #endif | 31 | #endif |
| 32 | #if defined(OLED_ENABLE) | 32 | #if defined(OLED_ENABLE) |
| 33 | # include "oled_stuff.h" | 33 | # include "oled/oled_stuff.h" |
| 34 | #endif | ||
| 35 | #if defined(PIMORONI_TRACKBALL_ENABLE) | ||
| 36 | # include "drivers/sensors/pimoroni_trackball.h" | ||
| 37 | #endif | 34 | #endif |
| 38 | #ifdef SPLIT_KEYBOARD | 35 | #ifdef SPLIT_KEYBOARD |
| 39 | # include "transport_sync.h" | 36 | # include "split/transport_sync.h" |
| 37 | #endif | ||
| 38 | #ifdef POINTING_DEVICE_ENABLE | ||
| 39 | # include "pointing/pointing.h" | ||
| 40 | #endif | 40 | #endif |
| 41 | 41 | ||
| 42 | /* Define layer names */ | 42 | /* Define layer names */ |
| @@ -113,6 +113,7 @@ typedef union { | |||
| 113 | bool nuke_switch :1; | 113 | bool nuke_switch :1; |
| 114 | bool swapped_numbers :1; | 114 | bool swapped_numbers :1; |
| 115 | bool rgb_matrix_idle_anim :1; | 115 | bool rgb_matrix_idle_anim :1; |
| 116 | bool autocorrection :1; | ||
| 116 | }; | 117 | }; |
| 117 | } userspace_config_t; | 118 | } userspace_config_t; |
| 118 | // clang-format on | 119 | // clang-format on |
diff --git a/users/drashna/keyrecords/autocorrection/autocorrection.c b/users/drashna/keyrecords/autocorrection/autocorrection.c new file mode 100644 index 000000000..7c8c28c67 --- /dev/null +++ b/users/drashna/keyrecords/autocorrection/autocorrection.c | |||
| @@ -0,0 +1,143 @@ | |||
| 1 | // Copyright 2021 Google LLC | ||
| 2 | // Copyright 2022 @filterpaper | ||
| 3 | // SPDX-License-Identifier: Apache-2.0 | ||
| 4 | // Original source: https://getreuer.info/posts/keyboards/autocorrection | ||
| 5 | |||
| 6 | #include "autocorrection.h" | ||
| 7 | #include <string.h> | ||
| 8 | |||
| 9 | #if __has_include("autocorrection_data.h") | ||
| 10 | # include "autocorrection_data.h" | ||
| 11 | # if AUTOCORRECTION_MIN_LENGTH < 4 | ||
| 12 | # error Minimum Length is too short and may cause overflows | ||
| 13 | # endif | ||
| 14 | |||
| 15 | bool process_autocorrection(uint16_t keycode, keyrecord_t* record) { | ||
| 16 | static uint8_t typo_buffer[AUTOCORRECTION_MAX_LENGTH] = {KC_SPC}; | ||
| 17 | static uint8_t typo_buffer_size = 1; | ||
| 18 | |||
| 19 | if (keycode == AUTO_CTN) { | ||
| 20 | if (record->event.pressed) { | ||
| 21 | typo_buffer_size = 0; | ||
| 22 | userspace_config.autocorrection ^= 1; | ||
| 23 | eeconfig_update_user(userspace_config.raw); | ||
| 24 | } | ||
| 25 | return false; | ||
| 26 | } | ||
| 27 | |||
| 28 | if (!userspace_config.autocorrection) { | ||
| 29 | typo_buffer_size = 0; | ||
| 30 | return true; | ||
| 31 | } | ||
| 32 | |||
| 33 | switch (keycode) { | ||
| 34 | case KC_LSFT: | ||
| 35 | case KC_RSFT: | ||
| 36 | return true; | ||
| 37 | # ifndef NO_ACTION_TAPPING | ||
| 38 | case QK_MOD_TAP ... QK_MOD_TAP_MAX: | ||
| 39 | if (((keycode >> 8) & 0xF) == MOD_LSFT) { | ||
| 40 | return true; | ||
| 41 | } | ||
| 42 | # ifndef NO_ACTION_LAYER | ||
| 43 | case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: | ||
| 44 | # endif | ||
| 45 | if (record->event.pressed || !record->tap.count) { | ||
| 46 | return true; | ||
| 47 | } | ||
| 48 | keycode &= 0xFF; | ||
| 49 | break; | ||
| 50 | # endif | ||
| 51 | # ifndef NO_ACTION_ONESHOT | ||
| 52 | case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX: | ||
| 53 | if ((keycode & 0xF) == MOD_LSFT) { | ||
| 54 | return true; | ||
| 55 | } | ||
| 56 | # endif | ||
| 57 | default: | ||
| 58 | if (!record->event.pressed) { | ||
| 59 | return true; | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | // Subtract buffer for Backspace key, reset for other non-alpha. | ||
| 64 | if (!(KC_A <= keycode && keycode <= KC_Z)) { | ||
| 65 | if (keycode == KC_BSPC) { | ||
| 66 | // Remove last character from the buffer. | ||
| 67 | if (typo_buffer_size > 0) { | ||
| 68 | --typo_buffer_size; | ||
| 69 | } | ||
| 70 | return true; | ||
| 71 | } else if (KC_1 <= keycode && keycode <= KC_SLSH && keycode != KC_ESC) { | ||
| 72 | // Set a word boundary if space, period, digit, etc. is pressed. | ||
| 73 | // Behave more conservatively for the enter key. Reset, so that enter | ||
| 74 | // can't be used on a word ending. | ||
| 75 | if (keycode == KC_ENT) { | ||
| 76 | typo_buffer_size = 0; | ||
| 77 | } | ||
| 78 | keycode = KC_SPC; | ||
| 79 | } else { | ||
| 80 | // Clear state if some other non-alpha key is pressed. | ||
| 81 | typo_buffer_size = 0; | ||
| 82 | return true; | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | // Rotate oldest character if buffer is full. | ||
| 87 | if (typo_buffer_size >= AUTOCORRECTION_MAX_LENGTH) { | ||
| 88 | memmove(typo_buffer, typo_buffer + 1, AUTOCORRECTION_MAX_LENGTH - 1); | ||
| 89 | typo_buffer_size = AUTOCORRECTION_MAX_LENGTH - 1; | ||
| 90 | } | ||
| 91 | |||
| 92 | // Append `keycode` to buffer. | ||
| 93 | typo_buffer[typo_buffer_size++] = keycode; | ||
| 94 | // Return if buffer is smaller than the shortest word. | ||
| 95 | if (typo_buffer_size < AUTOCORRECTION_MIN_LENGTH) { | ||
| 96 | return true; | ||
| 97 | } | ||
| 98 | |||
| 99 | // Check for typo in buffer using a trie stored in `autocorrection_data`. | ||
| 100 | uint16_t state = 0; | ||
| 101 | uint8_t code = pgm_read_byte(autocorrection_data + state); | ||
| 102 | for (uint8_t i = typo_buffer_size - 1; i >= 0; --i) { | ||
| 103 | uint8_t const key_i = typo_buffer[i]; | ||
| 104 | |||
| 105 | if (code & 64) { // Check for match in node with multiple children. | ||
| 106 | code &= 63; | ||
| 107 | for (; code != key_i; code = pgm_read_byte(autocorrection_data + (state += 3))) { | ||
| 108 | if (!code) return true; | ||
| 109 | } | ||
| 110 | // Follow link to child node. | ||
| 111 | state = (pgm_read_byte(autocorrection_data + state + 1) | pgm_read_byte(autocorrection_data + state + 2) << 8); | ||
| 112 | // Check for match in node with single child. | ||
| 113 | } else if (code != key_i) { | ||
| 114 | return true; | ||
| 115 | } else if (!(code = pgm_read_byte(autocorrection_data + (++state)))) { | ||
| 116 | ++state; | ||
| 117 | } | ||
| 118 | |||
| 119 | code = pgm_read_byte(autocorrection_data + state); | ||
| 120 | |||
| 121 | if (code & 128) { // A typo was found! Apply autocorrection. | ||
| 122 | const uint8_t backspaces = code & 63; | ||
| 123 | for (uint8_t i = 0; i < backspaces; ++i) { | ||
| 124 | tap_code(KC_BSPC); | ||
| 125 | } | ||
| 126 | send_string_P((char const*)(autocorrection_data + state + 1)); | ||
| 127 | |||
| 128 | if (keycode == KC_SPC) { | ||
| 129 | typo_buffer[0] = KC_SPC; | ||
| 130 | typo_buffer_size = 1; | ||
| 131 | return true; | ||
| 132 | } else { | ||
| 133 | typo_buffer_size = 0; | ||
| 134 | return false; | ||
| 135 | } | ||
| 136 | } | ||
| 137 | } | ||
| 138 | return true; | ||
| 139 | } | ||
| 140 | #else | ||
| 141 | # pragma message "Warning!!! Autocorrect is not corretly setup!" | ||
| 142 | bool process_autocorrection(uint16_t keycode, keyrecord_t* record) { return true; } | ||
| 143 | #endif | ||
diff --git a/users/drashna/keyrecords/autocorrection/autocorrection.h b/users/drashna/keyrecords/autocorrection/autocorrection.h new file mode 100644 index 000000000..57685eb4b --- /dev/null +++ b/users/drashna/keyrecords/autocorrection/autocorrection.h | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | // Copyright 2021 Google LLC | ||
| 2 | // Copyright 2022 @filterpaper | ||
| 3 | // SPDX-License-Identifier: Apache-2.0 | ||
| 4 | // Original source: https://getreuer.info/posts/keyboards/autocorrection | ||
| 5 | |||
| 6 | #pragma once | ||
| 7 | |||
| 8 | #include "drashna.h" | ||
| 9 | |||
| 10 | bool process_autocorrection(uint16_t keycode, keyrecord_t* record); | ||
diff --git a/users/drashna/keyrecords/autocorrection/make_autocorrection_data.py b/users/drashna/keyrecords/autocorrection/make_autocorrection_data.py new file mode 100755 index 000000000..27383b895 --- /dev/null +++ b/users/drashna/keyrecords/autocorrection/make_autocorrection_data.py | |||
| @@ -0,0 +1,273 @@ | |||
| 1 | # Copyright 2021 Google LLC | ||
| 2 | # | ||
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | # you may not use this file except in compliance with the License. | ||
| 5 | # You may obtain a copy of the License at | ||
| 6 | # | ||
| 7 | # https://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | # | ||
| 9 | # Unless required by applicable law or agreed to in writing, software | ||
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | # See the License for the specific language governing permissions and | ||
| 13 | # limitations under the License. | ||
| 14 | |||
| 15 | """Python program to make autocorrection_data.h. | ||
| 16 | |||
| 17 | This program reads "autocorrection_dict.txt" and generates a C source file | ||
| 18 | "autocorrection_data.h" with a serialized trie embedded as an array. Run this | ||
| 19 | program without arguments like | ||
| 20 | |||
| 21 | $ python3 make_autocorrection_data.py | ||
| 22 | |||
| 23 | Or to read from a different typo dict file, pass it as the first argument like | ||
| 24 | |||
| 25 | $ python3 make_autocorrection_data.py dict.txt | ||
| 26 | |||
| 27 | Each line of the dict file defines one typo and its correction with the syntax | ||
| 28 | "typo -> correction". Blank lines or lines starting with '#' are ignored. | ||
| 29 | Example: | ||
| 30 | |||
| 31 | :thier -> their | ||
| 32 | fitler -> filter | ||
| 33 | lenght -> length | ||
| 34 | ouput -> output | ||
| 35 | widht -> width | ||
| 36 | |||
| 37 | See autocorrection_dict_extra.txt for a larger example. | ||
| 38 | |||
| 39 | For full documentation, see | ||
| 40 | https://getreuer.info/posts/keyboards/autocorrection | ||
| 41 | """ | ||
| 42 | |||
| 43 | import sys | ||
| 44 | import textwrap | ||
| 45 | from typing import Any, Dict, List, Tuple | ||
| 46 | |||
| 47 | try: | ||
| 48 | from english_words import english_words_lower_alpha_set as CORRECT_WORDS | ||
| 49 | except ImportError: | ||
| 50 | print('Autocorrection will falsely trigger when a typo is a substring of a ' | ||
| 51 | 'correctly spelled word. To check for this, install the english_words ' | ||
| 52 | 'package and rerun this script:\n\n pip install english_words\n') | ||
| 53 | # Use a minimal word list as a fallback. | ||
| 54 | CORRECT_WORDS = ('information', 'available', 'international', 'language', | ||
| 55 | 'loosest', 'reference', 'wealthier', 'entertainment', | ||
| 56 | 'association', 'provides', 'technology', 'statehood') | ||
| 57 | |||
| 58 | KC_A = 4 | ||
| 59 | KC_SPC = 0x2c | ||
| 60 | |||
| 61 | def parse_file(file_name: str) -> List[Tuple[str, str]]: | ||
| 62 | """Parses autocorrections dictionary file. | ||
| 63 | |||
| 64 | Each line of the file defines one typo and its correction with the syntax | ||
| 65 | "typo -> correction". Blank lines or lines starting with '#' are ignored. The | ||
| 66 | function validates that typos only have characters a-z and that typos are not | ||
| 67 | substrings of other typos, otherwise the longer typo would never trigger. | ||
| 68 | |||
| 69 | Args: | ||
| 70 | file_name: String, path of the autocorrections dictionary. | ||
| 71 | Returns: | ||
| 72 | List of (typo, correction) tuples. | ||
| 73 | """ | ||
| 74 | |||
| 75 | autocorrections = [] | ||
| 76 | typos = set() | ||
| 77 | line_number = 0 | ||
| 78 | for line in open(file_name, 'rt'): | ||
| 79 | line_number += 1 | ||
| 80 | line = line.strip() | ||
| 81 | if line and line[0] != '#': | ||
| 82 | # Parse syntax "typo -> correction", using strip to ignore indenting. | ||
| 83 | tokens = [token.strip() for token in line.split('->', 1)] | ||
| 84 | if len(tokens) != 2 or not tokens[0]: | ||
| 85 | print(f'Error:{line_number}: Invalid syntax: "{line}"') | ||
| 86 | sys.exit(1) | ||
| 87 | |||
| 88 | typo, correction = tokens | ||
| 89 | typo = typo.lower() # Force typos to lowercase. | ||
| 90 | typo = typo.replace(' ', ':') | ||
| 91 | |||
| 92 | if typo in typos: | ||
| 93 | print(f'Warning:{line_number}: Ignoring duplicate typo: "{typo}"') | ||
| 94 | continue | ||
| 95 | |||
| 96 | # Check that `typo` is valid. | ||
| 97 | if not(all([ord('a') <= ord(c) <= ord('z') or c == ':' for c in typo])): | ||
| 98 | print(f'Error:{line_number}: Typo "{typo}" has ' | ||
| 99 | 'characters other than a-z and :.') | ||
| 100 | sys.exit(1) | ||
| 101 | for other_typo in typos: | ||
| 102 | if typo in other_typo or other_typo in typo: | ||
| 103 | print(f'Error:{line_number}: Typos may not be substrings of one ' | ||
| 104 | f'another, otherwise the longer typo would never trigger: ' | ||
| 105 | f'"{typo}" vs. "{other_typo}".') | ||
| 106 | sys.exit(1) | ||
| 107 | if len(typo) < 5: | ||
| 108 | print(f'Warning:{line_number}: It is suggested that typos are at ' | ||
| 109 | f'least 5 characters long to avoid false triggers: "{typo}"') | ||
| 110 | |||
| 111 | if typo.startswith(':') and typo.endswith(':'): | ||
| 112 | if typo[1:-1] in CORRECT_WORDS: | ||
| 113 | print(f'Warning:{line_number}: Typo "{typo}" is a correctly spelled ' | ||
| 114 | 'dictionary word.') | ||
| 115 | elif typo.startswith(':') and not typo.endswith(':'): | ||
| 116 | for word in CORRECT_WORDS: | ||
| 117 | if word.startswith(typo[1:]): | ||
| 118 | print(f'Warning:{line_number}: Typo "{typo}" would falsely trigger ' | ||
| 119 | f'on correctly spelled word "{word}".') | ||
| 120 | elif not typo.startswith(':') and typo.endswith(':'): | ||
| 121 | for word in CORRECT_WORDS: | ||
| 122 | if word.endswith(typo[:-1]): | ||
| 123 | print(f'Warning:{line_number}: Typo "{typo}" would falsely trigger ' | ||
| 124 | f'on correctly spelled word "{word}".') | ||
| 125 | elif not typo.startswith(':') and not typo.endswith(':'): | ||
| 126 | for word in CORRECT_WORDS: | ||
| 127 | if typo in word: | ||
| 128 | print(f'Warning:{line_number}: Typo "{typo}" would falsely trigger ' | ||
| 129 | f'on correctly spelled word "{word}".') | ||
| 130 | |||
| 131 | autocorrections.append((typo, correction)) | ||
| 132 | typos.add(typo) | ||
| 133 | |||
| 134 | return autocorrections | ||
| 135 | |||
| 136 | |||
| 137 | def make_trie(autocorrections: List[Tuple[str, str]]) -> Dict[str, Any]: | ||
| 138 | """Makes a trie from the the typos, writing in reverse. | ||
| 139 | |||
| 140 | Args: | ||
| 141 | autocorrections: List of (typo, correction) tuples. | ||
| 142 | Returns: | ||
| 143 | Dict of dict, representing the trie. | ||
| 144 | """ | ||
| 145 | trie = {} | ||
| 146 | for typo, correction in autocorrections: | ||
| 147 | node = trie | ||
| 148 | for letter in typo[::-1]: | ||
| 149 | node = node.setdefault(letter, {}) | ||
| 150 | node['LEAF'] = (typo, correction) | ||
| 151 | |||
| 152 | return trie | ||
| 153 | |||
| 154 | |||
| 155 | def serialize_trie(autocorrections: List[Tuple[str, str]], | ||
| 156 | trie: Dict[str, Any]) -> List[int]: | ||
| 157 | """Serializes trie and correction data in a form readable by the C code. | ||
| 158 | |||
| 159 | Args: | ||
| 160 | autocorrections: List of (typo, correction) tuples. | ||
| 161 | trie: Dict of dicts. | ||
| 162 | Returns: | ||
| 163 | List of ints in the range 0-255. | ||
| 164 | """ | ||
| 165 | table = [] | ||
| 166 | |||
| 167 | # Traverse trie in depth first order. | ||
| 168 | def traverse(trie_node): | ||
| 169 | if 'LEAF' in trie_node: # Handle a leaf trie node. | ||
| 170 | typo, correction = trie_node['LEAF'] | ||
| 171 | word_boundary_ending = typo[-1] == ':' | ||
| 172 | typo = typo.strip(':') | ||
| 173 | i = 0 # Make the autocorrection data for this entry and serialize it. | ||
| 174 | while i < min(len(typo), len(correction)) and typo[i] == correction[i]: | ||
| 175 | i += 1 | ||
| 176 | backspaces = len(typo) - i - 1 + word_boundary_ending | ||
| 177 | assert 0 <= backspaces <= 63 | ||
| 178 | correction = correction[i:] | ||
| 179 | data = [backspaces + 128] + list(bytes(correction, 'ascii')) + [0] | ||
| 180 | |||
| 181 | entry = {'data': data, 'links': [], 'byte_offset': 0} | ||
| 182 | table.append(entry) | ||
| 183 | elif len(trie_node) == 1: # Handle trie node with a single child. | ||
| 184 | c, trie_node = next(iter(trie_node.items())) | ||
| 185 | entry = {'chars': c, 'byte_offset': 0} | ||
| 186 | |||
| 187 | # It's common for a trie to have long chains of single-child nodes. We | ||
| 188 | # find the whole chain so that we can serialize it more efficiently. | ||
| 189 | while len(trie_node) == 1 and 'LEAF' not in trie_node: | ||
| 190 | c, trie_node = next(iter(trie_node.items())) | ||
| 191 | entry['chars'] += c | ||
| 192 | |||
| 193 | table.append(entry) | ||
| 194 | entry['links'] = [traverse(trie_node)] | ||
| 195 | else: # Handle trie node with multiple children. | ||
| 196 | entry = {'chars': ''.join(sorted(trie_node.keys())), 'byte_offset': 0} | ||
| 197 | table.append(entry) | ||
| 198 | entry['links'] = [traverse(trie_node[c]) for c in entry['chars']] | ||
| 199 | return entry | ||
| 200 | |||
| 201 | traverse(trie) | ||
| 202 | |||
| 203 | def serialize(e): | ||
| 204 | def kc_code(c): | ||
| 205 | if ord('a') <= ord(c) <= ord('z'): | ||
| 206 | return ord(c) - ord('a') + KC_A | ||
| 207 | elif c == ':': | ||
| 208 | return KC_SPC | ||
| 209 | else: | ||
| 210 | raise ValueError(f'Invalid character: {c}') | ||
| 211 | |||
| 212 | encode_link = lambda link: [link['byte_offset'] & 255, | ||
| 213 | link['byte_offset'] >> 8] | ||
| 214 | |||
| 215 | if not e['links']: # Handle a leaf table entry. | ||
| 216 | return e['data'] | ||
| 217 | elif len(e['links']) == 1: # Handle a chain table entry. | ||
| 218 | return list(map(kc_code, e['chars'])) + [0] #+ encode_link(e['links'][0])) | ||
| 219 | else: # Handle a branch table entry. | ||
| 220 | data = [] | ||
| 221 | for c, link in zip(e['chars'], e['links']): | ||
| 222 | data += [kc_code(c) | (0 if data else 64)] + encode_link(link) | ||
| 223 | return data + [0] | ||
| 224 | |||
| 225 | byte_offset = 0 | ||
| 226 | for e in table: # To encode links, first compute byte offset of each entry. | ||
| 227 | e['byte_offset'] = byte_offset | ||
| 228 | byte_offset += len(serialize(e)) | ||
| 229 | assert 0 <= byte_offset <= 0xffff | ||
| 230 | |||
| 231 | return [b for e in table for b in serialize(e)] # Serialize final table. | ||
| 232 | |||
| 233 | |||
| 234 | def write_generated_code(autocorrections: List[Tuple[str, str]], | ||
| 235 | data: List[int], | ||
| 236 | file_name: str) -> None: | ||
| 237 | """Writes autocorrection data as generated C code to `file_name`. | ||
| 238 | |||
| 239 | Args: | ||
| 240 | autocorrections: List of (typo, correction) tuples. | ||
| 241 | data: List of ints in 0-255, the serialized trie. | ||
| 242 | file_name: String, path of the output C file. | ||
| 243 | """ | ||
| 244 | assert all(0 <= b <= 255 for b in data) | ||
| 245 | typo_len = lambda e: len(e[0]) | ||
| 246 | min_typo = min(autocorrections, key=typo_len)[0] | ||
| 247 | max_typo = max(autocorrections, key=typo_len)[0] | ||
| 248 | generated_code = ''.join([ | ||
| 249 | '// Generated code.\n\n', | ||
| 250 | f'// Autocorrection dictionary ({len(autocorrections)} entries):\n', | ||
| 251 | ''.join(sorted(f'// {typo:<{len(max_typo)}} -> {correction}\n' | ||
| 252 | for typo, correction in autocorrections)), | ||
| 253 | f'\n#define AUTOCORRECTION_MIN_LENGTH {len(min_typo)} // "{min_typo}"\n', | ||
| 254 | f'#define AUTOCORRECTION_MAX_LENGTH {len(max_typo)} // "{max_typo}"\n\n', | ||
| 255 | textwrap.fill('static const uint8_t autocorrection_data[%d] PROGMEM = {%s};' % ( | ||
| 256 | len(data), ', '.join(map(str, data))), width=80, subsequent_indent=' '), | ||
| 257 | '\n\n']) | ||
| 258 | |||
| 259 | with open(file_name, 'wt') as f: | ||
| 260 | f.write(generated_code) | ||
| 261 | |||
| 262 | |||
| 263 | def main(argv): | ||
| 264 | dict_file = argv[1] if len(argv) > 1 else 'autocorrection_dict.txt' | ||
| 265 | autocorrections = parse_file(dict_file) | ||
| 266 | trie = make_trie(autocorrections) | ||
| 267 | data = serialize_trie(autocorrections, trie) | ||
| 268 | print(f'Processed %d autocorrection entries to table with %d bytes.' | ||
| 269 | % (len(autocorrections), len(data))) | ||
| 270 | write_generated_code(autocorrections, data, 'autocorrection_data.h') | ||
| 271 | |||
| 272 | if __name__ == '__main__': | ||
| 273 | main(sys.argv) | ||
diff --git a/users/drashna/keyrecords/caps_word.c b/users/drashna/keyrecords/caps_word.c new file mode 100644 index 000000000..731568328 --- /dev/null +++ b/users/drashna/keyrecords/caps_word.c | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | // Copyright 2021 Google LLC. | ||
| 2 | // SPDX-License-Identifier: Apache-2.0 | ||
| 3 | |||
| 4 | #include "caps_word.h" | ||
| 5 | |||
| 6 | bool caps_word_enabled = false; | ||
| 7 | bool caps_word_shifted = false; | ||
| 8 | |||
| 9 | bool process_caps_word(uint16_t keycode, keyrecord_t* record) { | ||
| 10 | if (!caps_word_enabled) { | ||
| 11 | // Pressing both shift keys at the same time enables caps word. | ||
| 12 | if (((get_mods() | get_oneshot_mods()) & MOD_MASK_SHIFT) == MOD_MASK_SHIFT) { | ||
| 13 | clear_mods(); | ||
| 14 | clear_oneshot_mods(); | ||
| 15 | caps_word_shifted = false; | ||
| 16 | caps_word_enabled = true; | ||
| 17 | return false; | ||
| 18 | } | ||
| 19 | return true; | ||
| 20 | } | ||
| 21 | |||
| 22 | if (!record->event.pressed) { | ||
| 23 | return true; | ||
| 24 | } | ||
| 25 | |||
| 26 | if (!((get_mods() | get_oneshot_mods()) & ~MOD_MASK_SHIFT)) { | ||
| 27 | switch (keycode) { | ||
| 28 | case QK_MOD_TAP ... QK_MOD_TAP_MAX: | ||
| 29 | case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: | ||
| 30 | // Earlier return if this has not been considered tapped yet. | ||
| 31 | if (record->tap.count == 0) { | ||
| 32 | return true; | ||
| 33 | } | ||
| 34 | // Get the base tapping keycode of a mod- or layer-tap key. | ||
| 35 | keycode &= 0xff; | ||
| 36 | } | ||
| 37 | |||
| 38 | switch (keycode) { | ||
| 39 | // Letter keys should be shifted. | ||
| 40 | case KC_A ... KC_Z: | ||
| 41 | if (!caps_word_shifted) { | ||
| 42 | register_code(KC_LSFT); | ||
| 43 | } | ||
| 44 | caps_word_shifted = true; | ||
| 45 | return true; | ||
| 46 | |||
| 47 | // Keycodes that continue caps word but shouldn't get shifted. | ||
| 48 | case KC_1 ... KC_0: | ||
| 49 | case KC_BSPC: | ||
| 50 | case KC_MINS: | ||
| 51 | case KC_UNDS: | ||
| 52 | if (caps_word_shifted) { | ||
| 53 | unregister_code(KC_LSFT); | ||
| 54 | } | ||
| 55 | caps_word_shifted = false; | ||
| 56 | return true; | ||
| 57 | |||
| 58 | // Any other keycode disables caps word. | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | // Disable caps word. | ||
| 63 | caps_word_enabled = false; | ||
| 64 | if (caps_word_shifted) { | ||
| 65 | unregister_code(KC_LSFT); | ||
| 66 | } | ||
| 67 | caps_word_shifted = false; | ||
| 68 | return true; | ||
| 69 | } | ||
diff --git a/users/drashna/keyrecords/caps_word.h b/users/drashna/keyrecords/caps_word.h new file mode 100644 index 000000000..79e410ddd --- /dev/null +++ b/users/drashna/keyrecords/caps_word.h | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | // Copyright 2021 Google LLC. | ||
| 2 | // SPDX-License-Identifier: Apache-2.0 | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "drashna.h" | ||
| 7 | |||
| 8 | bool process_caps_word(uint16_t keycode, keyrecord_t* record); | ||
diff --git a/users/drashna/process_records.c b/users/drashna/keyrecords/process_records.c index de572d893..c7d4a925b 100644 --- a/users/drashna/process_records.c +++ b/users/drashna/keyrecords/process_records.c | |||
| @@ -16,6 +16,12 @@ | |||
| 16 | 16 | ||
| 17 | #include "drashna.h" | 17 | #include "drashna.h" |
| 18 | #include "version.h" | 18 | #include "version.h" |
| 19 | #ifdef CAPS_WORD_ENABLE | ||
| 20 | # include "caps_word.h" | ||
| 21 | #endif | ||
| 22 | #ifdef AUTOCORRECTION_ENABLE | ||
| 23 | # include "autocorrection/autocorrection.h" | ||
| 24 | #endif | ||
| 19 | 25 | ||
| 20 | uint16_t copy_paste_timer; | 26 | uint16_t copy_paste_timer; |
| 21 | bool host_driver_disabled = false; | 27 | bool host_driver_disabled = false; |
| @@ -43,6 +49,15 @@ bool process_record_user(uint16_t keycode, keyrecord_t *re | |||
| 43 | #ifdef CUSTOM_UNICODE_ENABLE | 49 | #ifdef CUSTOM_UNICODE_ENABLE |
| 44 | && process_record_unicode(keycode, record) | 50 | && process_record_unicode(keycode, record) |
| 45 | #endif | 51 | #endif |
| 52 | #if defined(POINTING_DEVICE_ENABLE) | ||
| 53 | && process_record_pointing(keycode, record) | ||
| 54 | #endif | ||
| 55 | #ifdef CAPS_WORD_ENABLE | ||
| 56 | && process_caps_word(keycode, record) | ||
| 57 | #endif | ||
| 58 | #ifdef AUTOCORRECTION_ENABLE | ||
| 59 | && process_autocorrection(keycode, record) | ||
| 60 | #endif | ||
| 46 | && true)) { | 61 | && true)) { |
| 47 | return false; | 62 | return false; |
| 48 | } | 63 | } |
| @@ -196,7 +211,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *re | |||
| 196 | } | 211 | } |
| 197 | } | 212 | } |
| 198 | break; | 213 | break; |
| 199 | } | 214 | } |
| 200 | } | 215 | } |
| 201 | return true; | 216 | return true; |
| 202 | } | 217 | } |
diff --git a/users/drashna/process_records.h b/users/drashna/keyrecords/process_records.h index d8c198a2d..df506b364 100644 --- a/users/drashna/process_records.h +++ b/users/drashna/keyrecords/process_records.h | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | #pragma once | 17 | #pragma once |
| 18 | #include "drashna.h" | 18 | #include "drashna.h" |
| 19 | 19 | ||
| 20 | #if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right) | 20 | #if defined(KEYBOARD_handwired_tractyl_manuform) |
| 21 | # define PLACEHOLDER_SAFE_RANGE KEYMAP_SAFE_RANGE | 21 | # define PLACEHOLDER_SAFE_RANGE KEYMAP_SAFE_RANGE |
| 22 | #else | 22 | #else |
| 23 | # define PLACEHOLDER_SAFE_RANGE SAFE_RANGE | 23 | # define PLACEHOLDER_SAFE_RANGE SAFE_RANGE |
| @@ -56,7 +56,9 @@ enum userspace_custom_keycodes { | |||
| 56 | KC_REGIONAL, | 56 | KC_REGIONAL, |
| 57 | KC_AUSSIE, | 57 | KC_AUSSIE, |
| 58 | KC_ZALGO, | 58 | KC_ZALGO, |
| 59 | NEW_SAFE_RANGE // use "NEWPLACEHOLDER for keymap specific codes | 59 | KC_ACCEL, |
| 60 | AUTO_CTN, // Toggle Autocorrect status | ||
| 61 | NEW_SAFE_RANGE // use "NEWPLACEHOLDER for keymap specific codes | ||
| 60 | }; | 62 | }; |
| 61 | 63 | ||
| 62 | bool process_record_secrets(uint16_t keycode, keyrecord_t *record); | 64 | bool process_record_secrets(uint16_t keycode, keyrecord_t *record); |
| @@ -64,6 +66,7 @@ bool process_record_keymap(uint16_t keycode, keyrecord_t *record); | |||
| 64 | void post_process_record_keymap(uint16_t keycode, keyrecord_t *record); | 66 | void post_process_record_keymap(uint16_t keycode, keyrecord_t *record); |
| 65 | #ifdef CUSTOM_UNICODE_ENABLE | 67 | #ifdef CUSTOM_UNICODE_ENABLE |
| 66 | bool process_record_unicode(uint16_t keycode, keyrecord_t *record); | 68 | bool process_record_unicode(uint16_t keycode, keyrecord_t *record); |
| 69 | void matrix_init_unicode(void); | ||
| 67 | #endif | 70 | #endif |
| 68 | 71 | ||
| 69 | #define LOWER MO(_LOWER) | 72 | #define LOWER MO(_LOWER) |
diff --git a/users/drashna/tap_dances.c b/users/drashna/keyrecords/tap_dances.c index 01873489d..01873489d 100644 --- a/users/drashna/tap_dances.c +++ b/users/drashna/keyrecords/tap_dances.c | |||
diff --git a/users/drashna/tap_dances.h b/users/drashna/keyrecords/tap_dances.h index 81e462ce2..81e462ce2 100644 --- a/users/drashna/tap_dances.h +++ b/users/drashna/keyrecords/tap_dances.h | |||
diff --git a/users/drashna/unicoooode.c b/users/drashna/keyrecords/unicode.c index 0e276dec1..88df2c9df 100644 --- a/users/drashna/unicoooode.c +++ b/users/drashna/keyrecords/unicode.c | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | /* Copyright 2020 @tzarc | 1 | /* Copyright 2020 @ridingqwerty |
| 2 | * 2021 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | 2 | * Copyright 2020 @tzarc |
| 3 | * Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | ||
| 3 | * | 4 | * |
| 4 | * This program is free software: you can redistribute it and/or modify | 5 | * This program is free software: you can redistribute it and/or modify |
| 5 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
| @@ -278,5 +279,9 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record) { | |||
| 278 | } else if (typing_mode == KC_ZALGO) { | 279 | } else if (typing_mode == KC_ZALGO) { |
| 279 | return process_record_zalgo(keycode, record); | 280 | return process_record_zalgo(keycode, record); |
| 280 | } | 281 | } |
| 281 | return true; | 282 | return process_unicode_common(keycode, record); |
| 283 | } | ||
| 284 | |||
| 285 | void matrix_init_unicode(void) { | ||
| 286 | unicode_input_mode_init(); | ||
| 282 | } | 287 | } |
diff --git a/users/drashna/wrappers.h b/users/drashna/keyrecords/wrappers.h index c1ae81557..c1ae81557 100644 --- a/users/drashna/wrappers.h +++ b/users/drashna/keyrecords/wrappers.h | |||
diff --git a/users/drashna/drashna_font.h b/users/drashna/oled/drashna_font.h index 844292a53..844292a53 100644 --- a/users/drashna/drashna_font.h +++ b/users/drashna/oled/drashna_font.h | |||
diff --git a/users/drashna/oled_stuff.c b/users/drashna/oled/oled_stuff.c index 2c92ac6e9..9ee2cbfed 100644 --- a/users/drashna/oled_stuff.c +++ b/users/drashna/oled/oled_stuff.c | |||
| @@ -234,7 +234,11 @@ void render_bootmagic_status(void) { | |||
| 234 | oled_write_P(PSTR(" "), false); | 234 | oled_write_P(PSTR(" "), false); |
| 235 | oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NKRO), keymap_config.nkro); | 235 | oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NKRO), keymap_config.nkro); |
| 236 | oled_write_P(PSTR(" "), false); | 236 | oled_write_P(PSTR(" "), false); |
| 237 | #ifdef AUTOCORRECTION_ENABLE | ||
| 238 | oled_write_P(PSTR("CRCT"), userspace_config.autocorrection); | ||
| 239 | #else | ||
| 237 | oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NOGUI), keymap_config.no_gui); | 240 | oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NOGUI), keymap_config.no_gui); |
| 241 | #endif | ||
| 238 | #ifdef OLED_DISPLAY_128X64 | 242 | #ifdef OLED_DISPLAY_128X64 |
| 239 | oled_advance_page(true); | 243 | oled_advance_page(true); |
| 240 | oled_write_P(PSTR("Magic"), false); | 244 | oled_write_P(PSTR("Magic"), false); |
| @@ -344,7 +348,7 @@ void render_wpm(uint8_t padding) { | |||
| 344 | #endif | 348 | #endif |
| 345 | } | 349 | } |
| 346 | 350 | ||
| 347 | #if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right) | 351 | #if defined(KEYBOARD_handwired_tractyl_manuform) || defined(KEYBOARD_bastardkb_charybdis) |
| 348 | extern kb_config_data_t kb_config; | 352 | extern kb_config_data_t kb_config; |
| 349 | void render_pointing_dpi_status(uint8_t padding) { | 353 | void render_pointing_dpi_status(uint8_t padding) { |
| 350 | oled_write_P(PSTR("CPI:"), false); | 354 | oled_write_P(PSTR("CPI:"), false); |
| @@ -377,7 +381,7 @@ __attribute__((weak)) void oled_driver_render_logo_left(void) { | |||
| 377 | render_wpm(0); | 381 | render_wpm(0); |
| 378 | # endif | 382 | # endif |
| 379 | oled_write_P(PSTR(" "), false); | 383 | oled_write_P(PSTR(" "), false); |
| 380 | # if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right) | 384 | # if defined(KEYBOARD_handwired_tractyl_manuform) || defined(KEYBOARD_bastardkb_charybdis) |
| 381 | render_pointing_dpi_status(1); | 385 | render_pointing_dpi_status(1); |
| 382 | # endif | 386 | # endif |
| 383 | oled_set_cursor(0, 4); | 387 | oled_set_cursor(0, 4); |
diff --git a/users/drashna/oled_stuff.h b/users/drashna/oled/oled_stuff.h index 8795684d6..8795684d6 100644 --- a/users/drashna/oled_stuff.h +++ b/users/drashna/oled/oled_stuff.h | |||
diff --git a/users/drashna/pointing/pointing.c b/users/drashna/pointing/pointing.c new file mode 100644 index 000000000..0198a8ae2 --- /dev/null +++ b/users/drashna/pointing/pointing.c | |||
| @@ -0,0 +1,136 @@ | |||
| 1 | /* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "pointing.h" | ||
| 18 | |||
| 19 | static uint16_t mouse_timer = 0; | ||
| 20 | static uint16_t mouse_debounce_timer = 0; | ||
| 21 | static uint8_t mouse_keycode_tracker = 0; | ||
| 22 | bool tap_toggling = false, enable_acceleration = false; | ||
| 23 | |||
| 24 | #ifdef TAPPING_TERM_PER_KEY | ||
| 25 | # define TAP_CHECK get_tapping_term(KC_BTN1, NULL) | ||
| 26 | #else | ||
| 27 | # ifndef TAPPING_TERM | ||
| 28 | # define TAPPING_TERM 200 | ||
| 29 | # endif | ||
| 30 | # define TAP_CHECK TAPPING_TERM | ||
| 31 | #endif | ||
| 32 | |||
| 33 | __attribute__((weak)) report_mouse_t pointing_device_task_keymap(report_mouse_t mouse_report) { | ||
| 34 | return mouse_report; | ||
| 35 | } | ||
| 36 | |||
| 37 | report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { | ||
| 38 | int8_t x = mouse_report.x, y = mouse_report.y; | ||
| 39 | mouse_report.x = 0; | ||
| 40 | mouse_report.y = 0; | ||
| 41 | |||
| 42 | if (x != 0 && y != 0) { | ||
| 43 | mouse_timer = timer_read(); | ||
| 44 | #ifdef OLED_ENABLE | ||
| 45 | oled_timer = timer_read32(); | ||
| 46 | #endif | ||
| 47 | if (timer_elapsed(mouse_debounce_timer) > TAP_CHECK) { | ||
| 48 | if (enable_acceleration) { | ||
| 49 | x = (x > 0 ? x * x / 16 + x : -x * x / 16 + x); | ||
| 50 | y = (y > 0 ? y * y / 16 + y : -y * y / 16 + y); | ||
| 51 | } | ||
| 52 | mouse_report.x = x; | ||
| 53 | mouse_report.y = y; | ||
| 54 | if (!layer_state_is(_MOUSE)) { | ||
| 55 | layer_on(_MOUSE); | ||
| 56 | } | ||
| 57 | } | ||
| 58 | } | ||
| 59 | return pointing_device_task_keymap(mouse_report); | ||
| 60 | } | ||
| 61 | |||
| 62 | void matrix_scan_pointing(void) { | ||
| 63 | if (timer_elapsed(mouse_timer) > 650 && layer_state_is(_MOUSE) && !mouse_keycode_tracker && !tap_toggling) { | ||
| 64 | layer_off(_MOUSE); | ||
| 65 | } | ||
| 66 | if (tap_toggling) { | ||
| 67 | if (!layer_state_is(_MOUSE)) { | ||
| 68 | layer_on(_MOUSE); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | bool process_record_pointing(uint16_t keycode, keyrecord_t* record) { | ||
| 74 | switch (keycode) { | ||
| 75 | case TT(_MOUSE): | ||
| 76 | if (record->event.pressed) { | ||
| 77 | mouse_keycode_tracker++; | ||
| 78 | } else { | ||
| 79 | #if TAPPING_TOGGLE != 0 | ||
| 80 | if (record->tap.count == TAPPING_TOGGLE) { | ||
| 81 | tap_toggling ^= 1; | ||
| 82 | # if TAPPING_TOGGLE == 1 | ||
| 83 | if (!tap_toggling) mouse_keycode_tracker -= record->tap.count + 1; | ||
| 84 | # else | ||
| 85 | if (!tap_toggling) mouse_keycode_tracker -= record->tap.count; | ||
| 86 | # endif | ||
| 87 | } else { | ||
| 88 | mouse_keycode_tracker--; | ||
| 89 | } | ||
| 90 | #endif | ||
| 91 | } | ||
| 92 | mouse_timer = timer_read(); | ||
| 93 | break; | ||
| 94 | case TG(_MOUSE): | ||
| 95 | if (record->event.pressed) { | ||
| 96 | tap_toggling ^= 1; | ||
| 97 | } | ||
| 98 | break; | ||
| 99 | case MO(_MOUSE): | ||
| 100 | #if defined(KEYBOARD_ploopy) || defined(KEYBOARD_handwired_tractyl_manuform) | ||
| 101 | case DPI_CONFIG: | ||
| 102 | #elif defined(KEYBOARD_bastardkb_charybdis) | ||
| 103 | case SAFE_RANGE ... (CHARYBDIS_SAFE_RANGE-1): | ||
| 104 | #endif | ||
| 105 | case KC_MS_UP ... KC_MS_WH_RIGHT: | ||
| 106 | record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--; | ||
| 107 | mouse_timer = timer_read(); | ||
| 108 | break; | ||
| 109 | case KC_ACCEL: | ||
| 110 | enable_acceleration = record->event.pressed; | ||
| 111 | record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--; | ||
| 112 | mouse_timer = timer_read(); | ||
| 113 | break; | ||
| 114 | default: | ||
| 115 | if (IS_NOEVENT(record->event)) break; | ||
| 116 | if ((keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX) && (((keycode >> 0x8) & 0xF) == _MOUSE)) { | ||
| 117 | record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--; | ||
| 118 | mouse_timer = timer_read(); | ||
| 119 | break; | ||
| 120 | } | ||
| 121 | if (layer_state_is(_MOUSE) && !mouse_keycode_tracker) { | ||
| 122 | layer_off(_MOUSE); | ||
| 123 | } | ||
| 124 | mouse_keycode_tracker = 0; | ||
| 125 | mouse_debounce_timer = timer_read(); | ||
| 126 | break; | ||
| 127 | } | ||
| 128 | return true; | ||
| 129 | } | ||
| 130 | |||
| 131 | layer_state_t layer_state_set_pointing(layer_state_t state) { | ||
| 132 | if (layer_state_cmp(state, _GAMEPAD) || layer_state_cmp(state, _DIABLO)) { | ||
| 133 | state |= ((layer_state_t)1 << _MOUSE); | ||
| 134 | } | ||
| 135 | return state; | ||
| 136 | } | ||
diff --git a/users/drashna/pointing/pointing.h b/users/drashna/pointing/pointing.h new file mode 100644 index 000000000..4ad16eeff --- /dev/null +++ b/users/drashna/pointing/pointing.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | /* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "drashna.h" | ||
| 18 | |||
| 19 | report_mouse_t pointing_device_task_keymap(report_mouse_t mouse_report); | ||
| 20 | void matrix_scan_pointing(void); | ||
| 21 | bool process_record_pointing(uint16_t keycode, keyrecord_t* record); | ||
| 22 | layer_state_t layer_state_set_pointing(layer_state_t state); | ||
| 23 | extern bool tap_toggling, enable_acceleration; | ||
diff --git a/users/drashna/readme.md b/users/drashna/readme.md index d98d1d0a6..b8d10aada 100644 --- a/users/drashna/readme.md +++ b/users/drashna/readme.md | |||
| @@ -2,12 +2,12 @@ | |||
| 2 | 2 | ||
| 3 | This is my personal userspace file. Most of my code exists here, as it's heavily shared. | 3 | This is my personal userspace file. Most of my code exists here, as it's heavily shared. |
| 4 | 4 | ||
| 5 | * [RGB Customization](readme_rgb.md) | 5 | * [RGB Customization](readme/rgb.md) |
| 6 | * [Diablo Tap Dancing](readme_tap_dance.md) | 6 | * [Diablo Tap Dancing](readme/tap_dance.md) |
| 7 | * [Keymap Wrappers](readme_wrappers.md) | 7 | * [Keymap Wrappers](readme/wrappers.md) |
| 8 | * [Custom Function Handlers](readme_handlers.md) | 8 | * [Custom Function Handlers](readme/handlers.md) |
| 9 | * [Secret Macros](readme_secrets.md) | 9 | * [Secret Macros](readme/secrets.md) |
| 10 | * [Custom Keycodes](readme_keycodes.md) | 10 | * [Custom Keycodes](readme/keycodes.md) |
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | ## Pro Micro Hacking | 13 | ## Pro Micro Hacking |
diff --git a/users/drashna/readme_handlers.md b/users/drashna/readme/handlers.md index 4abaf5147..4abaf5147 100644 --- a/users/drashna/readme_handlers.md +++ b/users/drashna/readme/handlers.md | |||
diff --git a/users/drashna/readme_keycodes.md b/users/drashna/readme/keycodes.md index af4dd54bc..af4dd54bc 100644 --- a/users/drashna/readme_keycodes.md +++ b/users/drashna/readme/keycodes.md | |||
diff --git a/users/drashna/readme_rgb.md b/users/drashna/readme/rgb.md index acf01b051..acf01b051 100644 --- a/users/drashna/readme_rgb.md +++ b/users/drashna/readme/rgb.md | |||
diff --git a/users/drashna/readme_secrets.md b/users/drashna/readme/secrets.md index a9408dc2e..a9408dc2e 100644 --- a/users/drashna/readme_secrets.md +++ b/users/drashna/readme/secrets.md | |||
diff --git a/users/drashna/readme_tap_dance.md b/users/drashna/readme/tap_dance.md index a61dd1f2b..a61dd1f2b 100644 --- a/users/drashna/readme_tap_dance.md +++ b/users/drashna/readme/tap_dance.md | |||
diff --git a/users/drashna/readme_wrappers.md b/users/drashna/readme/wrappers.md index fd62ff160..fd62ff160 100644 --- a/users/drashna/readme_wrappers.md +++ b/users/drashna/readme/wrappers.md | |||
diff --git a/users/drashna/rgb_matrix_stuff.c b/users/drashna/rgb/rgb_matrix_stuff.c index 97811092c..97811092c 100644 --- a/users/drashna/rgb_matrix_stuff.c +++ b/users/drashna/rgb/rgb_matrix_stuff.c | |||
diff --git a/users/drashna/rgb_matrix_stuff.h b/users/drashna/rgb/rgb_matrix_stuff.h index b86f2f651..b86f2f651 100644 --- a/users/drashna/rgb_matrix_stuff.h +++ b/users/drashna/rgb/rgb_matrix_stuff.h | |||
diff --git a/users/drashna/rgb_stuff.c b/users/drashna/rgb/rgb_stuff.c index 15108bde0..15108bde0 100644 --- a/users/drashna/rgb_stuff.c +++ b/users/drashna/rgb/rgb_stuff.c | |||
diff --git a/users/drashna/rgb_stuff.h b/users/drashna/rgb/rgb_stuff.h index af1acdde7..af1acdde7 100644 --- a/users/drashna/rgb_stuff.h +++ b/users/drashna/rgb/rgb_stuff.h | |||
diff --git a/users/drashna/rules.mk b/users/drashna/rules.mk index bd661e00a..32afae22c 100644 --- a/users/drashna/rules.mk +++ b/users/drashna/rules.mk | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | SRC += $(USER_PATH)/drashna.c \ | 1 | SRC += $(USER_PATH)/drashna.c \ |
| 2 | $(USER_PATH)/process_records.c | 2 | $(USER_PATH)/keyrecords/process_records.c |
| 3 | 3 | ||
| 4 | ifneq ($(PLATFORM),CHIBIOS) | 4 | ifneq ($(PLATFORM),CHIBIOS) |
| 5 | ifneq ($(strip $(LTO_SUPPORTED)), no) | 5 | ifneq ($(strip $(LTO_SUPPORTED)), no) |
| @@ -10,8 +10,8 @@ SPACE_CADET_ENABLE = no | |||
| 10 | GRAVE_ESC_ENABLE = no | 10 | GRAVE_ESC_ENABLE = no |
| 11 | 11 | ||
| 12 | ifneq ($(strip $(NO_SECRETS)), yes) | 12 | ifneq ($(strip $(NO_SECRETS)), yes) |
| 13 | ifneq ("$(wildcard $(USER_PATH)/secrets.c)","") | 13 | ifneq ("$(wildcard $(USER_PATH)/keyrecords/secrets.c)","") |
| 14 | SRC += $(USER_PATH)/secrets.c | 14 | SRC += $(USER_PATH)/keyrecords/secrets.c |
| 15 | endif | 15 | endif |
| 16 | ifeq ($(strip $(NO_SECRETS)), lite) | 16 | ifeq ($(strip $(NO_SECRETS)), lite) |
| 17 | OPT_DEFS += -DNO_SECRETS | 17 | OPT_DEFS += -DNO_SECRETS |
| @@ -25,20 +25,20 @@ ifeq ($(strip $(CUSTOM_UNICODE_ENABLE)), yes) | |||
| 25 | UCIS_ENABLE = no | 25 | UCIS_ENABLE = no |
| 26 | UNICODE_COMMON = yes | 26 | UNICODE_COMMON = yes |
| 27 | OPT_DEFS += -DCUSTOM_UNICODE_ENABLE | 27 | OPT_DEFS += -DCUSTOM_UNICODE_ENABLE |
| 28 | SRC += unicoooode.c | 28 | SRC += $(USER_PATH)/keyrecords/unicode.c |
| 29 | endif | 29 | endif |
| 30 | 30 | ||
| 31 | CUSTOM_TAP_DANCE ?= yes | 31 | CUSTOM_TAP_DANCE ?= yes |
| 32 | ifeq ($(strip $(CUSTOM_TAP_DANCE)), yes) | 32 | ifeq ($(strip $(CUSTOM_TAP_DANCE)), yes) |
| 33 | ifeq ($(strip $(TAP_DANCE_ENABLE)), yes) | 33 | ifeq ($(strip $(TAP_DANCE_ENABLE)), yes) |
| 34 | SRC += $(USER_PATH)/tap_dances.c | 34 | SRC += $(USER_PATH)/keyrecords/tap_dances.c |
| 35 | endif | 35 | endif |
| 36 | endif | 36 | endif |
| 37 | 37 | ||
| 38 | CUSTOM_RGBLIGHT ?= yes | 38 | CUSTOM_RGBLIGHT ?= yes |
| 39 | ifeq ($(strip $(RGBLIGHT_ENABLE)), yes) | 39 | ifeq ($(strip $(RGBLIGHT_ENABLE)), yes) |
| 40 | ifeq ($(strip $(CUSTOM_RGBLIGHT)), yes) | 40 | ifeq ($(strip $(CUSTOM_RGBLIGHT)), yes) |
| 41 | SRC += $(USER_PATH)/rgb_stuff.c | 41 | SRC += $(USER_PATH)/rgb/rgb_stuff.c |
| 42 | ifeq ($(strip $(RGBLIGHT_NOEEPROM)), yes) | 42 | ifeq ($(strip $(RGBLIGHT_NOEEPROM)), yes) |
| 43 | OPT_DEFS += -DRGBLIGHT_NOEEPROM | 43 | OPT_DEFS += -DRGBLIGHT_NOEEPROM |
| 44 | endif | 44 | endif |
| @@ -51,7 +51,7 @@ endif | |||
| 51 | CUSTOM_RGB_MATRIX ?= yes | 51 | CUSTOM_RGB_MATRIX ?= yes |
| 52 | ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes) | 52 | ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes) |
| 53 | ifeq ($(strip $(CUSTOM_RGB_MATRIX)), yes) | 53 | ifeq ($(strip $(CUSTOM_RGB_MATRIX)), yes) |
| 54 | SRC += $(USER_PATH)/rgb_matrix_stuff.c | 54 | SRC += $(USER_PATH)/rgb/rgb_matrix_stuff.c |
| 55 | endif | 55 | endif |
| 56 | endif | 56 | endif |
| 57 | 57 | ||
| @@ -76,24 +76,36 @@ endif | |||
| 76 | CUSTOM_OLED_DRIVER ?= yes | 76 | CUSTOM_OLED_DRIVER ?= yes |
| 77 | ifeq ($(strip $(OLED_ENABLE)), yes) | 77 | ifeq ($(strip $(OLED_ENABLE)), yes) |
| 78 | ifeq ($(strip $(CUSTOM_OLED_DRIVER)), yes) | 78 | ifeq ($(strip $(CUSTOM_OLED_DRIVER)), yes) |
| 79 | SRC += $(USER_PATH)/oled_stuff.c | 79 | SRC += $(USER_PATH)/oled/oled_stuff.c |
| 80 | OPT_DEFS += -DCUSTOM_OLED_DRIVER_CODE | 80 | OPT_DEFS += -DCUSTOM_OLED_DRIVER_CODE |
| 81 | endif | 81 | endif |
| 82 | endif | 82 | endif |
| 83 | 83 | ||
| 84 | ifeq ($(strip $(PIMORONI_TRACKBALL_ENABLE)), yes) | 84 | CUSTOM_POINTING_DEVICE ?= yes |
| 85 | POINTING_DEVICE_ENABLE := yes | 85 | ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes) |
| 86 | OPT_DEFS += -DPIMORONI_TRACKBALL_ENABLE | 86 | ifeq ($(strip $(CUSTOM_POINTING_DEVICE)), yes) |
| 87 | SRC += drivers/sensors/pimoroni_trackball.c | 87 | SRC += $(USER_PATH)/pointing/pointing.c |
| 88 | QUANTUM_LIB_SRC += i2c_master.c | 88 | endif |
| 89 | endif | 89 | endif |
| 90 | 90 | ||
| 91 | CUSTOM_SPLIT_TRANSPORT_SYNC ?= yes | 91 | CUSTOM_SPLIT_TRANSPORT_SYNC ?= yes |
| 92 | ifeq ($(strip $(CUSTOM_SPLIT_TRANSPORT_SYNC)), yes) | 92 | ifeq ($(strip $(CUSTOM_SPLIT_TRANSPORT_SYNC)), yes) |
| 93 | ifeq ($(strip $(SPLIT_KEYBOARD)), yes) | 93 | ifeq ($(strip $(SPLIT_KEYBOARD)), yes) |
| 94 | QUANTUM_LIB_SRC += $(USER_PATH)/transport_sync.c | 94 | QUANTUM_LIB_SRC += $(USER_PATH)/split/transport_sync.c |
| 95 | OPT_DEFS += -DCUSTOM_SPLIT_TRANSPORT_SYNC | 95 | OPT_DEFS += -DCUSTOM_SPLIT_TRANSPORT_SYNC |
| 96 | endif | 96 | endif |
| 97 | endif | 97 | endif |
| 98 | 98 | ||
| 99 | # DEBUG_MATRIX_SCAN_RATE_ENABLE = api | 99 | # DEBUG_MATRIX_SCAN_RATE_ENABLE = api |
| 100 | |||
| 101 | AUTOCORRECTION_ENABLE ?= yes | ||
| 102 | ifeq ($(strip $(AUTOCORRECTION_ENABLE)), yes) | ||
| 103 | SRC += $(USER_PATH)/keyrecords/autocorrection/autocorrection.c | ||
| 104 | OPT_DEFS += -DAUTOCORRECTION_ENABLE | ||
| 105 | endif | ||
| 106 | |||
| 107 | CAPS_WORD_ENABLE ?= yes | ||
| 108 | ifeq ($(strip $(CAPS_WORD_ENABLE)), yes) | ||
| 109 | SRC += $(USER_PATH)/keyrecords/caps_word.c | ||
| 110 | OPT_DEFS += -DCAPS_WORD_ENABLE | ||
| 111 | endif | ||
diff --git a/users/drashna/transport_sync.c b/users/drashna/split/transport_sync.c index cee3f04c8..cee3f04c8 100644 --- a/users/drashna/transport_sync.c +++ b/users/drashna/split/transport_sync.c | |||
diff --git a/users/drashna/transport_sync.h b/users/drashna/split/transport_sync.h index 70b6ea522..70b6ea522 100644 --- a/users/drashna/transport_sync.h +++ b/users/drashna/split/transport_sync.h | |||
