]> granicus.if.org Git - vim/commitdiff
patch 8.2.2796: Vim9: redir to variable does not accept an index v8.2.2796
authorBram Moolenaar <Bram@vim.org>
Wed, 21 Apr 2021 12:24:24 +0000 (14:24 +0200)
committerBram Moolenaar <Bram@vim.org>
Wed, 21 Apr 2021 12:24:24 +0000 (14:24 +0200)
Problem:    Vim9: redir to variable does not accept an index.
Solution:   Make the index work.

src/testdir/test_vim9_cmd.vim
src/version.c
src/vim9compile.c

index 0ff2e280f2c71b67b957b47bfe344428db33f3e7..ddf3df2a4d7c26565f489fc5317be7d6f6f5276b 100644 (file)
@@ -1212,10 +1212,35 @@ def Test_redir_to_var()
   redir END
   assert_equal("\nsomething\nmore", result)
 
+  var d: dict<string>
+  redir => d.redir
+    echo 'dict'
+  redir END
+  assert_equal({redir: "\ndict"}, d)
+
+  var l = ['a', 'b', 'c']
+  redir => l[1]
+    echo 'list'
+  redir END
+  assert_equal(['a', "\nlist", 'c'], l)
+
+  var dl = {l: ['x']}
+  redir => dl.l[0]
+    echo 'dict-list'
+  redir END
+  assert_equal({l: ["\ndict-list"]}, dl)
+
   var lines =<< trim END
     redir => notexist
   END
   CheckDefFailure(lines, 'E1089:')
+
+  lines =<< trim END
+    var ls = 'asdf'
+    redir => ls[1]
+    redir END
+  END
+  CheckDefFailure(lines, 'E1141:')
 enddef
 
 
index 18d6c8069b792224bcdd0bb1347a33e5c19fc2b5..a72385929a230a3ff727becfc21ad3805e538941 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2796,
 /**/
     2795,
 /**/
index 4b81f3f1b765d27e3b4247594e3aeac148081495..d6ea322d3f26bef479b8f9a04f3e0b5e8baea7a1 100644 (file)
@@ -134,10 +134,14 @@ typedef enum {
 typedef struct {
     assign_dest_T   lhs_dest;      // type of destination
 
-    char_u         *lhs_name;      // allocated name including
+    char_u         *lhs_name;      // allocated name excluding the last
                                    // "[expr]" or ".name".
     size_t         lhs_varlen;     // length of the variable without
                                    // "[expr]" or ".name"
+    char_u         *lhs_whole;     // allocated name including the last
+                                   // "[expr]" or ".name" for :redir
+    size_t         lhs_varlen_total; // length of the variable including
+                                     // any "[expr]" or ".name"
     char_u         *lhs_dest_end;  // end of the destination, including
                                    // "[expr]" or ".name".
 
@@ -5845,6 +5849,7 @@ compile_lhs(
 
     // compute the length of the destination without "[expr]" or ".name"
     lhs->lhs_varlen = var_end - var_start;
+    lhs->lhs_varlen_total = lhs->lhs_varlen;
     lhs->lhs_name = vim_strnsave(var_start, lhs->lhs_varlen);
     if (lhs->lhs_name == NULL)
        return FAIL;
@@ -6073,7 +6078,10 @@ compile_lhs(
            {
                p = skip_index(after);
                if (*p != '[' && *p != '.')
+               {
+                   lhs->lhs_varlen_total = p - var_start;
                    break;
+               }
                after = p;
            }
            if (after > var_start + lhs->lhs_varlen)
@@ -8592,17 +8600,17 @@ compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
 compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
 {
     char_u *arg = eap->arg;
+    lhs_T      *lhs = &cctx->ctx_redir_lhs;
 
-    if (cctx->ctx_redir_lhs.lhs_name != NULL)
+    if (lhs->lhs_name != NULL)
     {
        if (STRNCMP(arg, "END", 3) == 0)
        {
-           if (cctx->ctx_redir_lhs.lhs_append)
+           if (lhs->lhs_append)
            {
-               if (compile_load_lhs(&cctx->ctx_redir_lhs,
-                            cctx->ctx_redir_lhs.lhs_name, NULL, cctx) == FAIL)
+               if (compile_load_lhs(lhs, lhs->lhs_name, NULL, cctx) == FAIL)
                    return NULL;
-               if (cctx->ctx_redir_lhs.lhs_has_index)
+               if (lhs->lhs_has_index)
                    emsg("redir with index not implemented yet");
            }
 
@@ -8610,13 +8618,22 @@ compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
            // in the variable.
            generate_instr_type(cctx, ISN_REDIREND, &t_string);
 
-           if (cctx->ctx_redir_lhs.lhs_append)
+           if (lhs->lhs_append)
                generate_instr_drop(cctx, ISN_CONCAT, 1);
 
-           if (generate_store_lhs(cctx, &cctx->ctx_redir_lhs, -1) == FAIL)
+           if (lhs->lhs_has_index)
+           {
+               // Use the info in "lhs" to store the value at the index in the
+               // list or dict.
+               if (compile_assign_unlet(lhs->lhs_whole, lhs, TRUE,
+                                                     &t_string, cctx) == FAIL)
+                   return NULL;
+           }
+           else if (generate_store_lhs(cctx, lhs, -1) == FAIL)
                return NULL;
 
-           VIM_CLEAR(cctx->ctx_redir_lhs.lhs_name);
+           VIM_CLEAR(lhs->lhs_name);
+           VIM_CLEAR(lhs->lhs_whole);
            return arg + 3;
        }
        emsg(_(e_cannot_nest_redir));
@@ -8625,7 +8642,7 @@ compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
 
     if (arg[0] == '=' && arg[1] == '>')
     {
-       int append = FALSE;
+       int         append = FALSE;
 
        // redirect to a variable is compiled
        arg += 2;
@@ -8636,13 +8653,19 @@ compile_redir(char_u *line, exarg_T *eap, cctx_T *cctx)
        }
        arg = skipwhite(arg);
 
-       if (compile_assign_lhs(arg, &cctx->ctx_redir_lhs, CMD_redir,
+       if (compile_assign_lhs(arg, lhs, CMD_redir,
                                                FALSE, FALSE, 1, cctx) == FAIL)
            return NULL;
        generate_instr(cctx, ISN_REDIRSTART);
-       cctx->ctx_redir_lhs.lhs_append = append;
+       lhs->lhs_append = append;
+       if (lhs->lhs_has_index)
+       {
+           lhs->lhs_whole = vim_strnsave(arg, lhs->lhs_varlen_total);
+           if (lhs->lhs_whole == NULL)
+               return NULL;
+       }
 
-       return arg + cctx->ctx_redir_lhs.lhs_varlen;
+       return arg + lhs->lhs_varlen_total;
     }
 
     // other redirects are handled like at script level
@@ -9335,6 +9358,7 @@ erret:
            ret = FAIL;
        }
        vim_free(cctx.ctx_redir_lhs.lhs_name);
+       vim_free(cctx.ctx_redir_lhs.lhs_whole);
     }
 
     current_sctx = save_current_sctx;