mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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:
commit
8ba5f4d19c
@ -38,7 +38,9 @@ List An ordered sequence of items |List|.
|
|||||||
|
|
||||||
Dictionary An associative, unordered array: Each entry has a key and a
|
Dictionary An associative, unordered array: Each entry has a key and a
|
||||||
value. |Dictionary|
|
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
|
The Number and String types are converted automatically, depending on how they
|
||||||
are used.
|
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
|
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
|
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
|
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
|
Number will be converted to the String '4'. The empty string can also be used
|
||||||
key.
|
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
|
A value can be any expression. Using a Dictionary for a value creates a
|
||||||
nested Dictionary: >
|
nested Dictionary: >
|
||||||
|
@ -3802,8 +3802,9 @@ static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string)
|
|||||||
*/
|
*/
|
||||||
for (;; ) {
|
for (;; ) {
|
||||||
op = **arg;
|
op = **arg;
|
||||||
if (op != '*' && op != '/' && op != '%')
|
if (op != '*' && op != '/' && op != '%') {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (evaluate) {
|
if (evaluate) {
|
||||||
if (rettv->v_type == VAR_FLOAT) {
|
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
|
// (expression) nested expression
|
||||||
// [expr, expr] List
|
// [expr, expr] List
|
||||||
// {key: val, key: val} Dictionary
|
// {key: val, key: val} Dictionary
|
||||||
|
// #{key: val, key: val} Dictionary with literal keys
|
||||||
//
|
//
|
||||||
// Also handle:
|
// Also handle:
|
||||||
// ! in front logical NOT
|
// ! in front logical NOT
|
||||||
@ -4012,11 +4014,21 @@ static int eval7(
|
|||||||
case '[': ret = get_list_tv(arg, rettv, evaluate);
|
case '[': ret = get_list_tv(arg, rettv, evaluate);
|
||||||
break;
|
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}
|
// Lambda: {arg, arg -> expr}
|
||||||
// Dictionary: {key: val, key: val}
|
// Dictionary: {'key': val, 'key': val}
|
||||||
case '{': ret = get_lambda_tv(arg, rettv, evaluate);
|
case '{': ret = get_lambda_tv(arg, rettv, evaluate);
|
||||||
if (ret == NOTDONE) {
|
if (ret == NOTDONE) {
|
||||||
ret = dict_get_tv(arg, rettv, evaluate);
|
ret = dict_get_tv(arg, rettv, evaluate, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -5347,11 +5359,31 @@ static inline bool set_ref_dict(dict_T *dict, int copyID)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate a variable for a Dictionary and fill it from "*arg".
|
// Get the key for *{key: val} into "tv" and advance "arg".
|
||||||
* Return OK or FAIL. Returns NOTDONE for {expr}.
|
// Return FAIL when there is no valid key.
|
||||||
*/
|
static int get_literal_key(char_u **arg, typval_T *tv)
|
||||||
static int dict_get_tv(char_u **arg, typval_T *rettv, int evaluate)
|
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;
|
dict_T *d = NULL;
|
||||||
typval_T tvkey;
|
typval_T tvkey;
|
||||||
@ -5385,7 +5417,9 @@ static int dict_get_tv(char_u **arg, typval_T *rettv, int evaluate)
|
|||||||
|
|
||||||
*arg = skipwhite(*arg + 1);
|
*arg = skipwhite(*arg + 1);
|
||||||
while (**arg != '}' && **arg != NUL) {
|
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;
|
goto failret;
|
||||||
}
|
}
|
||||||
if (**arg != ':') {
|
if (**arg != ':') {
|
||||||
|
@ -808,7 +808,7 @@ retry:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (STRLEN(IObuff) < IOSIZE - 1 || IObuff[IOSIZE - 1] == '\n') {
|
if (STRLEN(IObuff) < IOSIZE - 1 || IObuff[IOSIZE - 2] == '\n') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,6 +280,14 @@ func Test_dict_func_remove_in_use()
|
|||||||
call assert_equal(expected, d.func(string(remove(d, 'func'))))
|
call assert_equal(expected, d.func(string(remove(d, 'func'))))
|
||||||
endfunc
|
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)
|
" Nasty: deepcopy() dict that refers to itself (fails when noref used)
|
||||||
func Test_dict_deepcopy()
|
func Test_dict_deepcopy()
|
||||||
let d = {1:1, 2:2}
|
let d = {1:1, 2:2}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
source shared.vim
|
source shared.vim
|
||||||
source screendump.vim
|
source screendump.vim
|
||||||
|
source check.vim
|
||||||
|
|
||||||
let g:months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
|
let g:months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
|
||||||
let g:setting = ''
|
let g:setting = ''
|
||||||
@ -755,6 +756,52 @@ func Test_popup_and_previewwindow_dump()
|
|||||||
call delete('Xscript')
|
call delete('Xscript')
|
||||||
endfunc
|
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()
|
func Test_popup_position()
|
||||||
if !CanRunVimInTerminal()
|
if !CanRunVimInTerminal()
|
||||||
return
|
return
|
||||||
|
@ -1597,6 +1597,24 @@ func Test_long_lines()
|
|||||||
call s:long_lines_tests('l')
|
call s:long_lines_tests('l')
|
||||||
endfunc
|
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)
|
func s:create_test_file(filename)
|
||||||
let l = []
|
let l = []
|
||||||
for i in range(1, 20)
|
for i in range(1, 20)
|
||||||
|
Loading…
Reference in New Issue
Block a user