Skip to content

Commit bce51d9

Browse files
yegappanchrisbra
authored andcommitted
patch 9.1.0335: String interpolation fails for List type
Problem: String interpolation fails for List type Solution: use implicit string(list) for string interpolation and :put = (Yegappan Lakshmanan) related: #14529 closes: #14556 Signed-off-by: Yegappan Lakshmanan <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent a59e031 commit bce51d9

File tree

15 files changed

+160
-33
lines changed

15 files changed

+160
-33
lines changed

src/eval.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -575,17 +575,16 @@ skip_expr_concatenate(
575575

576576
/*
577577
* Convert "tv" to a string.
578-
* When "convert" is TRUE convert a List into a sequence of lines and a Dict
579-
* into a textual representation of the Dict.
578+
* When "join_list" is TRUE convert a List into a sequence of lines.
580579
* Returns an allocated string (NULL when out of memory).
581580
*/
582581
char_u *
583-
typval2string(typval_T *tv, int convert)
582+
typval2string(typval_T *tv, int join_list)
584583
{
585584
garray_T ga;
586585
char_u *retval;
587586

588-
if (convert && tv->v_type == VAR_LIST)
587+
if (join_list && tv->v_type == VAR_LIST)
589588
{
590589
ga_init2(&ga, sizeof(char), 80);
591590
if (tv->vval.v_list != NULL)
@@ -597,8 +596,16 @@ typval2string(typval_T *tv, int convert)
597596
ga_append(&ga, NUL);
598597
retval = (char_u *)ga.ga_data;
599598
}
600-
else if (convert && tv->v_type == VAR_DICT)
601-
retval = dict2string(tv, get_copyID(), FALSE);
599+
else if (tv->v_type == VAR_LIST || tv->v_type == VAR_DICT)
600+
{
601+
char_u *tofree;
602+
char_u numbuf[NUMBUFLEN];
603+
604+
retval = tv2string(tv, &tofree, numbuf, 0);
605+
// Make a copy if we have a value but it's not in allocated memory.
606+
if (retval != NULL && tofree == NULL)
607+
retval = vim_strsave(retval);
608+
}
602609
else
603610
retval = vim_strsave(tv_get_string(tv));
604611
return retval;
@@ -607,13 +614,13 @@ typval2string(typval_T *tv, int convert)
607614
/*
608615
* Top level evaluation function, returning a string. Does not handle line
609616
* breaks.
610-
* When "convert" is TRUE convert a List into a sequence of lines.
617+
* When "join_list" is TRUE convert a List into a sequence of lines.
611618
* Return pointer to allocated memory, or NULL for failure.
612619
*/
613620
char_u *
614621
eval_to_string_eap(
615622
char_u *arg,
616-
int convert,
623+
int join_list,
617624
exarg_T *eap,
618625
int use_simple_function)
619626
{
@@ -631,7 +638,7 @@ eval_to_string_eap(
631638
retval = NULL;
632639
else
633640
{
634-
retval = typval2string(&tv, convert);
641+
retval = typval2string(&tv, join_list);
635642
clear_tv(&tv);
636643
}
637644
clear_evalarg(&evalarg, NULL);
@@ -642,10 +649,10 @@ eval_to_string_eap(
642649
char_u *
643650
eval_to_string(
644651
char_u *arg,
645-
int convert,
652+
int join_list,
646653
int use_simple_function)
647654
{
648-
return eval_to_string_eap(arg, convert, NULL, use_simple_function);
655+
return eval_to_string_eap(arg, join_list, NULL, use_simple_function);
649656
}
650657

651658
/*

src/evalvars.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ eval_one_expr_in_str(char_u *p, garray_T *gap, int evaluate)
662662
if (evaluate)
663663
{
664664
*block_end = NUL;
665-
expr_val = eval_to_string(block_start, TRUE, FALSE);
665+
expr_val = eval_to_string(block_start, FALSE, FALSE);
666666
*block_end = '}';
667667
if (expr_val == NULL)
668668
return NULL;

src/proto/eval.pro

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ void init_evalarg(evalarg_T *evalarg);
1414
void clear_evalarg(evalarg_T *evalarg, exarg_T *eap);
1515
int skip_expr(char_u **pp, evalarg_T *evalarg);
1616
int skip_expr_concatenate(char_u **arg, char_u **start, char_u **end, evalarg_T *evalarg);
17-
char_u *typval2string(typval_T *tv, int convert);
18-
char_u *eval_to_string_eap(char_u *arg, int convert, exarg_T *eap, int use_simple_function);
19-
char_u *eval_to_string(char_u *arg, int convert, int use_simple_function);
17+
char_u *typval2string(typval_T *tv, int join_list);
18+
char_u *eval_to_string_eap(char_u *arg, int join_list, exarg_T *eap, int use_simple_function);
19+
char_u *eval_to_string(char_u *arg, int join_list, int use_simple_function);
2020
char_u *eval_to_string_safe(char_u *arg, int use_sandbox, int keep_script_version, int use_simple_function);
2121
varnumber_T eval_to_number(char_u *expr, int use_simple_function);
2222
typval_T *eval_expr(char_u *arg, exarg_T *eap);

src/proto/vim9instr.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ int generate_CONSTRUCT(cctx_T *cctx, class_T *cl);
77
int generate_GET_OBJ_MEMBER(cctx_T *cctx, int idx, type_T *type);
88
int generate_GET_ITF_MEMBER(cctx_T *cctx, class_T *itf, int idx, type_T *type);
99
int generate_STORE_THIS(cctx_T *cctx, int idx);
10-
int may_generate_2STRING(int offset, int tolerant, cctx_T *cctx);
10+
int may_generate_2STRING(int offset, int tostring_flags, cctx_T *cctx);
1111
int generate_add_instr(cctx_T *cctx, vartype_T vartype, type_T *type1, type_T *type2, exprtype_T expr_type);
1212
vartype_T operator_type(type_T *type1, type_T *type2);
1313
int generate_two_op(cctx_T *cctx, char_u *op);

src/testdir/test_expr.vim

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,18 @@ func Test_string_interp()
953953
#" Dict interpolation
954954
VAR d = {'a': 10, 'b': [1, 2]}
955955
call assert_equal("{'a': 10, 'b': [1, 2]}", $'{d}')
956+
VAR emptydict = {}
957+
call assert_equal("a{}b", $'a{emptydict}b')
958+
VAR nulldict = test_null_dict()
959+
call assert_equal("a{}b", $'a{nulldict}b')
960+
961+
#" List interpolation
962+
VAR l = ['a', 'b', 'c']
963+
call assert_equal("['a', 'b', 'c']", $'{l}')
964+
VAR emptylist = []
965+
call assert_equal("a[]b", $'a{emptylist}b')
966+
VAR nulllist = test_null_list()
967+
call assert_equal("a[]b", $'a{nulllist}b')
956968

957969
#" Stray closing brace.
958970
call assert_fails('echo $"moo}"', 'E1278:')

src/testdir/test_let.vim

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,41 @@ END
696696
END
697697
call assert_equal(["let d2 = {'a': 10, 'b': 'ss', 'c': {}}"], code)
698698

699+
" Empty dictionary
700+
let d1 = {}
701+
let code =<< eval trim END
702+
let d2 = {d1}
703+
END
704+
call assert_equal(["let d2 = {}"], code)
705+
706+
" null dictionary
707+
let d1 = test_null_dict()
708+
let code =<< eval trim END
709+
let d2 = {d1}
710+
END
711+
call assert_equal(["let d2 = {}"], code)
712+
713+
" Evaluate a List
714+
let l1 = ['a', 'b', 'c']
715+
let code =<< eval trim END
716+
let l2 = {l1}
717+
END
718+
call assert_equal(["let l2 = ['a', 'b', 'c']"], code)
719+
720+
" Empty List
721+
let l1 = []
722+
let code =<< eval trim END
723+
let l2 = {l1}
724+
END
725+
call assert_equal(["let l2 = []"], code)
726+
727+
" Null List
728+
let l1 = test_null_list()
729+
let code =<< eval trim END
730+
let l2 = {l1}
731+
END
732+
call assert_equal(["let l2 = []"], code)
733+
699734
let code = 'xxx'
700735
let code =<< eval trim END
701736
let n = {5 +

src/testdir/test_put.vim

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,4 +328,12 @@ func Test_put_dict()
328328
bw!
329329
endfunc
330330

331+
func Test_put_list()
332+
new
333+
let l = ['a', 'b', 'c']
334+
put! =l
335+
call assert_equal(['a', 'b', 'c', ''], getline(1, '$'))
336+
bw!
337+
endfunc
338+
331339
" vim: shiftwidth=2 sts=2 expandtab

src/testdir/test_vim9_assign.vim

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2994,6 +2994,56 @@ def Test_heredoc_expr()
29942994
CODE
29952995
v9.CheckDefAndScriptSuccess(lines)
29962996

2997+
# Evaluate an empty dictionary
2998+
lines =<< trim CODE
2999+
var d1 = {}
3000+
var code =<< trim eval END
3001+
var d2 = {d1}
3002+
END
3003+
assert_equal(["var d2 = {}"], code)
3004+
CODE
3005+
v9.CheckDefAndScriptSuccess(lines)
3006+
3007+
# Evaluate a null dictionary
3008+
lines =<< trim CODE
3009+
var d1 = test_null_dict()
3010+
var code =<< trim eval END
3011+
var d2 = {d1}
3012+
END
3013+
assert_equal(["var d2 = {}"], code)
3014+
CODE
3015+
v9.CheckDefAndScriptSuccess(lines)
3016+
3017+
# Evaluate a List
3018+
lines =<< trim CODE
3019+
var l1 = ['a', 'b', 'c']
3020+
var code =<< trim eval END
3021+
var l2 = {l1}
3022+
END
3023+
assert_equal(["var l2 = ['a', 'b', 'c']"], code)
3024+
CODE
3025+
v9.CheckDefAndScriptSuccess(lines)
3026+
3027+
# Evaluate an empty List
3028+
lines =<< trim CODE
3029+
var l1 = []
3030+
var code =<< trim eval END
3031+
var l2 = {l1}
3032+
END
3033+
assert_equal(["var l2 = []"], code)
3034+
CODE
3035+
v9.CheckDefAndScriptSuccess(lines)
3036+
3037+
# Evaluate a null List
3038+
lines =<< trim CODE
3039+
var l1 = test_null_list()
3040+
var code =<< trim eval END
3041+
var l2 = {l1}
3042+
END
3043+
assert_equal(["var l2 = []"], code)
3044+
CODE
3045+
v9.CheckDefAndScriptSuccess(lines)
3046+
29973047
lines =<< trim CODE
29983048
var code =<< eval trim END
29993049
var s = "{$SOME_ENV_VAR}"

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,8 @@ static char *(features[]) =
704704

705705
static int included_patches[] =
706706
{ /* Add new patch number below this line */
707+
/**/
708+
335,
707709
/**/
708710
334,
709711
/**/

src/vim9.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ typedef struct {
460460
// arguments to ISN_2STRING and ISN_2STRING_ANY
461461
typedef struct {
462462
int offset;
463-
int tolerant;
463+
int flags;
464464
} tostring_T;
465465

466466
// arguments to ISN_2BOOL
@@ -880,3 +880,10 @@ typedef enum {
880880

881881
// flags for call_def_function()
882882
#define DEF_USE_PT_ARGV 1 // use the partial arguments
883+
884+
// Flag used for conversion to string by may_generate_2STRING()
885+
#define TOSTRING_NONE 0x0
886+
// Convert a List to series of values separated by newline
887+
#define TOSTRING_INTERPOLATE 0x1
888+
// Convert a List to a textual representation of the list "[...]"
889+
#define TOSTRING_TOLERANT 0x2

0 commit comments

Comments
 (0)