diff options
-rw-r--r-- | src/nvim/eval.c | 26 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.c | 21 | ||||
-rw-r--r-- | src/nvim/testdir/test_vimscript.vim | 70 |
3 files changed, 102 insertions, 15 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index bedfe2d6d0..d314e3a732 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -21301,7 +21301,8 @@ void ex_function(exarg_T *eap) hashtab_T *ht; int todo; hashitem_T *hi; - int sourcing_lnum_off; + linenr_T sourcing_lnum_off; + linenr_T sourcing_lnum_top; bool show_block = false; bool do_concat = true; @@ -21550,15 +21551,17 @@ void ex_function(exarg_T *eap) cmdline_row = msg_row; } + // Save the starting line number. + sourcing_lnum_top = sourcing_lnum; + indent = 2; nesting = 0; for (;; ) { if (KeyTyped) { - msg_scroll = TRUE; - saved_wait_return = FALSE; + msg_scroll = true; + saved_wait_return = false; } - need_wait_return = FALSE; - sourcing_lnum_off = sourcing_lnum; + need_wait_return = false; if (line_arg != NULL) { /* Use eap->arg, split up in parts by line breaks. */ @@ -21591,11 +21594,13 @@ void ex_function(exarg_T *eap) ui_ext_cmdline_block_append((size_t)indent, (const char *)theline); } - /* Detect line continuation: sourcing_lnum increased more than one. */ - if (sourcing_lnum > sourcing_lnum_off + 1) - sourcing_lnum_off = sourcing_lnum - sourcing_lnum_off - 1; - else + // Detect line continuation: sourcing_lnum increased more than one. + sourcing_lnum_off = get_sourced_lnum(eap->getline, eap->cookie); + if (sourcing_lnum < sourcing_lnum_off) { + sourcing_lnum_off -= sourcing_lnum; + } else { sourcing_lnum_off = 0; + } if (skip_until != NULL) { // Between ":append" and "." and between ":python <<EOF" and "EOF" @@ -21896,7 +21901,8 @@ void ex_function(exarg_T *eap) fp->uf_flags = flags; fp->uf_calls = 0; fp->uf_script_ctx = current_sctx; - fp->uf_script_ctx.sc_lnum += sourcing_lnum - newlines.ga_len - 1; + fp->uf_script_ctx.sc_lnum += sourcing_lnum_top; + goto ret_free; erret: diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 272c81e29b..84291b3637 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -97,10 +97,11 @@ typedef struct sn_prl_S { struct source_cookie { FILE *fp; ///< opened file for sourcing char_u *nextline; ///< if not NULL: line that was read ahead + linenr_T sourcing_lnum; ///< line number of the source file int finished; ///< ":finish" used #if defined(USE_CRNL) int fileformat; ///< EOL_UNKNOWN, EOL_UNIX or EOL_DOS - bool error; ///< true if LF found after CR-LF + bool error; ///< true if LF found after CR-LF #endif linenr_T breakpoint; ///< next line with breakpoint or zero char_u *fname; ///< name of sourced file @@ -3124,6 +3125,7 @@ int do_source(char_u *fname, int check_other, int is_vimrc) #endif cookie.nextline = NULL; + cookie.sourcing_lnum = 0; cookie.finished = false; // Check if this script has a breakpoint. @@ -3375,6 +3377,13 @@ void free_scriptnames(void) } # endif +linenr_T get_sourced_lnum(LineGetter fgetline, void *cookie) +{ + return fgetline == getsourceline + ? ((struct source_cookie *)cookie)->sourcing_lnum + : sourcing_lnum; +} + /// Get one full line from a sourced file. /// Called by do_cmdline() when it's called from do_source(). @@ -3395,6 +3404,8 @@ char_u *getsourceline(int c, void *cookie, int indent, bool do_concat) if (do_profiling == PROF_YES) { script_line_end(); } + // Set the current sourcing line number. + sourcing_lnum = sp->sourcing_lnum + 1; // Get current line. If there is a read-ahead line, use it, otherwise get // one now. if (sp->finished) { @@ -3404,7 +3415,7 @@ char_u *getsourceline(int c, void *cookie, int indent, bool do_concat) } else { line = sp->nextline; sp->nextline = NULL; - sourcing_lnum++; + sp->sourcing_lnum++; } if (line != NULL && do_profiling == PROF_YES) { script_line_start(); @@ -3414,7 +3425,7 @@ char_u *getsourceline(int c, void *cookie, int indent, bool do_concat) // contain the 'C' flag. if (line != NULL && do_concat && (vim_strchr(p_cpo, CPO_CONCAT) == NULL)) { // compensate for the one line read-ahead - sourcing_lnum--; + sp->sourcing_lnum--; // Get the next line and concatenate it when it starts with a // backslash. We always need to read the next line, keep it in @@ -3492,7 +3503,7 @@ static char_u *get_one_sourceline(struct source_cookie *sp) ga_init(&ga, 1, 250); // Loop until there is a finished line (or end-of-file). - sourcing_lnum++; + sp->sourcing_lnum++; for (;; ) { // make room to read at least 120 (more) characters ga_grow(&ga, 120); @@ -3559,7 +3570,7 @@ retry: // len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--) {} if ((len & 1) != (c & 1)) { // escaped NL, read more - sourcing_lnum++; + sp->sourcing_lnum++; continue; } diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim index f39e53d6dd..3fcba4134e 100644 --- a/src/nvim/testdir/test_vimscript.vim +++ b/src/nvim/testdir/test_vimscript.vim @@ -1409,6 +1409,76 @@ func Test_compound_assignment_operators() let @/ = '' endfunc +func Test_function_defined_line() + if has('gui_running') + " Can't catch the output of gvim. + return + endif + + let lines =<< trim [CODE] + " F1 + func F1() + " F2 + func F2() + " + " + " + return + endfunc + " F3 + execute "func F3()\n\n\n\nreturn\nendfunc" + " F4 + execute "func F4()\n + \\n + \\n + \\n + \return\n + \endfunc" + endfunc + " F5 + execute "func F5()\n\n\n\nreturn\nendfunc" + " F6 + execute "func F6()\n + \\n + \\n + \\n + \return\n + \endfunc" + call F1() + verbose func F1 + verbose func F2 + verbose func F3 + verbose func F4 + verbose func F5 + verbose func F6 + qall! + [CODE] + + call writefile(lines, 'Xtest.vim') + let res = system(v:progpath .. ' --clean -es -X -S Xtest.vim') + call assert_equal(0, v:shell_error) + + let m = matchstr(res, 'function F1()[^[:print:]]*[[:print:]]*') + call assert_match(' line 2$', m) + + let m = matchstr(res, 'function F2()[^[:print:]]*[[:print:]]*') + call assert_match(' line 4$', m) + + let m = matchstr(res, 'function F3()[^[:print:]]*[[:print:]]*') + call assert_match(' line 11$', m) + + let m = matchstr(res, 'function F4()[^[:print:]]*[[:print:]]*') + call assert_match(' line 13$', m) + + let m = matchstr(res, 'function F5()[^[:print:]]*[[:print:]]*') + call assert_match(' line 21$', m) + + let m = matchstr(res, 'function F6()[^[:print:]]*[[:print:]]*') + call assert_match(' line 23$', m) + + call delete('Xtest.vim') +endfunc + "------------------------------------------------------------------------------- " Modelines {{{1 " vim: ts=8 sw=4 tw=80 fdm=marker |