0
0
mirror of https://github.com/vim/vim.git synced 2025-08-27 20:13:38 -04:00

updated for version 7.0031

This commit is contained in:
Bram Moolenaar 2005-01-05 22:19:46 +00:00
parent 1280586e4b
commit 3d60ec2aaf
5 changed files with 433 additions and 181 deletions

View File

@ -1,4 +1,4 @@
*todo.txt* For Vim version 7.0aa. Last change: 2005 Jan 04 *todo.txt* For Vim version 7.0aa. Last change: 2005 Jan 05
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@ -30,16 +30,16 @@ be worked on, but only if you sponsor Vim development. See |sponsor|.
*known-bugs* *known-bugs*
-------------------- Known bugs and current work ----------------------- -------------------- Known bugs and current work -----------------------
When 'insertmode' is set CTRL-I 4isometext<Esc> and then some typing hangs
Vim. (Jens Paulus)
:let completion stops after the first argument.
List data type: List data type:
- When removing items from the condition stack may free cs_fors.
- don't copy the list, use a list-watcher to adjust the item pointer when it's
deleted.
- "for a in list" - "for a in list"
Make copy of the list to avoid trouble when it changes. As one big block?
- "for [a, b] in [[1, 2], [3, 4]]" - "for [a, b] in [[1, 2], [3, 4]]"
- support list generator: items are obtained with a function by index.
"range(1, 400, 2)" creates one.
- == (same value) and "is" (same list) - == (same value) and "is" (same list)
- store in viminfo: read_viminfo_varlist()
- add many functions: - add many functions:
call(func, list) call function call(func, list) call function
keys(list) list of all indexes 0 - (len(list) - 1) keys(list) list of all indexes 0 - (len(list) - 1)
@ -56,6 +56,8 @@ List data type:
getval(list, idx[, default]) get value at idx or default getval(list, idx[, default]) get value at idx or default
file2lines() file2lines()
file2words() file2words()
str2list() parse string to list in several ways: white
separated, [] form, etc.
Fix the error numbers E999 in eval.c. Fix the error numbers E999 in eval.c.
Function reference: Define a nameless (numbered) function and assign Function reference: Define a nameless (numbered) function and assign

View File

@ -1,4 +1,4 @@
*version7.txt* For Vim version 7.0aa. Last change: 2005 Jan 04 *version7.txt* For Vim version 7.0aa. Last change: 2005 Jan 05
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@ -645,4 +645,6 @@ Use a Vim command to fix all fileformats to dos before executing the tests.
When using ":new" and the file fits in the window, lines could still be above When using ":new" and the file fits in the window, lines could still be above
the window. Now remove empty lines instead of keeping the relative position. the window. Now remove empty lines instead of keeping the relative position.
Cmdline completion didn't work after ":let var1 var<Tab>".
vim:tw=78:ts=8:ft=help:norl: vim:tw=78:ts=8:ft=help:norl:

View File

