mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:8.1.1625: script line numbers are not exactly right
Problem: Script line numbers are not exactly right.
Solution: Handle heredoc and continuation lines better. (Ozaki Kiichi,
closes vim/vim#4611, closes vim/vim#4511)
bc2cfe4672
This commit is contained in:
parent
6c012b0624
commit
fcc24d0df3
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user