]> granicus.if.org Git - vim/commitdiff
updated for version 7.0031 v7.0031
authorBram Moolenaar <Bram@vim.org>
Wed, 5 Jan 2005 22:19:46 +0000 (22:19 +0000)
committerBram Moolenaar <Bram@vim.org>
Wed, 5 Jan 2005 22:19:46 +0000 (22:19 +0000)
runtime/doc/todo.txt
runtime/doc/version7.txt
src/eval.c
src/ex_cmds.c
src/ex_cmds.h

index 924853b92388c768018091e95c690269e24f4324..54213cfc25ca2df22b974694b811e0eca46a525c 100644 (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
@@ -30,16 +30,16 @@ be worked on, but only if you sponsor Vim development.  See |sponsor|.
                                                        *known-bugs*
 -------------------- 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:
+- 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"
+    Make copy of the list to avoid trouble when it changes.  As one big block?
 - "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)
-- store in viminfo: read_viminfo_varlist()
 - add many functions:
     call(func, list)           call function
     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
     file2lines()
     file2words()
+    str2list()                 parse string to list in several ways: white
+                               separated, [] form, etc.
 Fix the error numbers E999 in eval.c.
 
 Function reference: Define a nameless (numbered) function and assign
index 02814008ec43b443e9e198b89c7e666bdd993503..b5191486efbdf51663bb09abe56694785bfcb9ac 100644 (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
@@ -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
 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:
index e812e5329ffc2d2ed0623c96d56f65262a4bd20d..6ed5c9fab36082d2bcd73fc682f11db6b061e7c2 100644 (file)
@@ -82,13 +82,23 @@ struct listitem_S
 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
 {
     int                lv_refcount;    /* reference count */
     listitem   *lv_first;      /* first 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;
@@ -169,6 +179,18 @@ struct funccall
     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.
  */
@@ -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 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 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 *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
@@ -1021,14 +1047,16 @@ ex_let(eap)
     int                i;
     int                var_count = 0;
     int                semicolon = 0;
-    listvar    *l;
-    listitem   *item;
 
-    if (*arg != '[')
-       expr = vim_strchr(find_name_end(arg, NULL, NULL, TRUE), '=');
-    if (*arg != '[' && expr == NULL)
+    expr = skip_var_list(arg, &var_count, &semicolon);
+    if (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" */
            arg = list_arg_vars(eap, arg);
        else if (!eap->skip)
@@ -1038,54 +1066,11 @@ ex_let(eap)
     }
     else
     {
-       if (*arg == '[')
-       {
-           /* ":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;
-           }
-       }
+       expr = skipwhite(expr + 1);
 
        if (eap->skip)
            ++emsg_skip;
-       i = eval0(expr + 1, &rettv, &eap->nextcmd, !eap->skip);
+       i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
        if (eap->skip)
        {
            if (i != FAIL)
@@ -1094,70 +1079,169 @@ ex_let(eap)
        }
        else if (i != FAIL)
        {
-           /* Move "arg" back to the variable name(s). */
-           arg = eap->arg;
-           if (*arg != '[')
+           (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
+                                                              (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 != '[')
+    {
+       /*
+        * ":let var = expr" or ":for var in list"
+        */
+       if (ex_let_one(arg, tv, copy, nextchars) == NULL)
+           return FAIL;
+       return OK;
+    }
+
+    /*
+     * ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
+     */
+    l = tv->vval.v_list;
+    if (tv->v_type != VAR_LIST || l == NULL)
+    {
+       EMSG(_(e_listreq));
+       return FAIL;
+    }
+
+    i = list_len(l);
+    if (semicolon == 0 && var_count < i)
+    {
+       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;
+    while (*arg != ']')
+    {
+       arg = skipwhite(arg + 1);
+       arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]");
+       item = item->li_next;
+       if (arg == NULL)
+           return FAIL;
+
+       arg = skipwhite(arg);
+       if (*arg == ';')
+       {
+           /* Put the rest of the list (may be empty) in the var after ';'.
+            * Create a new list for this. */
+           l = list_alloc();
+           if (l == NULL)
+               return FAIL;
+           while (item != NULL)
+           {
+               list_append_tv(l, &item->li_tv);
+               item = item->li_next;
+           }
+
+           ltv.v_type = VAR_LIST;
+           ltv.vval.v_list = l;
+           l->lv_refcount = 1;
+
+           arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE, (char_u *)"]");
+           clear_tv(&ltv);
+           if (arg == NULL)
+               return FAIL;
+           break;
+       }
+       else if (*arg != ',' && *arg != ']')
+       {
+           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)
            {
-               /* ":let var = expr" */
-               (void)ex_let_one(arg, &rettv, FALSE, (char_u *)"=");
+               EMSG2(_(e_invarg2), p);
+               return NULL;
            }
-           else
+           ++*var_count;
+
+           p = skipwhite(s);
+           if (*p == ']')
+               break;
+           else if (*p == ';')
            {
-               /* ":let [v1, v2] = list" */
-               l = rettv.vval.v_list;
-               if (rettv.v_type != VAR_LIST || l == NULL)
-                   EMSG(_("E999: List required"));
-               else
+               if (*semicolon == 1)
                {
-                   i = list_len(l);
-                   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
-                   {
-                       item = l->lv_first;
-                       while (*arg != ']')
-                       {
-                           arg = skipwhite(arg + 1);
-                           arg = ex_let_one(arg, &item->li_tv,
-                                                      TRUE, (char_u *)",;]");
-                           item = item->li_next;
-                           if (arg == NULL)
-                               break;
-
-                           arg = skipwhite(arg);
-                           if (*arg == ';')
-                           {
-                               /* Put the rest of the list (may be empty) in
-                                * the var after ';'. */
-                               l = list_alloc();
-                               if (l == NULL)
-                                   break;
-                               while (item != NULL)
-                               {
-                                   list_append_tv(l, &item->li_tv);
-                                   item = item->li_next;
-                               }
-                               list_unref(rettv.vval.v_list);
-                               rettv.vval.v_list = l;
-                               l->lv_refcount = 1;
-                               (void)ex_let_one(skipwhite(arg + 1), &rettv,
-                                                        FALSE, (char_u *)"]");
-                               break;
-                           }
-                           else if (*arg != ',' && *arg != ']')
-                           {
-                               EMSG2(_(e_intern2), "ex_let()");
-                               break;
-                           }
-                       }
-                   }
+                   EMSG(_("Double ; in list of variables"));
+                   return NULL;
                }
+               *semicolon = 1;
+           }
+           else if (*p != ',')
+           {
+               EMSG2(_(e_invarg2), p);
+               return NULL;
            }
-           clear_tv(&rettv);
        }
+       return p + 1;
     }
+    else
+       return skip_var_one(arg);
+}
+
+    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
@@ -1309,7 +1393,7 @@ ex_let_one(arg, tv, copy, endchars)
     char_u     *arg;           /* points to variable name */
     typeval    *tv;            /* value to assign to variable */
     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;
     char_u     *name;
@@ -1331,7 +1415,8 @@ ex_let_one(arg, tv, copy, endchars)
            EMSG2(_(e_invarg2), name - 1);
        else
        {
-           if (vim_strchr(endchars, *skipwhite(arg)) == NULL)
+           if (endchars != NULL
+                            && vim_strchr(endchars, *skipwhite(arg)) == NULL)
                EMSG(_(e_letunexp));
            else
            {
@@ -1360,7 +1445,8 @@ ex_let_one(arg, tv, copy, endchars)
     {
        /* Find the end of the name. */
        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));
        else
        {
@@ -1379,7 +1465,8 @@ ex_let_one(arg, tv, copy, endchars)
     else if (*arg == '@')
     {
        ++arg;
-       if (vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
+       if (endchars != NULL
+                        && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
            EMSG(_(e_letunexp));
        else
        {
@@ -1415,7 +1502,8 @@ ex_let_one(arg, tv, copy, endchars)
        }
        else if (*p == '[')
            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));
        else if (STRNCMP(arg, "b:changedtick", 13) == 0
                                            && !eval_isnamec(arg[13]))
@@ -1505,7 +1593,7 @@ set_var_idx(name, ip, rettv, copy, endchars)
 
     if (p != NULL)
     {
-       if (vim_strchr(endchars, *p) == NULL)
+       if (endchars != NULL && vim_strchr(endchars, *p) == NULL)
        {
            EMSG(_(e_letunexp));
            p = NULL;
@@ -1525,6 +1613,157 @@ set_var_idx(name, ip, rettv, copy, endchars)
     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)
 
     void
@@ -1535,10 +1774,27 @@ set_context_for_expression(xp, arg, cmdidx)
 {
     int                got_eq = FALSE;
     int                c;
+    char_u     *p;
 
-    xp->xp_context = cmdidx == CMD_let ? EXPAND_USER_VARS
-                                      : cmdidx == CMD_call ? EXPAND_FUNCTIONS
-                                      : EXPAND_EXPRESSION;
+    if (cmdidx == CMD_let)
+    {
+       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;
     while ((xp->xp_pattern = vim_strpbrk(arg,
                                  (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
     {
@@ -1601,7 +1857,9 @@ set_context_for_expression(xp, arg, cmdidx)
                xp->xp_context = EXPAND_EXPRESSION;
        }
        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;
        if (*arg != NUL)
            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
 listitem_free(item)
@@ -3471,6 +3729,7 @@ list_getrem(l, n)
     item = list_find(l, n);
     if (item != NULL)
     {
+       list_fix_watch(l, item);        /* notify watchers */
        if (item->li_next == NULL)
            l->lv_last = item->li_prev;
        else
@@ -11806,8 +12065,7 @@ read_viminfo_varlist(virp, writing)
 {
     char_u     *tab;
     int                is_string = FALSE;
-    typeval    *tvp = NULL;
-    char_u     *val;
+    typeval    tv;
 
     if (!writing && (find_viminfo_parameter('!') != NULL))
     {
@@ -11821,29 +12079,20 @@ read_viminfo_varlist(virp, writing)
            tab = vim_strchr(tab, '\t');
            if (tab != NULL)
            {
-               /* create a typeval to hold the value */
                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);
-                   if (val != NULL)
-                       tvp = alloc_string_tv(val);
                }
                else
                {
-                   tvp = alloc_tv();
-                   if (tvp != NULL)
-                   {
-                       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);
+                   tv.v_type = VAR_NUMBER;
+                   tv.vval.v_number = atol((char *)tab + 1);
                }
+               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_NUMBER: s = "NUM"; break;
-               case VAR_LIST:   s = "LST"; break;
-               case VAR_FUNC:   s = "FUN"; break;
-               default:
-                    EMSGN(_("E999: Internal error: write_viminfo_varlist(): %ld"), (long)this_var->tv.v_type);
-                    s = "ERR";
+               default: continue;
            }
            fprintf(fp, "!%s\t%s\t", this_var->v_name, s);
            viminfo_writestring(fp, tv2string(&this_var->tv, &tofree));
@@ -11905,34 +12150,33 @@ store_session_globals(fd)
     for (i = gap->ga_len; --i >= 0; )
     {
        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)
-           {
-               /* Escapse special characters with a backslash.  Turn a LF and
-                * CR into \n and \r. */
-               p = vim_strsave_escaped(get_var_string(this_var),
+           /* Escape special characters with a backslash.  Turn a LF and
+            * CR into \n and \r. */
+           p = vim_strsave_escaped(get_var_string(this_var),
                                                        (char_u *)"\\\"\n\r");
-               if (p == NULL)      /* out of memory */
-                   continue;
-               for (t = p; *t != NUL; ++t)
-                   if (*t == '\n')
-                       *t = 'n';
-                   else if (*t == '\r')
-                       *t = 'r';
-               if ((fprintf(fd, "let %s = %c%s%c",
-                          this_var->v_name,
-                          (this_var->tv.v_type == VAR_STRING) ? '"' : ' ',
-                          p,
-                          (this_var->tv.v_type == VAR_STRING) ? '"' : ' ') < 0)
-                       || put_eol(fd) == FAIL)
-               {
-                   vim_free(p);
-                   return FAIL;
-               }
+           if (p == NULL)          /* out of memory */
+               continue;
+           for (t = p; *t != NUL; ++t)
+               if (*t == '\n')
+                   *t = 'n';
+               else if (*t == '\r')
+                   *t = 'r';
+           if ((fprintf(fd, "let %s = %c%s%c",
+                      this_var->v_name,
+                      (this_var->tv.v_type == VAR_STRING) ? '"' : ' ',
+                      p,
+                      (this_var->tv.v_type == VAR_STRING) ? '"' : ' ') < 0)
+                   || put_eol(fd) == FAIL)
+           {
                vim_free(p);
+               return FAIL;
            }
-
+           vim_free(p);
        }
     }
     return OK;
index adac95b8362f1f432505a21fcf81bba6b04b04c4..7bcdaf2e914f725ed33a35b34dd2e31694f4ad7d 100644 (file)
@@ -3258,13 +3258,13 @@ ex_append(eap)
        if (eap->getline == NULL)
            theline = getcmdline(
 #ifdef FEAT_EVAL
-                   eap->cstack->cs_whilelevel > 0 ? -1 :
+                   eap->cstack->cs_looplevel > 0 ? -1 :
 #endif
                    NUL, 0L, 0);
        else
            theline = eap->getline(
 #ifdef FEAT_EVAL
-                   eap->cstack->cs_whilelevel > 0 ? -1 :
+                   eap->cstack->cs_looplevel > 0 ? -1 :
 #endif
                    NUL, eap->cookie, 0);
        lines_left = Rows - 1;
index b44dd1de2b31bdc18d5349c3420b7efb5e2451c2..870fcb43ba7e3d94b7e06d05d6d245b670d31f75 100644 (file)
@@ -342,6 +342,8 @@ EX(CMD_endif,               "endif",        ex_endif,
                        TRLBAR|SBOXOK|CMDWIN),
 EX(CMD_endfunction,    "endfunction",  ex_endfunction,
                        TRLBAR|CMDWIN),
+EX(CMD_endfor,         "endfor",       ex_endwhile,
+                       TRLBAR|SBOXOK|CMDWIN),
 EX(CMD_endtry,         "endtry",       ex_endtry,
                        TRLBAR|SBOXOK|CMDWIN),
 EX(CMD_endwhile,       "endwhile",     ex_endwhile,
@@ -382,6 +384,8 @@ EX(CMD_folddoclosed,        "folddoclosed", ex_folddo,
                        RANGE|DFLALL|NEEDARG|EXTRA|NOTRLCOM),
 EX(CMD_foldopen,       "foldopen",     ex_foldopen,
                        RANGE|BANG|WHOLEFOLD|TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_for,            "for",          ex_while,
+                       EXTRA|NOTRLCOM|SBOXOK|CMDWIN),
 EX(CMD_function,       "function",     ex_function,
                        EXTRA|BANG|CMDWIN),
 EX(CMD_global,         "global",       ex_global,