diff options
author | LemonBoy <thatlemon@gmail.com> | 2023-08-27 21:52:27 +0200 |
---|---|---|
committer | Christian Brabandt <cb@256bit.org> | 2023-08-27 21:52:27 +0200 |
commit | d08745040bb82c5e9a81b6c8a414e50951642492 (patch) | |
tree | c00c0753b754d3b514f84f16ddf53fa14826148f /src/spell.c | |
parent | 6c93c949298c1a6cb294a09b10d690cae357a8bf (diff) |
patch 9.0.1810: camel-case spelling has issues with digitsv9.0.1810
Problem: camel-case spelling has issues with digits
Solution: Improve the camCase spell checking by taking digits
and caps into account
Rewrite the conditions to check for word boundaries by taking into
account the presence of digits and all-caps sequences such as acronyms.
closes: #12644
closes: #12933
Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: LemonBoy <thatlemon@gmail.com>
Diffstat (limited to 'src/spell.c')
-rw-r--r-- | src/spell.c | 103 |
1 files changed, 83 insertions, 20 deletions
diff --git a/src/spell.c b/src/spell.c index 1f4c60ed82..da8ece0360 100644 --- a/src/spell.c +++ b/src/spell.c @@ -125,6 +125,11 @@ static int spell_mb_isword_class(int cl, win_T *wp); #define FIND_COMPOUND 3 // find case-folded compound word #define FIND_KEEPCOMPOUND 4 // find keep-case compound word +// type values for get_char_type +#define CHAR_OTHER 0 +#define CHAR_UPPER 1 +#define CHAR_DIGIT 2 + static void find_word(matchinf_T *mip, int mode); static void find_prefix(matchinf_T *mip, int mode); static int fold_more(matchinf_T *mip); @@ -138,6 +143,7 @@ static void spell_soundfold_sal(slang_T *slang, char_u *inword, char_u *res); static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res); static void dump_word(slang_T *slang, char_u *word, char_u *pat, int *dir, int round, int flags, linenr_T lnum); static linenr_T dump_prefixes(slang_T *slang, char_u *word, char_u *pat, int *dir, int round, int flags, linenr_T startlnum); +static char_u *advance_camelcase_word(char_u *p, win_T *wp, int *is_camel_case); /* * Main spell-checking function. @@ -170,7 +176,7 @@ spell_check( int lpi; int count_word = docount; int use_camel_case = *wp->w_s->b_p_spo != NUL; - int camel_case = 0; + int is_camel_case = FALSE; // A word never starts at a space or a control character. Return quickly // then, skipping over the character. @@ -202,27 +208,15 @@ spell_check( mi.mi_fend = ptr; if (spell_iswordp(mi.mi_fend, wp)) { - int prev_upper; - int this_upper = FALSE; // init for gcc - if (use_camel_case) + mi.mi_fend = advance_camelcase_word(ptr, wp, &is_camel_case); + else { - c = PTR2CHAR(mi.mi_fend); - this_upper = SPELL_ISUPPER(c); - } - - do - { - MB_PTR_ADV(mi.mi_fend); - if (use_camel_case) + do { - prev_upper = this_upper; - c = PTR2CHAR(mi.mi_fend); - this_upper = SPELL_ISUPPER(c); - camel_case = !prev_upper && this_upper; - } - } while (*mi.mi_fend != NUL && spell_iswordp(mi.mi_fend, wp) - && !camel_case); + MB_PTR_ADV(mi.mi_fend); + } while (*mi.mi_fend != NUL && spell_iswordp(mi.mi_fend, wp)); + } if (capcol != NULL && *capcol == 0 && wp->w_s->b_cap_prog != NULL) { @@ -253,7 +247,7 @@ spell_check( MAXWLEN + 1); mi.mi_fwordlen = (int)STRLEN(mi.mi_fword); - if (camel_case && mi.mi_fwordlen > 0) + if (is_camel_case && mi.mi_fwordlen > 0) // Introduce a fake word end space into the folded word. mi.mi_fword[mi.mi_fwordlen - 1] = ' '; @@ -388,6 +382,75 @@ spell_check( } /* + * Determine the type of character 'c'. + */ + static int +get_char_type(int c) +{ + if (VIM_ISDIGIT(c)) + return CHAR_DIGIT; + if (SPELL_ISUPPER(c)) + return CHAR_UPPER; + return CHAR_OTHER; +} + +/* + * Returns a pointer to the end of the word starting at "str". + * Supports camelCase words. + */ + static char_u * +advance_camelcase_word(char_u *str, win_T *wp, int *is_camel_case) +{ + int last_type, last_last_type, this_type; + int c; + char_u *end = str; + + *is_camel_case = FALSE; + + if (*str == NUL) + return str; + + c = PTR2CHAR(end); + MB_PTR_ADV(end); + // We need at most the types of the type of the last two chars. + last_last_type = -1; + last_type = get_char_type(c); + + while (*end != NUL && spell_iswordp(end, wp)) + { + c = PTR2CHAR(end); + this_type = get_char_type(c); + + if (last_last_type == CHAR_UPPER && last_type == CHAR_UPPER + && this_type == CHAR_OTHER) + { + // Handle the following cases: + // UpperUpperLower + *is_camel_case = TRUE; + // Back up by one char. + MB_PTR_BACK(str, end); + break; + } + else if ((this_type == CHAR_UPPER && last_type == CHAR_OTHER) + || (this_type != last_type + && (this_type == CHAR_DIGIT || last_type == CHAR_DIGIT))) + { + // Handle the following cases: + // LowerUpper LowerDigit UpperDigit DigitUpper DigitLower + *is_camel_case = TRUE; + break; + } + + last_last_type = last_type; + last_type = this_type; + + MB_PTR_ADV(end); + } + + return end; +} + +/* * Check if the word at "mip->mi_word" is in the tree. * When "mode" is FIND_FOLDWORD check in fold-case word tree. * When "mode" is FIND_KEEPWORD check in keep-case word tree. |