[Enhancement] More info on apply_autocorrect (#21056)

Co-authored-by: Drashna Jaelre <drashna@live.com>
This commit is contained in:
Pablo Martínez 2023-07-07 16:13:15 +02:00 committed by GitHub
parent 21263438e5
commit 55295ed3dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 9 deletions

View file

@ -198,7 +198,9 @@ bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *t
### Apply Autocorrect ### Apply Autocorrect
Additionally, `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). Additionally, `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).
?> 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`.
#### Apply Autocorrect Example #### Apply Autocorrect Example
@ -209,7 +211,7 @@ This following example will play a sound when a typo is autocorrected and execut
float autocorrect_song[][2] = SONG(TERMINAL_SOUND); float autocorrect_song[][2] = SONG(TERMINAL_SOUND);
#endif #endif
bool apply_autocorrect(uint8_t backspaces, const char *str) { bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) {
#ifdef AUDIO_ENABLE #ifdef AUDIO_ENABLE
PLAY_SONG(autocorrect_song); PLAY_SONG(autocorrect_song);
#endif #endif
@ -223,14 +225,17 @@ bool apply_autocorrect(uint8_t backspaces, const char *str) {
?> 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. ?> 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.
!> ***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`. !> ***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`.
You can also use `apply_autocorrect` to detect and display the event but allow internal code to execute the autocorrection with `return true`: You can also use `apply_autocorrect` to detect and display the event but allow internal code to execute the autocorrection with `return true`:
```c ```c
bool apply_autocorrect(uint8_t backspaces, const char *str) { bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) {
#ifdef OLED_ENABLE #ifdef OLED_ENABLE
oled_write_P(PSTR("Auto-corrected"), false); oled_write_P(PSTR("Auto-corrected"), false);
#endif
#ifdef CONSOLE_ENABLE
printf("'%s' was corrected to '%s'\n", typo, correct);
#endif #endif
return true; return true;
} }

View file

@ -1,5 +1,6 @@
// Copyright 2021 Google LLC // Copyright 2021 Google LLC
// Copyright 2021 @filterpaper // Copyright 2021 @filterpaper
// Copyright 2023 Pablo Martinez (@elpekenin) <elpekenin@elpekenin.dev>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Original source: https://getreuer.info/posts/keyboards/autocorrection // Original source: https://getreuer.info/posts/keyboards/autocorrection
@ -174,10 +175,12 @@ bool process_autocorrect_default_handler(uint16_t *keycode, keyrecord_t *record,
* *
* @param backspaces number of characters to remove * @param backspaces number of characters to remove
* @param str pointer to PROGMEM string to replace mistyped seletion with * @param str pointer to PROGMEM string to replace mistyped seletion with
* @param typo the wrong string that triggered a correction
* @param correct what it would become after the changes
* @return true apply correction * @return true apply correction
* @return false user handled replacement * @return false user handled replacement
*/ */
__attribute__((weak)) bool apply_autocorrect(uint8_t backspaces, const char *str) { __attribute__((weak)) bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) {
return true; return true;
} }
@ -301,11 +304,57 @@ bool process_autocorrect(uint16_t keycode, keyrecord_t *record) {
if (code & 128) { // A typo was found! Apply autocorrect. if (code & 128) { // A typo was found! Apply autocorrect.
const uint8_t backspaces = (code & 63) + !record->event.pressed; const uint8_t backspaces = (code & 63) + !record->event.pressed;
if (apply_autocorrect(backspaces, (char const *)(autocorrect_data + state + 1))) { const char * changes = (const char *)(autocorrect_data + state + 1);
/* Gather info about the typo'd word
*
* Since buffer may contain several words, delimited by spaces, we
* iterate from the end to find the start and length of the typo
*/
char typo[AUTOCORRECT_MAX_LENGTH + 1] = {0}; // extra char for null terminator
uint8_t typo_len = 0;
uint8_t typo_start = 0;
bool space_last = typo_buffer[typo_buffer_size - 1] == KC_SPC;
for (uint8_t i = typo_buffer_size; i > 0; --i) {
// stop counting after finding space (unless it is the last thing)
if (typo_buffer[i - 1] == KC_SPC && i != typo_buffer_size) {
typo_start = i;
break;
}
++typo_len;
}
// when detecting 'typo:', reduce the length of the string by one
if (space_last) {
--typo_len;
}
// convert buffer of keycodes into a string
for (uint8_t i = 0; i < typo_len; ++i) {
typo[i] = typo_buffer[typo_start + i] - KC_A + 'a';
}
/* Gather the corrected word
*
* A) Correction of 'typo:' -- Code takes into account
* an extra backspace to delete the space (which we dont copy)
* for this reason the offset is correct to "skip" the null terminator
*
* B) When correcting 'typo' -- Need extra offset for terminator
*/
char correct[AUTOCORRECT_MAX_LENGTH + 10] = {0}; // let's hope this is big enough
uint8_t offset = space_last ? backspaces : backspaces + 1;
strcpy(correct, typo);
strcpy_P(correct + typo_len - offset, changes);
if (apply_autocorrect(backspaces, changes, typo, correct)) {
for (uint8_t i = 0; i < backspaces; ++i) { for (uint8_t i = 0; i < backspaces; ++i) {
tap_code(KC_BSPC); tap_code(KC_BSPC);
} }
send_string_P((char const *)(autocorrect_data + state + 1)); send_string_P(changes);
} }
if (keycode == KC_SPC) { if (keycode == KC_SPC) {

View file

@ -1,5 +1,6 @@
// Copyright 2021 Google LLC // Copyright 2021 Google LLC
// Copyright 2021 @filterpaper // Copyright 2021 @filterpaper
// Copyright 2023 Pablo Martinez (@elpekenin) <elpekenin@elpekenin.dev>
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Original source: https://getreuer.info/posts/keyboards/autocorrection // Original source: https://getreuer.info/posts/keyboards/autocorrection
@ -10,7 +11,7 @@
bool process_autocorrect(uint16_t keycode, keyrecord_t *record); bool process_autocorrect(uint16_t keycode, keyrecord_t *record);
bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods); bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods);
bool process_autocorrect_default_handler(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods); bool process_autocorrect_default_handler(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods);
bool apply_autocorrect(uint8_t backspaces, const char *str); bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct);
bool autocorrect_is_enabled(void); bool autocorrect_is_enabled(void);
void autocorrect_enable(void); void autocorrect_enable(void);

View file

@ -141,7 +141,7 @@ float autocorrect_song[][2] = SONG(PLOVER_GOODBYE_SOUND);
# endif # endif
# endif # endif
bool apply_autocorrect(uint8_t backspaces, const char *str) { bool apply_autocorrect(uint8_t backspaces, const char* str, char *typo, char *correct) {
if (layer_state_is(_GAMEPAD)) { if (layer_state_is(_GAMEPAD)) {
return false; return false;
} }