From 98ab0bb5f7d2138be0b6019769e237e42aafad1a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 14 Aug 2022 06:32:00 +0800 Subject: [PATCH 1/4] vim-patch:8.2.1297: when a test fails it's often not easy to see where Problem: When a test fails it's often not easy to see what the call stack is. Solution: Add more entries from the call stack in the exception message. https://github.com/vim/vim/commit/a5d0423fa16f18b4576a2a07e50034e489587a7d Use docs from latest Vim. --- runtime/doc/builtin.txt | 1 + runtime/doc/cmdline.txt | 16 ++++--- src/nvim/debugger.c | 6 +-- src/nvim/ex_docmd.c | 7 ++- src/nvim/ex_eval.c | 4 +- src/nvim/message.c | 2 +- src/nvim/runtime.c | 63 ++++++++++++++++----------- src/nvim/testdir/test_expand_func.vim | 19 ++++++-- src/nvim/testing.c | 2 +- 9 files changed, 77 insertions(+), 43 deletions(-) diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 291eea7263..0fc8a30c20 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -2010,6 +2010,7 @@ expand({string} [, {nosuf} [, {list}]]) *expand()* a function "123_" where "123" is the current script ID || + call stack word under the cursor WORD under the cursor the {clientid} of the last received diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index 87f1589ea1..29eff75bfa 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -879,12 +879,18 @@ Note: these are typed literally, they are not special keys! *:* ** 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 (this is for backwards compatibility, using + is preferred). Note that filename-modifiers are useless when is - used inside a function. + not used inside a script. + *:* ** + 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}]" + If there is no call stack you get error *E489* . *:* ** When executing a `:source` command, is replaced with the line number. *E842* diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c index 76e1caff49..663f4feb08 100644 --- a/src/nvim/debugger.c +++ b/src/nvim/debugger.c @@ -99,7 +99,7 @@ void do_debug(char_u *cmd) xfree(debug_newval); debug_newval = NULL; } - char *sname = estack_sfile(); + char *sname = estack_sfile(false); if (sname != NULL) { msg(sname); } @@ -324,7 +324,7 @@ static void do_checkbacktracelevel(void) debug_backtrace_level = 0; msg(_("frame is zero")); } else { - char *sname = estack_sfile(); + char *sname = estack_sfile(false); int max = get_maxbacktrace_level(sname); if (debug_backtrace_level > max) { @@ -337,7 +337,7 @@ static void do_checkbacktracelevel(void) static void do_showbacktrace(char_u *cmd) { - char *sname = estack_sfile(); + char *sname = estack_sfile(false); int max = get_maxbacktrace_level(sname); if (sname != NULL) { int i = 0; diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 5ea6a224d6..34768f62a9 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -7912,9 +7912,12 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum 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 \"\""); + *errormsg = spec_idx == SPEC_SFILE + ? _("E498: no :source file name to substitute for \"\"") + : _("E489: no call stack to substitute for \"\""); return NULL; } resultbuf = result; // remember allocated string diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index 66c782d12e..61456acc2a 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -278,7 +278,7 @@ bool cause_errthrow(const char *mesg, bool severe, bool *ignore) // 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; } return true; @@ -490,7 +490,7 @@ static int throw_exception(void *value, except_type_T type, char *cmdname) entry->sfile = NULL; excp->throw_lnum = entry->slnum; } else { - excp->throw_name = estack_sfile(); + excp->throw_name = estack_sfile(false); if (excp->throw_name == NULL) { excp->throw_name = xstrdup(""); } diff --git a/src/nvim/message.c b/src/nvim/message.c index c97e68207b..62827ffabc 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -555,7 +555,7 @@ static char *get_emsg_source(void) FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT { if (SOURCING_NAME != NULL && other_sourcing_name()) { - char *sname = estack_sfile(); + char *sname = estack_sfile(false); char *tofree = sname; if (sname == NULL) { diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 8299f8ec45..1cafd22b0a 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -100,42 +100,55 @@ void estack_pop(void) } /// Get the current value for in allocated memory. -char *estack_sfile(void) +/// @param is_sfile true for itself. +char *estack_sfile(bool is_sfile) { estack_T *entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1; - if (entry->es_name == NULL) { - return NULL; - } - if (entry->es_info.ufunc == NULL) { + if (is_sfile && entry->es_type != ETYPE_UFUNC) { + if (entry->es_name == NULL) { + return NULL; + } return xstrdup(entry->es_name); } + // 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" - size_t len = STRLEN(entry->es_name) + 10; - int idx; - for (idx = exestack.ga_len - 2; idx >= 0; idx--) { + garray_T ga; + ga_init(&ga, sizeof(char), 100); + etype_T last_type = ETYPE_SCRIPT; + for (int idx = 0; idx < exestack.ga_len; idx++) { entry = ((estack_T *)exestack.ga_data) + idx; - if (entry->es_name == NULL || entry->es_info.ufunc == NULL) { - idx++; - break; + if (entry->es_name != NULL) { + size_t len = strlen(entry->es_name) + 15; + char *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); + ga_grow(&ga, (int)len); + if (idx == exestack.ga_len - 1 || entry->es_lnum == 0) { + // For the bottom entry: do not add the line number, it is used + // in . Also leave it out when the number is not set. + vim_snprintf((char *)ga.ga_data + ga.ga_len, len, "%s%s%s", + type_name, entry->es_name, idx == exestack.ga_len - 1 ? "" : ".."); + } else { + vim_snprintf((char *)ga.ga_data + ga.ga_len, len, "%s%s[%" PRIdLINENR "]..", + type_name, entry->es_name, entry->es_lnum); + } + ga.ga_len += (int)strlen((char *)ga.ga_data + ga.ga_len); } - len += STRLEN(entry->es_name) + 15; } - char *res = (char *)xmalloc(len); - STRCPY(res, "function "); - size_t done; - while (idx < exestack.ga_len - 1) { - done = STRLEN(res); - entry = ((estack_T *)exestack.ga_data) + idx; - vim_snprintf(res + done, len - done, "%s[%" PRIdLINENR "]..", 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 res; + return (char *)ga.ga_data; } static bool runtime_search_path_valid = false; diff --git a/src/nvim/testdir/test_expand_func.vim b/src/nvim/testdir/test_expand_func.vim index b48c2e8a19..388620f87e 100644 --- a/src/nvim/testdir/test_expand_func.vim +++ b/src/nvim/testdir/test_expand_func.vim @@ -37,17 +37,28 @@ func Test_expand_sflnum() delcommand Flnum endfunc -func Test_expand_sfile() +func Test_expand_sfile_and_stack() call assert_match('test_expand_func\.vim$', s:sfile) - call assert_match('^function .*\.\.Test_expand_sfile$', expand('')) + let expected = 'script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack$' + call assert_match(expected , expand('')) + call assert_match(expected , expand('')) " Call in script-local function - call assert_match('^function .*\.\.Test_expand_sfile\[5\]\.\.\d\+_expand_sfile$', s:expand_sfile()) + call assert_match('script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack\[7\]\.\.\d\+_expand_sfile$', s:expand_sfile()) " Call in command command Sfile echo expand('') - 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 from sourced script. + let lines =<< trim END + let g:stack_value = expand('') + END + call writefile(lines, 'Xstack') + source Xstack + call assert_match('\ Date: Sun, 14 Aug 2022 07:07:32 +0800 Subject: [PATCH 2/4] vim-patch:8.2.1653: expand('') does not include the final line number Problem: Expand('') does not include the final line number. Solution: Add the line nuber. (closes vim/vim#6927) https://github.com/vim/vim/commit/4f25b1aba050b85fa97ca2316aa04dd4b0b22530 --- src/nvim/debugger.c | 6 +++--- src/nvim/ex_docmd.c | 3 ++- src/nvim/ex_eval.c | 4 ++-- src/nvim/message.c | 2 +- src/nvim/runtime.c | 21 ++++++++++++++------- src/nvim/runtime.h | 7 +++++++ src/nvim/testdir/test_expand_func.vim | 9 +++++---- src/nvim/testing.c | 2 +- 8 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c index 663f4feb08..72d776d1e4 100644 --- a/src/nvim/debugger.c +++ b/src/nvim/debugger.c @@ -99,7 +99,7 @@ void do_debug(char_u *cmd) xfree(debug_newval); debug_newval = NULL; } - char *sname = estack_sfile(false); + char *sname = estack_sfile(ESTACK_NONE); if (sname != NULL) { msg(sname); } @@ -324,7 +324,7 @@ static void do_checkbacktracelevel(void) debug_backtrace_level = 0; msg(_("frame is zero")); } else { - char *sname = estack_sfile(false); + char *sname = estack_sfile(ESTACK_NONE); int max = get_maxbacktrace_level(sname); if (debug_backtrace_level > max) { @@ -337,7 +337,7 @@ static void do_checkbacktracelevel(void) static void do_showbacktrace(char_u *cmd) { - char *sname = estack_sfile(false); + char *sname = estack_sfile(ESTACK_NONE); int max = get_maxbacktrace_level(sname); if (sname != NULL) { int i = 0; diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 34768f62a9..de62d90610 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -7719,6 +7719,7 @@ ssize_t find_cmdline_var(const char_u *src, size_t *usedlen) /// '' to C-expression under the cursor /// '' to path name under the cursor /// '' to sourced file name +/// '' to call stack /// '' to sourced file line number /// '' to file name for autocommand /// '' to buffer number for autocommand @@ -7913,7 +7914,7 @@ char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnum case SPEC_SFILE: // file name for ":so" command case SPEC_STACK: // call stack - result = estack_sfile(spec_idx == SPEC_SFILE); + result = estack_sfile(spec_idx == SPEC_SFILE ? ESTACK_SFILE : ESTACK_STACK); if (result == NULL) { *errormsg = spec_idx == SPEC_SFILE ? _("E498: no :source file name to substitute for \"\"") diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index 61456acc2a..c39bb16498 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -278,7 +278,7 @@ bool cause_errthrow(const char *mesg, bool severe, bool *ignore) // Get the source name and lnum now, it may change before // reaching do_errthrow(). - elem->sfile = estack_sfile(false); + elem->sfile = estack_sfile(ESTACK_NONE); elem->slnum = SOURCING_LNUM; } return true; @@ -490,7 +490,7 @@ static int throw_exception(void *value, except_type_T type, char *cmdname) entry->sfile = NULL; excp->throw_lnum = entry->slnum; } else { - excp->throw_name = estack_sfile(false); + excp->throw_name = estack_sfile(ESTACK_NONE); if (excp->throw_name == NULL) { excp->throw_name = xstrdup(""); } diff --git a/src/nvim/message.c b/src/nvim/message.c index 62827ffabc..6910fc16ae 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -555,7 +555,7 @@ static char *get_emsg_source(void) FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT { if (SOURCING_NAME != NULL && other_sourcing_name()) { - char *sname = estack_sfile(false); + char *sname = estack_sfile(ESTACK_NONE); char *tofree = sname; if (sname == NULL) { diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 1cafd22b0a..fba3dce92d 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -100,11 +100,11 @@ void estack_pop(void) } /// Get the current value for in allocated memory. -/// @param is_sfile true for itself. -char *estack_sfile(bool is_sfile) +/// @param which ESTACK_SFILE for and ESTACK_STACK for . +char *estack_sfile(estack_arg_T which) { estack_T *entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1; - if (is_sfile && entry->es_type != ETYPE_UFUNC) { + if (which == ESTACK_SFILE && entry->es_type != ETYPE_UFUNC) { if (entry->es_name == NULL) { return NULL; } @@ -135,14 +135,21 @@ char *estack_sfile(bool is_sfile) } len += strlen(type_name); ga_grow(&ga, (int)len); - if (idx == exestack.ga_len - 1 || entry->es_lnum == 0) { - // For the bottom entry: do not add the line number, it is used - // in . Also leave it out when the number is not set. + linenr_T lnum = 0; + if (idx == exestack.ga_len - 1) { + lnum = which == ESTACK_STACK ? SOURCING_LNUM : 0; + } else { + lnum = entry->es_lnum; + } + if (lnum == 0) { + // For the bottom entry of : do not add the line number, + // it is used in . Also leave it out when the number is + // not set. vim_snprintf((char *)ga.ga_data + ga.ga_len, len, "%s%s%s", type_name, entry->es_name, idx == exestack.ga_len - 1 ? "" : ".."); } else { vim_snprintf((char *)ga.ga_data + ga.ga_len, len, "%s%s[%" PRIdLINENR "]..", - type_name, entry->es_name, entry->es_lnum); + type_name, entry->es_name, lnum); } ga.ga_len += (int)strlen((char *)ga.ga_data + ga.ga_len); } diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h index 6f9f31c9c4..a255c6c096 100644 --- a/src/nvim/runtime.h +++ b/src/nvim/runtime.h @@ -42,6 +42,13 @@ extern garray_T exestack; /// line number in the message source or zero #define SOURCING_LNUM (((estack_T *)exestack.ga_data)[exestack.ga_len - 1].es_lnum) +/// Argument for estack_sfile(). +typedef enum { + ESTACK_NONE, + ESTACK_SFILE, + ESTACK_STACK, +} estack_arg_T; + typedef struct scriptitem_S { char_u *sn_name; bool sn_prof_on; ///< true when script is/was profiled diff --git a/src/nvim/testdir/test_expand_func.vim b/src/nvim/testdir/test_expand_func.vim index 388620f87e..3094aad3a4 100644 --- a/src/nvim/testdir/test_expand_func.vim +++ b/src/nvim/testdir/test_expand_func.vim @@ -39,9 +39,9 @@ endfunc func Test_expand_sfile_and_stack() call assert_match('test_expand_func\.vim$', s:sfile) - let expected = 'script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack$' - call assert_match(expected , expand('')) - call assert_match(expected , expand('')) + let expected = 'script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack' + call assert_match(expected .. '$', expand('')) + call assert_match(expected .. '\[4\]' , expand('')) " Call in script-local function call assert_match('script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack\[7\]\.\.\d\+_expand_sfile$', s:expand_sfile()) @@ -53,11 +53,12 @@ func Test_expand_sfile_and_stack() " Use from sourced script. let lines =<< trim END + " comment here let g:stack_value = expand('') END call writefile(lines, 'Xstack') source Xstack - call assert_match('\ Date: Sun, 14 Aug 2022 07:18:06 +0800 Subject: [PATCH 3/4] vim-patch:8.2.1658: expand('') has trailing ".." Problem: Expand('') has trailing "..". Solution: Remove the "..". (closes vim/vim#6927) https://github.com/vim/vim/commit/a810db3f17d477e057059c72062c08fd97bcea43 --- src/nvim/runtime.c | 16 +++++++--------- src/nvim/testdir/test_expand_func.vim | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index fba3dce92d..044294f3b0 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -135,21 +135,19 @@ char *estack_sfile(estack_arg_T which) } len += strlen(type_name); ga_grow(&ga, (int)len); - linenr_T lnum = 0; - if (idx == exestack.ga_len - 1) { - lnum = which == ESTACK_STACK ? SOURCING_LNUM : 0; - } else { - lnum = entry->es_lnum; - } + linenr_T lnum = idx == exestack.ga_len - 1 + ? which == ESTACK_STACK ? SOURCING_LNUM : 0 + : entry->es_lnum; + char *dots = idx == exestack.ga_len - 1 ? "" : ".."; if (lnum == 0) { // For the bottom entry of : do not add the line number, // it is used in . Also leave it out when the number is // not set. vim_snprintf((char *)ga.ga_data + ga.ga_len, len, "%s%s%s", - type_name, entry->es_name, idx == exestack.ga_len - 1 ? "" : ".."); + type_name, entry->es_name, dots); } else { - vim_snprintf((char *)ga.ga_data + ga.ga_len, len, "%s%s[%" PRIdLINENR "]..", - type_name, entry->es_name, lnum); + vim_snprintf((char *)ga.ga_data + ga.ga_len, len, "%s%s[%" PRIdLINENR "]%s", + type_name, entry->es_name, lnum, dots); } ga.ga_len += (int)strlen((char *)ga.ga_data + ga.ga_len); } diff --git a/src/nvim/testdir/test_expand_func.vim b/src/nvim/testdir/test_expand_func.vim index 3094aad3a4..fc0f7619c4 100644 --- a/src/nvim/testdir/test_expand_func.vim +++ b/src/nvim/testdir/test_expand_func.vim @@ -58,7 +58,7 @@ func Test_expand_sfile_and_stack() END call writefile(lines, 'Xstack') source Xstack - call assert_match('\ Date: Mon, 15 Aug 2022 08:28:20 +0800 Subject: [PATCH 4/4] fix(source): make changing 'shellslash' change expand() result --- src/nvim/lua/executor.c | 2 +- src/nvim/runtime.c | 13 ++++++------ test/functional/ex_cmds/source_spec.lua | 28 +++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 2e5b411fad..a86f23db8e 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1906,7 +1906,7 @@ void nlua_set_sctx(sctx_T *current) break; } char *source_path = fix_fname(info->source + 1); - get_current_script_id((char_u *)source_path, current); + get_current_script_id(&source_path, current); xfree(source_path); current->sc_lnum = info->currentline; current->sc_seq = -1; diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 044294f3b0..4eb38c2c9e 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -1964,7 +1964,7 @@ int do_source(char *fname, int check_other, int is_vimrc) save_funccal(&funccalp_entry); const sctx_T save_current_sctx = current_sctx; - si = get_current_script_id((char_u *)fname_exp, ¤t_sctx); + si = get_current_script_id(&fname_exp, ¤t_sctx); if (l_do_profiling == PROF_YES) { bool forceit = false; @@ -2077,9 +2077,9 @@ theend: /// Check if fname was sourced before to finds its SID. /// If it's new, generate a new SID. /// -/// @param[in] fname file path of script -/// @param[out] ret_sctx sctx of this script -scriptitem_T *get_current_script_id(char_u *fname, sctx_T *ret_sctx) +/// @param[in,out] fnamep pointer to file path of script +/// @param[out] ret_sctx sctx of this script +scriptitem_T *get_current_script_id(char **fnamep, sctx_T *ret_sctx) { static int last_current_SID_seq = 0; @@ -2096,13 +2096,14 @@ scriptitem_T *get_current_script_id(char_u *fname, sctx_T *ret_sctx) // - If a script is deleted and another script is written, with a // different name, the inode may be re-used. si = &SCRIPT_ITEM(script_sctx.sc_sid); - if (si->sn_name != NULL && FNAMECMP(si->sn_name, fname) == 0) { + if (si->sn_name != NULL && FNAMECMP(si->sn_name, *fnamep) == 0) { // Found it! break; } } if (script_sctx.sc_sid == 0) { - si = new_script_item((char *)vim_strsave(fname), &script_sctx.sc_sid); + si = new_script_item(*fnamep, &script_sctx.sc_sid); + *fnamep = xstrdup((char *)si->sn_name); } if (ret_sctx != NULL) { *ret_sctx = script_sctx; diff --git a/test/functional/ex_cmds/source_spec.lua b/test/functional/ex_cmds/source_spec.lua index 13a40fcc53..4bc3355e9e 100644 --- a/test/functional/ex_cmds/source_spec.lua +++ b/test/functional/ex_cmds/source_spec.lua @@ -13,6 +13,10 @@ local exec_lua = helpers.exec_lua local eval = helpers.eval local exec_capture = helpers.exec_capture local neq = helpers.neq +local matches = helpers.matches +local iswin = helpers.iswin +local mkdir = helpers.mkdir +local rmdir = helpers.rmdir describe(':source', function() before_each(function() @@ -39,6 +43,30 @@ describe(':source', function() os.remove(test_file) end) + it("changing 'shellslash' changes the result of expand()", function() + if not iswin() then + pending("'shellslash' only works on Windows") + return + end + mkdir('Xshellslash') + local script = [[ + let g:result1 = expand('') + set shellslash + let g:result2 = expand('') + set noshellslash + let g:result3 = expand('') + ]] + write_file([[Xshellslash/Xexpand.vim]], script) + + meths.set_option('shellslash', false) + command([[source Xshellslash/Xexpand.vim]]) + matches([[Xshellslash\Xexpand%.vim]], meths.get_var('result1')) + matches([[Xshellslash/Xexpand%.vim]], meths.get_var('result2')) + matches([[Xshellslash\Xexpand%.vim]], meths.get_var('result3')) + + rmdir('Xshellslash') + end) + it('current buffer', function() insert([[ let a = 2