Merge pull request #13064 from janlazo/vim-8.1.2325

vim-patch:8.1.{1683,1686,1692,1705,2325},8.2.1599
This commit is contained in:
Jan Edmund Lazo 2020-10-07 17:58:38 -04:00 committed by GitHub
commit 8ba5f4d19c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 128 additions and 13 deletions

View File

@ -38,7 +38,9 @@ List An ordered sequence of items |List|.
Dictionary An associative, unordered array: Each entry has a key and a
value. |Dictionary|
Example: {'blue': "#0000ff", 'red': "#ff0000"}
Examples:
{'blue': "#0000ff", 'red': "#ff0000"}
#{blue: "#0000ff", red: "#ff0000"}
The Number and String types are converted automatically, depending on how they
are used.
@ -436,8 +438,14 @@ only appear once. Examples: >
A key is always a String. You can use a Number, it will be converted to a
String automatically. Thus the String '4' and the number 4 will find the same
entry. Note that the String '04' and the Number 04 are different, since the
Number will be converted to the String '4'. The empty string can be used as a
key.
Number will be converted to the String '4'. The empty string can also be used
as a key.
*literal-Dict*
To avoid having to put quotes around every key the #{} form can be used. This
does require the key to consist only of ASCII letters, digits, '-' and '_'.
Example: >
let mydict = #{zero: 0, one_key: 1, two-key: 2, 333: 3}
Note that 333 here is the string "333". Empty keys are not possible with #{}.
A value can be any expression. Using a Dictionary for a value creates a
nested Dictionary: >

View File

