0
0
mirror of https://github.com/vim/vim.git synced 2025-09-29 04:34:16 -04:00

patch 8.2.4866: duplicate code in "get" functions

Problem:    Duplicate code in "get" functions.
Solution:   Use get_var_from() for getwinvar(), gettabvar(), gettabwinvar()
            and getbufvar(). (closes #10335)
This commit is contained in:
LemonBoy
2022-05-04 18:12:55 +01:00
committed by Bram Moolenaar
parent cd5dbad184
commit 47d4e317f8
2 changed files with 86 additions and 110 deletions

View File

@@ -4036,48 +4036,53 @@ valid_varname(char_u *varname, int len, int autoload)
} }
/* /*
* getwinvar() and gettabwinvar() * Implements the logic to retrieve local variable and option values.
* Used by "getwinvar()" "gettabvar()" "gettabwinvar()" "getbufvar()".
*/ */
static void static void
getwinvar( get_var_from(
typval_T *argvars, char_u *varname,
typval_T *rettv, typval_T *rettv,
int off) // 1 for gettabwinvar() typval_T *deftv, // Default value if not found.
int htname, // 't'ab, 'w'indow or 'b'uffer local.
tabpage_T *tp, // can be NULL
win_T *win,
buf_T *buf) // Ignored if htname is not 'b'.
{ {
win_T *win;
char_u *varname;
dictitem_T *v; dictitem_T *v;
tabpage_T *tp = NULL;
int done = FALSE; int done = FALSE;
switchwin_T switchwin; switchwin_T switchwin;
int need_switch_win; int need_switch_win;
if (off == 1)
tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
else
tp = curtab;
win = find_win_by_nr(&argvars[off], tp);
varname = tv_get_string_chk(&argvars[off + 1]);
++emsg_off; ++emsg_off;
rettv->v_type = VAR_STRING; rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL; rettv->vval.v_string = NULL;
if (win != NULL && varname != NULL) if (varname != NULL && tp != NULL && win != NULL
&& (htname != 'b' || buf != NULL))
{ {
// Set curwin to be our win, temporarily. Also set the tabpage, // Set curwin to be our win, temporarily. Also set the tabpage,
// otherwise the window is not valid. Only do this when needed, // otherwise the window is not valid. Only do this when needed,
// autocommands get blocked. // autocommands get blocked.
need_switch_win = !(tp == curtab && win == curwin); // If we have a buffer reference avoid the switching, we're saving and
if (!need_switch_win // restoring curbuf directly.
|| switch_win(&switchwin, win, tp, TRUE) == OK) need_switch_win = !(tp == curtab && win == curwin) || (buf != NULL);
if (!need_switch_win || switch_win(&switchwin, win, tp, TRUE) == OK)
{ {
if (*varname == '&') // Handle options. There are no tab-local options.
if (*varname == '&' && htname != 't')
{ {
buf_T *save_curbuf = curbuf;
// Change curbuf so the option is read from the correct buffer.
if (buf != NULL && htname == 'b')
curbuf = buf;
if (varname[1] == NUL) if (varname[1] == NUL)
{ {
// get all window-local options in a dict // get all window-local options in a dict
dict_T *opts = get_winbuf_options(FALSE); dict_T *opts = get_winbuf_options(htname == 'b');
if (opts != NULL) if (opts != NULL)
{ {
@@ -4085,16 +4090,37 @@ getwinvar(
done = TRUE; done = TRUE;
} }
} }
else if (eval_option(&varname, rettv, 1) == OK) else if (eval_option(&varname, rettv, TRUE) == OK)
// window-local-option // Local option
done = TRUE; done = TRUE;
curbuf = save_curbuf;
}
else if (*varname == NUL)
{
// Empty string: return a dict with all the local variables.
if (htname == 'b')
v = &buf->b_bufvar;
else if (htname == 'w')
v = &win->w_winvar;
else
v = &tp->tp_winvar;
copy_tv(&v->di_tv, rettv);
done = TRUE;
} }
else else
{ {
hashtab_T *ht;
if (htname == 'b')
ht = &buf->b_vars->dv_hashtab;
else if (htname == 'w')
ht = &win->w_vars->dv_hashtab;
else
ht = &tp->tp_vars->dv_hashtab;
// Look up the variable. // Look up the variable.
// Let getwinvar({nr}, "") return the "w:" dictionary. v = find_var_in_ht(ht, htname, varname, FALSE);
v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w',
varname, FALSE);
if (v != NULL) if (v != NULL)
{ {
copy_tv(&v->di_tv, rettv); copy_tv(&v->di_tv, rettv);
@@ -4108,13 +4134,36 @@ getwinvar(
restore_win(&switchwin, TRUE); restore_win(&switchwin, TRUE);
} }
if (!done && argvars[off + 2].v_type != VAR_UNKNOWN) if (!done && deftv->v_type != VAR_UNKNOWN)
// use the default return value // use the default value
copy_tv(&argvars[off + 2], rettv); copy_tv(deftv, rettv);
--emsg_off; --emsg_off;
} }
/*
* getwinvar() and gettabwinvar()
*/
static void
getwinvar(
typval_T *argvars,
typval_T *rettv,
int off) // 1 for gettabwinvar()
{
char_u *varname;
tabpage_T *tp;
win_T *win;
if (off == 1)
tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
else
tp = curtab;
win = find_win_by_nr(&argvars[off], tp);
varname = tv_get_string_chk(&argvars[off + 1]);
get_var_from(varname, rettv, &argvars[off + 2], 'w', tp, win, NULL);
}
/* /*
* Set option "varname" to the value of "varp" for the current buffer/window. * Set option "varname" to the value of "varp" for the current buffer/window.
*/ */
@@ -4444,14 +4493,9 @@ get_clear_redir_ga(void)
void void
f_gettabvar(typval_T *argvars, typval_T *rettv) f_gettabvar(typval_T *argvars, typval_T *rettv)
{ {
switchwin_T switchwin;
tabpage_T *tp;
dictitem_T *v;
char_u *varname; char_u *varname;
int done = FALSE; tabpage_T *tp;
win_T *win = NULL;
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
if (in_vim9script() if (in_vim9script()
&& (check_for_number_arg(argvars, 0) == FAIL && (check_for_number_arg(argvars, 0) == FAIL
@@ -4460,30 +4504,11 @@ f_gettabvar(typval_T *argvars, typval_T *rettv)
varname = tv_get_string_chk(&argvars[1]); varname = tv_get_string_chk(&argvars[1]);
tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); tp = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL));
if (tp != NULL && varname != NULL) if (tp != NULL)
{ win = tp == curtab || tp->tp_firstwin == NULL ? firstwin
// Set tp to be our tabpage, temporarily. Also set the window to the : tp->tp_firstwin;
// first window in the tabpage, otherwise the window is not valid.
if (switch_win(&switchwin,
tp == curtab || tp->tp_firstwin == NULL ? firstwin
: tp->tp_firstwin, tp, TRUE) == OK)
{
// look up the variable
// Let gettabvar({nr}, "") return the "t:" dictionary.
v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', varname, FALSE);
if (v != NULL)
{
copy_tv(&v->di_tv, rettv);
done = TRUE;
}
}
// restore previous notion of curwin get_var_from(varname, rettv, &argvars[2], 't', tp, win, NULL);
restore_win(&switchwin, TRUE);
}
if (!done && argvars[2].v_type != VAR_UNKNOWN)
copy_tv(&argvars[2], rettv);
} }
/* /*
@@ -4521,10 +4546,8 @@ f_getwinvar(typval_T *argvars, typval_T *rettv)
void void
f_getbufvar(typval_T *argvars, typval_T *rettv) f_getbufvar(typval_T *argvars, typval_T *rettv)
{ {
buf_T *buf;
char_u *varname; char_u *varname;
dictitem_T *v; buf_T *buf;
int done = FALSE;
if (in_vim9script() if (in_vim9script()
&& (check_for_buffer_arg(argvars, 0) == FAIL && (check_for_buffer_arg(argvars, 0) == FAIL
@@ -4534,56 +4557,7 @@ f_getbufvar(typval_T *argvars, typval_T *rettv)
varname = tv_get_string_chk(&argvars[1]); varname = tv_get_string_chk(&argvars[1]);
buf = tv_get_buf_from_arg(&argvars[0]); buf = tv_get_buf_from_arg(&argvars[0]);
rettv->v_type = VAR_STRING; get_var_from(varname, rettv, &argvars[2], 'b', curtab, curwin, buf);
rettv->vval.v_string = NULL;
if (buf != NULL && varname != NULL)
{
if (*varname == '&')
{
buf_T *save_curbuf = curbuf;
// set curbuf to be our buf, temporarily
curbuf = buf;
if (varname[1] == NUL)
{
// get all buffer-local options in a dict
dict_T *opts = get_winbuf_options(TRUE);
if (opts != NULL)
{
rettv_dict_set(rettv, opts);
done = TRUE;
}
}
else if (eval_option(&varname, rettv, TRUE) == OK)
// buffer-local-option
done = TRUE;
// restore previous notion of curbuf
curbuf = save_curbuf;
}
else
{
// Look up the variable.
if (*varname == NUL)
// Let getbufvar({nr}, "") return the "b:" dictionary.
v = &buf->b_bufvar;
else
v = find_var_in_ht(&buf->b_vars->dv_hashtab, 'b',
varname, FALSE);
if (v != NULL)
{
copy_tv(&v->di_tv, rettv);
done = TRUE;
}
}
}
if (!done && argvars[2].v_type != VAR_UNKNOWN)
// use the default value
copy_tv(&argvars[2], rettv);
} }
/* /*

View File

@@ -746,6 +746,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
4866,
/**/ /**/
4865, 4865,
/**/ /**/