diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-10-24 07:22:04 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-24 07:22:04 +0800 |
commit | 611c416359e2beb90d4ca73c86bcaa43cb17892c (patch) | |
tree | 773b1eac63cedfcf82a9f0f630672873d587cafa /src | |
parent | 230b0c7f021a57647a658edce27fe115343f083f (diff) | |
parent | 19204ebde9fe7a706d5afd1a9d14cfe71ff3a810 (diff) | |
download | rneovim-611c416359e2beb90d4ca73c86bcaa43cb17892c.tar.gz rneovim-611c416359e2beb90d4ca73c86bcaa43cb17892c.tar.bz2 rneovim-611c416359e2beb90d4ca73c86bcaa43cb17892c.zip |
Merge pull request #30918 from zeertzjq/vim-9.1.0802
vim-patch:9.1.{0802,0803,0804,0806,0812}: :setglobal fixes
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/buffer.c | 6 | ||||
-rw-r--r-- | src/nvim/charset.c | 196 | ||||
-rw-r--r-- | src/nvim/indent.c | 20 | ||||
-rw-r--r-- | src/nvim/option.c | 6 | ||||
-rw-r--r-- | src/nvim/options.lua | 2 | ||||
-rw-r--r-- | src/nvim/optionstr.c | 31 | ||||
-rw-r--r-- | src/nvim/window.c | 43 |
7 files changed, 187 insertions, 117 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index ce47705aa6..2142b5b298 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -255,7 +255,7 @@ int open_buffer(bool read_stdin, exarg_T *eap, int flags_arg) emsg(_("E83: Cannot allocate buffer, using other one...")); enter_buffer(curbuf); if (old_tw != curbuf->b_p_tw) { - check_colorcolumn(curwin); + check_colorcolumn(NULL, curwin); } return FAIL; } @@ -1029,7 +1029,7 @@ void handle_swap_exists(bufref_T *old_curbuf) enter_buffer(buf); if (old_tw != curbuf->b_p_tw) { - check_colorcolumn(curwin); + check_colorcolumn(NULL, curwin); } } // If "old_curbuf" is NULL we are in big trouble here... @@ -1669,7 +1669,7 @@ void set_curbuf(buf_T *buf, int action, bool update_jumplist) // enter some buffer. Using the last one is hopefully OK. enter_buffer(valid ? buf : lastbuf); if (old_tw != curbuf->b_p_tw) { - check_colorcolumn(curwin); + check_colorcolumn(NULL, curwin); } } 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/indent.c b/src/nvim/indent.c index b7e3842aad..58215f738c 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -769,9 +769,15 @@ int get_number_indent(linenr_T lnum) return (int)col; } +/// Check "briopt" as 'breakindentopt' and update the members of "wp". /// This is called when 'breakindentopt' is changed and when a window is /// initialized -bool briopt_check(win_T *wp) +/// +/// @param briopt when NULL: use "wp->w_p_briopt" +/// @param wp when NULL: only check "briopt" +/// +/// @return FAIL for failure, OK otherwise. +bool briopt_check(char *briopt, win_T *wp) { int bri_shift = 0; int bri_min = 20; @@ -779,7 +785,13 @@ bool briopt_check(win_T *wp) int bri_list = 0; int bri_vcol = 0; - char *p = wp->w_p_briopt; + char *p = empty_string_option; + if (briopt != NULL) { + p = briopt; + } else if (wp != NULL) { + p = wp->w_p_briopt; + } + while (*p != NUL) { // Note: Keep this in sync with p_briopt_values if (strncmp(p, "shift:", 6) == 0 @@ -807,6 +819,10 @@ bool briopt_check(win_T *wp) } } + if (wp == NULL) { + return OK; + } + wp->w_briopt_shift = bri_shift; wp->w_briopt_min = bri_min; wp->w_briopt_sbr = bri_sbr; diff --git a/src/nvim/option.c b/src/nvim/option.c index 89753f7cf8..933ee4ba75 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2592,7 +2592,7 @@ static const char *did_set_swapfile(optset_T *args) static const char *did_set_textwidth(optset_T *args FUNC_ATTR_UNUSED) { FOR_ALL_TAB_WINDOWS(tp, wp) { - check_colorcolumn(wp); + check_colorcolumn(NULL, wp); } return NULL; @@ -5111,8 +5111,8 @@ void didset_window_options(win_T *wp, bool valid_cursor) } else { wp->w_skipcol = 0; } - check_colorcolumn(wp); - briopt_check(wp); + check_colorcolumn(NULL, wp); + briopt_check(NULL, wp); fill_culopt_flags(NULL, wp); set_chars_option(wp, wp->w_p_fcs, kFillchars, true, NULL, 0); set_chars_option(wp, wp->w_p_lcs, kListchars, true, NULL, 0); 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 b560275de7..23b70ab5ad 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -717,11 +717,14 @@ const char *did_set_breakat(optset_T *args FUNC_ATTR_UNUSED) const char *did_set_breakindentopt(optset_T *args) { win_T *win = (win_T *)args->os_win; - if (briopt_check(win) == FAIL) { + char **varp = (char **)args->os_varp; + + if (briopt_check(*varp, varp == &win->w_p_briopt ? win : NULL) == FAIL) { return e_invarg; } + // list setting requires a redraw - if (win == curwin && win->w_briopt_list) { + if (varp == &win->w_p_briopt && win->w_briopt_list) { redraw_all_later(UPD_NOT_VALID); } @@ -898,7 +901,8 @@ int expand_set_clipboard(optexpand_T *args, int *numMatches, char ***matches) const char *did_set_colorcolumn(optset_T *args) { win_T *win = (win_T *)args->os_win; - return check_colorcolumn(win); + char **varp = (char **)args->os_varp; + return check_colorcolumn(*varp, varp == &win->w_p_cc ? win : NULL); } /// The 'comments' option is changed. @@ -1448,8 +1452,7 @@ const char *did_set_foldmethod(optset_T *args) { win_T *win = (win_T *)args->os_win; char **varp = (char **)args->os_varp; - if (check_opt_strings(*varp, p_fdm_values, false) != OK - || *win->w_p_fdm == NUL) { + if (check_opt_strings(*varp, p_fdm_values, false) != OK || **varp == NUL) { return e_invarg; } foldUpdateAll(win); @@ -1573,12 +1576,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/src/nvim/window.c b/src/nvim/window.c index 91a69c3ec4..5147bbd23b 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -7371,18 +7371,37 @@ static int int_cmp(const void *pa, const void *pb) return a == b ? 0 : a < b ? -1 : 1; } -/// Handle setting 'colorcolumn' or 'textwidth' in window "wp". +/// Check "cc" as 'colorcolumn' and update the members of "wp". +/// This is called when 'colorcolumn' or 'textwidth' is changed. +/// +/// @param cc when NULL: use "wp->w_p_cc" +/// @param wp when NULL: only parse "cc" /// /// @return error message, NULL if it's OK. -const char *check_colorcolumn(win_T *wp) +const char *check_colorcolumn(char *cc, win_T *wp) { - if (wp->w_buffer == NULL) { + if (wp != NULL && wp->w_buffer == NULL) { return NULL; // buffer was closed } + char *s = empty_string_option; + if (cc != NULL) { + s = cc; + } else if (wp != NULL) { + s = wp->w_p_cc; + } + + OptInt tw; + if (wp != NULL) { + tw = wp->w_buffer->b_p_tw; + } else { + // buffer-local value not set, assume zero + tw = 0; + } + unsigned count = 0; int color_cols[256]; - for (char *s = wp->w_p_cc; *s != NUL && count < 255;) { + while (*s != NUL && count < 255) { int col; if (*s == '-' || *s == '+') { // -N and +N: add to 'textwidth' @@ -7392,16 +7411,12 @@ const char *check_colorcolumn(win_T *wp) return e_invarg; } col = col * getdigits_int(&s, true, 0); - if (wp->w_buffer->b_p_tw == 0) { + if (tw == 0) { goto skip; // 'textwidth' not set, skip this item } - assert((col >= 0 - && wp->w_buffer->b_p_tw <= INT_MAX - col - && wp->w_buffer->b_p_tw + col >= INT_MIN) - || (col < 0 - && wp->w_buffer->b_p_tw >= INT_MIN - col - && wp->w_buffer->b_p_tw + col <= INT_MAX)); - col += (int)wp->w_buffer->b_p_tw; + assert((col >= 0 && tw <= INT_MAX - col && tw + col >= INT_MIN) + || (col < 0 && tw >= INT_MIN - col && tw + col <= INT_MAX)); + col += (int)tw; if (col < 0) { goto skip; } @@ -7423,6 +7438,10 @@ skip: } } + if (wp == NULL) { + return NULL; // only parse "cc" + } + xfree(wp->w_p_cc_cols); if (count == 0) { wp->w_p_cc_cols = NULL; |