mirror of
https://github.com/neovim/neovim.git
synced 2025-09-29 06:28:35 +00:00
vim-patch:9.1.0335: String interpolation fails for List type (#28364)
Problem: String interpolation fails for List type
Solution: use implicit string(list) for string interpolation and :put =
(Yegappan Lakshmanan)
related: vim/vim#14529
closes: vim/vim#14556
bce51d9005
Cherry-pick eval_to_string_eap() from patch 8.2.1914.
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
This commit is contained in:
@@ -969,13 +969,12 @@ int skip_expr(char **pp, evalarg_T *const evalarg)
|
|||||||
|
|
||||||
/// Convert "tv" to a string.
|
/// Convert "tv" to a string.
|
||||||
///
|
///
|
||||||
/// @param convert when true convert a List into a sequence of lines
|
/// @param join_list when true convert a List into a sequence of lines.
|
||||||
/// and a Dict into a textual representation of the Dict.
|
|
||||||
///
|
///
|
||||||
/// @return an allocated string.
|
/// @return an allocated string.
|
||||||
static char *typval2string(typval_T *tv, bool convert)
|
static char *typval2string(typval_T *tv, bool join_list)
|
||||||
{
|
{
|
||||||
if (convert && tv->v_type == VAR_LIST) {
|
if (join_list && tv->v_type == VAR_LIST) {
|
||||||
garray_T ga;
|
garray_T ga;
|
||||||
ga_init(&ga, (int)sizeof(char), 80);
|
ga_init(&ga, (int)sizeof(char), 80);
|
||||||
if (tv->vval.v_list != NULL) {
|
if (tv->vval.v_list != NULL) {
|
||||||
@@ -986,7 +985,7 @@ static char *typval2string(typval_T *tv, bool convert)
|
|||||||
}
|
}
|
||||||
ga_append(&ga, NUL);
|
ga_append(&ga, NUL);
|
||||||
return (char *)ga.ga_data;
|
return (char *)ga.ga_data;
|
||||||
} else if (convert && tv->v_type == VAR_DICT) {
|
} else if (tv->v_type == VAR_LIST || tv->v_type == VAR_DICT) {
|
||||||
return encode_tv2string(tv, NULL);
|
return encode_tv2string(tv, NULL);
|
||||||
}
|
}
|
||||||
return xstrdup(tv_get_string(tv));
|
return xstrdup(tv_get_string(tv));
|
||||||
@@ -994,18 +993,20 @@ static char *typval2string(typval_T *tv, bool convert)
|
|||||||
|
|
||||||
/// Top level evaluation function, returning a string.
|
/// Top level evaluation function, returning a string.
|
||||||
///
|
///
|
||||||
/// @param convert when true convert a List into a sequence of lines.
|
/// @param join_list when true convert a List into a sequence of lines.
|
||||||
///
|
///
|
||||||
/// @return pointer to allocated memory, or NULL for failure.
|
/// @return pointer to allocated memory, or NULL for failure.
|
||||||
char *eval_to_string(char *arg, bool convert)
|
char *eval_to_string_eap(char *arg, bool join_list, exarg_T *eap)
|
||||||
{
|
{
|
||||||
typval_T tv;
|
typval_T tv;
|
||||||
char *retval;
|
char *retval;
|
||||||
|
|
||||||
if (eval0(arg, &tv, NULL, &EVALARG_EVALUATE) == FAIL) {
|
evalarg_T evalarg;
|
||||||
|
fill_evalarg_from_eap(&evalarg, eap, eap != NULL && eap->skip);
|
||||||
|
if (eval0(arg, &tv, NULL, &evalarg) == FAIL) {
|
||||||
retval = NULL;
|
retval = NULL;
|
||||||
} else {
|
} else {
|
||||||
retval = typval2string(&tv, convert);
|
retval = typval2string(&tv, join_list);
|
||||||
tv_clear(&tv);
|
tv_clear(&tv);
|
||||||
}
|
}
|
||||||
clear_evalarg(&EVALARG_EVALUATE, NULL);
|
clear_evalarg(&EVALARG_EVALUATE, NULL);
|
||||||
@@ -1013,6 +1014,11 @@ char *eval_to_string(char *arg, bool convert)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *eval_to_string(char *arg, bool join_list)
|
||||||
|
{
|
||||||
|
return eval_to_string_eap(arg, join_list, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/// Call eval_to_string() without using current local variables and using
|
/// Call eval_to_string() without using current local variables and using
|
||||||
/// textlock.
|
/// textlock.
|
||||||
///
|
///
|
||||||
|
@@ -88,7 +88,7 @@ char *eval_one_expr_in_str(char *p, garray_T *gap, bool evaluate)
|
|||||||
}
|
}
|
||||||
if (evaluate) {
|
if (evaluate) {
|
||||||
*block_end = NUL;
|
*block_end = NUL;
|
||||||
char *expr_val = eval_to_string(block_start, true);
|
char *expr_val = eval_to_string(block_start, false);
|
||||||
*block_end = '}';
|
*block_end = '}';
|
||||||
if (expr_val == NULL) {
|
if (expr_val == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@@ -907,6 +907,18 @@ func Test_string_interp()
|
|||||||
#" Dict interpolation
|
#" Dict interpolation
|
||||||
VAR d = {'a': 10, 'b': [1, 2]}
|
VAR d = {'a': 10, 'b': [1, 2]}
|
||||||
call assert_equal("{'a': 10, 'b': [1, 2]}", $'{d}')
|
call assert_equal("{'a': 10, 'b': [1, 2]}", $'{d}')
|
||||||
|
VAR emptydict = {}
|
||||||
|
call assert_equal("a{}b", $'a{emptydict}b')
|
||||||
|
VAR nulldict = v:_null_dict
|
||||||
|
call assert_equal("a{}b", $'a{nulldict}b')
|
||||||
|
|
||||||
|
#" List interpolation
|
||||||
|
VAR l = ['a', 'b', 'c']
|
||||||
|
call assert_equal("['a', 'b', 'c']", $'{l}')
|
||||||
|
VAR emptylist = []
|
||||||
|
call assert_equal("a[]b", $'a{emptylist}b')
|
||||||
|
VAR nulllist = v:_null_list
|
||||||
|
call assert_equal("a[]b", $'a{nulllist}b')
|
||||||
|
|
||||||
#" Stray closing brace.
|
#" Stray closing brace.
|
||||||
call assert_fails('echo $"moo}"', 'E1278:')
|
call assert_fails('echo $"moo}"', 'E1278:')
|
||||||
|
@@ -694,6 +694,41 @@ END
|
|||||||
END
|
END
|
||||||
call assert_equal(["let d2 = {'a': 10, 'b': 'ss', 'c': {}}"], code)
|
call assert_equal(["let d2 = {'a': 10, 'b': 'ss', 'c': {}}"], code)
|
||||||
|
|
||||||
|
" Empty dictionary
|
||||||
|
let d1 = {}
|
||||||
|
let code =<< eval trim END
|
||||||
|
let d2 = {d1}
|
||||||
|
END
|
||||||
|
call assert_equal(["let d2 = {}"], code)
|
||||||
|
|
||||||
|
" null dictionary
|
||||||
|
let d1 = v:_null_dict
|
||||||
|
let code =<< eval trim END
|
||||||
|
let d2 = {d1}
|
||||||
|
END
|
||||||
|
call assert_equal(["let d2 = {}"], code)
|
||||||
|
|
||||||
|
" Evaluate a List
|
||||||
|
let l1 = ['a', 'b', 'c']
|
||||||
|
let code =<< eval trim END
|
||||||
|
let l2 = {l1}
|
||||||
|
END
|
||||||
|
call assert_equal(["let l2 = ['a', 'b', 'c']"], code)
|
||||||
|
|
||||||
|
" Empty List
|
||||||
|
let l1 = []
|
||||||
|
let code =<< eval trim END
|
||||||
|
let l2 = {l1}
|
||||||
|
END
|
||||||
|
call assert_equal(["let l2 = []"], code)
|
||||||
|
|
||||||
|
" Null List
|
||||||
|
let l1 = v:_null_list
|
||||||
|
let code =<< eval trim END
|
||||||
|
let l2 = {l1}
|
||||||
|
END
|
||||||
|
call assert_equal(["let l2 = []"], code)
|
||||||
|
|
||||||
let code = 'xxx'
|
let code = 'xxx'
|
||||||
let code =<< eval trim END
|
let code =<< eval trim END
|
||||||
let n = {5 +
|
let n = {5 +
|
||||||
|
@@ -332,4 +332,12 @@ func Test_put_dict()
|
|||||||
call assert_equal(["{'a': {'b': 'abc'}, 'c': [1, 2], 'd': 0z10}", ''],
|
call assert_equal(["{'a': {'b': 'abc'}, 'c': [1, 2], 'd': 0z10}", ''],
|
||||||
\ getline(1, '$'))
|
\ getline(1, '$'))
|
||||||
bw!
|
bw!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_put_list()
|
||||||
|
new
|
||||||
|
let l = ['a', 'b', 'c']
|
||||||
|
put! =l
|
||||||
|
call assert_equal(['a', 'b', 'c', ''], getline(1, '$'))
|
||||||
|
bw!
|
||||||
endfunc
|
endfunc
|
||||||
|
Reference in New Issue
Block a user