aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-10-24 07:22:04 +0800
committerGitHub <noreply@github.com>2024-10-24 07:22:04 +0800
commit611c416359e2beb90d4ca73c86bcaa43cb17892c (patch)
tree773b1eac63cedfcf82a9f0f630672873d587cafa /src
parent230b0c7f021a57647a658edce27fe115343f083f (diff)
parent19204ebde9fe7a706d5afd1a9d14cfe71ff3a810 (diff)
downloadrneovim-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.c6
-rw-r--r--src/nvim/charset.c196
-rw-r--r--src/nvim/indent.c20
-rw-r--r--src/nvim/option.c6
-rw-r--r--src/nvim/options.lua2
-rw-r--r--src/nvim/optionstr.c31
-rw-r--r--src/nvim/window.c43
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;