mirror of
https://github.com/vim/vim.git
synced 2025-09-07 22:03:36 -04:00
patch 8.1.1981: the evalfunc.c file is too big
Problem: The evalfunc.c file is too big. Solution: Move undo functions to undo.c. Move cmdline functions to ex_getln.c. Move some container functions to list.c.
This commit is contained in:
parent
0f63ed33fd
commit
08c308aeb5
487
src/evalfunc.c
487
src/evalfunc.c
@ -24,13 +24,10 @@
|
||||
# include <time.h> // for time_t
|
||||
#endif
|
||||
|
||||
static char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob");
|
||||
|
||||
#ifdef FEAT_FLOAT
|
||||
static void f_abs(typval_T *argvars, typval_T *rettv);
|
||||
static void f_acos(typval_T *argvars, typval_T *rettv);
|
||||
#endif
|
||||
static void f_add(typval_T *argvars, typval_T *rettv);
|
||||
static void f_and(typval_T *argvars, typval_T *rettv);
|
||||
static void f_append(typval_T *argvars, typval_T *rettv);
|
||||
static void f_appendbufline(typval_T *argvars, typval_T *rettv);
|
||||
@ -73,7 +70,6 @@ static void f_copy(typval_T *argvars, typval_T *rettv);
|
||||
static void f_cos(typval_T *argvars, typval_T *rettv);
|
||||
static void f_cosh(typval_T *argvars, typval_T *rettv);
|
||||
#endif
|
||||
static void f_count(typval_T *argvars, typval_T *rettv);
|
||||
static void f_cscope_connection(typval_T *argvars, typval_T *rettv);
|
||||
static void f_cursor(typval_T *argsvars, typval_T *rettv);
|
||||
#ifdef MSWIN
|
||||
@ -96,7 +92,6 @@ static void f_exp(typval_T *argvars, typval_T *rettv);
|
||||
#endif
|
||||
static void f_expand(typval_T *argvars, typval_T *rettv);
|
||||
static void f_expandcmd(typval_T *argvars, typval_T *rettv);
|
||||
static void f_extend(typval_T *argvars, typval_T *rettv);
|
||||
static void f_feedkeys(typval_T *argvars, typval_T *rettv);
|
||||
#ifdef FEAT_FLOAT
|
||||
static void f_float2nr(typval_T *argvars, typval_T *rettv);
|
||||
@ -115,9 +110,6 @@ static void f_getchangelist(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getchar(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getcharmod(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getcharsearch(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getcmdline(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getcmdpos(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getcmdtype(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getcmdwintype(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getenv(typval_T *argvars, typval_T *rettv);
|
||||
static void f_getfontname(typval_T *argvars, typval_T *rettv);
|
||||
@ -149,7 +141,6 @@ static void f_inputlist(typval_T *argvars, typval_T *rettv);
|
||||
static void f_inputrestore(typval_T *argvars, typval_T *rettv);
|
||||
static void f_inputsave(typval_T *argvars, typval_T *rettv);
|
||||
static void f_inputsecret(typval_T *argvars, typval_T *rettv);
|
||||
static void f_insert(typval_T *argvars, typval_T *rettv);
|
||||
static void f_invert(typval_T *argvars, typval_T *rettv);
|
||||
static void f_islocked(typval_T *argvars, typval_T *rettv);
|
||||
#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
|
||||
@ -221,10 +212,8 @@ static void f_remote_peek(typval_T *argvars, typval_T *rettv);
|
||||
static void f_remote_read(typval_T *argvars, typval_T *rettv);
|
||||
static void f_remote_send(typval_T *argvars, typval_T *rettv);
|
||||
static void f_remote_startserver(typval_T *argvars, typval_T *rettv);
|
||||
static void f_remove(typval_T *argvars, typval_T *rettv);
|
||||
static void f_rename(typval_T *argvars, typval_T *rettv);
|
||||
static void f_repeat(typval_T *argvars, typval_T *rettv);
|
||||
static void f_reverse(typval_T *argvars, typval_T *rettv);
|
||||
#ifdef FEAT_FLOAT
|
||||
static void f_round(typval_T *argvars, typval_T *rettv);
|
||||
#endif
|
||||
@ -246,7 +235,6 @@ static void f_server2client(typval_T *argvars, typval_T *rettv);
|
||||
static void f_serverlist(typval_T *argvars, typval_T *rettv);
|
||||
static void f_setbufline(typval_T *argvars, typval_T *rettv);
|
||||
static void f_setcharsearch(typval_T *argvars, typval_T *rettv);
|
||||
static void f_setcmdpos(typval_T *argvars, typval_T *rettv);
|
||||
static void f_setenv(typval_T *argvars, typval_T *rettv);
|
||||
static void f_setfperm(typval_T *argvars, typval_T *rettv);
|
||||
static void f_setline(typval_T *argvars, typval_T *rettv);
|
||||
@ -320,8 +308,6 @@ static void f_trim(typval_T *argvars, typval_T *rettv);
|
||||
static void f_trunc(typval_T *argvars, typval_T *rettv);
|
||||
#endif
|
||||
static void f_type(typval_T *argvars, typval_T *rettv);
|
||||
static void f_undofile(typval_T *argvars, typval_T *rettv);
|
||||
static void f_undotree(typval_T *argvars, typval_T *rettv);
|
||||
static void f_virtcol(typval_T *argvars, typval_T *rettv);
|
||||
static void f_visualmode(typval_T *argvars, typval_T *rettv);
|
||||
static void f_wildmenumode(typval_T *argvars, typval_T *rettv);
|
||||
@ -1217,44 +1203,6 @@ f_acos(typval_T *argvars, typval_T *rettv)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* "add(list, item)" function
|
||||
*/
|
||||
static void
|
||||
f_add(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
list_T *l;
|
||||
blob_T *b;
|
||||
|
||||
rettv->vval.v_number = 1; /* Default: Failed */
|
||||
if (argvars[0].v_type == VAR_LIST)
|
||||
{
|
||||
if ((l = argvars[0].vval.v_list) != NULL
|
||||
&& !var_check_lock(l->lv_lock,
|
||||
(char_u *)N_("add() argument"), TRUE)
|
||||
&& list_append_tv(l, &argvars[1]) == OK)
|
||||
copy_tv(&argvars[0], rettv);
|
||||
}
|
||||
else if (argvars[0].v_type == VAR_BLOB)
|
||||
{
|
||||
if ((b = argvars[0].vval.v_blob) != NULL
|
||||
&& !var_check_lock(b->bv_lock,
|
||||
(char_u *)N_("add() argument"), TRUE))
|
||||
{
|
||||
int error = FALSE;
|
||||
varnumber_T n = tv_get_number_chk(&argvars[1], &error);
|
||||
|
||||
if (!error)
|
||||
{
|
||||
ga_append(&b->bv_ga, (int)n);
|
||||
copy_tv(&argvars[0], rettv);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
emsg(_(e_listblobreq));
|
||||
}
|
||||
|
||||
/*
|
||||
* "and(expr, expr)" function
|
||||
*/
|
||||
@ -2148,113 +2096,6 @@ f_cosh(typval_T *argvars, typval_T *rettv)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* "count()" function
|
||||
*/
|
||||
static void
|
||||
f_count(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
long n = 0;
|
||||
int ic = FALSE;
|
||||
int error = FALSE;
|
||||
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
ic = (int)tv_get_number_chk(&argvars[2], &error);
|
||||
|
||||
if (argvars[0].v_type == VAR_STRING)
|
||||
{
|
||||
char_u *expr = tv_get_string_chk(&argvars[1]);
|
||||
char_u *p = argvars[0].vval.v_string;
|
||||
char_u *next;
|
||||
|
||||
if (!error && expr != NULL && *expr != NUL && p != NULL)
|
||||
{
|
||||
if (ic)
|
||||
{
|
||||
size_t len = STRLEN(expr);
|
||||
|
||||
while (*p != NUL)
|
||||
{
|
||||
if (MB_STRNICMP(p, expr, len) == 0)
|
||||
{
|
||||
++n;
|
||||
p += len;
|
||||
}
|
||||
else
|
||||
MB_PTR_ADV(p);
|
||||
}
|
||||
}
|
||||
else
|
||||
while ((next = (char_u *)strstr((char *)p, (char *)expr))
|
||||
!= NULL)
|
||||
{
|
||||
++n;
|
||||
p = next + STRLEN(expr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (argvars[0].v_type == VAR_LIST)
|
||||
{
|
||||
listitem_T *li;
|
||||
list_T *l;
|
||||
long idx;
|
||||
|
||||
if ((l = argvars[0].vval.v_list) != NULL)
|
||||
{
|
||||
li = l->lv_first;
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
if (argvars[3].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
idx = (long)tv_get_number_chk(&argvars[3], &error);
|
||||
if (!error)
|
||||
{
|
||||
li = list_find(l, idx);
|
||||
if (li == NULL)
|
||||
semsg(_(e_listidx), idx);
|
||||
}
|
||||
}
|
||||
if (error)
|
||||
li = NULL;
|
||||
}
|
||||
|
||||
for ( ; li != NULL; li = li->li_next)
|
||||
if (tv_equal(&li->li_tv, &argvars[1], ic, FALSE))
|
||||
++n;
|
||||
}
|
||||
}
|
||||
else if (argvars[0].v_type == VAR_DICT)
|
||||
{
|
||||
int todo;
|
||||
dict_T *d;
|
||||
hashitem_T *hi;
|
||||
|
||||
if ((d = argvars[0].vval.v_dict) != NULL)
|
||||
{
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
if (argvars[3].v_type != VAR_UNKNOWN)
|
||||
emsg(_(e_invarg));
|
||||
}
|
||||
|
||||
todo = error ? 0 : (int)d->dv_hashtab.ht_used;
|
||||
for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
|
||||
{
|
||||
if (!HASHITEM_EMPTY(hi))
|
||||
{
|
||||
--todo;
|
||||
if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic, FALSE))
|
||||
++n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
semsg(_(e_listdictarg), "count()");
|
||||
rettv->vval.v_number = n;
|
||||
}
|
||||
|
||||
/*
|
||||
* "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
|
||||
*
|
||||
@ -3043,92 +2884,6 @@ f_expandcmd(typval_T *argvars, typval_T *rettv)
|
||||
rettv->vval.v_string = cmdstr;
|
||||
}
|
||||
|
||||
/*
|
||||
* "extend(list, list [, idx])" function
|
||||
* "extend(dict, dict [, action])" function
|
||||
*/
|
||||
static void
|
||||
f_extend(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u *arg_errmsg = (char_u *)N_("extend() argument");
|
||||
|
||||
if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
|
||||
{
|
||||
list_T *l1, *l2;
|
||||
listitem_T *item;
|
||||
long before;
|
||||
int error = FALSE;
|
||||
|
||||
l1 = argvars[0].vval.v_list;
|
||||
l2 = argvars[1].vval.v_list;
|
||||
if (l1 != NULL && !var_check_lock(l1->lv_lock, arg_errmsg, TRUE)
|
||||
&& l2 != NULL)
|
||||
{
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
before = (long)tv_get_number_chk(&argvars[2], &error);
|
||||
if (error)
|
||||
return; /* type error; errmsg already given */
|
||||
|
||||
if (before == l1->lv_len)
|
||||
item = NULL;
|
||||
else
|
||||
{
|
||||
item = list_find(l1, before);
|
||||
if (item == NULL)
|
||||
{
|
||||
semsg(_(e_listidx), before);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
item = NULL;
|
||||
list_extend(l1, l2, item);
|
||||
|
||||
copy_tv(&argvars[0], rettv);
|
||||
}
|
||||
}
|
||||
else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
|
||||
{
|
||||
dict_T *d1, *d2;
|
||||
char_u *action;
|
||||
int i;
|
||||
|
||||
d1 = argvars[0].vval.v_dict;
|
||||
d2 = argvars[1].vval.v_dict;
|
||||
if (d1 != NULL && !var_check_lock(d1->dv_lock, arg_errmsg, TRUE)
|
||||
&& d2 != NULL)
|
||||
{
|
||||
/* Check the third argument. */
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
static char *(av[]) = {"keep", "force", "error"};
|
||||
|
||||
action = tv_get_string_chk(&argvars[2]);
|
||||
if (action == NULL)
|
||||
return; /* type error; errmsg already given */
|
||||
for (i = 0; i < 3; ++i)
|
||||
if (STRCMP(action, av[i]) == 0)
|
||||
break;
|
||||
if (i == 3)
|
||||
{
|
||||
semsg(_(e_invarg2), action);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
action = (char_u *)"force";
|
||||
|
||||
dict_extend(d1, d2, action);
|
||||
|
||||
copy_tv(&argvars[0], rettv);
|
||||
}
|
||||
}
|
||||
else
|
||||
semsg(_(e_listdictarg), "extend()");
|
||||
}
|
||||
|
||||
/*
|
||||
* "feedkeys()" function
|
||||
*/
|
||||
@ -4058,40 +3813,6 @@ f_getcharsearch(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "getcmdline()" function
|
||||
*/
|
||||
static void
|
||||
f_getcmdline(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
{
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = get_cmdline_str();
|
||||
}
|
||||
|
||||
/*
|
||||
* "getcmdpos()" function
|
||||
*/
|
||||
static void
|
||||
f_getcmdpos(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
{
|
||||
rettv->vval.v_number = get_cmdline_pos() + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* "getcmdtype()" function
|
||||
*/
|
||||
static void
|
||||
f_getcmdtype(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
{
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = alloc(2);
|
||||
if (rettv->vval.v_string != NULL)
|
||||
{
|
||||
rettv->vval.v_string[0] = get_cmdline_type();
|
||||
rettv->vval.v_string[1] = NUL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "getcmdwintype()" function
|
||||
*/
|
||||
@ -5734,82 +5455,6 @@ f_inputsecret(typval_T *argvars, typval_T *rettv)
|
||||
--inputsecret_flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* "insert()" function
|
||||
*/
|
||||
static void
|
||||
f_insert(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
long before = 0;
|
||||
listitem_T *item;
|
||||
list_T *l;
|
||||
int error = FALSE;
|
||||
|
||||
if (argvars[0].v_type == VAR_BLOB)
|
||||
{
|
||||
int val, len;
|
||||
char_u *p;
|
||||
|
||||
len = blob_len(argvars[0].vval.v_blob);
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
before = (long)tv_get_number_chk(&argvars[2], &error);
|
||||
if (error)
|
||||
return; // type error; errmsg already given
|
||||
if (before < 0 || before > len)
|
||||
{
|
||||
semsg(_(e_invarg2), tv_get_string(&argvars[2]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
val = tv_get_number_chk(&argvars[1], &error);
|
||||
if (error)
|
||||
return;
|
||||
if (val < 0 || val > 255)
|
||||
{
|
||||
semsg(_(e_invarg2), tv_get_string(&argvars[1]));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ga_grow(&argvars[0].vval.v_blob->bv_ga, 1) == FAIL)
|
||||
return;
|
||||
p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data;
|
||||
mch_memmove(p + before + 1, p + before, (size_t)len - before);
|
||||
*(p + before) = val;
|
||||
++argvars[0].vval.v_blob->bv_ga.ga_len;
|
||||
|
||||
copy_tv(&argvars[0], rettv);
|
||||
}
|
||||
else if (argvars[0].v_type != VAR_LIST)
|
||||
semsg(_(e_listblobarg), "insert()");
|
||||
else if ((l = argvars[0].vval.v_list) != NULL
|
||||
&& !var_check_lock(l->lv_lock,
|
||||
(char_u *)N_("insert() argument"), TRUE))
|
||||
{
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
before = (long)tv_get_number_chk(&argvars[2], &error);
|
||||
if (error)
|
||||
return; /* type error; errmsg already given */
|
||||
|
||||
if (before == l->lv_len)
|
||||
item = NULL;
|
||||
else
|
||||
{
|
||||
item = list_find(l, before);
|
||||
if (item == NULL)
|
||||
{
|
||||
semsg(_(e_listidx), before);
|
||||
l = NULL;
|
||||
}
|
||||
}
|
||||
if (l != NULL)
|
||||
{
|
||||
list_insert_tv(l, &argvars[1], item);
|
||||
copy_tv(&argvars[0], rettv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "invert(expr)" function
|
||||
*/
|
||||
@ -7361,24 +7006,6 @@ f_remote_startserver(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* "remove()" function
|
||||
*/
|
||||
static void
|
||||
f_remove(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u *arg_errmsg = (char_u *)N_("remove() argument");
|
||||
|
||||
if (argvars[0].v_type == VAR_DICT)
|
||||
dict_remove(argvars, rettv, arg_errmsg);
|
||||
else if (argvars[0].v_type == VAR_BLOB)
|
||||
blob_remove(argvars, rettv);
|
||||
else if (argvars[0].v_type == VAR_LIST)
|
||||
list_remove(argvars, rettv, arg_errmsg);
|
||||
else
|
||||
semsg(_(e_listdictblobarg), "remove()");
|
||||
}
|
||||
|
||||
/*
|
||||
* "rename({from}, {to})" function
|
||||
*/
|
||||
@ -7439,51 +7066,6 @@ f_repeat(typval_T *argvars, typval_T *rettv)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "reverse({list})" function
|
||||
*/
|
||||
static void
|
||||
f_reverse(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
list_T *l;
|
||||
listitem_T *li, *ni;
|
||||
|
||||
if (argvars[0].v_type == VAR_BLOB)
|
||||
{
|
||||
blob_T *b = argvars[0].vval.v_blob;
|
||||
int i, len = blob_len(b);
|
||||
|
||||
for (i = 0; i < len / 2; i++)
|
||||
{
|
||||
int tmp = blob_get(b, i);
|
||||
|
||||
blob_set(b, i, blob_get(b, len - i - 1));
|
||||
blob_set(b, len - i - 1, tmp);
|
||||
}
|
||||
rettv_blob_set(rettv, b);
|
||||
return;
|
||||
}
|
||||
|
||||
if (argvars[0].v_type != VAR_LIST)
|
||||
semsg(_(e_listblobarg), "reverse()");
|
||||
else if ((l = argvars[0].vval.v_list) != NULL
|
||||
&& !var_check_lock(l->lv_lock,
|
||||
(char_u *)N_("reverse() argument"), TRUE))
|
||||
{
|
||||
li = l->lv_last;
|
||||
l->lv_first = l->lv_last = NULL;
|
||||
l->lv_len = 0;
|
||||
while (li != NULL)
|
||||
{
|
||||
ni = li->li_prev;
|
||||
list_append(l, li);
|
||||
li = ni;
|
||||
}
|
||||
rettv_list_set(rettv, l);
|
||||
l->lv_idx = l->lv_len - l->lv_idx - 1;
|
||||
}
|
||||
}
|
||||
|
||||
#define SP_NOMOVE 0x01 /* don't move cursor */
|
||||
#define SP_REPEAT 0x02 /* repeat to find outer pair */
|
||||
#define SP_RETCOUNT 0x04 /* return matchcount */
|
||||
@ -8286,18 +7868,6 @@ f_setcharsearch(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "setcmdpos()" function
|
||||
*/
|
||||
static void
|
||||
f_setcmdpos(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
int pos = (int)tv_get_number(&argvars[0]) - 1;
|
||||
|
||||
if (pos >= 0)
|
||||
rettv->vval.v_number = set_cmdline_pos(pos);
|
||||
}
|
||||
|
||||
/*
|
||||
* "setenv()" function
|
||||
*/
|
||||
@ -10572,63 +10142,6 @@ f_type(typval_T *argvars, typval_T *rettv)
|
||||
rettv->vval.v_number = n;
|
||||
}
|
||||
|
||||
/*
|
||||
* "undofile(name)" function
|
||||
*/
|
||||
static void
|
||||
f_undofile(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
{
|
||||
rettv->v_type = VAR_STRING;
|
||||
#ifdef FEAT_PERSISTENT_UNDO
|
||||
{
|
||||
char_u *fname = tv_get_string(&argvars[0]);
|
||||
|
||||
if (*fname == NUL)
|
||||
{
|
||||
/* If there is no file name there will be no undo file. */
|
||||
rettv->vval.v_string = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
char_u *ffname = FullName_save(fname, TRUE);
|
||||
|
||||
if (ffname != NULL)
|
||||
rettv->vval.v_string = u_get_undo_file_name(ffname, FALSE);
|
||||
vim_free(ffname);
|
||||
}
|
||||
}
|
||||
#else
|
||||
rettv->vval.v_string = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* "undotree()" function
|
||||
*/
|
||||
static void
|
||||
f_undotree(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
{
|
||||
if (rettv_dict_alloc(rettv) == OK)
|
||||
{
|
||||
dict_T *dict = rettv->vval.v_dict;
|
||||
list_T *list;
|
||||
|
||||
dict_add_number(dict, "synced", (long)curbuf->b_u_synced);
|
||||
dict_add_number(dict, "seq_last", curbuf->b_u_seq_last);
|
||||
dict_add_number(dict, "save_last", (long)curbuf->b_u_save_nr_last);
|
||||
dict_add_number(dict, "seq_cur", curbuf->b_u_seq_cur);
|
||||
dict_add_number(dict, "time_cur", (long)curbuf->b_u_time_cur);
|
||||
dict_add_number(dict, "save_cur", (long)curbuf->b_u_save_nr_cur);
|
||||
|
||||
list = list_alloc();
|
||||
if (list != NULL)
|
||||
{
|
||||
u_eval_tree(curbuf->b_u_oldhead, list);
|
||||
dict_add_list(dict, "entries", list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "virtcol(string)" function
|
||||
*/
|
||||
|
@ -3868,7 +3868,7 @@ get_ccline_ptr(void)
|
||||
* Only works when the command line is being edited.
|
||||
* Returns NULL when something is wrong.
|
||||
*/
|
||||
char_u *
|
||||
static char_u *
|
||||
get_cmdline_str(void)
|
||||
{
|
||||
cmdline_info_T *p;
|
||||
@ -3882,19 +3882,26 @@ get_cmdline_str(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current command line position, counted in bytes.
|
||||
* Zero is the first position.
|
||||
* Only works when the command line is being edited.
|
||||
* Returns -1 when something is wrong.
|
||||
* "getcmdline()" function
|
||||
*/
|
||||
int
|
||||
get_cmdline_pos(void)
|
||||
void
|
||||
f_getcmdline(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
{
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = get_cmdline_str();
|
||||
}
|
||||
|
||||
/*
|
||||
* "getcmdpos()" function
|
||||
*/
|
||||
void
|
||||
f_getcmdpos(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
{
|
||||
cmdline_info_T *p = get_ccline_ptr();
|
||||
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
return p->cmdpos;
|
||||
rettv->vval.v_number = 0;
|
||||
if (p != NULL)
|
||||
rettv->vval.v_number = p->cmdpos + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3902,7 +3909,7 @@ get_cmdline_pos(void)
|
||||
* Only works when the command line is being edited.
|
||||
* Returns 1 when failed, 0 when OK.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
set_cmdline_pos(
|
||||
int pos)
|
||||
{
|
||||
@ -3919,6 +3926,34 @@ set_cmdline_pos(
|
||||
new_cmdpos = pos;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* "setcmdpos()" function
|
||||
*/
|
||||
void
|
||||
f_setcmdpos(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
int pos = (int)tv_get_number(&argvars[0]) - 1;
|
||||
|
||||
if (pos >= 0)
|
||||
rettv->vval.v_number = set_cmdline_pos(pos);
|
||||
}
|
||||
|
||||
/*
|
||||
* "getcmdtype()" function
|
||||
*/
|
||||
void
|
||||
f_getcmdtype(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
{
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = alloc(2);
|
||||
if (rettv->vval.v_string != NULL)
|
||||
{
|
||||
rettv->vval.v_string[0] = get_cmdline_type();
|
||||
rettv->vval.v_string[1] = NUL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(FEAT_EVAL) || defined(FEAT_CMDWIN) || defined(PROTO)
|
||||
|
374
src/list.c
374
src/list.c
@ -8,13 +8,15 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* list.c: List support
|
||||
* list.c: List support and container (List, Dict, Blob) functions.
|
||||
*/
|
||||
|
||||
#include "vim.h"
|
||||
|
||||
#if defined(FEAT_EVAL) || defined(PROTO)
|
||||
|
||||
static char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob");
|
||||
|
||||
/* List heads for garbage collection. */
|
||||
static list_T *first_list = NULL; /* list of all lists */
|
||||
|
||||
@ -1763,4 +1765,374 @@ f_map(typval_T *argvars, typval_T *rettv)
|
||||
filter_map(argvars, rettv, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* "add(list, item)" function
|
||||
*/
|
||||
void
|
||||
f_add(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
list_T *l;
|
||||
blob_T *b;
|
||||
|
||||
rettv->vval.v_number = 1; /* Default: Failed */
|
||||
if (argvars[0].v_type == VAR_LIST)
|
||||
{
|
||||
if ((l = argvars[0].vval.v_list) != NULL
|
||||
&& !var_check_lock(l->lv_lock,
|
||||
(char_u *)N_("add() argument"), TRUE)
|
||||
&& list_append_tv(l, &argvars[1]) == OK)
|
||||
copy_tv(&argvars[0], rettv);
|
||||
}
|
||||
else if (argvars[0].v_type == VAR_BLOB)
|
||||
{
|
||||
if ((b = argvars[0].vval.v_blob) != NULL
|
||||
&& !var_check_lock(b->bv_lock,
|
||||
(char_u *)N_("add() argument"), TRUE))
|
||||
{
|
||||
int error = FALSE;
|
||||
varnumber_T n = tv_get_number_chk(&argvars[1], &error);
|
||||
|
||||
if (!error)
|
||||
{
|
||||
ga_append(&b->bv_ga, (int)n);
|
||||
copy_tv(&argvars[0], rettv);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
emsg(_(e_listblobreq));
|
||||
}
|
||||
|
||||
/*
|
||||
* "count()" function
|
||||
*/
|
||||
void
|
||||
f_count(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
long n = 0;
|
||||
int ic = FALSE;
|
||||
int error = FALSE;
|
||||
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
ic = (int)tv_get_number_chk(&argvars[2], &error);
|
||||
|
||||
if (argvars[0].v_type == VAR_STRING)
|
||||
{
|
||||
char_u *expr = tv_get_string_chk(&argvars[1]);
|
||||
char_u *p = argvars[0].vval.v_string;
|
||||
char_u *next;
|
||||
|
||||
if (!error && expr != NULL && *expr != NUL && p != NULL)
|
||||
{
|
||||
if (ic)
|
||||
{
|
||||
size_t len = STRLEN(expr);
|
||||
|
||||
while (*p != NUL)
|
||||
{
|
||||
if (MB_STRNICMP(p, expr, len) == 0)
|
||||
{
|
||||
++n;
|
||||
p += len;
|
||||
}
|
||||
else
|
||||
MB_PTR_ADV(p);
|
||||
}
|
||||
}
|
||||
else
|
||||
while ((next = (char_u *)strstr((char *)p, (char *)expr))
|
||||
!= NULL)
|
||||
{
|
||||
++n;
|
||||
p = next + STRLEN(expr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (argvars[0].v_type == VAR_LIST)
|
||||
{
|
||||
listitem_T *li;
|
||||
list_T *l;
|
||||
long idx;
|
||||
|
||||
if ((l = argvars[0].vval.v_list) != NULL)
|
||||
{
|
||||
li = l->lv_first;
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
if (argvars[3].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
idx = (long)tv_get_number_chk(&argvars[3], &error);
|
||||
if (!error)
|
||||
{
|
||||
li = list_find(l, idx);
|
||||
if (li == NULL)
|
||||
semsg(_(e_listidx), idx);
|
||||
}
|
||||
}
|
||||
if (error)
|
||||
li = NULL;
|
||||
}
|
||||
|
||||
for ( ; li != NULL; li = li->li_next)
|
||||
if (tv_equal(&li->li_tv, &argvars[1], ic, FALSE))
|
||||
++n;
|
||||
}
|
||||
}
|
||||
else if (argvars[0].v_type == VAR_DICT)
|
||||
{
|
||||
int todo;
|
||||
dict_T *d;
|
||||
hashitem_T *hi;
|
||||
|
||||
if ((d = argvars[0].vval.v_dict) != NULL)
|
||||
{
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
if (argvars[3].v_type != VAR_UNKNOWN)
|
||||
emsg(_(e_invarg));
|
||||
}
|
||||
|
||||
todo = error ? 0 : (int)d->dv_hashtab.ht_used;
|
||||
for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
|
||||
{
|
||||
if (!HASHITEM_EMPTY(hi))
|
||||
{
|
||||
--todo;
|
||||
if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic, FALSE))
|
||||
++n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
semsg(_(e_listdictarg), "count()");
|
||||
rettv->vval.v_number = n;
|
||||
}
|
||||
|
||||
/*
|
||||
* "extend(list, list [, idx])" function
|
||||
* "extend(dict, dict [, action])" function
|
||||
*/
|
||||
void
|
||||
f_extend(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u *arg_errmsg = (char_u *)N_("extend() argument");
|
||||
|
||||
if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
|
||||
{
|
||||
list_T *l1, *l2;
|
||||
listitem_T *item;
|
||||
long before;
|
||||
int error = FALSE;
|
||||
|
||||
l1 = argvars[0].vval.v_list;
|
||||
l2 = argvars[1].vval.v_list;
|
||||
if (l1 != NULL && !var_check_lock(l1->lv_lock, arg_errmsg, TRUE)
|
||||
&& l2 != NULL)
|
||||
{
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
before = (long)tv_get_number_chk(&argvars[2], &error);
|
||||
if (error)
|
||||
return; /* type error; errmsg already given */
|
||||
|
||||
if (before == l1->lv_len)
|
||||
item = NULL;
|
||||
else
|
||||
{
|
||||
item = list_find(l1, before);
|
||||
if (item == NULL)
|
||||
{
|
||||
semsg(_(e_listidx), before);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
item = NULL;
|
||||
list_extend(l1, l2, item);
|
||||
|
||||
copy_tv(&argvars[0], rettv);
|
||||
}
|
||||
}
|
||||
else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
|
||||
{
|
||||
dict_T *d1, *d2;
|
||||
char_u *action;
|
||||
int i;
|
||||
|
||||
d1 = argvars[0].vval.v_dict;
|
||||
d2 = argvars[1].vval.v_dict;
|
||||
if (d1 != NULL && !var_check_lock(d1->dv_lock, arg_errmsg, TRUE)
|
||||
&& d2 != NULL)
|
||||
{
|
||||
/* Check the third argument. */
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
static char *(av[]) = {"keep", "force", "error"};
|
||||
|
||||
action = tv_get_string_chk(&argvars[2]);
|
||||
if (action == NULL)
|
||||
return; /* type error; errmsg already given */
|
||||
for (i = 0; i < 3; ++i)
|
||||
if (STRCMP(action, av[i]) == 0)
|
||||
break;
|
||||
if (i == 3)
|
||||
{
|
||||
semsg(_(e_invarg2), action);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
action = (char_u *)"force";
|
||||
|
||||
dict_extend(d1, d2, action);
|
||||
|
||||
copy_tv(&argvars[0], rettv);
|
||||
}
|
||||
}
|
||||
else
|
||||
semsg(_(e_listdictarg), "extend()");
|
||||
}
|
||||
|
||||
/*
|
||||
* "insert()" function
|
||||
*/
|
||||
void
|
||||
f_insert(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
long before = 0;
|
||||
listitem_T *item;
|
||||
list_T *l;
|
||||
int error = FALSE;
|
||||
|
||||
if (argvars[0].v_type == VAR_BLOB)
|
||||
{
|
||||
int val, len;
|
||||
char_u *p;
|
||||
|
||||
len = blob_len(argvars[0].vval.v_blob);
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
before = (long)tv_get_number_chk(&argvars[2], &error);
|
||||
if (error)
|
||||
return; // type error; errmsg already given
|
||||
if (before < 0 || before > len)
|
||||
{
|
||||
semsg(_(e_invarg2), tv_get_string(&argvars[2]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
val = tv_get_number_chk(&argvars[1], &error);
|
||||
if (error)
|
||||
return;
|
||||
if (val < 0 || val > 255)
|
||||
{
|
||||
semsg(_(e_invarg2), tv_get_string(&argvars[1]));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ga_grow(&argvars[0].vval.v_blob->bv_ga, 1) == FAIL)
|
||||
return;
|
||||
p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data;
|
||||
mch_memmove(p + before + 1, p + before, (size_t)len - before);
|
||||
*(p + before) = val;
|
||||
++argvars[0].vval.v_blob->bv_ga.ga_len;
|
||||
|
||||
copy_tv(&argvars[0], rettv);
|
||||
}
|
||||
else if (argvars[0].v_type != VAR_LIST)
|
||||
semsg(_(e_listblobarg), "insert()");
|
||||
else if ((l = argvars[0].vval.v_list) != NULL
|
||||
&& !var_check_lock(l->lv_lock,
|
||||
(char_u *)N_("insert() argument"), TRUE))
|
||||
{
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
before = (long)tv_get_number_chk(&argvars[2], &error);
|
||||
if (error)
|
||||
return; /* type error; errmsg already given */
|
||||
|
||||
if (before == l->lv_len)
|
||||
item = NULL;
|
||||
else
|
||||
{
|
||||
item = list_find(l, before);
|
||||
if (item == NULL)
|
||||
{
|
||||
semsg(_(e_listidx), before);
|
||||
l = NULL;
|
||||
}
|
||||
}
|
||||
if (l != NULL)
|
||||
{
|
||||
list_insert_tv(l, &argvars[1], item);
|
||||
copy_tv(&argvars[0], rettv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "remove()" function
|
||||
*/
|
||||
void
|
||||
f_remove(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u *arg_errmsg = (char_u *)N_("remove() argument");
|
||||
|
||||
if (argvars[0].v_type == VAR_DICT)
|
||||
dict_remove(argvars, rettv, arg_errmsg);
|
||||
else if (argvars[0].v_type == VAR_BLOB)
|
||||
blob_remove(argvars, rettv);
|
||||
else if (argvars[0].v_type == VAR_LIST)
|
||||
list_remove(argvars, rettv, arg_errmsg);
|
||||
else
|
||||
semsg(_(e_listdictblobarg), "remove()");
|
||||
}
|
||||
|
||||
/*
|
||||
* "reverse({list})" function
|
||||
*/
|
||||
void
|
||||
f_reverse(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
list_T *l;
|
||||
listitem_T *li, *ni;
|
||||
|
||||
if (argvars[0].v_type == VAR_BLOB)
|
||||
{
|
||||
blob_T *b = argvars[0].vval.v_blob;
|
||||
int i, len = blob_len(b);
|
||||
|
||||
for (i = 0; i < len / 2; i++)
|
||||
{
|
||||
int tmp = blob_get(b, i);
|
||||
|
||||
blob_set(b, i, blob_get(b, len - i - 1));
|
||||
blob_set(b, len - i - 1, tmp);
|
||||
}
|
||||
rettv_blob_set(rettv, b);
|
||||
return;
|
||||
}
|
||||
|
||||
if (argvars[0].v_type != VAR_LIST)
|
||||
semsg(_(e_listblobarg), "reverse()");
|
||||
else if ((l = argvars[0].vval.v_list) != NULL
|
||||
&& !var_check_lock(l->lv_lock,
|
||||
(char_u *)N_("reverse() argument"), TRUE))
|
||||
{
|
||||
li = l->lv_last;
|
||||
l->lv_first = l->lv_last = NULL;
|
||||
l->lv_len = 0;
|
||||
while (li != NULL)
|
||||
{
|
||||
ni = li->li_prev;
|
||||
list_append(l, li);
|
||||
li = ni;
|
||||
}
|
||||
rettv_list_set(rettv, l);
|
||||
l->lv_idx = l->lv_len - l->lv_idx - 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // defined(FEAT_EVAL)
|
||||
|
@ -28,9 +28,10 @@ char_u *vim_strsave_fnameescape(char_u *fname, int shell);
|
||||
void escape_fname(char_u **pp);
|
||||
void tilde_replace(char_u *orig_pat, int num_files, char_u **files);
|
||||
cmdline_info_T *get_cmdline_info(void);
|
||||
char_u *get_cmdline_str(void);
|
||||
int get_cmdline_pos(void);
|
||||
int set_cmdline_pos(int pos);
|
||||
void f_getcmdline(typval_T *argvars, typval_T *rettv);
|
||||
void f_getcmdpos(typval_T *argvars, typval_T *rettv);
|
||||
void f_setcmdpos(typval_T *argvars, typval_T *rettv);
|
||||
void f_getcmdtype(typval_T *argvars, typval_T *rettv);
|
||||
int get_cmdline_type(void);
|
||||
int get_cmdline_firstc(void);
|
||||
int get_list_range(char_u **str, int *num1, int *num2);
|
||||
|
@ -43,4 +43,10 @@ void f_sort(typval_T *argvars, typval_T *rettv);
|
||||
void f_uniq(typval_T *argvars, typval_T *rettv);
|
||||
void f_filter(typval_T *argvars, typval_T *rettv);
|
||||
void f_map(typval_T *argvars, typval_T *rettv);
|
||||
void f_add(typval_T *argvars, typval_T *rettv);
|
||||
void f_count(typval_T *argvars, typval_T *rettv);
|
||||
void f_extend(typval_T *argvars, typval_T *rettv);
|
||||
void f_insert(typval_T *argvars, typval_T *rettv);
|
||||
void f_remove(typval_T *argvars, typval_T *rettv);
|
||||
void f_reverse(typval_T *argvars, typval_T *rettv);
|
||||
/* vim: set ft=c : */
|
||||
|
@ -28,4 +28,6 @@ int anyBufIsChanged(void);
|
||||
int bufIsChangedNotTerm(buf_T *buf);
|
||||
int curbufIsChanged(void);
|
||||
void u_eval_tree(u_header_T *first_uhp, list_T *list);
|
||||
void f_undofile(typval_T *argvars, typval_T *rettv);
|
||||
void f_undotree(typval_T *argvars, typval_T *rettv);
|
||||
/* vim: set ft=c : */
|
||||
|
59
src/undo.c
59
src/undo.c
@ -3572,6 +3572,7 @@ curbufIsChanged(void)
|
||||
}
|
||||
|
||||
#if defined(FEAT_EVAL) || defined(PROTO)
|
||||
|
||||
/*
|
||||
* For undotree(): Append the list of undo blocks at "first_uhp" to "list".
|
||||
* Recursive.
|
||||
@ -3612,4 +3613,62 @@ u_eval_tree(u_header_T *first_uhp, list_T *list)
|
||||
uhp = uhp->uh_prev.ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "undofile(name)" function
|
||||
*/
|
||||
void
|
||||
f_undofile(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
{
|
||||
rettv->v_type = VAR_STRING;
|
||||
#ifdef FEAT_PERSISTENT_UNDO
|
||||
{
|
||||
char_u *fname = tv_get_string(&argvars[0]);
|
||||
|
||||
if (*fname == NUL)
|
||||
{
|
||||
/* If there is no file name there will be no undo file. */
|
||||
rettv->vval.v_string = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
char_u *ffname = FullName_save(fname, TRUE);
|
||||
|
||||
if (ffname != NULL)
|
||||
rettv->vval.v_string = u_get_undo_file_name(ffname, FALSE);
|
||||
vim_free(ffname);
|
||||
}
|
||||
}
|
||||
#else
|
||||
rettv->vval.v_string = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* "undotree()" function
|
||||
*/
|
||||
void
|
||||
f_undotree(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
{
|
||||
if (rettv_dict_alloc(rettv) == OK)
|
||||
{
|
||||
dict_T *dict = rettv->vval.v_dict;
|
||||
list_T *list;
|
||||
|
||||
dict_add_number(dict, "synced", (long)curbuf->b_u_synced);
|
||||
dict_add_number(dict, "seq_last", curbuf->b_u_seq_last);
|
||||
dict_add_number(dict, "save_last", (long)curbuf->b_u_save_nr_last);
|
||||
dict_add_number(dict, "seq_cur", curbuf->b_u_seq_cur);
|
||||
dict_add_number(dict, "time_cur", (long)curbuf->b_u_time_cur);
|
||||
dict_add_number(dict, "save_cur", (long)curbuf->b_u_save_nr_cur);
|
||||
|
||||
list = list_alloc();
|
||||
if (list != NULL)
|
||||
{
|
||||
u_eval_tree(curbuf->b_u_oldhead, list);
|
||||
dict_add_list(dict, "entries", list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -757,6 +757,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1981,
|
||||
/**/
|
||||
1980,
|
||||
/**/
|
||||
|
Loading…
x
Reference in New Issue
Block a user