@ -3802,8 +3802,9 @@ static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string)
*/
for (;; ) {
op = **arg;
if (op != '*' && op != '/' && op != '%')
if (op != '*' && op != '/' && op != '%') {
break;
}
if (evaluate) {
if (rettv->v_type == VAR_FLOAT) {
@ -3905,6 +3906,7 @@ static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string)
// (expression) nested expression
// [expr, expr] List
// {key: val, key: val} Dictionary
// #{key: val, key: val} Dictionary with literal keys
//
// Also handle:
// ! in front logical NOT
@ -4012,11 +4014,21 @@ static int eval7(
case '[': ret = get_list_tv(arg, rettv, evaluate);
break;
// Dictionary: #{key: val, key: val}
case '#':
if ((*arg)[1] == '{') {
(*arg)++;
ret = dict_get_tv(arg, rettv, evaluate, true);
} else {
ret = NOTDONE;
}
break;
// Lambda: {arg, arg -> expr}
// Dictionary: {key: val, key: val}
// Dictionary: {'key': val, 'key': val}
case '{': ret = get_lambda_tv(arg, rettv, evaluate);
if (ret == NOTDONE) {
ret = dict_get_tv(arg, rettv, evaluate);
ret = dict_get_tv(arg, rettv, evaluate, false);
}
break;
@ -5347,11 +5359,31 @@ static inline bool set_ref_dict(dict_T *dict, int copyID)
return false;
}
/*
* Allocate a variable for a Dictionary and fill it from "*arg".
* Return OK or FAIL. Returns NOTDONE for {expr}.
*/
static int dict_get_tv(char_u **arg, typval_T *rettv, int evaluate)
// Get the key for *{key: val} into "tv" and advance "arg".
// Return FAIL when there is no valid key.
static int get_literal_key(char_u **arg, typval_T *tv)
FUNC_ATTR_NONNULL_ALL
{
char_u *p;
if (!ASCII_ISALNUM(**arg) && **arg != '_' && **arg != '-') {
return FAIL;
}
for (p = *arg; ASCII_ISALNUM(*p) || *p == '_' || *p == '-'; p++) {
}
tv->v_type = VAR_STRING;
tv->vval.v_string = vim_strnsave(*arg, (int)(p - *arg));
*arg = skipwhite(p);
return OK;
}
// Allocate a variable for a Dictionary and fill it from "*arg".
// "literal" is true for *{key: val}
// Return OK or FAIL. Returns NOTDONE for {expr}.
static int dict_get_tv(char_u **arg, typval_T *rettv, int evaluate,
bool literal)
{
dict_T *d = NULL;
typval_T tvkey;
@ -5385,7 +5417,9 @@ static int dict_get_tv(char_u **arg, typval_T *rettv, int evaluate)
*arg = skipwhite(*arg + 1);
while (**arg != '}' && **arg != NUL) {
if (eval1(arg, &tvkey, evaluate) == FAIL) { // recursive!
if ((literal
? get_literal_key(arg, &tvkey)
: eval1(arg, &tvkey, evaluate)) == FAIL) { // recursive!
goto failret;
}
if (**arg != ':') {

View File

@ -808,7 +808,7 @@ retry:
}
break;
}
if (STRLEN(IObuff) < IOSIZE - 1 || IObuff[IOSIZE - 1] == '\n') {
if (STRLEN(IObuff) < IOSIZE - 1 || IObuff[IOSIZE - 2] == '\n') {
break;
}
}

View File

@ -280,6 +280,14 @@ func Test_dict_func_remove_in_use()
call assert_equal(expected, d.func(string(remove(d, 'func'))))
endfunc
func Test_dict_literal_keys()
call assert_equal({'one': 1, 'two2': 2, '3three': 3, '44': 4}, #{one: 1, two2: 2, 3three: 3, 44: 4},)
" why *{} cannot be used
let blue = 'blue'
call assert_equal('6', trim(execute('echo 2 *{blue: 3}.blue')))
endfunc
" Nasty: deepcopy() dict that refers to itself (fails when noref used)
func Test_dict_deepcopy()
let d = {1:1, 2:2}

View File

@ -2,6 +2,7 @@
source shared.vim
source screendump.vim
source check.vim
let g:months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
let g:setting = ''
@ -755,6 +756,52 @@ func Test_popup_and_previewwindow_dump()
call delete('Xscript')
endfunc
func Test_balloon_split()
CheckFunction balloon_split
call assert_equal([
\ 'tempname: 0x555555e380a0 "/home/mool/.viminfz.tmp"',
\ ], balloon_split(
\ 'tempname: 0x555555e380a0 "/home/mool/.viminfz.tmp"'))
call assert_equal([
\ 'one two three four one two three four one two thre',
\ 'e four',
\ ], balloon_split(
\ 'one two three four one two three four one two three four'))
eval 'struct = {one = 1, two = 2, three = 3}'
\ ->balloon_split()
\ ->assert_equal([
\ 'struct = {',
\ ' one = 1,',
\ ' two = 2,',
\ ' three = 3}',
\ ])
call assert_equal([
\ 'struct = {',
\ ' one = 1,',
\ ' nested = {',
\ ' n1 = "yes",',
\ ' n2 = "no"}',
\ ' two = 2}',
\ ], balloon_split(
\ 'struct = {one = 1, nested = {n1 = "yes", n2 = "no"} two = 2}'))
call assert_equal([
\ 'struct = 0x234 {',
\ ' long = 2343 "\\"some long string that will be wr',
\ 'apped in two\\"",',
\ ' next = 123}',
\ ], balloon_split(
\ 'struct = 0x234 {long = 2343 "\\"some long string that will be wrapped in two\\"", next = 123}'))
call assert_equal([
\ 'Some comment',
\ '',
\ 'typedef this that;',
\ ], balloon_split(
\ "Some comment\n\ntypedef this that;"))
endfunc
func Test_popup_position()
if !CanRunVimInTerminal()
return

View File

@ -1597,6 +1597,24 @@ func Test_long_lines()
call s:long_lines_tests('l')
endfunc
func Test_cgetfile_on_long_lines()
" Problematic values if the line is longer than 4096 bytes. Then 1024 bytes
" are read at a time.
for len in [4078, 4079, 4080, 5102, 5103, 5104, 6126, 6127, 6128, 7150, 7151, 7152]
let lines = [
\ '/tmp/file1:1:1:aaa',
\ '/tmp/file2:1:1:%s',
\ '/tmp/file3:1:1:bbb',
\ '/tmp/file4:1:1:ccc',
\ ]
let lines[1] = substitute(lines[1], '%s', repeat('x', len), '')
call writefile(lines, 'Xcqetfile.txt')
cgetfile Xcqetfile.txt
call assert_equal(4, getqflist(#{size: v:true}).size, 'with length ' .. len)
endfor
call delete('Xcqetfile.txt')
endfunc
func s:create_test_file(filename)
let l = []
for i in range(1, 20)