diff options
-rw-r--r-- | runtime/doc/cmdline.txt | 16 | ||||
-rw-r--r-- | src/debugger.c | 6 | ||||
-rw-r--r-- | src/ex_docmd.c | 11 | ||||
-rw-r--r-- | src/ex_eval.c | 4 | ||||
-rw-r--r-- | src/message.c | 2 | ||||
-rw-r--r-- | src/proto/scriptfile.pro | 2 | ||||
-rw-r--r-- | src/scriptfile.c | 70 | ||||
-rw-r--r-- | src/testdir/test_expand_func.vim | 56 | ||||
-rw-r--r-- | src/testing.c | 2 | ||||
-rw-r--r-- | src/version.c | 2 |
10 files changed, 102 insertions, 69 deletions
diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index ecaa73e89..8e4e2a018 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -876,7 +876,7 @@ Also see |`=|. *:<cword>* *<cword>* *:<cWORD>* *<cWORD>* *:<cexpr>* *<cexpr>* *:<cfile>* *<cfile>* *:<afile>* *<afile>* *:<abuf>* *<abuf>* - *:<amatch>* *<amatch>* + *:<amatch>* *<amatch>* *:<stack>* *<stack>* *:<sfile>* *<sfile>* *:<slnum>* *<slnum>* *:<sflnum>* *<sflnum>* *E499* *E500* Note: these are typed literally, they are not special keys! @@ -903,12 +903,16 @@ Note: these are typed literally, they are not special keys! events). <sfile> When executing a ":source" command, is replaced with the file name of the sourced file. *E498* - When executing a function, is replaced with: - "function {function-name}[{lnum}]" - function call nesting is indicated like this: - "function {function-name1}[{lnum}]..{function-name2}[{lnum}]" + When executing a function, is replaced with the call stack, + as with <stack> (this is for backwards compatibility, using + <stack> is preferred). Note that filename-modifiers are useless when <sfile> is - used inside a function. + not used inside a script. + <stack> is replaced with the call stack, using + "function {function-name}[{lnum}]" for a function line + and "script {file-name}[{lnum}]" for a script line, and + ".." in between items. E.g.: + "function {function-name1}[{lnum}]..{function-name2}[{lnum}]" <slnum> When executing a ":source" command, is replaced with the line number. *E842* When executing a function it's the line number relative to diff --git a/src/debugger.c b/src/debugger.c index 91ab5ee1f..00fb9c8f8 100644 --- a/src/debugger.c +++ b/src/debugger.c @@ -105,7 +105,7 @@ do_debug(char_u *cmd) vim_free(debug_newval); debug_newval = NULL; } - sname = estack_sfile(); + sname = estack_sfile(FALSE); if (sname != NULL) msg((char *)sname); vim_free(sname); @@ -344,7 +344,7 @@ do_checkbacktracelevel(void) } else { - char_u *sname = estack_sfile(); + char_u *sname = estack_sfile(FALSE); int max = get_maxbacktrace_level(sname); if (debug_backtrace_level > max) @@ -365,7 +365,7 @@ do_showbacktrace(char_u *cmd) int i = 0; int max; - sname = estack_sfile(); + sname = estack_sfile(FALSE); max = get_maxbacktrace_level(sname); if (sname != NULL) { diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 04c3b465a..987e92dea 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -8268,8 +8268,10 @@ find_cmdline_var(char_u *src, int *usedlen) #define SPEC_SFILE (SPEC_CFILE + 1) "<slnum>", // ":so" file line number #define SPEC_SLNUM (SPEC_SFILE + 1) + "<stack>", // call stack +#define SPEC_STACK (SPEC_SLNUM + 1) "<afile>", // autocommand file name -#define SPEC_AFILE (SPEC_SLNUM + 1) +#define SPEC_AFILE (SPEC_STACK + 1) "<abuf>", // autocommand buffer number #define SPEC_ABUF (SPEC_AFILE + 1) "<amatch>", // autocommand match name @@ -8520,10 +8522,13 @@ eval_vars( break; case SPEC_SFILE: // file name for ":so" command - result = estack_sfile(); + case SPEC_STACK: // call stack + result = estack_sfile(spec_idx == SPEC_SFILE); if (result == NULL) { - *errormsg = _("E498: no :source file name to substitute for \"<sfile>\""); + *errormsg = spec_idx == SPEC_SFILE + ? _("E498: no :source file name to substitute for \"<sfile>\"") + : _("E489: no call stack to substitute for \"<stack>\""); return NULL; } resultbuf = result; // remember allocated string diff --git a/src/ex_eval.c b/src/ex_eval.c index f0ffaffdd..58088a070 100644 --- a/src/ex_eval.c +++ b/src/ex_eval.c @@ -290,7 +290,7 @@ cause_errthrow( // Get the source name and lnum now, it may change before // reaching do_errthrow(). - elem->sfile = estack_sfile(); + elem->sfile = estack_sfile(FALSE); elem->slnum = SOURCING_LNUM; } } @@ -549,7 +549,7 @@ throw_exception(void *value, except_type_T type, char_u *cmdname) } else { - excp->throw_name = estack_sfile(); + excp->throw_name = estack_sfile(FALSE); if (excp->throw_name == NULL) excp->throw_name = vim_strsave((char_u *)""); if (excp->throw_name == NULL) diff --git a/src/message.c b/src/message.c index 76ec45679..91b2fe237 100644 --- a/src/message.c +++ b/src/message.c @@ -461,7 +461,7 @@ get_emsg_source(void) if (SOURCING_NAME != NULL && other_sourcing_name()) { - char_u *sname = estack_sfile(); + char_u *sname = estack_sfile(FALSE); char_u *tofree = sname; if (sname == NULL) diff --git a/src/proto/scriptfile.pro b/src/proto/scriptfile.pro index fd4c10473..00f1301ee 100644 --- a/src/proto/scriptfile.pro +++ b/src/proto/scriptfile.pro @@ -4,7 +4,7 @@ estack_T *estack_push(etype_T type, char_u *name, long lnum); estack_T *estack_push_ufunc(ufunc_T *ufunc, long lnum); int estack_top_is_ufunc(ufunc_T *ufunc, long lnum); estack_T *estack_pop(void); -char_u *estack_sfile(void); +char_u *estack_sfile(int is_sfile); void ex_runtime(exarg_T *eap); int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie); int do_in_runtimepath(char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie); diff --git a/src/scriptfile.c b/src/scriptfile.c index ce269a1cd..ce9c15d31 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -111,58 +111,68 @@ estack_pop(void) /* * Get the current value for <sfile> in allocated memory. + * "is_sfile" is TRUE for <sfile> itself. */ char_u * -estack_sfile(void) +estack_sfile(int is_sfile) { estack_T *entry; #ifdef FEAT_EVAL + garray_T ga; size_t len; int idx; - char *res; - size_t done; + etype_T last_type = ETYPE_SCRIPT; + char *type_name; #endif entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1; - if (entry->es_name == NULL) - return NULL; #ifdef FEAT_EVAL - if (entry->es_info.ufunc == NULL) + if (is_sfile && entry->es_type != ETYPE_UFUNC) #endif + { + if (entry->es_name == NULL) + return NULL; return vim_strsave(entry->es_name); - + } #ifdef FEAT_EVAL + // Give information about each stack entry up to the root. // For a function we compose the call stack, as it was done in the past: // "function One[123]..Two[456]..Three" - len = STRLEN(entry->es_name) + 10; - for (idx = exestack.ga_len - 2; idx >= 0; --idx) + ga_init2(&ga, sizeof(char), 100); + for (idx = 0; idx < exestack.ga_len; ++idx) { entry = ((estack_T *)exestack.ga_data) + idx; - if (entry->es_name == NULL || entry->es_info.ufunc == NULL) + if (entry->es_name != NULL) { - ++idx; - break; + len = STRLEN(entry->es_name) + 15; + type_name = ""; + if (entry->es_type != last_type) + { + switch (entry->es_type) + { + case ETYPE_SCRIPT: type_name = "script "; break; + case ETYPE_UFUNC: type_name = "function "; break; + default: type_name = ""; break; + } + last_type = entry->es_type; + } + len += STRLEN(type_name); + if (ga_grow(&ga, len) == FAIL) + break; + if (idx == exestack.ga_len - 1 || entry->es_lnum == 0) + // For the bottom entry: do not add the line number, it is used + // in <slnum>. Also leave it out when the number is not set. + vim_snprintf(ga.ga_data + ga.ga_len, len, "%s%s%s", + type_name, entry->es_name, + idx == exestack.ga_len - 1 ? "" : ".."); + else + vim_snprintf(ga.ga_data + ga.ga_len, len, "%s%s[%ld]..", + type_name, entry->es_name, entry->es_lnum); + ga.ga_len += STRLEN(ga.ga_data + ga.ga_len); } - len += STRLEN(entry->es_name) + 15; } - res = (char *)alloc((int)len); - if (res != NULL) - { - STRCPY(res, "function "); - while (idx < exestack.ga_len - 1) - { - done = STRLEN(res); - entry = ((estack_T *)exestack.ga_data) + idx; - vim_snprintf(res + done, len - done, "%s[%ld]..", - entry->es_name, entry->es_lnum); - ++idx; - } - done = STRLEN(res); - entry = ((estack_T *)exestack.ga_data) + idx; - vim_snprintf(res + done, len - done, "%s", entry->es_name); - } - return (char_u *)res; + return (char_u *)ga.ga_data; #endif } diff --git a/src/testdir/test_expand_func.vim b/src/testdir/test_expand_func.vim index 18437b758..41673e50a 100644 --- a/src/testdir/test_expand_func.vim +++ b/src/testdir/test_expand_func.vim @@ -16,17 +16,47 @@ func s:expand_sflnum() return str2nr(expand('<sflnum>')) endfunc -func Test_expand_sfile() +" This test depends on the location in the test file, put it first. +func Test_expand_sflnum() + call assert_equal(5, s:sflnum) + call assert_equal(22, str2nr(expand('<sflnum>'))) + + " Line-continuation + call assert_equal( + \ 25, + \ str2nr(expand('<sflnum>'))) + + " Call in script-local function + call assert_equal(16, s:expand_sflnum()) + + " Call in command + command Flnum echo expand('<sflnum>') + call assert_equal(34, str2nr(trim(execute('Flnum')))) + delcommand Flnum +endfunc + +func Test_expand_sfile_and_stack() call assert_match('test_expand_func\.vim$', s:sfile) - call assert_match('^function .*\.\.Test_expand_sfile$', expand('<sfile>')) + let expected = 'script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack$' + call assert_match(expected , expand('<sfile>')) + call assert_match(expected , expand('<stack>')) " Call in script-local function - call assert_match('^function .*\.\.Test_expand_sfile\[5\]\.\.<SNR>\d\+_expand_sfile$', s:expand_sfile()) + call assert_match('script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack\[7\]\.\.<SNR>\d\+_expand_sfile$', s:expand_sfile()) " Call in command command Sfile echo expand('<sfile>') - call assert_match('^function .*\.\.Test_expand_sfile$', trim(execute('Sfile'))) + call assert_match('script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack$', trim(execute('Sfile'))) delcommand Sfile + + " Use <stack> from sourced script. + let lines =<< trim END + let g:stack_value = expand('<stack>') + END + call writefile(lines, 'Xstack') + source Xstack + call assert_match('\<Xstack$', g:stack_value) + call delete('Xstack') endfunc func Test_expand_slnum() @@ -47,24 +77,6 @@ func Test_expand_slnum() delcommand Slnum endfunc -func Test_expand_sflnum() - call assert_equal(5, s:sflnum) - call assert_equal(52, str2nr(expand('<sflnum>'))) - - " Line-continuation - call assert_equal( - \ 55, - \ str2nr(expand('<sflnum>'))) - - " Call in script-local function - call assert_equal(16, s:expand_sflnum()) - - " Call in command - command Flnum echo expand('<sflnum>') - call assert_equal(64, str2nr(trim(execute('Flnum')))) - delcommand Flnum -endfunc - func Test_expand() new call assert_equal("", expand('%:S')) diff --git a/src/testing.c b/src/testing.c index de89bd9fd..137d5fe9f 100644 --- a/src/testing.c +++ b/src/testing.c @@ -22,7 +22,7 @@ prepare_assert_error(garray_T *gap) { char buf[NUMBUFLEN]; - char_u *sname = estack_sfile(); + char_u *sname = estack_sfile(FALSE); ga_init2(gap, 1, 100); if (sname != NULL) diff --git a/src/version.c b/src/version.c index 6a5f19951..c45c15519 100644 --- a/src/version.c +++ b/src/version.c @@ -755,6 +755,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1297, +/**/ 1296, /**/ 1295, |