summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/feature_autocorrect.md13
-rw-r--r--quantum/process_keycode/process_autocorrect.c55
-rw-r--r--quantum/process_keycode/process_autocorrect.h3
-rw-r--r--users/drashna/drashna.c2
4 files changed, 64 insertions, 9 deletions
diff --git a/docs/feature_autocorrect.md b/docs/feature_autocorrect.md
index 9f80c93f82..3a0a49095c 100644
--- a/docs/feature_autocorrect.md
+++ b/docs/feature_autocorrect.md
@@ -198,7 +198,9 @@ bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *t
198 198
199### Apply Autocorrect 199### Apply Autocorrect
200 200
201Additionally, `apply_autocorrect(uint8_t backspaces, const char *str)` allows for users to add additional handling to the autocorrection, or replace the functionality entirely. This passes on the number of backspaces needed to replace the words, as well as the replacement string (partial word, not the full word). 201Additionally, `apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct)` allows for users to add additional handling to the autocorrection, or replace the functionality entirely. This passes on the number of backspaces needed to replace the words, as well as the replacement string (partial word, not the full word), and the typo and corrected strings (complete words).
202
203?> Due to the way code works (no notion of words, just a stream of letters), the `typo` and `correct` strings are a best bet and could be "wrong". For example you may get `wordtpyo` & `wordtypo` instead of the expected `tpyo` & `typo`.
202 204
203#### Apply Autocorrect Example 205#### Apply Autocorrect Example
204 206
@@ -209,7 +211,7 @@ This following example will play a sound when a typo is autocorrected and execut
209float autocorrect_song[][2] = SONG(TERMINAL_SOUND); 211float autocorrect_song[][2] = SONG(TERMINAL_SOUND);
210#endif 212#endif
211 213
212bool apply_autocorrect(uint8_t backspaces, const char *str) { 214bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) {
213#ifdef AUDIO_ENABLE 215#ifdef AUDIO_ENABLE
214 PLAY_SONG(autocorrect_song); 216 PLAY_SONG(autocorrect_song);
215#endif 217#endif
@@ -223,15 +225,18 @@ bool apply_autocorrect(uint8_t backspaces, const char *str) {
223 225
224?> In this callback function, `return false` will stop the normal processing of autocorrect, which requires manually handling of removing the "bad" characters and typing the new characters. 226?> In this callback function, `return false` will stop the normal processing of autocorrect, which requires manually handling of removing the "bad" characters and typing the new characters.
225 227
226!> ***IMPORTANT***: `str` is a pointer to `PROGMEM` data for the autocorrection. If you return false, and want to send the string, this needs to use `send_string_P` and not `send_string` or `SEND_STRING`. 228!> ***IMPORTANT***: `str` is a pointer to `PROGMEM` data for the autocorrection. If you return false, and want to send the string, this needs to use `send_string_P` and not `send_string` nor `SEND_STRING`.
227 229
228You can also use `apply_autocorrect` to detect and display the event but allow internal code to execute the autocorrection with `return true`: 230You can also use `apply_autocorrect` to detect and display the event but allow internal code to execute the autocorrection with `return true`:
229 231
230```c 232```c
231bool apply_autocorrect(uint8_t backspaces, const char *str) { 233bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) {
232#ifdef OLED_ENABLE 234#ifdef OLED_ENABLE
233 oled_write_P(PSTR("Auto-corrected"), false); 235 oled_write_P(PSTR("Auto-corrected"), false);
234#endif 236#endif
237#ifdef CONSOLE_ENABLE
238 printf("'%s' was corrected to '%s'\n", typo, correct);
239#endif
235 return true; 240 return true;
236} 241}
237``` 242```
diff --git a/quantum/process_keycode/process_autocorrect.c b/quantum/process_keycode/process_autocorrect.c
index 7c9cb814e5..cc1f19e4f9 100644
--- a/quantum/process_keycode/process_autocorrect.c
+++ b/quantum/process_keycode/process_autocorrect.c
@@ -1,5 +1,6 @@
1// Copyright 2021 Google LLC 1// Copyright 2021 Google LLC
2// Copyright 2021 @filterpaper 2// Copyright 2021 @filterpaper
3// Copyright 2023 Pablo Martinez (@elpekenin) <elpekenin@elpekenin.dev>
3// SPDX-License-Identifier: Apache-2.0 4// SPDX-License-Identifier: Apache-2.0
4// Original source: https://getreuer.info/posts/keyboards/autocorrection 5// Original source: https://getreuer.info/posts/keyboards/autocorrection
5 6
@@ -174,10 +175,12 @@ bool process_autocorrect_default_handler(uint16_t *keycode, keyrecord_t *record,
174 * 175 *
175 * @param backspaces number of characters to remove 176 * @param backspaces number of characters to remove
176 * @param str pointer to PROGMEM string to replace mistyped seletion with 177 * @param str pointer to PROGMEM string to replace mistyped seletion with
178 * @param typo the wrong string that triggered a correction
179 * @param correct what it would become after the changes
177 * @return true apply correction 180 * @return true apply correction
178 * @return false user handled replacement 181 * @return false user handled replacement
179 */ 182 */
180__attribute__((weak)) bool apply_autocorrect(uint8_t backspaces, const char *str) { 183__attribute__((weak)) bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) {
181 return true; 184 return true;
182} 185}
183 186
@@ -301,11 +304,57 @@ bool process_autocorrect(uint16_t keycode, keyrecord_t *record) {
301 304
302 if (code & 128) { // A typo was found! Apply autocorrect. 305 if (code & 128) { // A typo was found! Apply autocorrect.
303 const uint8_t backspaces = (code & 63) + !record->event.pressed; 306 const uint8_t backspaces = (code & 63) + !record->event.pressed;
304 if (apply_autocorrect(backspaces, (char const *)(autocorrect_data + state + 1))) { 307 const char * changes = (const char *)(autocorrect_data + state + 1);
308
309 /* Gather info about the typo'd word
310 *
311 * Since buffer may contain several words, delimited by spaces, we
312 * iterate from the end to find the start and length of the typo
313 */
314 char typo[AUTOCORRECT_MAX_LENGTH + 1] = {0}; // extra char for null terminator
315
316 uint8_t typo_len = 0;
317 uint8_t typo_start = 0;
318 bool space_last = typo_buffer[typo_buffer_size - 1] == KC_SPC;
319 for (uint8_t i = typo_buffer_size; i > 0; --i) {
320 // stop counting after finding space (unless it is the last thing)
321 if (typo_buffer[i - 1] == KC_SPC && i != typo_buffer_size) {
322 typo_start = i;
323 break;
324 }
325
326 ++typo_len;
327 }
328
329 // when detecting 'typo:', reduce the length of the string by one
330 if (space_last) {
331 --typo_len;
332 }
333
334 // convert buffer of keycodes into a string
335 for (uint8_t i = 0; i < typo_len; ++i) {
336 typo[i] = typo_buffer[typo_start + i] - KC_A + 'a';
337 }
338
339 /* Gather the corrected word
340 *
341 * A) Correction of 'typo:' -- Code takes into account
342 * an extra backspace to delete the space (which we dont copy)
343 * for this reason the offset is correct to "skip" the null terminator
344 *
345 * B) When correcting 'typo' -- Need extra offset for terminator
346 */
347 char correct[AUTOCORRECT_MAX_LENGTH + 10] = {0}; // let's hope this is big enough
348
349 uint8_t offset = space_last ? backspaces : backspaces + 1;
350 strcpy(correct, typo);
351 strcpy_P(correct + typo_len - offset, changes);
352
353 if (apply_autocorrect(backspaces, changes, typo, correct)) {
305 for (uint8_t i = 0; i < backspaces; ++i) { 354 for (uint8_t i = 0; i < backspaces; ++i) {
306 tap_code(KC_BSPC); 355 tap_code(KC_BSPC);
307 } 356 }
308 send_string_P((char const *)(autocorrect_data + state + 1)); 357 send_string_P(changes);
309 } 358 }
310 359
311 if (keycode == KC_SPC) { 360 if (keycode == KC_SPC) {
diff --git a/quantum/process_keycode/process_autocorrect.h b/quantum/process_keycode/process_autocorrect.h
index 00dacbf958..9cc7d46a8b 100644
--- a/quantum/process_keycode/process_autocorrect.h
+++ b/quantum/process_keycode/process_autocorrect.h
@@ -1,5 +1,6 @@
1// Copyright 2021 Google LLC 1// Copyright 2021 Google LLC
2// Copyright 2021 @filterpaper 2// Copyright 2021 @filterpaper
3// Copyright 2023 Pablo Martinez (@elpekenin) <elpekenin@elpekenin.dev>
3// SPDX-License-Identifier: Apache-2.0 4// SPDX-License-Identifier: Apache-2.0
4// Original source: https://getreuer.info/posts/keyboards/autocorrection 5// Original source: https://getreuer.info/posts/keyboards/autocorrection
5 6
@@ -10,7 +11,7 @@
10bool process_autocorrect(uint16_t keycode, keyrecord_t *record); 11bool process_autocorrect(uint16_t keycode, keyrecord_t *record);
11bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods); 12bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods);
12bool process_autocorrect_default_handler(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods); 13bool process_autocorrect_default_handler(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods);
13bool apply_autocorrect(uint8_t backspaces, const char *str); 14bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct);
14 15
15bool autocorrect_is_enabled(void); 16bool autocorrect_is_enabled(void);
16void autocorrect_enable(void); 17void autocorrect_enable(void);
diff --git a/users/drashna/drashna.c b/users/drashna/drashna.c
index cad6db8f3d..b8ccbb028c 100644
--- a/users/drashna/drashna.c
+++ b/users/drashna/drashna.c
@@ -141,7 +141,7 @@ float autocorrect_song[][2] = SONG(PLOVER_GOODBYE_SOUND);
141# endif 141# endif
142# endif 142# endif
143 143
144bool apply_autocorrect(uint8_t backspaces, const char *str) { 144bool apply_autocorrect(uint8_t backspaces, const char* str, char *typo, char *correct) {
145 if (layer_state_is(_GAMEPAD)) { 145 if (layer_state_is(_GAMEPAD)) {
146 return false; 146 return false;
147 } 147 }