@ -82,13 +82,23 @@ struct listitem_S
typedef struct listitem_S listitem; typedef struct listitem_S listitem;
/* /*
* Structure to hold the info about a list. * Struct used by those that are using an item in a list.
*/
typedef struct listwatch_S
{
listitem *lw_item; /* item being watched */
struct listwatch_S *lw_next; /* next watcher */
} listwatch;
/*
* Structure to hold info about a list.
*/ */
struct listvar_S struct listvar_S
{ {
int lv_refcount; /* reference count */ int lv_refcount; /* reference count */
listitem *lv_first; /* first item, NULL if none */ listitem *lv_first; /* first item, NULL if none */
listitem *lv_last; /* last item, NULL if none */ listitem *lv_last; /* last item, NULL if none */
listwatch *lv_watch; /* first watcher, NULL if none */
}; };
typedef struct listvar_S listvar; typedef struct listvar_S listvar;
@ -169,6 +179,18 @@ struct funccall
int level; /* top nesting level of executed function */ int level; /* top nesting level of executed function */
}; };
/*
* Info used by a ":for" loop.
*/
typedef struct forinfo_S
{
int fi_semicolon; /* TRUE if ending in '; var]' */
int fi_varcount; /* nr of variables in the list */
listwatch fi_lw; /* keep an eye on the item used. */
listvar *fi_list; /* list being used */
} forinfo;
/* /*
* Return the name of the executed function. * Return the name of the executed function.
*/ */
@ -504,10 +526,14 @@ static void call_user_func __ARGS((ufunc_T *fp, int argcount, typeval *argvars,
static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end)); static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end));
static int ex_let_vars __ARGS((char_u *arg, typeval *tv, int copy, int semicolon, int var_count, char_u *nextchars));
static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon));
static char_u *skip_var_one __ARGS((char_u *arg));
static void list_all_vars __ARGS((void)); static void list_all_vars __ARGS((void));
static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg)); static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg));
static char_u *ex_let_one __ARGS((char_u *arg, typeval *tv, int copy, char_u *endchars)); static char_u *ex_let_one __ARGS((char_u *arg, typeval *tv, int copy, char_u *endchars));
static char_u *set_var_idx __ARGS((char_u *name, char_u *ip, typeval *rettv, int copy, char_u *endchars)); static char_u *set_var_idx __ARGS((char_u *name, char_u *ip, typeval *rettv, int copy, char_u *endchars));
static void list_add_watch __ARGS((listvar *l, listwatch *lw));
/* /*
* Set an internal variable to a string value. Creates the variable if it does * Set an internal variable to a string value. Creates the variable if it does
@ -1021,14 +1047,16 @@ ex_let(eap)
int i; int i;
int var_count = 0; int var_count = 0;
int semicolon = 0; int semicolon = 0;
listvar *l;
listitem *item;
if (*arg != '[') expr = skip_var_list(arg, &var_count, &semicolon);
expr = vim_strchr(find_name_end(arg, NULL, NULL, TRUE), '='); if (expr == NULL)
if (*arg != '[' && expr == NULL) return;
expr = vim_strchr(expr, '=');
if (expr == NULL)
{ {
if (!ends_excmd(*arg)) if (*arg == '[')
EMSG(_(e_invarg));
else if (!ends_excmd(*arg))
/* ":let var1 var2" */ /* ":let var1 var2" */
arg = list_arg_vars(eap, arg); arg = list_arg_vars(eap, arg);
else if (!eap->skip) else if (!eap->skip)
@ -1038,54 +1066,11 @@ ex_let(eap)
} }
else else
{ {
if (*arg == '[') expr = skipwhite(expr + 1);
{
/* ":let [a, b] = expr": find the matching ']' to get to the
* expression. */
while (1)
{
arg = skipwhite(arg + 1);
if (vim_strchr((char_u *)"$@&", *arg) != NULL)
++arg;
expr = find_name_end(arg, NULL, NULL, TRUE);
if (expr == arg)
{
EMSG2(_(e_invarg2), arg);
return;
}
++var_count;
arg = skipwhite(expr);
if (*arg == ']')
break;
else if (*arg == ';')
{
if (semicolon == 1)
{
EMSG(_("Double ; in :let"));
return;
}
semicolon = 1;
}
else if (*arg != ',')
{
EMSG2(_(e_invarg2), arg);
return;
}
}
/* check for '=' after the ']' */
expr = skipwhite(arg + 1);
if (*expr != '=')
{
EMSG(_(e_letunexp));
return;
}
}
if (eap->skip) if (eap->skip)
++emsg_skip; ++emsg_skip;
i = eval0(expr + 1, &rettv, &eap->nextcmd, !eap->skip); i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
if (eap->skip) if (eap->skip)
{ {
if (i != FAIL) if (i != FAIL)
@ -1094,70 +1079,169 @@ ex_let(eap)
} }
else if (i != FAIL) else if (i != FAIL)
{ {
/* Move "arg" back to the variable name(s). */ (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
arg = eap->arg; (char_u *)"=");
clear_tv(&rettv);
}
}
}
/*
* Assign the typevalue "tv" to the variable or variables at "arg_start".
* Handles both "var" with any type and "[var, var; var]" with a list type.
* Returns OK or FAIL;
*/
static int
ex_let_vars(arg_start, tv, copy, semicolon, var_count, nextchars)
char_u *arg_start;
typeval *tv;
int copy; /* copy values from "tv", don't move */
int semicolon; /* from skip_var_list() */
int var_count; /* from skip_var_list() */
char_u *nextchars; /* characters that must follow or NULL */
{
char_u *arg = arg_start;
listvar *l;
int i;
listitem *item;
typeval ltv;
if (*arg != '[') if (*arg != '[')
{ {
/* ":let var = expr" */ /*
(void)ex_let_one(arg, &rettv, FALSE, (char_u *)"="); * ":let var = expr" or ":for var in list"
*/
if (ex_let_one(arg, tv, copy, nextchars) == NULL)
return FAIL;
return OK;
} }
else
{ /*
/* ":let [v1, v2] = list" */ * ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
l = rettv.vval.v_list; */
if (rettv.v_type != VAR_LIST || l == NULL) l = tv->vval.v_list;
EMSG(_("E999: List required")); if (tv->v_type != VAR_LIST || l == NULL)
else
{ {
EMSG(_(e_listreq));
return FAIL;
}
i = list_len(l); i = list_len(l);
if (semicolon == 0 && var_count < i) if (semicolon == 0 && var_count < i)
EMSG(_("E999: Less targets than List items"));
else if (var_count - semicolon > i)
EMSG(_("E999: More targets than List items"));
else
{ {
EMSG(_("E999: Less targets than List items"));
return FAIL;
}
if (var_count - semicolon > i)
{
EMSG(_("E999: More targets than List items"));
return FAIL;
}
item = l->lv_first; item = l->lv_first;
while (*arg != ']') while (*arg != ']')
{ {
arg = skipwhite(arg + 1); arg = skipwhite(arg + 1);
arg = ex_let_one(arg, &item->li_tv, arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]");
TRUE, (char_u *)",;]");
item = item->li_next; item = item->li_next;
if (arg == NULL) if (arg == NULL)
break; return FAIL;
arg = skipwhite(arg); arg = skipwhite(arg);
if (*arg == ';') if (*arg == ';')
{ {
/* Put the rest of the list (may be empty) in /* Put the rest of the list (may be empty) in the var after ';'.
* the var after ';'. */ * Create a new list for this. */
l = list_alloc(); l = list_alloc();
if (l == NULL) if (l == NULL)
break; return FAIL;
while (item != NULL) while (item != NULL)
{ {
list_append_tv(l, &item->li_tv); list_append_tv(l, &item->li_tv);
item = item->li_next; item = item->li_next;
} }
list_unref(rettv.vval.v_list);
rettv.vval.v_list = l; ltv.v_type = VAR_LIST;
ltv.vval.v_list = l;
l->lv_refcount = 1; l->lv_refcount = 1;
(void)ex_let_one(skipwhite(arg + 1), &rettv,
FALSE, (char_u *)"]"); arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE, (char_u *)"]");
clear_tv(&ltv);
if (arg == NULL)
return FAIL;
break; break;
} }
else if (*arg != ',' && *arg != ']') else if (*arg != ',' && *arg != ']')
{ {
EMSG2(_(e_intern2), "ex_let()"); EMSG2(_(e_intern2), "ex_let_vars()");
return FAIL;
}
}
return OK;
}
/*
* Skip over assignable variable "var" or list of variables "[var, var]".
* Used for ":let varvar = expr" and ":for varvar in expr".
* For "[var, var]" increment "*var_count" for each variable.
* for "[var, var; var]" set "semicolon".
* Return NULL for an error.
*/
static char_u *
skip_var_list(arg, var_count, semicolon)
char_u *arg;
int *var_count;
int *semicolon;
{
char_u *p, *s;
if (*arg == '[')
{
/* "[var, var]": find the matching ']'. */
p = arg;
while (1)
{
p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */
s = skip_var_one(p);
if (s == p)
{
EMSG2(_(e_invarg2), p);
return NULL;
}
++*var_count;
p = skipwhite(s);
if (*p == ']')
break; break;
else if (*p == ';')
{
if (*semicolon == 1)
{
EMSG(_("Double ; in list of variables"));
return NULL;
}
*semicolon = 1;
}
else if (*p != ',')
{
EMSG2(_(e_invarg2), p);
return NULL;
} }
} }
return p + 1;
} }
else
return skip_var_one(arg);
} }
}
clear_tv(&rettv); static char_u *
} skip_var_one(arg)
} char_u *arg;
{
if (vim_strchr((char_u *)"$@&", *arg) != NULL)
++arg;
return find_name_end(arg, NULL, NULL, TRUE);
} }
static void static void
@ -1309,7 +1393,7 @@ ex_let_one(arg, tv, copy, endchars)
char_u *arg; /* points to variable name */ char_u *arg; /* points to variable name */
typeval *tv; /* value to assign to variable */ typeval *tv; /* value to assign to variable */
int copy; /* copy value from "tv" */ int copy; /* copy value from "tv" */
char_u *endchars; /* valid chars after variable name */ char_u *endchars; /* valid chars after variable name or NULL */
{ {
int c1; int c1;
char_u *name; char_u *name;
@ -1331,7 +1415,8 @@ ex_let_one(arg, tv, copy, endchars)
EMSG2(_(e_invarg2), name - 1); EMSG2(_(e_invarg2), name - 1);
else else
{ {
if (vim_strchr(endchars, *skipwhite(arg)) == NULL) if (endchars != NULL
&& vim_strchr(endchars, *skipwhite(arg)) == NULL)
EMSG(_(e_letunexp)); EMSG(_(e_letunexp));
else else
{ {
@ -1360,7 +1445,8 @@ ex_let_one(arg, tv, copy, endchars)
{ {
/* Find the end of the name. */ /* Find the end of the name. */
p = find_option_end(&arg, &opt_flags); p = find_option_end(&arg, &opt_flags);
if (p == NULL || vim_strchr(endchars, *skipwhite(p)) == NULL) if (p == NULL || (endchars != NULL
&& vim_strchr(endchars, *skipwhite(p)) == NULL))
EMSG(_(e_letunexp)); EMSG(_(e_letunexp));
else else
{ {
@ -1379,7 +1465,8 @@ ex_let_one(arg, tv, copy, endchars)
else if (*arg == '@') else if (*arg == '@')
{ {
++arg; ++arg;
if (vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) if (endchars != NULL
&& vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
EMSG(_(e_letunexp)); EMSG(_(e_letunexp));
else else
{ {
@ -1415,7 +1502,8 @@ ex_let_one(arg, tv, copy, endchars)
} }
else if (*p == '[') else if (*p == '[')
arg_end = set_var_idx(arg, p, tv, copy, endchars); arg_end = set_var_idx(arg, p, tv, copy, endchars);
else if (vim_strchr(endchars, *skipwhite(p)) == NULL) else if (endchars != NULL
&& vim_strchr(endchars, *skipwhite(p)) == NULL)
EMSG(_(e_letunexp)); EMSG(_(e_letunexp));
else if (STRNCMP(arg, "b:changedtick", 13) == 0 else if (STRNCMP(arg, "b:changedtick", 13) == 0
&& !eval_isnamec(arg[13])) && !eval_isnamec(arg[13]))
@ -1505,7 +1593,7 @@ set_var_idx(name, ip, rettv, copy, endchars)
if (p != NULL) if (p != NULL)
{ {
if (vim_strchr(endchars, *p) == NULL) if (endchars != NULL && vim_strchr(endchars, *p) == NULL)
{ {
EMSG(_(e_letunexp)); EMSG(_(e_letunexp));
p = NULL; p = NULL;
@ -1525,6 +1613,157 @@ set_var_idx(name, ip, rettv, copy, endchars)
return p; return p;
} }
/*
* Add a watcher to a list.
*/
static void
list_add_watch(l, lw)
listvar *l;
listwatch *lw;
{
lw->lw_next = l->lv_watch;
l->lv_watch = lw;
}
/*
* Remove a watches from a list.
* No warning when it isn't found...
*/
static void
list_rem_watch(l, lwrem)
listvar *l;
listwatch *lwrem;
{
listwatch *lw, **lwp;
lwp = &l->lv_watch;
for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
{
if (lw == lwrem)
{
*lwp = lw->lw_next;
break;
}
lwp = &lw->lw_next;
}
}
/*
* Just before removing an item from a list: advance watchers to the next
* item.
*/
static void
list_fix_watch(l, item)
listvar *l;
listitem *item;
{
listwatch *lw;
for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
if (lw->lw_item == item)
lw->lw_item = item->li_next;
}
/*
* Evaluate the expression used in a ":for var in expr" command.
* "arg" points to "var".
* Set "*errp" to TRUE for an error, FALSE otherwise;
* Return a pointer that holds the info. Null when there is an error.
*/
void *
eval_for_line(arg, errp, nextcmdp, skip)
char_u *arg;
int *errp;
char_u **nextcmdp;
int skip;
{
forinfo *fi;
char_u *expr;
typeval tv;
listvar *l;
*errp = TRUE; /* default: there is an error */
fi = (forinfo *)alloc_clear(sizeof(forinfo));
if (fi == NULL)
return NULL;
expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
if (expr == NULL)
return fi;
expr = skipwhite(expr);
if (expr[0] != 'i' || expr[1] != 'n' || !vim_iswhite(expr[2]))
{
EMSG(_("E999: Missing \"in\" after :for"));
return fi;
}
if (skip)
++emsg_skip;
if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK)
{
*errp = FALSE;
if (!skip)
{
l = tv.vval.v_list;
if (tv.v_type != VAR_LIST || l == NULL)
EMSG(_(e_listreq));
else
{
fi->fi_list = l;
list_add_watch(l, &fi->fi_lw);
fi->fi_lw.lw_item = l->lv_first;
}
}
}
if (skip)
--emsg_skip;
return fi;
}
/*
* Use the first item in a ":for" list. Advance to the next.
* Assign the values to the variable (list). "arg" points to the first one.
* Return TRUE when a valid item was found, FALSE when at end of list or
* something wrong.
*/
int
next_for_item(fi_void, arg)
void *fi_void;
char_u *arg;
{
forinfo *fi = (forinfo *)fi_void;
int result;
listitem *item;
item = fi->fi_lw.lw_item;
if (item == NULL)
result = FALSE;
else
{
fi->fi_lw.lw_item = item->li_next;
result = (ex_let_vars(arg, &item->li_tv, TRUE,
fi->fi_semicolon, fi->fi_varcount, NULL) == OK);
}
return result;
}
/*
* Free the structure used to store info used by ":for".
*/
void
free_for_info(fi_void)
void *fi_void;
{
forinfo *fi = (forinfo *)fi_void;
if (fi->fi_list != NULL)
list_rem_watch(fi->fi_list, &fi->fi_lw);
vim_free(fi);
}
#if defined(FEAT_CMDL_COMPL) || defined(PROTO) #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
void void
@ -1535,9 +1774,26 @@ set_context_for_expression(xp, arg, cmdidx)
{ {
int got_eq = FALSE; int got_eq = FALSE;
int c; int c;
char_u *p;
xp->xp_context = cmdidx == CMD_let ? EXPAND_USER_VARS if (cmdidx == CMD_let)
: cmdidx == CMD_call ? EXPAND_FUNCTIONS {
xp->xp_context = EXPAND_USER_VARS;
if (vim_strchr(arg, '=') == NULL)
{
/* ":let var1 var2 ...": find last space. */
for (p = arg + STRLEN(arg); p > arg; )
{
xp->xp_pattern = p;
p = mb_ptr_back(arg, p);
if (vim_iswhite(*p))
break;
}
return;
}
}
else
xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS
: EXPAND_EXPRESSION; : EXPAND_EXPRESSION;
while ((xp->xp_pattern = vim_strpbrk(arg, while ((xp->xp_pattern = vim_strpbrk(arg,
(char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL) (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
@ -1601,7 +1857,9 @@ set_context_for_expression(xp, arg, cmdidx)
xp->xp_context = EXPAND_EXPRESSION; xp->xp_context = EXPAND_EXPRESSION;
} }
else else
xp->xp_context = EXPAND_NOTHING; /* Doesn't look like something valid, expand as an expression
* anyway. */
xp->xp_context = EXPAND_EXPRESSION;
arg = xp->xp_pattern; arg = xp->xp_pattern;
if (*arg != NUL) if (*arg != NUL)
while ((c = *++arg) != NUL && (c == ' ' || c == '\t')) while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
@ -3303,7 +3561,7 @@ listitem_alloc()
} }
/* /*
* Free a list item. Also clears the value; * Free a list item. Also clears the value. Does not notify watchers.
*/ */
static void static void
listitem_free(item) listitem_free(item)
@ -3471,6 +3729,7 @@ list_getrem(l, n)
item = list_find(l, n); item = list_find(l, n);
if (item != NULL) if (item != NULL)
{ {
list_fix_watch(l, item); /* notify watchers */
if (item->li_next == NULL) if (item->li_next == NULL)
l->lv_last = item->li_prev; l->lv_last = item->li_prev;
else else
@ -11806,8 +12065,7 @@ read_viminfo_varlist(virp, writing)
{ {
char_u *tab; char_u *tab;
int is_string = FALSE; int is_string = FALSE;
typeval *tvp = NULL; typeval tv;
char_u *val;
if (!writing && (find_viminfo_parameter('!') != NULL)) if (!writing && (find_viminfo_parameter('!') != NULL))
{ {
@ -11821,29 +12079,20 @@ read_viminfo_varlist(virp, writing)
tab = vim_strchr(tab, '\t'); tab = vim_strchr(tab, '\t');
if (tab != NULL) if (tab != NULL)
{ {
/* create a typeval to hold the value */
if (is_string) if (is_string)
{ {
val = viminfo_readstring(virp, tv.v_type = VAR_STRING;
tv.vval.v_string = viminfo_readstring(virp,
(int)(tab - virp->vir_line + 1), TRUE); (int)(tab - virp->vir_line + 1), TRUE);
if (val != NULL)
tvp = alloc_string_tv(val);
} }
else else
{ {
tvp = alloc_tv(); tv.v_type = VAR_NUMBER;
if (tvp != NULL) tv.vval.v_number = atol((char *)tab + 1);
{
tvp->v_type = VAR_NUMBER;
tvp->vval.v_number = atol((char *)tab + 1);
}
}
/* assign the value to the variable */
if (tvp != NULL)
{
set_var(virp->vir_line + 1, tvp, FALSE);
free_tv(tvp);
} }
set_var(virp->vir_line + 1, &tv, FALSE);
if (is_string)
vim_free(tv.vval.v_string);
} }
} }
} }
@ -11878,11 +12127,7 @@ write_viminfo_varlist(fp)
{ {
case VAR_STRING: s = "STR"; break; case VAR_STRING: s = "STR"; break;
case VAR_NUMBER: s = "NUM"; break; case VAR_NUMBER: s = "NUM"; break;
case VAR_LIST: s = "LST"; break; default: continue;
case VAR_FUNC: s = "FUN"; break;
default:
EMSGN(_("E999: Internal error: write_viminfo_varlist(): %ld"), (long)this_var->tv.v_type);
s = "ERR";
} }
fprintf(fp, "!%s\t%s\t", this_var->v_name, s); fprintf(fp, "!%s\t%s\t", this_var->v_name, s);
viminfo_writestring(fp, tv2string(&this_var->tv, &tofree)); viminfo_writestring(fp, tv2string(&this_var->tv, &tofree));
@ -11905,11 +12150,12 @@ store_session_globals(fd)
for (i = gap->ga_len; --i >= 0; ) for (i = gap->ga_len; --i >= 0; )
{ {
this_var = &VAR_GAP_ENTRY(i, gap); this_var = &VAR_GAP_ENTRY(i, gap);
if (this_var->v_name != NULL) if (this_var->v_name != NULL
&& (this_var->tv.v_type == VAR_NUMBER
|| this_var->tv.v_type == VAR_STRING)
&& var_flavour(this_var->v_name) == VAR_FLAVOUR_SESSION)
{ {
if (var_flavour(this_var->v_name) == VAR_FLAVOUR_SESSION) /* Escape special characters with a backslash. Turn a LF and
{
/* Escapse special characters with a backslash. Turn a LF and
* CR into \n and \r. */ * CR into \n and \r. */
p = vim_strsave_escaped(get_var_string(this_var), p = vim_strsave_escaped(get_var_string(this_var),
(char_u *)"\\\"\n\r"); (char_u *)"\\\"\n\r");
@ -11932,8 +12178,6 @@ store_session_globals(fd)
} }
vim_free(p); vim_free(p);
} }
}
} }
return OK; return OK;
} }

View File

@ -3258,13 +3258,13 @@ ex_append(eap)
if (eap->getline == NULL) if (eap->getline == NULL)
theline = getcmdline( theline = getcmdline(
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
eap->cstack->cs_whilelevel > 0 ? -1 : eap->cstack->cs_looplevel > 0 ? -1 :
#endif #endif
NUL, 0L, 0); NUL, 0L, 0);
else else
theline = eap->getline( theline = eap->getline(
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
eap->cstack->cs_whilelevel > 0 ? -1 : eap->cstack->cs_looplevel > 0 ? -1 :
#endif #endif
NUL, eap->cookie, 0); NUL, eap->cookie, 0);
lines_left = Rows - 1; lines_left = Rows - 1;

View File

@ -342,6 +342,8 @@ EX(CMD_endif, "endif", ex_endif,
TRLBAR|SBOXOK|CMDWIN), TRLBAR|SBOXOK|CMDWIN),
EX(CMD_endfunction, "endfunction", ex_endfunction, EX(CMD_endfunction, "endfunction", ex_endfunction,
TRLBAR|CMDWIN), TRLBAR|CMDWIN),
EX(CMD_endfor, "endfor", ex_endwhile,
TRLBAR|SBOXOK|CMDWIN),
EX(CMD_endtry, "endtry", ex_endtry, EX(CMD_endtry, "endtry", ex_endtry,
TRLBAR|SBOXOK|CMDWIN), TRLBAR|SBOXOK|CMDWIN),
EX(CMD_endwhile, "endwhile", ex_endwhile, EX(CMD_endwhile, "endwhile", ex_endwhile,
@ -382,6 +384,8 @@ EX(CMD_folddoclosed, "folddoclosed", ex_folddo,
RANGE|DFLALL|NEEDARG|EXTRA|NOTRLCOM), RANGE|DFLALL|NEEDARG|EXTRA|NOTRLCOM),
EX(CMD_foldopen, "foldopen", ex_foldopen, EX(CMD_foldopen, "foldopen", ex_foldopen,
RANGE|BANG|WHOLEFOLD|TRLBAR|SBOXOK|CMDWIN), RANGE|BANG|WHOLEFOLD|TRLBAR|SBOXOK|CMDWIN),
EX(CMD_for, "for", ex_while,
EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
EX(CMD_function, "function", ex_function, EX(CMD_function, "function", ex_function,
EXTRA|BANG|CMDWIN), EXTRA|BANG|CMDWIN),
EX(CMD_global, "global", ex_global, EX(CMD_global, "global", ex_global,