summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-04-21 14:24:24 +0200
committerBram Moolenaar <Bram@vim.org>2021-04-21 14:24:24 +0200
commit753bcf8c7d7cf7b9e1572a80cc513a67020814ac (patch)
tree5f5efad06ee0a97505aa04376d26c08d001b7759
parent169502fb0beb7eb21f72d6c4590483c069353b53 (diff)
downloadvim-git-753bcf8c7d7cf7b9e1572a80cc513a67020814ac.tar.gz
patch 8.2.2796: Vim9: redir to variable does not accept an indexv8.2.2796
Problem: Vim9: redir to variable does not accept an index. Solution: Make the index work.
-rw-r--r--src/testdir/test_vim9_cmd.vim25
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c50
3 files changed, 64 insertions, 13 deletions
diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim
index 0ff2e280f..ddf3df2a4 100644
--- a/src/testdir/test_vim9_cmd.vim
+++ b/src/testdir/test_vim9_cmd.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index 18d6c8069..a72385929 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2796,
+/**/
2795,
/**/
2794,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 4b81f3f1b..d6ea322d3 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -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;