diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-10-24 06:10:06 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2024-10-24 06:56:12 +0800 |
commit | 3d2aca83de7f57ad0ba1c67acb87e55876569d0a (patch) | |
tree | 45cf0b6775f65842e4d68c8df5d0192246b4f87a | |
parent | 6d2cf5ad3112d12b4b55df9df1e0921086b54fec (diff) | |
download | rneovim-3d2aca83de7f57ad0ba1c67acb87e55876569d0a.tar.gz rneovim-3d2aca83de7f57ad0ba1c67acb87e55876569d0a.tar.bz2 rneovim-3d2aca83de7f57ad0ba1c67acb87e55876569d0a.zip |
vim-patch:9.1.0803: tests: no error check when setting global 'isk'
Problem: tests: no error check when setting global 'isk'
Solution: also parse and check global 'isk' value (Milly)
closes: vim/vim#15915
https://github.com/vim/vim/commit/5e7a6a4a106923e45c67dae6810e4c9753f88025
Co-authored-by: Milly <milly.ca@gmail.com>
-rw-r--r-- | src/nvim/charset.c | 196 | ||||
-rw-r--r-- | src/nvim/options.lua | 2 | ||||
-rw-r--r-- | src/nvim/optionstr.c | 18 | ||||
-rw-r--r-- | test/old/testdir/gen_opt_test.vim | 1 |
4 files changed, 124 insertions, 93 deletions
diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 430f6b15fe..1afd590b0e 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -88,13 +88,11 @@ int init_chartab(void) /// an error, OK otherwise. int buf_init_chartab(buf_T *buf, bool global) { - int c; - if (global) { // Set the default size for printable characters: // From <Space> to '~' is 1 (printable), others are 2 (not printable). // This also inits all 'isident' and 'isfname' flags to false. - c = 0; + int c = 0; while (c < ' ') { g_chartab[c++] = (dy_flags & DY_UHEX) ? 4 : 2; @@ -124,9 +122,7 @@ int buf_init_chartab(buf_T *buf, bool global) SET_CHARTAB(buf, '-'); } - // Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint' - // options Each option is a list of characters, character numbers or - // ranges, separated by commas, e.g.: "200-210,x,#-178,-" + // Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint' options. for (int i = global ? 0 : 3; i <= 3; i++) { const char *p; if (i == 0) { @@ -142,110 +138,130 @@ int buf_init_chartab(buf_T *buf, bool global) // fourth round: 'iskeyword' p = buf->b_p_isk; } + if (parse_isopt(p, buf, false) == FAIL) { + return FAIL; + } + } - while (*p) { - bool tilde = false; - bool do_isalpha = false; + chartab_initialized = true; + return OK; +} - if ((*p == '^') && (p[1] != NUL)) { - tilde = true; - p++; - } +/// Checks the format for the option settings 'iskeyword', 'isident', 'isfname' +/// or 'isprint'. +/// Returns FAIL if has an error, OK otherwise. +int check_isopt(char *var) +{ + return parse_isopt(var, NULL, true); +} + +/// @param only_check if false: refill g_chartab[] +static int parse_isopt(const char *var, buf_T *buf, bool only_check) +{ + const char *p = var; + + // Parses the 'isident', 'iskeyword', 'isfname' and 'isprint' options. + // Each option is a list of characters, character numbers or ranges, + // separated by commas, e.g.: "200-210,x,#-178,-" + while (*p) { + bool tilde = false; + bool do_isalpha = false; + + if (*p == '^' && p[1] != NUL) { + tilde = true; + p++; + } + + int c; + if (ascii_isdigit(*p)) { + c = getdigits_int((char **)&p, true, 0); + } else { + c = mb_ptr2char_adv(&p); + } + int c2 = -1; + + if (*p == '-' && p[1] != NUL) { + p++; if (ascii_isdigit(*p)) { - c = getdigits_int((char **)&p, true, 0); + c2 = getdigits_int((char **)&p, true, 0); } else { - c = mb_ptr2char_adv(&p); + c2 = mb_ptr2char_adv(&p); } - int c2 = -1; + } - if ((*p == '-') && (p[1] != NUL)) { - p++; + if (c <= 0 || c >= 256 || (c2 < c && c2 != -1) || c2 >= 256 + || !(*p == NUL || *p == ',')) { + return FAIL; + } - if (ascii_isdigit(*p)) { - c2 = getdigits_int((char **)&p, true, 0); - } else { - c2 = mb_ptr2char_adv(&p); - } - } + bool trail_comma = *p == ','; + p = skip_to_option_part(p); + if (trail_comma && *p == NUL) { + // Trailing comma is not allowed. + return FAIL; + } - if ((c <= 0) - || (c >= 256) - || ((c2 < c) && (c2 != -1)) - || (c2 >= 256) - || !((*p == NUL) || (*p == ','))) { - return FAIL; - } + if (only_check) { + continue; + } - if (c2 == -1) { // not a range - // A single '@' (not "@-@"): - // Decide on letters being ID/printable/keyword chars with - // standard function isalpha(). This takes care of locale for - // single-byte characters). - if (c == '@') { - do_isalpha = true; - c = 1; - c2 = 255; - } else { - c2 = c; - } + if (c2 == -1) { // not a range + // A single '@' (not "@-@"): + // Decide on letters being ID/printable/keyword chars with + // standard function isalpha(). This takes care of locale for + // single-byte characters). + if (c == '@') { + do_isalpha = true; + c = 1; + c2 = 255; + } else { + c2 = c; } + } - while (c <= c2) { - // Use the MB_ functions here, because isalpha() doesn't - // work properly when 'encoding' is "latin1" and the locale is - // "C". - if (!do_isalpha - || mb_islower(c) - || mb_isupper(c)) { - if (i == 0) { - // (re)set ID flag - if (tilde) { - g_chartab[c] &= (uint8_t) ~CT_ID_CHAR; - } else { - g_chartab[c] |= CT_ID_CHAR; - } - } else if (i == 1) { - // (re)set printable - if (c < ' ' || c > '~') { - if (tilde) { - g_chartab[c] = (uint8_t)((g_chartab[c] & ~CT_CELL_MASK) - + ((dy_flags & DY_UHEX) ? 4 : 2)); - g_chartab[c] &= (uint8_t) ~CT_PRINT_CHAR; - } else { - g_chartab[c] = (uint8_t)((g_chartab[c] & ~CT_CELL_MASK) + 1); - g_chartab[c] |= CT_PRINT_CHAR; - } - } - } else if (i == 2) { - // (re)set fname flag - if (tilde) { - g_chartab[c] &= (uint8_t) ~CT_FNAME_CHAR; - } else { - g_chartab[c] |= CT_FNAME_CHAR; - } - } else { // i == 3 - // (re)set keyword flag + while (c <= c2) { + // Use the MB_ functions here, because isalpha() doesn't + // work properly when 'encoding' is "latin1" and the locale is + // "C". + if (!do_isalpha + || mb_islower(c) + || mb_isupper(c)) { + if (var == p_isi) { // (re)set ID flag + if (tilde) { + g_chartab[c] &= (uint8_t) ~CT_ID_CHAR; + } else { + g_chartab[c] |= CT_ID_CHAR; + } + } else if (var == p_isp) { // (re)set printable + if (c < ' ' || c > '~') { if (tilde) { - RESET_CHARTAB(buf, c); + g_chartab[c] = (uint8_t)((g_chartab[c] & ~CT_CELL_MASK) + + ((dy_flags & DY_UHEX) ? 4 : 2)); + g_chartab[c] &= (uint8_t) ~CT_PRINT_CHAR; } else { - SET_CHARTAB(buf, c); + g_chartab[c] = (uint8_t)((g_chartab[c] & ~CT_CELL_MASK) + 1); + g_chartab[c] |= CT_PRINT_CHAR; } } + } else if (var == p_isf) { // (re)set fname flag + if (tilde) { + g_chartab[c] &= (uint8_t) ~CT_FNAME_CHAR; + } else { + g_chartab[c] |= CT_FNAME_CHAR; + } + } else { // (var == p_isk || var == buf->b_p_isk) (re)set keyword flag + if (tilde) { + RESET_CHARTAB(buf, c); + } else { + SET_CHARTAB(buf, c); + } } - c++; - } - - c = (uint8_t)(*p); - p = skip_to_option_part(p); - - if ((c == ',') && (*p == NUL)) { - // Trailing comma is not allowed. - return FAIL; } + c++; } } - chartab_initialized = true; + return OK; } diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 4e4de1ba31..734d9a4a02 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -4459,7 +4459,7 @@ return { { abbreviation = 'isk', alloced = true, - cb = 'did_set_isopt', + cb = 'did_set_iskeyword', defaults = { if_true = '@,48-57,_,192-255' }, deny_duplicates = true, desc = [=[ diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index c801ec0a26..f9be1be3d2 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1572,12 +1572,28 @@ int expand_set_inccommand(optexpand_T *args, int *numMatches, char ***matches) matches); } +/// The 'iskeyword' option is changed. +const char *did_set_iskeyword(optset_T *args) +{ + char **varp = (char **)args->os_varp; + + if (varp == &p_isk) { // only check for global-value + if (check_isopt(*varp) == FAIL) { + return e_invarg; + } + } else { // fallthrough for local-value + return did_set_isopt(args); + } + + return NULL; +} + /// The 'isident' or the 'iskeyword' or the 'isprint' or the 'isfname' option is /// changed. const char *did_set_isopt(optset_T *args) { buf_T *buf = (buf_T *)args->os_buf; - // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[] + // 'isident', 'iskeyword', 'isprint' or 'isfname' option: refill g_chartab[] // If the new option is invalid, use old value. // 'lisp' option: refill g_chartab[] for '-' char if (buf_init_chartab(buf, true) == FAIL) { diff --git a/test/old/testdir/gen_opt_test.vim b/test/old/testdir/gen_opt_test.vim index 85abeb2639..8a6d534c62 100644 --- a/test/old/testdir/gen_opt_test.vim +++ b/test/old/testdir/gen_opt_test.vim @@ -49,7 +49,6 @@ let skip_setglobal_reasons = #{ \ colorcolumn: 'TODO: fix missing error handling for setglobal', \ conceallevel: 'TODO: fix missing error handling for setglobal', \ foldcolumn: 'TODO: fix missing error handling for setglobal', - \ iskeyword: 'TODO: fix missing error handling for setglobal', \ numberwidth: 'TODO: fix missing error handling for setglobal', \ scrolloff: 'TODO: fix missing error handling for setglobal', \ shiftwidth: 'TODO: fix missing error handling for setglobal', |