From b1ada8ec2159fbc69b58cc40eb62a4e76edd8d45 Mon Sep 17 00:00:00 2001 From: Jurica Bradaric Date: Sun, 22 Sep 2019 21:47:24 +0200 Subject: [PATCH 1/4] vim-patch:8.1.1354: getting a list of text lines is clumsy Problem: Getting a list of text lines is clumsy. Solution: Add the =<< assignment. (Yegappan Lakshmanan, closes vim/vim#4386) https://github.com/vim/vim/commit/f5842c5a533346c4ff41ff666e465c85f1de35d5 --- runtime/doc/eval.txt | 38 +++++++++++++++ src/nvim/eval.c | 92 +++++++++++++++++++++++++++++++++++ src/nvim/testdir/test_let.vim | 55 +++++++++++++++++++++ 3 files changed, 185 insertions(+) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 5e6bfd0dbc..607e88b7c8 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -9779,6 +9779,44 @@ This does NOT work: > Like above, but append/add/subtract the value for each |List| item. + *:let=<<* *:let-heredoc* *E990* *E991* +:let {var-name} =<< [trim] {marker} +text... +text... +{marker} + Set internal variable {var-name} to a List containing + the lines of text bounded by the string {marker}. + {marker} must not contain white space. + The last line should end only with the {marker} string + without any other character. Watch out for white + space after {marker}! + If {marker} is not supplied, then "." is used as the + default marker. + + Any white space characters in the lines of text are + preserved. If "trim" is specified before {marker}, + then all the leading indentation exactly matching the + leading indentation before `let` is stripped from the + input lines and the line containing {marker}. Note + that the difference between space and tab matters + here. + + If {var-name} didn't exist yet, it is created. + Cannot be followed by another command, but can be + followed by a comment. + + Examples: > + let var1 =<< END + Sample text 1 + Sample text 2 + Sample text 3 + END + + let data =<< trim DATA + 1 2 3 4 + 5 6 7 8 + DATA +< *E121* :let {var-name} .. List the value of variable {var-name}. Multiple variable names may be given. Special names recognized diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 925b64d42c..9b12ca1e12 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1504,6 +1504,87 @@ void ex_const(exarg_T *eap) ex_let_const(eap, true); } +// Get a list of lines from a HERE document. The here document is a list of +// lines surrounded by a marker. +// cmd << {marker} +// {line1} +// {line2} +// .... +// {marker} +// +// The {marker} is a string. If the optional 'trim' word is supplied before the +// marker, then the leading indentation before the lines (matching the +// indentation in the 'cmd' line) is stripped. +// Returns a List with {lines} or NULL. +static list_T * +heredoc_get(exarg_T *eap, char_u *cmd) +{ + char_u *marker; + char_u *p; + int indent_len = 0; + + if (eap->getline == NULL) { + EMSG(_("E991: cannot use =<< here")); + return NULL; + } + + // Check for the optional 'trim' word before the marker + cmd = skipwhite(cmd); + if (STRNCMP(cmd, "trim", 4) == 0 + && (cmd[4] == NUL || ascii_iswhite(cmd[4]))) { + cmd = skipwhite(cmd + 4); + + // Trim the indentation from all the lines in the here document + // The amount of indentation trimmed is the same as the indentation of + // the :let command line. + p = *eap->cmdlinep; + while (ascii_iswhite(*p)) { + p++; + indent_len++; + } + } + + // The marker is the next word. Default marker is "." + if (*cmd != NUL && *cmd != '"') { + marker = skipwhite(cmd); + p = skiptowhite(marker); + if (*skipwhite(p) != NUL && *skipwhite(p) != '"') { + EMSG(_(e_trailing)); + return NULL; + } + *p = NUL; + } else { + marker = (char_u *)"."; + } + + list_T *l = tv_list_alloc(0); + for (;;) { + int i = 0; + + char_u *theline = eap->getline(NUL, eap->cookie, 0); + if (theline != NULL && indent_len > 0) { + // trim the indent matching the first line + if (STRNCMP(theline, *eap->cmdlinep, indent_len) == 0) { + i = indent_len; + } + } + + if (theline == NULL) { + EMSG2(_("E990: Missing end marker '%s'"), marker); + break; + } + if (STRCMP(marker, theline + i) == 0) { + xfree(theline); + break; + } + + tv_list_append_string(l, (char *)(theline + i), -1); + xfree(theline); + } + + return l; +} + // ":let" list all variable values // ":let var1 var2" list variable values // ":let var = expr" assignment command. @@ -1560,6 +1641,17 @@ static void ex_let_const(exarg_T *eap, const bool is_const) list_vim_vars(&first); } eap->nextcmd = check_nextcmd(arg); + } else if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<') { + // HERE document + list_T *l = heredoc_get(eap, expr + 3); + if (l != NULL) { + tv_list_set_ret(&rettv, l); + op[0] = '='; + op[1] = NUL; + (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, + is_const, op); + tv_clear(&rettv); + } } else { op[0] = '='; op[1] = NUL; diff --git a/src/nvim/testdir/test_let.vim b/src/nvim/testdir/test_let.vim index 8a6f1bc320..9887fb531e 100644 --- a/src/nvim/testdir/test_let.vim +++ b/src/nvim/testdir/test_let.vim @@ -140,3 +140,58 @@ func Test_let_varg_fail() call assert_fails('call s:set_varg7(1)', 'E742:') call s:set_varg8([0]) endfunction + + +" Test for the setting a variable using the heredoc syntax +func Test_let_heredoc() + let var1 =<< END +Some sample text + Text with indent + !@#$%^&*()-+_={}|[]\~`:";'<>?,./ +END + + call assert_equal(["Some sample text", "\tText with indent", " !@#$%^&*()-+_={}|[]\\~`:\";'<>?,./"], var1) + + let var2 =<< +Editor +. + call assert_equal(['Editor'], var2) + + let var3 =< Date: Mon, 23 Sep 2019 19:46:45 +0200 Subject: [PATCH 2/4] vim-patch:8.1.1356: some text in heredoc assignment ends the text Problem: Some text in heredoc assignment ends the text. (Ozaki Kiichi) Solution: Recognize "let v =<<" and skip until the end. https://github.com/vim/vim/commit/8471e57026714c5a0faf89288ceef5231fb88d4f --- src/nvim/eval.c | 34 +++++++++++++-- src/nvim/testdir/test_let.vim | 79 ++++++++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 18 deletions(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 9b12ca1e12..6d706939a1 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -21269,6 +21269,7 @@ void ex_function(exarg_T *eap) int indent; int nesting; char_u *skip_until = NULL; + char_u *trimmed = NULL; dictitem_T *v; funcdict_T fudi; static int func_nr = 0; /* number for nameless function */ @@ -21572,10 +21573,14 @@ void ex_function(exarg_T *eap) sourcing_lnum_off = 0; if (skip_until != NULL) { - /* between ":append" and "." and between ":python < Date: Mon, 23 Sep 2019 22:12:02 +0200 Subject: [PATCH 3/4] vim-patch:8.1.1362: code and data in tests can be hard to read Problem: Code and data in tests can be hard to read. Solution: Use the new heredoc style. (Yegappan Lakshmanan, closes vim/vim#4400) https://github.com/vim/vim/commit/c79745a82faeb5a6058e915ca49a4c69fa60ea01 --- src/nvim/testdir/test_autocmd.vim | 102 +++--- src/nvim/testdir/test_cindent.vim | 60 ++-- src/nvim/testdir/test_exit.vim | 66 ++-- src/nvim/testdir/test_fold.vim | 23 +- src/nvim/testdir/test_goto.vim | 406 ++++++++++++----------- src/nvim/testdir/test_mksession_utf8.vim | 57 ++-- src/nvim/testdir/test_normal.vim | 181 +++++++--- src/nvim/testdir/test_profile.vim | 266 +++++++-------- src/nvim/testdir/test_quickfix.vim | 252 +++++++------- src/nvim/testdir/test_startup.vim | 150 +++++---- 10 files changed, 859 insertions(+), 704 deletions(-) diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index 4dd48beef4..275b053bc9 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -425,18 +425,20 @@ func Test_autocmd_bufwipe_in_SessLoadPost() set noswapfile mksession! - let content = ['set nocp noswapfile', - \ 'let v:swapchoice="e"', - \ 'augroup test_autocmd_sessionload', - \ 'autocmd!', - \ 'autocmd SessionLoadPost * exe bufnr("Xsomething") . "bw!"', - \ 'augroup END', - \ '', - \ 'func WriteErrors()', - \ ' call writefile([execute("messages")], "Xerrors")', - \ 'endfunc', - \ 'au VimLeave * call WriteErrors()', - \ ] + let content =<< trim [CODE] + set nocp noswapfile + let v:swapchoice="e" + augroup test_autocmd_sessionload + autocmd! + autocmd SessionLoadPost * exe bufnr("Xsomething") . "bw!" + augroup END + + func WriteErrors() + call writefile([execute("messages")], "Xerrors") + endfunc + au VimLeave * call WriteErrors() + [CODE] + call writefile(content, 'Xvimrc') call system(v:progpath. ' --headless -i NONE -u Xvimrc --noplugins -S Session.vim -c cq') let errors = join(readfile('Xerrors')) @@ -454,27 +456,29 @@ func Test_autocmd_bufwipe_in_SessLoadPost2() set noswapfile mksession! - let content = ['set nocp noswapfile', - \ 'function! DeleteInactiveBufs()', - \ ' tabfirst', - \ ' let tabblist = []', - \ ' for i in range(1, tabpagenr(''$''))', - \ ' call extend(tabblist, tabpagebuflist(i))', - \ ' endfor', - \ ' for b in range(1, bufnr(''$''))', - \ ' if bufexists(b) && buflisted(b) && (index(tabblist, b) == -1 || bufname(b) =~# ''^$'')', - \ ' exec ''bwipeout '' . b', - \ ' endif', - \ ' endfor', - \ ' echomsg "SessionLoadPost DONE"', - \ 'endfunction', - \ 'au SessionLoadPost * call DeleteInactiveBufs()', - \ '', - \ 'func WriteErrors()', - \ ' call writefile([execute("messages")], "Xerrors")', - \ 'endfunc', - \ 'au VimLeave * call WriteErrors()', - \ ] + let content =<< trim [CODE] + set nocp noswapfile + function! DeleteInactiveBufs() + tabfirst + let tabblist = [] + for i in range(1, tabpagenr(''$'')) + call extend(tabblist, tabpagebuflist(i)) + endfor + for b in range(1, bufnr(''$'')) + if bufexists(b) && buflisted(b) && (index(tabblist, b) == -1 || bufname(b) =~# ''^$'') + exec ''bwipeout '' . b + endif + endfor + echomsg "SessionLoadPost DONE" + endfunction + au SessionLoadPost * call DeleteInactiveBufs() + + func WriteErrors() + call writefile([execute("messages")], "Xerrors") + endfunc + au VimLeave * call WriteErrors() + [CODE] + call writefile(content, 'Xvimrc') call system(v:progpath. ' --headless -i NONE -u Xvimrc --noplugins -S Session.vim -c cq') let errors = join(readfile('Xerrors')) @@ -936,21 +940,23 @@ func Test_bufunload_all() call writefile(['Test file Xxx1'], 'Xxx1')" call writefile(['Test file Xxx2'], 'Xxx2')" - let content = [ - \ "func UnloadAllBufs()", - \ " let i = 1", - \ " while i <= bufnr('$')", - \ " if i != bufnr('%') && bufloaded(i)", - \ " exe i . 'bunload'", - \ " endif", - \ " let i += 1", - \ " endwhile", - \ "endfunc", - \ "au BufUnload * call UnloadAllBufs()", - \ "au VimLeave * call writefile(['Test Finished'], 'Xout')", - \ "edit Xxx1", - \ "split Xxx2", - \ "q"] + let content =<< trim [CODE] + func UnloadAllBufs() + let i = 1 + while i <= bufnr('$') + if i != bufnr('%') && bufloaded(i) + exe i . 'bunload' + endif + let i += 1 + endwhile + endfunc + au BufUnload * call UnloadAllBufs() + au VimLeave * call writefile(['Test Finished'], 'Xout') + edit Xxx1 + split Xxx2 + q + [CODE] + call writefile(content, 'Xtest') call delete('Xout') diff --git a/src/nvim/testdir/test_cindent.vim b/src/nvim/testdir/test_cindent.vim index 7c2c5e341c..f979e354ba 100644 --- a/src/nvim/testdir/test_cindent.vim +++ b/src/nvim/testdir/test_cindent.vim @@ -18,25 +18,25 @@ endfunc func Test_cino_extern_c() " Test for cino-E - let without_ind = [ - \ '#ifdef __cplusplus', - \ 'extern "C" {', - \ '#endif', - \ 'int func_a(void);', - \ '#ifdef __cplusplus', - \ '}', - \ '#endif' - \ ] + let without_ind =<< trim [CODE] + #ifdef __cplusplus + extern "C" { + #endif + int func_a(void); + #ifdef __cplusplus + } + #endif + [CODE] - let with_ind = [ - \ '#ifdef __cplusplus', - \ 'extern "C" {', - \ '#endif', - \ "\tint func_a(void);", - \ '#ifdef __cplusplus', - \ '}', - \ '#endif' - \ ] + let with_ind =<< trim [CODE] + #ifdef __cplusplus + extern "C" { + #endif + int func_a(void); + #ifdef __cplusplus + } + #endif + [CODE] new setlocal cindent cinoptions=E0 call setline(1, without_ind) @@ -89,16 +89,32 @@ func Test_cindent_expr() return v:lnum == 1 ? shiftwidth() : 0 endfunc setl expandtab sw=8 indentkeys+=; indentexpr=MyIndentFunction() - call setline(1, ['var_a = something()', 'b = something()']) + let testinput =<< trim [CODE] + var_a = something() + b = something() + [CODE] + call setline(1, testinput) call cursor(1, 1) call feedkeys("^\j$A;\", 'tnix') - call assert_equal([' var_a = something();', 'b = something();'], getline(1, '$')) + let expected =<< trim [CODE] + var_a = something(); + b = something(); + [CODE] + call assert_equal(expected, getline(1, '$')) %d - call setline(1, [' var_a = something()', ' b = something()']) + let testinput =<< trim [CODE] + var_a = something() + b = something() + [CODE] + call setline(1, testinput) call cursor(1, 1) call feedkeys("^\j$A;\", 'tnix') - call assert_equal([' var_a = something();', ' b = something()'], getline(1, '$')) + let expected =<< trim [CODE] + var_a = something(); + b = something() + [CODE] + call assert_equal(expected, getline(1, '$')) bw! endfunc diff --git a/src/nvim/testdir/test_exit.vim b/src/nvim/testdir/test_exit.vim index 8f02fd29e3..3797626abf 100644 --- a/src/nvim/testdir/test_exit.vim +++ b/src/nvim/testdir/test_exit.vim @@ -3,52 +3,56 @@ source shared.vim func Test_exiting() - let after = [ - \ 'au QuitPre * call writefile(["QuitPre"], "Xtestout")', - \ 'au ExitPre * call writefile(["ExitPre"], "Xtestout", "a")', - \ 'quit', - \ ] + let after =<< trim [CODE] + au QuitPre * call writefile(["QuitPre"], "Xtestout") + au ExitPre * call writefile(["ExitPre"], "Xtestout", "a") + quit + [CODE] + if RunVim([], after, '') call assert_equal(['QuitPre', 'ExitPre'], readfile('Xtestout')) endif call delete('Xtestout') - let after = [ - \ 'au QuitPre * call writefile(["QuitPre"], "Xtestout")', - \ 'au ExitPre * call writefile(["ExitPre"], "Xtestout", "a")', - \ 'help', - \ 'wincmd w', - \ 'quit', - \ ] + let after =<< trim [CODE] + au QuitPre * call writefile(["QuitPre"], "Xtestout") + au ExitPre * call writefile(["ExitPre"], "Xtestout", "a") + help + wincmd w + quit + [CODE] + if RunVim([], after, '') call assert_equal(['QuitPre', 'ExitPre'], readfile('Xtestout')) endif call delete('Xtestout') - let after = [ - \ 'au QuitPre * call writefile(["QuitPre"], "Xtestout")', - \ 'au ExitPre * call writefile(["ExitPre"], "Xtestout", "a")', - \ 'split', - \ 'new', - \ 'qall', - \ ] + let after =<< trim [CODE] + au QuitPre * call writefile(["QuitPre"], "Xtestout") + au ExitPre * call writefile(["ExitPre"], "Xtestout", "a") + split + new + qall + [CODE] + if RunVim([], after, '') call assert_equal(['QuitPre', 'ExitPre'], readfile('Xtestout')) endif call delete('Xtestout') - let after = [ - \ 'au QuitPre * call writefile(["QuitPre"], "Xtestout", "a")', - \ 'au ExitPre * call writefile(["ExitPre"], "Xtestout", "a")', - \ 'augroup nasty', - \ ' au ExitPre * split', - \ 'augroup END', - \ 'quit', - \ 'augroup nasty', - \ ' au! ExitPre', - \ 'augroup END', - \ 'quit', - \ ] + let after =<< trim [CODE] + au QuitPre * call writefile(["QuitPre"], "Xtestout", "a") + au ExitPre * call writefile(["ExitPre"], "Xtestout", "a") + augroup nasty + au ExitPre * split + augroup END + quit + augroup nasty + au! ExitPre + augroup END + quit + [CODE] + if RunVim([], after, '') call assert_equal(['QuitPre', 'ExitPre', 'QuitPre', 'ExitPre'], \ readfile('Xtestout')) diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim index 03723b3cb5..324f3f8cf2 100644 --- a/src/nvim/testdir/test_fold.vim +++ b/src/nvim/testdir/test_fold.vim @@ -520,17 +520,18 @@ func Test_fold_create_marker_in_C() set fdm=marker fdl=9 set filetype=c - let content = [ - \ '/*', - \ ' * comment', - \ ' * ', - \ ' *', - \ ' */', - \ 'int f(int* p) {', - \ ' *p = 3;', - \ ' return 0;', - \ '}' - \] + let content =<< trim [CODE] + /* + * comment + * + * + */ + int f(int* p) { + *p = 3; + return 0; + } + [CODE] + for c in range(len(content) - 1) bw! call append(0, content) diff --git a/src/nvim/testdir/test_goto.vim b/src/nvim/testdir/test_goto.vim index c0235b1707..f04a5a7e3d 100644 --- a/src/nvim/testdir/test_goto.vim +++ b/src/nvim/testdir/test_goto.vim @@ -15,262 +15,283 @@ func XTest_goto_decl(cmd, lines, line, col) endfunc func Test_gD() - let lines = [ - \ 'int x;', - \ '', - \ 'int func(void)', - \ '{', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + int x; + + int func(void) + { + return x; + } + [CODE] + call XTest_goto_decl('gD', lines, 1, 5) endfunc func Test_gD_too() - let lines = [ - \ 'Filename x;', - \ '', - \ 'int Filename', - \ 'int func() {', - \ ' Filename x;', - \ ' return x;', - \ ] + let lines =<< trim [CODE] + Filename x; + + int Filename + int func() { + Filename x; + return x; + [CODE] + call XTest_goto_decl('gD', lines, 1, 10) endfunc func Test_gD_comment() - let lines = [ - \ '/* int x; */', - \ 'int x;', - \ '', - \ 'int func(void)', - \ '{', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + /* int x; */ + int x; + + int func(void) + { + return x; + } + [CODE] + call XTest_goto_decl('gD', lines, 2, 5) endfunc func Test_gD_inline_comment() - let lines = [ - \ 'int y /* , x */;', - \ 'int x;', - \ '', - \ 'int func(void)', - \ '{', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + int y /* , x */; + int x; + + int func(void) + { + return x; + } + [CODE] + call XTest_goto_decl('gD', lines, 2, 5) endfunc func Test_gD_string() - let lines = [ - \ 'char *s[] = "x";', - \ 'int x = 1;', - \ '', - \ 'int func(void)', - \ '{', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + char *s[] = "x"; + int x = 1; + + int func(void) + { + return x; + } + [CODE] + call XTest_goto_decl('gD', lines, 2, 5) endfunc func Test_gD_string_same_line() - let lines = [ - \ 'char *s[] = "x", int x = 1;', - \ '', - \ 'int func(void)', - \ '{', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + char *s[] = "x", int x = 1; + + int func(void) + { + return x; + } + [CODE] + call XTest_goto_decl('gD', lines, 1, 22) endfunc func Test_gD_char() - let lines = [ - \ "char c = 'x';", - \ 'int x = 1;', - \ '', - \ 'int func(void)', - \ '{', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + char c = 'x'; + int x = 1; + + int func(void) + { + return x; + } + [CODE] + call XTest_goto_decl('gD', lines, 2, 5) endfunc func Test_gd() - let lines = [ - \ 'int x;', - \ '', - \ 'int func(int x)', - \ '{', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + int x; + + int func(int x) + { + return x; + } + [CODE] + call XTest_goto_decl('gd', lines, 3, 14) endfunc func Test_gd_not_local() - let lines = [ - \ 'int func1(void)', - \ '{', - \ ' return x;', - \ '}', - \ '', - \ 'int func2(int x)', - \ '{', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + int func1(void) + { + return x; + } + + int func2(int x) + { + return x; + } + [CODE] + call XTest_goto_decl('gd', lines, 3, 10) endfunc func Test_gd_kr_style() - let lines = [ - \ 'int func(x)', - \ ' int x;', - \ '{', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + int func(x) + int x; + { + return x; + } + [CODE] + call XTest_goto_decl('gd', lines, 2, 7) endfunc func Test_gd_missing_braces() - let lines = [ - \ 'def func1(a)', - \ ' a + 1', - \ 'end', - \ '', - \ 'a = 1', - \ '', - \ 'def func2()', - \ ' return a', - \ 'end', - \ ] + let lines =<< trim [CODE] + def func1(a) + a + 1 + end + + a = 1 + + def func2() + return a + end + [CODE] + call XTest_goto_decl('gd', lines, 1, 11) endfunc func Test_gd_comment() - let lines = [ - \ 'int func(void)', - \ '{', - \ ' /* int x; */', - \ ' int x;', - \ ' return x;', - \ '}', - \] + let lines =<< trim [CODE] + int func(void) + { + /* int x; */ + int x; + return x; + } + [CODE] + call XTest_goto_decl('gd', lines, 4, 7) endfunc func Test_gd_comment_in_string() - let lines = [ - \ 'int func(void)', - \ '{', - \ ' char *s ="//"; int x;', - \ ' int x;', - \ ' return x;', - \ '}', - \] + let lines =<< trim [CODE] + int func(void) + { + char *s ="//"; int x; + int x; + return x; + } + [CODE] + call XTest_goto_decl('gd', lines, 3, 22) endfunc func Test_gd_string_in_comment() set comments= - let lines = [ - \ 'int func(void)', - \ '{', - \ ' /* " */ int x;', - \ ' int x;', - \ ' return x;', - \ '}', - \] + let lines =<< trim [CODE] + int func(void) + { + /* " */ int x; + int x; + return x; + } + [CODE] + call XTest_goto_decl('gd', lines, 3, 15) set comments& endfunc func Test_gd_inline_comment() - let lines = [ - \ 'int func(/* x is an int */ int x)', - \ '{', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + int func(/* x is an int */ int x) + { + return x; + } + [CODE] + call XTest_goto_decl('gd', lines, 1, 32) endfunc func Test_gd_inline_comment_only() - let lines = [ - \ 'int func(void) /* one lonely x */', - \ '{', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + int func(void) /* one lonely x */ + { + return x; + } + [CODE] + call XTest_goto_decl('gd', lines, 3, 10) endfunc func Test_gd_inline_comment_body() - let lines = [ - \ 'int func(void)', - \ '{', - \ ' int y /* , x */;', - \ '', - \ ' for (/* int x = 0 */; y < 2; y++);', - \ '', - \ ' int x = 0;', - \ '', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + int func(void) + { + int y /* , x */; + + for (/* int x = 0 */; y < 2; y++); + + int x = 0; + + return x; + } + [CODE] + call XTest_goto_decl('gd', lines, 7, 7) endfunc func Test_gd_trailing_multiline_comment() - let lines = [ - \ 'int func(int x) /* x is an int */', - \ '{', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + int func(int x) /* x is an int */ + { + return x; + } + [CODE] + call XTest_goto_decl('gd', lines, 1, 14) endfunc func Test_gd_trailing_comment() - let lines = [ - \ 'int func(int x) // x is an int', - \ '{', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + int func(int x) // x is an int + { + return x; + } + [CODE] + call XTest_goto_decl('gd', lines, 1, 14) endfunc func Test_gd_string() - let lines = [ - \ 'int func(void)', - \ '{', - \ ' char *s = "x";', - \ ' int x = 1;', - \ '', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + int func(void) + { + char *s = "x"; + int x = 1; + + return x; + } + [CODE] + call XTest_goto_decl('gd', lines, 4, 7) endfunc func Test_gd_string_only() - let lines = [ - \ 'int func(void)', - \ '{', - \ ' char *s = "x";', - \ '', - \ ' return x;', - \ '}', - \ ] + let lines =<< trim [CODE] + int func(void) + { + char *s = "x"; + + return x; + } + [CODE] + call XTest_goto_decl('gd', lines, 5, 10) endfunc @@ -289,24 +310,25 @@ func Test_cursorline_keep_col() endfunc func Test_gd_local_block() - let lines = [ - \ ' int main()', - \ '{', - \ ' char *a = "NOT NULL";', - \ ' if(a)', - \ ' {', - \ ' char *b = a;', - \ ' printf("%s\n", b);', - \ ' }', - \ ' else', - \ ' {', - \ ' char *b = "NULL";', - \ ' return b;', - \ ' }', - \ '', - \ ' return 0;', - \ '}', - \ ] + let lines =<< trim [CODE] + int main() + { + char *a = "NOT NULL"; + if(a) + { + char *b = a; + printf("%s\n", b); + } + else + { + char *b = "NULL"; + return b; + } + + return 0; + } + [CODE] + call XTest_goto_decl('1gd', lines, 11, 11) endfunc diff --git a/src/nvim/testdir/test_mksession_utf8.vim b/src/nvim/testdir/test_mksession_utf8.vim index 67af3a9ca2..36f07512a8 100644 --- a/src/nvim/testdir/test_mksession_utf8.vim +++ b/src/nvim/testdir/test_mksession_utf8.vim @@ -65,34 +65,35 @@ func Test_mksession_utf8() call wincol() mksession! test_mks.out let li = filter(readfile('test_mks.out'), 'v:val =~# "\\(^ *normal! 0\\|^ *exe ''normal!\\)"') - let expected = [ - \ 'normal! 016|', - \ 'normal! 016|', - \ 'normal! 016|', - \ 'normal! 08|', - \ 'normal! 08|', - \ 'normal! 016|', - \ 'normal! 016|', - \ 'normal! 016|', - \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", - \ " normal! 016|", - \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", - \ " normal! 016|", - \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", - \ " normal! 016|", - \ " exe 'normal! ' . s:c . '|zs' . 8 . '|'", - \ " normal! 08|", - \ " exe 'normal! ' . s:c . '|zs' . 8 . '|'", - \ " normal! 08|", - \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", - \ " normal! 016|", - \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", - \ " normal! 016|", - \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", - \ " normal! 016|", - \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", - \ " normal! 016|" - \ ] + let expected =<< trim [DATA] + normal! 016| + normal! 016| + normal! 016| + normal! 08| + normal! 08| + normal! 016| + normal! 016| + normal! 016| + exe 'normal! ' . s:c . '|zs' . 16 . '|' + normal! 016| + exe 'normal! ' . s:c . '|zs' . 16 . '|' + normal! 016| + exe 'normal! ' . s:c . '|zs' . 16 . '|' + normal! 016| + exe 'normal! ' . s:c . '|zs' . 8 . '|' + normal! 08| + exe 'normal! ' . s:c . '|zs' . 8 . '|' + normal! 08| + exe 'normal! ' . s:c . '|zs' . 16 . '|' + normal! 016| + exe 'normal! ' . s:c . '|zs' . 16 . '|' + normal! 016| + exe 'normal! ' . s:c . '|zs' . 16 . '|' + normal! 016| + exe 'normal! ' . s:c . '|zs' . 16 . '|' + normal! 016| + [DATA] + call assert_equal(expected, li) tabclose! diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim index 8bc4228359..b967f84626 100644 --- a/src/nvim/testdir/test_normal.vim +++ b/src/nvim/testdir/test_normal.vim @@ -1563,52 +1563,94 @@ endfunc fun! Test_normal29_brace() " basic test for { and } movements - let text= ['A paragraph begins after each empty line, and also at each of a set of', - \ 'paragraph macros, specified by the pairs of characters in the ''paragraphs''', - \ 'option. The default is "IPLPPPQPP TPHPLIPpLpItpplpipbp", which corresponds to', - \ 'the macros ".IP", ".LP", etc. (These are nroff macros, so the dot must be in', - \ 'the first column). A section boundary is also a paragraph boundary.', - \ 'Note that a blank line (only containing white space) is NOT a paragraph', - \ 'boundary.', - \ '', - \ '', - \ 'Also note that this does not include a ''{'' or ''}'' in the first column. When', - \ 'the ''{'' flag is in ''cpoptions'' then ''{'' in the first column is used as a', - \ 'paragraph boundary |posix|.', - \ '{', - \ 'This is no paragraph', - \ 'unless the ''{'' is set', - \ 'in ''cpoptions''', - \ '}', - \ '.IP', - \ 'The nroff macros IP separates a paragraph', - \ 'That means, it must be a ''.''', - \ 'followed by IP', - \ '.LPIt does not matter, if afterwards some', - \ 'more characters follow.', - \ '.SHAlso section boundaries from the nroff', - \ 'macros terminate a paragraph. That means', - \ 'a character like this:', - \ '.NH', - \ 'End of text here'] + let text =<< trim [DATA] + A paragraph begins after each empty line, and also at each of a set of + paragraph macros, specified by the pairs of characters in the 'paragraphs' + option. The default is "IPLPPPQPP TPHPLIPpLpItpplpipbp", which corresponds to + the macros ".IP", ".LP", etc. (These are nroff macros, so the dot must be in + the first column). A section boundary is also a paragraph boundary. + Note that a blank line (only containing white space) is NOT a paragraph + boundary. + + + Also note that this does not include a '{' or '}' in the first column. When + the '{' flag is in 'cpoptions' then '{' in the first column is used as a + paragraph boundary |posix|. + { + This is no paragraph + unless the '{' is set + in 'cpoptions' + } + .IP + The nroff macros IP separates a paragraph + That means, it must be a '.' + followed by IP + .LPIt does not matter, if afterwards some + more characters follow. + .SHAlso section boundaries from the nroff + macros terminate a paragraph. That means + a character like this: + .NH + End of text here + [DATA] + new call append(0, text) 1 norm! 0d2} - call assert_equal(['.IP', - \ 'The nroff macros IP separates a paragraph', 'That means, it must be a ''.''', 'followed by IP', - \ '.LPIt does not matter, if afterwards some', 'more characters follow.', '.SHAlso section boundaries from the nroff', - \ 'macros terminate a paragraph. That means', 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$')) + + let expected =<< trim [DATA] + .IP + The nroff macros IP separates a paragraph + That means, it must be a '.' + followed by IP + .LPIt does not matter, if afterwards some + more characters follow. + .SHAlso section boundaries from the nroff + macros terminate a paragraph. That means + a character like this: + .NH + End of text here + + [DATA] + call assert_equal(expected, getline(1, '$')) + norm! 0d} - call assert_equal(['.LPIt does not matter, if afterwards some', 'more characters follow.', - \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means', - \ 'a character like this:', '.NH', 'End of text here', ''], getline(1, '$')) + + let expected =<< trim [DATA] + .LPIt does not matter, if afterwards some + more characters follow. + .SHAlso section boundaries from the nroff + macros terminate a paragraph. That means + a character like this: + .NH + End of text here + + [DATA] + call assert_equal(expected, getline(1, '$')) + $ norm! d{ - call assert_equal(['.LPIt does not matter, if afterwards some', 'more characters follow.', - \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means', 'a character like this:', ''], getline(1, '$')) + + let expected =<< trim [DATA] + .LPIt does not matter, if afterwards some + more characters follow. + .SHAlso section boundaries from the nroff + macros terminate a paragraph. That means + a character like this: + + [DATA] + call assert_equal(expected, getline(1, '$')) + norm! d{ - call assert_equal(['.LPIt does not matter, if afterwards some', 'more characters follow.', ''], getline(1,'$')) + + let expected =<< trim [DATA] + .LPIt does not matter, if afterwards some + more characters follow. + + [DATA] + call assert_equal(expected, getline(1, '$')) + " Test with { in cpooptions %d call append(0, text) @@ -1616,21 +1658,62 @@ fun! Test_normal29_brace() " set cpo+={ " 1 " norm! 0d2} - " call assert_equal(['{', 'This is no paragraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', - " \ '.IP', 'The nroff macros IP separates a paragraph', 'That means, it must be a ''.''', - " \ 'followed by IP', '.LPIt does not matter, if afterwards some', 'more characters follow.', - " \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means', - " \ 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$')) + " let expected =<< trim [DATA] + " { + " This is no paragraph + " unless the '{' is set + " in 'cpoptions' + " } + " .IP + " The nroff macros IP separates a paragraph + " That means, it must be a '.' + " followed by IP + " .LPIt does not matter, if afterwards some + " more characters follow. + " .SHAlso section boundaries from the nroff + " macros terminate a paragraph. That means + " a character like this: + " .NH + " End of text here + " + " [DATA] + " call assert_equal(expected, getline(1, '$')) + " " $ " norm! d} - " call assert_equal(['{', 'This is no paragraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', - " \ '.IP', 'The nroff macros IP separates a paragraph', 'That means, it must be a ''.''', - " \ 'followed by IP', '.LPIt does not matter, if afterwards some', 'more characters follow.', - " \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means', - " \ 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$')) + " let expected =<< trim [DATA] + " { + " This is no paragraph + " unless the '{' is set + " in 'cpoptions' + " } + " .IP + " The nroff macros IP separates a paragraph + " That means, it must be a '.' + " followed by IP + " .LPIt does not matter, if afterwards some + " more characters follow. + " .SHAlso section boundaries from the nroff + " macros terminate a paragraph. That means + " a character like this: + " .NH + " End of text here + " + " [DATA] + " call assert_equal(expected, getline(1, '$')) + " " norm! gg} " norm! d5} - " call assert_equal(['{', 'This is no paragraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', ''], getline(1,'$')) + " + " let expected =<< trim [DATA] + " { + " This is no paragraph + " unless the '{' is set + " in 'cpoptions' + " } + + " [DATA] + " call assert_equal(expected, getline(1, '$')) " clean up set cpo-={ diff --git a/src/nvim/testdir/test_profile.vim b/src/nvim/testdir/test_profile.vim index b677ac3704..4ab20a9c77 100644 --- a/src/nvim/testdir/test_profile.vim +++ b/src/nvim/testdir/test_profile.vim @@ -6,34 +6,34 @@ endif source screendump.vim func Test_profile_func() - let lines = [ - \ 'profile start Xprofile_func.log', - \ 'profile func Foo*"', - \ "func! Foo1()", - \ "endfunc", - \ "func! Foo2()", - \ " let l:count = 100", - \ " while l:count > 0", - \ " let l:count = l:count - 1", - \ " endwhile", - \ "endfunc", - \ "func! Foo3()", - \ "endfunc", - \ "func! Bar()", - \ "endfunc", - \ "call Foo1()", - \ "call Foo1()", - \ "profile pause", - \ "call Foo1()", - \ "profile continue", - \ "call Foo2()", - \ "call Foo3()", - \ "call Bar()", - \ "if !v:profiling", - \ " delfunc Foo2", - \ "endif", - \ "delfunc Foo3", - \ ] + let lines =<< trim [CODE] + profile start Xprofile_func.log + profile func Foo* + func! Foo1() + endfunc + func! Foo2() + let l:count = 100 + while l:count > 0 + let l:count = l:count - 1 + endwhile + endfunc + func! Foo3() + endfunc + func! Bar() + endfunc + call Foo1() + call Foo1() + profile pause + call Foo1() + profile continue + call Foo2() + call Foo3() + call Bar() + if !v:profiling + delfunc Foo2 + endif + delfunc Foo3 + [CODE] call writefile(lines, 'Xprofile_func.vim') call system(v:progpath @@ -88,38 +88,38 @@ func Test_profile_func() endfunc func Test_profile_func_with_ifelse() - let lines = [ - \ "func! Foo1()", - \ " if 1", - \ " let x = 0", - \ " elseif 1", - \ " let x = 1", - \ " else", - \ " let x = 2", - \ " endif", - \ "endfunc", - \ "func! Foo2()", - \ " if 0", - \ " let x = 0", - \ " elseif 1", - \ " let x = 1", - \ " else", - \ " let x = 2", - \ " endif", - \ "endfunc", - \ "func! Foo3()", - \ " if 0", - \ " let x = 0", - \ " elseif 0", - \ " let x = 1", - \ " else", - \ " let x = 2", - \ " endif", - \ "endfunc", - \ "call Foo1()", - \ "call Foo2()", - \ "call Foo3()", - \ ] + let lines =<< trim [CODE] + func! Foo1() + if 1 + let x = 0 + elseif 1 + let x = 1 + else + let x = 2 + endif + endfunc + func! Foo2() + if 0 + let x = 0 + elseif 1 + let x = 1 + else + let x = 2 + endif + endfunc + func! Foo3() + if 0 + let x = 0 + elseif 0 + let x = 1 + else + let x = 2 + endif + endfunc + call Foo1() + call Foo2() + call Foo3() + [CODE] call writefile(lines, 'Xprofile_func.vim') call system(v:progpath @@ -198,41 +198,41 @@ func Test_profile_func_with_ifelse() endfunc func Test_profile_func_with_trycatch() - let lines = [ - \ "func! Foo1()", - \ " try", - \ " let x = 0", - \ " catch", - \ " let x = 1", - \ " finally", - \ " let x = 2", - \ " endtry", - \ "endfunc", - \ "func! Foo2()", - \ " try", - \ " throw 0", - \ " catch", - \ " let x = 1", - \ " finally", - \ " let x = 2", - \ " endtry", - \ "endfunc", - \ "func! Foo3()", - \ " try", - \ " throw 0", - \ " catch", - \ " throw 1", - \ " finally", - \ " let x = 2", - \ " endtry", - \ "endfunc", - \ "call Foo1()", - \ "call Foo2()", - \ "try", - \ " call Foo3()", - \ "catch", - \ "endtry", - \ ] + let lines =<< trim [CODE] + func! Foo1() + try + let x = 0 + catch + let x = 1 + finally + let x = 2 + endtry + endfunc + func! Foo2() + try + throw 0 + catch + let x = 1 + finally + let x = 2 + endtry + endfunc + func! Foo3() + try + throw 0 + catch + throw 1 + finally + let x = 2 + endtry + endfunc + call Foo1() + call Foo2() + try + call Foo3() + catch + endtry + [CODE] call writefile(lines, 'Xprofile_func.vim') call system(v:progpath @@ -311,15 +311,15 @@ func Test_profile_func_with_trycatch() endfunc func Test_profile_file() - let lines = [ - \ 'func! Foo()', - \ 'endfunc', - \ 'for i in range(10)', - \ ' " a comment', - \ ' call Foo()', - \ 'endfor', - \ 'call Foo()', - \ ] + let lines =<< trim [CODE] + func! Foo() + endfunc + for i in range(10) + " a comment + call Foo() + endfor + call Foo() + [CODE] call writefile(lines, 'Xprofile_file.vim') call system(v:progpath @@ -450,26 +450,27 @@ func Test_profile_truncate_mbyte() endfunc func Test_profdel_func() - let lines = [ - \ 'profile start Xprofile_file.log', - \ 'func! Foo1()', - \ 'endfunc', - \ 'func! Foo2()', - \ 'endfunc', - \ 'func! Foo3()', - \ 'endfunc', - \ '', - \ 'profile func Foo1', - \ 'profile func Foo2', - \ 'call Foo1()', - \ 'call Foo2()', - \ '', - \ 'profile func Foo3', - \ 'profdel func Foo2', - \ 'profdel func Foo3', - \ 'call Foo1()', - \ 'call Foo2()', - \ 'call Foo3()' ] + let lines =<< trim [CODE] + profile start Xprofile_file.log + func! Foo1() + endfunc + func! Foo2() + endfunc + func! Foo3() + endfunc + + profile func Foo1 + profile func Foo2 + call Foo1() + call Foo2() + + profile func Foo3 + profdel func Foo2 + profdel func Foo3 + call Foo1() + call Foo2() + call Foo3() + [CODE] call writefile(lines, 'Xprofile_file.vim') call system(v:progpath . ' -es --clean -c "so Xprofile_file.vim" -c q') call assert_equal(0, v:shell_error) @@ -496,14 +497,15 @@ endfunc func Test_profdel_star() " Foo() is invoked once before and once after 'profdel *'. " So profiling should report it only once. - let lines = [ - \ 'profile start Xprofile_file.log', - \ 'func! Foo()', - \ 'endfunc', - \ 'profile func Foo', - \ 'call Foo()', - \ 'profdel *', - \ 'call Foo()' ] + let lines =<< trim [CODE] + profile start Xprofile_file.log + func! Foo() + endfunc + profile func Foo + call Foo() + profdel * + call Foo() + [CODE] call writefile(lines, 'Xprofile_file.vim') call system(v:progpath . ' -es --clean -c "so Xprofile_file.vim" -c q') call assert_equal(0, v:shell_error) diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 597be0aa89..b9a22aff51 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -775,68 +775,68 @@ func Test_efm1() return endif - let l = [ - \ '"Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set.', - \ '"Xtestfile", line 6 col 19; this is an error', - \ 'gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include version.c', - \ 'Xtestfile:9: parse error before `asd''', - \ 'make: *** [vim] Error 1', - \ 'in file "Xtestfile" linenr 10: there is an error', - \ '', - \ '2 returned', - \ '"Xtestfile", line 11 col 1; this is an error', - \ '"Xtestfile", line 12 col 2; this is another error', - \ '"Xtestfile", line 14:10; this is an error in column 10', - \ '=Xtestfile=, line 15:10; this is another error, but in vcol 10 this time', - \ '"Xtestfile", linenr 16: yet another problem', - \ 'Error in "Xtestfile" at line 17:', - \ 'x should be a dot', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17', - \ ' ^', - \ 'Error in "Xtestfile" at line 18:', - \ 'x should be a dot', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18', - \ '.............^', - \ 'Error in "Xtestfile" at line 19:', - \ 'x should be a dot', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19', - \ '--------------^', - \ 'Error in "Xtestfile" at line 20:', - \ 'x should be a dot', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20', - \ ' ^', - \ '', - \ 'Does anyone know what is the problem and how to correction it?', - \ '"Xtestfile", line 21 col 9: What is the title of the quickfix window?', - \ '"Xtestfile", line 22 col 9: What is the title of the quickfix window?' - \ ] + let l =<< trim [DATA] + "Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set. + "Xtestfile", line 6 col 19; this is an error + gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include version.c + Xtestfile:9: parse error before `asd' + make: *** [vim] Error 1 + in file "Xtestfile" linenr 10: there is an error + + 2 returned + "Xtestfile", line 11 col 1; this is an error + "Xtestfile", line 12 col 2; this is another error + "Xtestfile", line 14:10; this is an error in column 10 + =Xtestfile=, line 15:10; this is another error, but in vcol 10 this time + "Xtestfile", linenr 16: yet another problem + Error in "Xtestfile" at line 17: + x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17 + ^ + Error in "Xtestfile" at line 18: + x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18 + .............^ + Error in "Xtestfile" at line 19: + x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19 + --------------^ + Error in "Xtestfile" at line 20: + x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20 + ^ + + Does anyone know what is the problem and how to correction it? + "Xtestfile", line 21 col 9: What is the title of the quickfix window? + "Xtestfile", line 22 col 9: What is the title of the quickfix window? + [DATA] call writefile(l, 'Xerrorfile1') call writefile(l[:-2], 'Xerrorfile2') - let m = [ - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 2', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 3', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 4', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 5', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 6', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 7', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 8', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 9', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 10', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 11', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 12', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 13', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 14', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 15', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 16', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 21', - \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 22' - \ ] + let m =<< trim [DATA] + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 2 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 3 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 4 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 5 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 6 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 7 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 8 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 9 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 10 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 11 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 12 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 13 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 14 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 15 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 16 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 21 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 22 + [DATA] call writefile(m, 'Xtestfile') let save_efm = &efm @@ -895,20 +895,21 @@ func s:dir_stack_tests(cchar) let save_efm=&efm set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f' - let lines = ["Entering dir 'dir1/a'", - \ 'habits2.txt:1:Nine Healthy Habits', - \ "Entering dir 'b'", - \ 'habits3.txt:2:0 Hours of television', - \ 'habits2.txt:7:5 Small meals', - \ "Entering dir 'dir1/c'", - \ 'habits4.txt:3:1 Hour of exercise', - \ "Leaving dir 'dir1/c'", - \ "Leaving dir 'dir1/a'", - \ 'habits1.txt:4:2 Liters of water', - \ "Entering dir 'dir2'", - \ 'habits5.txt:5:3 Cups of hot green tea', - \ "Leaving dir 'dir2'" - \] + let lines =<< trim [DATA] + Entering dir 'dir1/a' + habits2.txt:1:Nine Healthy Habits + Entering dir 'b' + habits3.txt:2:0 Hours of television + habits2.txt:7:5 Small meals + Entering dir 'dir1/c' + habits4.txt:3:1 Hour of exercise + Leaving dir 'dir1/c' + Leaving dir 'dir1/a' + habits1.txt:4:2 Liters of water + Entering dir 'dir2' + habits5.txt:5:3 Cups of hot green tea + Leaving dir 'dir2 + [DATA] Xexpr "" for l in lines @@ -942,18 +943,20 @@ func Test_efm_dirstack() call mkdir('dir1/c') call mkdir('dir2') - let lines = ["Nine Healthy Habits", - \ "0 Hours of television", - \ "1 Hour of exercise", - \ "2 Liters of water", - \ "3 Cups of hot green tea", - \ "4 Short mental breaks", - \ "5 Small meals", - \ "6 AM wake up time", - \ "7 Minutes of laughter", - \ "8 Hours of sleep (at least)", - \ "9 PM end of the day and off to bed" - \ ] + let lines =<< trim [DATA] + Nine Healthy Habits, + 0 Hours of television, + 1 Hour of exercise, + 2 Liters of water, + 3 Cups of hot green tea, + 4 Short mental breaks, + 5 Small meals, + 6 AM wake up time, + 7 Minutes of laughter, + 8 Hours of sleep (at least), + 9 PM end of the day and off to bed + [DATA] + call writefile(lines, 'habits1.txt') call writefile(lines, 'dir1/a/habits2.txt') call writefile(lines, 'dir1/a/b/habits3.txt') @@ -1049,21 +1052,22 @@ func Test_efm2() call assert_equal([' 1 Xtestfile:^\VLine search text\$: '], l) " Test for %P, %Q and %t format specifiers - let lines=["[Xtestfile1]", - \ "(1,17) error: ';' missing", - \ "(21,2) warning: variable 'z' not defined", - \ "(67,3) error: end of file found before string ended", - \ "--", - \ "", - \ "[Xtestfile2]", - \ "--", - \ "", - \ "[Xtestfile3]", - \ "NEW compiler v1.1", - \ "(2,2) warning: variable 'x' not defined", - \ "(67,3) warning: 's' already defined", - \ "--" - \] + let lines =<< trim [DATA] + [Xtestfile1] + (1,17) error: ';' missing + (21,2) warning: variable 'z' not defined + (67,3) error: end of file found before string ended + -- + + [Xtestfile2] + -- + + [Xtestfile3] + NEW compiler v1.1 + (2,2) warning: variable 'x' not defined + (67,3) warning: 's' already defined + - + [DATA] set efm=%+P[%f]%r,(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%+Q--%r " To exercise the push/pop file functionality in quickfix, the test files " need to be created. @@ -1085,11 +1089,13 @@ func Test_efm2() call delete('Xtestfile3') " Tests for %E, %C and %Z format specifiers - let lines = ["Error 275", - \ "line 42", - \ "column 3", - \ "' ' expected after '--'" - \] + let lines =<< trim [DATA] + Error 275 + line 42 + column 3 + ' ' expected after '--' + [DATA] + set efm=%EError\ %n,%Cline\ %l,%Ccolumn\ %c,%Z%m cgetexpr lines let l = getqflist() @@ -1100,9 +1106,11 @@ func Test_efm2() call assert_equal("\n' ' expected after '--'", l[0].text) " Test for %> - let lines = ["Error in line 147 of foo.c:", - \"unknown variable 'i'" - \] + let lines =<< trim [DATA] + Error in line 147 of foo.c: + unknown variable 'i' + [DATA] + set efm=unknown\ variable\ %m,%E%>Error\ in\ line\ %l\ of\ %f:,%Z%m cgetexpr lines let l = getqflist() @@ -1111,21 +1119,21 @@ func Test_efm2() call assert_equal("\nunknown variable 'i'", l[0].text) " Test for %A, %C and other formats - let lines = [ - \"==============================================================", - \"FAIL: testGetTypeIdCachesResult (dbfacadeTest.DjsDBFacadeTest)", - \"--------------------------------------------------------------", - \"Traceback (most recent call last):", - \' File "unittests/dbfacadeTest.py", line 89, in testFoo', - \" self.assertEquals(34, dtid)", - \' File "/usr/lib/python2.2/unittest.py", line 286, in', - \" failUnlessEqual", - \" raise self.failureException, \\", - \"AssertionError: 34 != 33", - \"", - \"--------------------------------------------------------------", - \"Ran 27 tests in 0.063s" - \] + let lines =<< trim [DATA] + ============================================================== + FAIL: testGetTypeIdCachesResult (dbfacadeTest.DjsDBFacadeTest) + -------------------------------------------------------------- + Traceback (most recent call last): + File "unittests/dbfacadeTest.py", line 89, in testFoo + self.assertEquals(34, dtid) + File "/usr/lib/python2.2/unittest.py", line 286, in + failUnlessEqual + raise self.failureException, \\ + AssertionError: 34 != 33 + + -------------------------------------------------------------- + Ran 27 tests in 0.063s + [DATA] set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m cgetexpr lines let l = getqflist() diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim index 1e70f28a00..a38625cca8 100644 --- a/src/nvim/testdir/test_startup.vim +++ b/src/nvim/testdir/test_startup.vim @@ -20,25 +20,27 @@ func Test_after_comes_later() if !has('packages') return endif - let before = [ - \ 'set nocp viminfo+=nviminfo', - \ 'set guioptions+=M', - \ 'let $HOME = "/does/not/exist"', - \ 'set loadplugins', - \ 'set rtp=Xhere,Xafter,Xanother', - \ 'set packpath=Xhere,Xafter', - \ 'set nomore', - \ 'let g:sequence = ""', - \ ] - let after = [ - \ 'redir! > Xtestout', - \ 'scriptnames', - \ 'redir END', - \ 'redir! > Xsequence', - \ 'echo g:sequence', - \ 'redir END', - \ 'quit', - \ ] + let before =<< trim [CODE] + set nocp viminfo+=nviminfo + set guioptions+=M + let $HOME = "/does/not/exist" + set loadplugins + set rtp=Xhere,Xafter,Xanother + set packpath=Xhere,Xafter + set nomore + let g:sequence = "" + [CODE] + + let after =<< trim [CODE] + redir! > Xtestout + scriptnames + redir END + redir! > Xsequence + echo g:sequence + redir END + quit + [CODE] + call mkdir('Xhere/plugin', 'p') call writefile(['let g:sequence .= "here "'], 'Xhere/plugin/here.vim') call mkdir('Xanother/plugin', 'p') @@ -77,15 +79,16 @@ func Test_pack_in_rtp_when_plugins_run() if !has('packages') return endif - let before = [ - \ 'set nocp viminfo+=nviminfo', - \ 'set guioptions+=M', - \ 'let $HOME = "/does/not/exist"', - \ 'set loadplugins', - \ 'set rtp=Xhere', - \ 'set packpath=Xhere', - \ 'set nomore', - \ ] + let before =<< trim [CODE] + set nocp viminfo+=nviminfo + set guioptions+=M + let $HOME = "/does/not/exist" + set loadplugins + set rtp=Xhere + set packpath=Xhere + set nomore + [CODE] + let after = [ \ 'quit', \ ] @@ -133,11 +136,12 @@ endfunc func Test_compatible_args() throw "skipped: Nvim is always 'nocompatible'" - let after = [ - \ 'call writefile([string(&compatible)], "Xtestout")', - \ 'set viminfo+=nviminfo', - \ 'quit', - \ ] + let after =<< trim [CODE] + call writefile([string(&compatible)], "Xtestout") + set viminfo+=nviminfo + quit + [CODE] + if RunVim([], after, '-C') let lines = readfile('Xtestout') call assert_equal('1', lines[0]) @@ -154,14 +158,15 @@ endfunc " Test the -o[N] and -O[N] arguments to open N windows split " horizontally or vertically. func Test_o_arg() - let after = [ - \ 'call writefile([winnr("$"), - \ winheight(1), winheight(2), &lines, - \ winwidth(1), winwidth(2), &columns, - \ bufname(winbufnr(1)), bufname(winbufnr(2))], - \ "Xtestout")', - \ 'qall', - \ ] + let after =<< trim [CODE] + call writefile([winnr("$"), + \ winheight(1), winheight(2), &lines, + \ winwidth(1), winwidth(2), &columns, + \ bufname(winbufnr(1)), bufname(winbufnr(2))], + \ "Xtestout") + qall + [CODE] + if RunVim([], after, '-o2') " Open 2 windows split horizontally. Expect: " - 2 windows @@ -230,10 +235,11 @@ endfunc " Test the -p[N] argument to open N tabpages. func Test_p_arg() - let after = [ - \ 'call writefile(split(execute("tabs"), "\n"), "Xtestout")', - \ 'qall', - \ ] + let after =<< trim [CODE] + call writefile(split(execute("tabs"), "\n"), "Xtestout") + qall + [CODE] + if RunVim([], after, '-p2') let lines = readfile('Xtestout') call assert_equal(4, len(lines)) @@ -290,10 +296,11 @@ endfunc " -M resets 'modifiable' and 'write' " -R sets 'readonly' func Test_m_M_R() - let after = [ - \ 'call writefile([&write, &modifiable, &readonly, &updatecount], "Xtestout")', - \ 'qall', - \ ] + let after =<< trim [CODE] + call writefile([&write, &modifiable, &readonly, &updatecount], "Xtestout") + qall + [CODE] + if RunVim([], after, '') let lines = readfile('Xtestout') call assert_equal(['1', '1', '0', '200'], lines) @@ -316,10 +323,11 @@ endfunc " Test the -A, -F and -H arguments (Arabic, Farsi and Hebrew modes). func Test_A_F_H_arg() - let after = [ - \ 'call writefile([&rightleft, &arabic, 0, &hkmap], "Xtestout")', - \ 'qall', - \ ] + let after =<< trim [CODE] + call writefile([&rightleft, &arabic, 0, &hkmap], "Xtestout") + qall + [CODE] + " Use silent Ex mode to avoid the hit-Enter prompt for the warning that " 'encoding' is not utf-8. if has('arabic') && &encoding == 'utf-8' && RunVim([], after, '-e -s -A') @@ -423,10 +431,11 @@ func Test_invalid_args() endfunc func Test_file_args() - let after = [ - \ 'call writefile(argv(), "Xtestout")', - \ 'qall', - \ ] + let after =<< trim [CODE] + call writefile(argv(), "Xtestout") + qall + [CODE] + if RunVim([], after, '') let lines = readfile('Xtestout') call assert_equal(0, len(lines)) @@ -487,10 +496,11 @@ func Test_startuptime() endfunc func Test_read_stdin() - let after = [ - \ 'write Xtestout', - \ 'quit!', - \ ] + let after =<< trim [CODE] + write Xtestout + quit! + [CODE] + if RunVimPiped([], after, '-', 'echo something | ') let lines = readfile('Xtestout') " MS-Windows adds a space after the word @@ -540,20 +550,22 @@ endfunc func Test_zzz_startinsert() " Test :startinsert call writefile(['123456'], 'Xtestout') - let after = [ - \ ':startinsert', - \ 'call feedkeys("foobar\:wq\","t")' - \ ] + let after =<< trim [CODE] + :startinsert + call feedkeys("foobar\:wq\","t") + [CODE] + if RunVim([], after, 'Xtestout') let lines = readfile('Xtestout') call assert_equal(['foobar123456'], lines) endif " Test :startinsert! call writefile(['123456'], 'Xtestout') - let after = [ - \ ':startinsert!', - \ 'call feedkeys("foobar\:wq\","t")' - \ ] + let after =<< trim [CODE] + :startinsert! + call feedkeys("foobar\:wq\","t") + [CODE] + if RunVim([], after, 'Xtestout') let lines = readfile('Xtestout') call assert_equal(['123456foobar'], lines) From 0586a4b512b2495d32f20c46946d35a0d403bd52 Mon Sep 17 00:00:00 2001 From: Jurica Bradaric Date: Mon, 23 Sep 2019 21:19:26 +0200 Subject: [PATCH 4/4] vim-patch:8.1.1588: in :let-heredoc line continuation is recognized Problem: In :let-heredoc line continuation is recognized. Solution: Do not consume line continuation. (Ozaki Kiichi, closes vim/vim#4580) https://github.com/vim/vim/commit/e96a2498f9a2d3e93ac07431f6d4afd77f30afdf --- src/nvim/digraph.c | 2 +- src/nvim/eval.c | 13 +++++++---- src/nvim/ex_cmds.c | 4 ++-- src/nvim/ex_cmds2.c | 6 ++--- src/nvim/ex_cmds_defs.h | 2 +- src/nvim/ex_docmd.c | 52 ++++++++++++++++++++++------------------- src/nvim/ex_getln.c | 23 ++++++++++-------- src/nvim/fileio.c | 10 ++++---- src/nvim/getchar.c | 2 +- src/nvim/normal.c | 2 +- src/nvim/ops.c | 10 ++++---- 11 files changed, 68 insertions(+), 58 deletions(-) diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c index 5a07137831..65d95ff158 100644 --- a/src/nvim/digraph.c +++ b/src/nvim/digraph.c @@ -1887,7 +1887,7 @@ void ex_loadkeymap(exarg_T *eap) // Get each line of the sourced file, break at the end. for (;;) { - line = eap->getline(0, eap->cookie, 0); + line = eap->getline(0, eap->cookie, 0, true); if (line == NULL) { break; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 6d706939a1..c18d687cc1 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1561,7 +1561,7 @@ heredoc_get(exarg_T *eap, char_u *cmd) for (;;) { int i = 0; - char_u *theline = eap->getline(NUL, eap->cookie, 0); + char_u *theline = eap->getline(NUL, eap->cookie, 0, false); if (theline != NULL && indent_len > 0) { // trim the indent matching the first line if (STRNCMP(theline, *eap->cmdlinep, indent_len) == 0) { @@ -8734,7 +8734,7 @@ typedef struct { const listitem_T *li; } GetListLineCookie; -static char_u *get_list_line(int c, void *cookie, int indent) +static char_u *get_list_line(int c, void *cookie, int indent, bool do_concat) { GetListLineCookie *const p = (GetListLineCookie *)cookie; @@ -21279,6 +21279,7 @@ void ex_function(exarg_T *eap) hashitem_T *hi; int sourcing_lnum_off; bool show_block = false; + bool do_concat = true; /* * ":function" without argument: list functions. @@ -21548,9 +21549,9 @@ void ex_function(exarg_T *eap) } else { xfree(line_to_free); if (eap->getline == NULL) { - theline = getcmdline(':', 0L, indent); + theline = getcmdline(':', 0L, indent, do_concat); } else { - theline = eap->getline(':', eap->cookie, indent); + theline = eap->getline(':', eap->cookie, indent, do_concat); } line_to_free = theline; } @@ -21580,6 +21581,7 @@ void ex_function(exarg_T *eap) if (STRCMP(p, skip_until) == 0) { XFREE_CLEAR(skip_until); XFREE_CLEAR(trimmed); + do_concat = true; } } } else { @@ -21699,6 +21701,7 @@ void ex_function(exarg_T *eap) } else { skip_until = vim_strnsave(p, (int)(skiptowhite(p) - p)); } + do_concat = false; } } @@ -23522,7 +23525,7 @@ char_u *get_return_cmd(void *rettv) * Called by do_cmdline() to get the next line. * Returns allocated string, or NULL for end of function. */ -char_u *get_func_line(int c, void *cookie, int indent) +char_u *get_func_line(int c, void *cookie, int indent, bool do_concat) { funccall_T *fcp = (funccall_T *)cookie; ufunc_T *fp = fcp->func; diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index b2d7ded6be..00de7a3d66 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -2767,7 +2767,7 @@ void ex_append(exarg_T *eap) State = CMDLINE; theline = eap->getline( eap->cstack->cs_looplevel > 0 ? -1 : - NUL, eap->cookie, indent); + NUL, eap->cookie, indent, true); State = save_State; } lines_left = Rows - 1; @@ -3630,7 +3630,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, for (; i <= (long)ec; ++i) msg_putchar('^'); - resp = getexmodeline('?', NULL, 0); + resp = getexmodeline('?', NULL, 0, true); if (resp != NULL) { typed = *resp; xfree(resp); diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 87eae2dd4f..272c81e29b 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -3218,7 +3218,7 @@ int do_source(char_u *fname, int check_other, int is_vimrc) cookie.conv.vc_type = CONV_NONE; // no conversion // Read the first line so we can check for a UTF-8 BOM. - firstline = getsourceline(0, (void *)&cookie, 0); + firstline = getsourceline(0, (void *)&cookie, 0, true); if (firstline != NULL && STRLEN(firstline) >= 3 && firstline[0] == 0xef && firstline[1] == 0xbb && firstline[2] == 0xbf) { // Found BOM; setup conversion, skip over BOM and recode the line. @@ -3381,7 +3381,7 @@ void free_scriptnames(void) /// /// @return pointer to the line in allocated memory, or NULL for end-of-file or /// some error. -char_u *getsourceline(int c, void *cookie, int indent) +char_u *getsourceline(int c, void *cookie, int indent, bool do_concat) { struct source_cookie *sp = (struct source_cookie *)cookie; char_u *line; @@ -3412,7 +3412,7 @@ char_u *getsourceline(int c, void *cookie, int indent) // Only concatenate lines starting with a \ when 'cpoptions' doesn't // contain the 'C' flag. - if (line != NULL && (vim_strchr(p_cpo, CPO_CONCAT) == NULL)) { + if (line != NULL && do_concat && (vim_strchr(p_cpo, CPO_CONCAT) == NULL)) { // compensate for the one line read-ahead sourcing_lnum--; diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h index 42ba1060e9..3a9fd01dd9 100644 --- a/src/nvim/ex_cmds_defs.h +++ b/src/nvim/ex_cmds_defs.h @@ -88,7 +88,7 @@ typedef struct exarg exarg_T; typedef void (*ex_func_T)(exarg_T *eap); -typedef char_u *(*LineGetter)(int, void *, int); +typedef char_u *(*LineGetter)(int, void *, int, bool); /// Structure for command definition. typedef struct cmdname { diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 8d67ab5348..0da2cd67d6 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -117,11 +117,11 @@ typedef struct { * reads more lines that may come from the while/for loop. */ struct loop_cookie { - garray_T *lines_gap; /* growarray with line info */ - int current_line; /* last read line from growarray */ - int repeating; /* TRUE when looping a second time */ - /* When "repeating" is FALSE use "getline" and "cookie" to get lines */ - char_u *(*getline)(int, void *, int); + garray_T *lines_gap; // growarray with line info + int current_line; // last read line from growarray + int repeating; // TRUE when looping a second time + // When "repeating" is FALSE use "getline" and "cookie" to get lines + char_u *(*getline)(int, void *, int, bool); void *cookie; }; @@ -313,8 +313,8 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, struct msglist **saved_msg_list = NULL; struct msglist *private_msg_list; - /* "fgetline" and "cookie" passed to do_one_cmd() */ - char_u *(*cmd_getline)(int, void *, int); + // "fgetline" and "cookie" passed to do_one_cmd() + char_u *(*cmd_getline)(int, void *, int, bool); void *cmd_cookie; struct loop_cookie cmd_loop_cookie; void *real_cookie; @@ -507,17 +507,20 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, * Need to set msg_didout for the first line after an ":if", * otherwise the ":if" will be overwritten. */ - if (count == 1 && getline_equal(fgetline, cookie, getexline)) - msg_didout = TRUE; - if (fgetline == NULL || (next_cmdline = fgetline(':', cookie, - cstack.cs_idx < - 0 ? 0 : (cstack.cs_idx + 1) * 2 - )) == NULL) { - /* Don't call wait_return for aborted command line. The NULL - * returned for the end of a sourced file or executed function - * doesn't do this. */ - if (KeyTyped && !(flags & DOCMD_REPEAT)) - need_wait_return = FALSE; + if (count == 1 && getline_equal(fgetline, cookie, getexline)) { + msg_didout = true; + } + if (fgetline == NULL + || (next_cmdline = fgetline(':', cookie, + cstack.cs_idx < + 0 ? 0 : (cstack.cs_idx + 1) * 2, + true)) == NULL) { + // Don't call wait_return for aborted command line. The NULL + // returned for the end of a sourced file or executed function + // doesn't do this. + if (KeyTyped && !(flags & DOCMD_REPEAT)) { + need_wait_return = false; + } retval = FAIL; break; } @@ -951,7 +954,7 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, /* * Obtain a line when inside a ":while" or ":for" loop. */ -static char_u *get_loop_line(int c, void *cookie, int indent) +static char_u *get_loop_line(int c, void *cookie, int indent, bool do_concat) { struct loop_cookie *cp = (struct loop_cookie *)cookie; wcmd_T *wp; @@ -961,11 +964,12 @@ static char_u *get_loop_line(int c, void *cookie, int indent) if (cp->repeating) return NULL; /* trying to read past ":endwhile"/":endfor" */ - /* First time inside the ":while"/":for": get line normally. */ - if (cp->getline == NULL) - line = getcmdline(c, 0L, indent); - else - line = cp->getline(c, cp->cookie, indent); + // First time inside the ":while"/":for": get line normally. + if (cp->getline == NULL) { + line = getcmdline(c, 0L, indent, do_concat); + } else { + line = cp->getline(c, cp->cookie, indent, do_concat); + } if (line != NULL) { store_loop_line(cp->lines_gap, line); ++cp->current_line; diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index d0af8a0fdf..5235b9e648 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1991,7 +1991,8 @@ char_u * getcmdline ( int firstc, long count, // only used for incremental search - int indent // indent for inside conditionals + int indent, // indent for inside conditionals + bool do_concat // unused ) { // Be prepared for situations where cmdline can be invoked recursively. @@ -2167,17 +2168,18 @@ static void correct_screencol(int idx, int cells, int *col) * Get an Ex command line for the ":" command. */ char_u * -getexline ( - int c, /* normally ':', NUL for ":append" */ +getexline( + int c, // normally ':', NUL for ":append" void *cookie, - int indent /* indent for inside conditionals */ + int indent, // indent for inside conditionals + bool do_concat ) { /* When executing a register, remove ':' that's in front of each line. */ if (exec_from_reg && vpeekc() == ':') (void)vgetc(); - return getcmdline(c, 1L, indent); + return getcmdline(c, 1L, indent, do_concat); } /* @@ -2187,11 +2189,12 @@ getexline ( * Returns a string in allocated memory or NULL. */ char_u * -getexmodeline ( - int promptc, /* normally ':', NUL for ":append" and '?' for - :s prompt */ +getexmodeline( + int promptc, // normally ':', NUL for ":append" and '?' + // for :s prompt void *cookie, - int indent /* indent for inside conditionals */ + int indent, // indent for inside conditionals + bool do_concat ) { garray_T line_ga; @@ -6308,7 +6311,7 @@ char *script_get(exarg_T *const eap, size_t *const lenp) for (;;) { char *const theline = (char *)eap->getline( eap->cstack->cs_looplevel > 0 ? -1 : - NUL, eap->cookie, 0); + NUL, eap->cookie, 0, true); if (theline == NULL || strcmp(end_pattern, theline) == 0) { xfree(theline); diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 0394639a16..58e6b2ae92 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -7100,12 +7100,10 @@ auto_next_pat( } } -/* - * Get next autocommand command. - * Called by do_cmdline() to get the next line for ":if". - * Returns allocated string, or NULL for end of autocommands. - */ -char_u *getnextac(int c, void *cookie, int indent) +/// Get next autocommand command. +/// Called by do_cmdline() to get the next line for ":if". +/// @return allocated string, or NULL for end of autocommands. +char_u *getnextac(int c, void *cookie, int indent, bool do_concat) { AutoPatCmd *acp = (AutoPatCmd *)cookie; char_u *retval; diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 1f82df3241..399f0671b4 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -4419,7 +4419,7 @@ mapblock_T *get_maphash(int index, buf_T *buf) } /// Get command argument for key -char_u * getcmdkeycmd(int promptc, void *cookie, int indent) +char_u * getcmdkeycmd(int promptc, void *cookie, int indent, bool do_concat) { garray_T line_ga; int c1 = -1, c2; diff --git a/src/nvim/normal.c b/src/nvim/normal.c index e32b738c7e..e0dc9d4f23 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -5343,7 +5343,7 @@ static void nv_search(cmdarg_T *cap) // When using 'incsearch' the cursor may be moved to set a different search // start position. - cap->searchbuf = getcmdline(cap->cmdchar, cap->count1, 0); + cap->searchbuf = getcmdline(cap->cmdchar, cap->count1, 0, true); if (cap->searchbuf == NULL) { clearop(oap); diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 6f515151d6..0d27365d2b 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -671,13 +671,15 @@ int get_expr_register(void) { char_u *new_line; - new_line = getcmdline('=', 0L, 0); - if (new_line == NULL) + new_line = getcmdline('=', 0L, 0, true); + if (new_line == NULL) { return NUL; - if (*new_line == NUL) /* use previous line */ + } + if (*new_line == NUL) { // use previous line xfree(new_line); - else + } else { set_expr_line(new_line); + } return '='; }