Patch 8.2.4726

9 views
Skip to first unread message

Bram Moolenaar

unread,
Apr 9, 2022, 4:42:52 PM4/9/22
to vim...@googlegroups.com

Patch 8.2.4726
Problem: Cannot use expand() to get the script name.
Solution: Support expand('<script>'). (closes #10121)
Files: runtime/doc/cmdline.txt, src/errors.h, src/ex_docmd.c,
src/scriptfile.c, src/vim.h, src/testdir/test_expand.vim


*** ../vim-8.2.4725/runtime/doc/cmdline.txt 2021-01-31 16:02:06.246490203 +0000
--- runtime/doc/cmdline.txt 2022-04-09 21:32:10.881446139 +0100
***************
*** 910,924 ****
*:<amatch>* *<amatch>*
<amatch> When executing autocommands, is replaced with the match for
which this autocommand was executed. *E497*
! It differs from <afile> only when the file name isn't used
! to match with (for FileType, Syntax and SpellFileMissing
events).
*:<sfile>* *<sfile>*
<sfile> When executing a ":source" command, is replaced with the
file name of the sourced file. *E498*
! 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
not used inside a script.
*:<stack>* *<stack>*
--- 929,947 ----
*:<amatch>* *<amatch>*
<amatch> When executing autocommands, is replaced with the match for
which this autocommand was executed. *E497*
! It differs from <afile> when the file name isn't used to
! match with (for FileType, Syntax and SpellFileMissing
events).
+ When the match is with a file name, it is expanded to the
+ full path.
*:<sfile>* *<sfile>*
<sfile> When executing a ":source" command, is replaced with the
file name of the sourced file. *E498*
! When executing a legacy function, is replaced with the call
! stack, as with <stack> (this is for backwards
! compatibility, using <stack> or <script> is preferred).
! In Vim9 script using <sfile> in a function gives error
! *E1245* .
Note that filename-modifiers are useless when <sfile> is
not used inside a script.
*:<stack>* *<stack>*
***************
*** 927,932 ****
--- 950,962 ----
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* .
+ *:<script>* *<script>*
+ <script> When executing a `:source` command, is replaced with the file
+ name of the sourced file. When executing a function, is
+ replaced with the file name of the script where it is
+ defined.
+ If the file name cannot be determined you get error *E1274* .
*:<slnum>* *<slnum>*
<slnum> When executing a ":source" command, is replaced with the
line number. *E842*
*** ../vim-8.2.4725/src/errors.h 2022-04-04 18:32:29.185670084 +0100
--- src/errors.h 2022-04-09 21:32:29.157437320 +0100
***************
*** 3258,3260 ****
--- 3258,3262 ----
#endif
EXTERN char e_nfa_regexp_missing_value_in_chr[]
INIT(= N_("E1273: (NFA regexp) missing value in '\\%%%c'"));
+ EXTERN char e_no_script_file_name_to_substitute_for_script[]
+ INIT(= N_("E1274: No script file name to substitute for \"<script>\""));
*** ../vim-8.2.4725/src/ex_docmd.c 2022-04-09 18:17:30.056746549 +0100
--- src/ex_docmd.c 2022-04-09 21:28:14.649559755 +0100
***************
*** 8957,8964 ****
#define SPEC_SLNUM (SPEC_SFILE + 1)
"<stack>", // call stack
#define SPEC_STACK (SPEC_SLNUM + 1)
"<afile>", // autocommand file name
! #define SPEC_AFILE (SPEC_STACK + 1)
"<abuf>", // autocommand buffer number
#define SPEC_ABUF (SPEC_AFILE + 1)
"<amatch>", // autocommand match name
--- 8957,8966 ----
#define SPEC_SLNUM (SPEC_SFILE + 1)
"<stack>", // call stack
#define SPEC_STACK (SPEC_SLNUM + 1)
+ "<script>", // script file name
+ #define SPEC_SCRIPT (SPEC_STACK + 1)
"<afile>", // autocommand file name
! #define SPEC_AFILE (SPEC_SCRIPT + 1)
"<abuf>", // autocommand buffer number
#define SPEC_ABUF (SPEC_AFILE + 1)
"<amatch>", // autocommand match name
***************
*** 9226,9239 ****
break;

case SPEC_SFILE: // file name for ":so" command
case SPEC_STACK: // call stack
! result = estack_sfile(spec_idx == SPEC_SFILE
! ? ESTACK_SFILE : ESTACK_STACK);
if (result == NULL)
{
! *errormsg = spec_idx == SPEC_SFILE
! ? _(e_no_source_file_name_to_substitute_for_sfile)
! : _(e_no_call_stack_to_substitute_for_stack);
return NULL;
}
resultbuf = result; // remember allocated string
--- 9228,9255 ----
break;

case SPEC_SFILE: // file name for ":so" command
+ result = estack_sfile(ESTACK_SFILE);
+ if (result == NULL)
+ {
+ *errormsg = _(e_no_source_file_name_to_substitute_for_sfile);
+ return NULL;
+ }
+ resultbuf = result; // remember allocated string
+ break;
case SPEC_STACK: // call stack
! result = estack_sfile(ESTACK_STACK);
! if (result == NULL)
! {
! *errormsg = _(e_no_call_stack_to_substitute_for_stack);
! return NULL;
! }
! resultbuf = result; // remember allocated string
! break;
! case SPEC_SCRIPT: // script file name
! result = estack_sfile(ESTACK_SCRIPT);
if (result == NULL)
{
! *errormsg = _(e_no_script_file_name_to_substitute_for_script);
return NULL;
}
resultbuf = result; // remember allocated string
*** ../vim-8.2.4725/src/scriptfile.c 2022-03-30 21:12:16.447923057 +0100
--- src/scriptfile.c 2022-04-09 21:34:54.296501875 +0100
***************
*** 118,124 ****

/*
* Get the current value for <sfile> in allocated memory.
! * "which" is ESTACK_SFILE for <sfile> and ESTACK_STACK for <stack>.
*/
char_u *
estack_sfile(estack_arg_T which UNUSED)
--- 118,125 ----

/*
* Get the current value for <sfile> in allocated memory.
! * "which" is ESTACK_SFILE for <sfile>, ESTACK_STACK for <stack> or
! * ESTACK_SCRIPT for <script>.
*/
char_u *
estack_sfile(estack_arg_T which UNUSED)
***************
*** 156,161 ****
--- 157,188 ----
return NULL;
}

+ // If evaluated in a function return the path of the script where the
+ // function is defined, at script level the current script path is returned
+ // instead.
+ if (which == ESTACK_SCRIPT)
+ {
+ if (entry->es_type == ETYPE_UFUNC)
+ {
+ sctx_T *def_ctx = &entry->es_info.ufunc->uf_script_ctx;
+
+ if (def_ctx->sc_sid > 0)
+ return vim_strsave(SCRIPT_ITEM(def_ctx->sc_sid)->sn_name);
+ }
+ else if (exestack.ga_len > 0)
+ {
+ // Walk the stack backwards, starting from the current frame.
+ for (idx = exestack.ga_len - 1; idx; --idx)
+ {
+ entry = ((estack_T *)exestack.ga_data) + idx;
+
+ if (entry->es_type == ETYPE_SCRIPT)
+ return vim_strsave(entry->es_name);
+ }
+ }
+ return NULL;
+ }
+
// 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"
*** ../vim-8.2.4725/src/vim.h 2022-04-09 21:02:58.506251763 +0100
--- src/vim.h 2022-04-09 21:28:14.649559755 +0100
***************
*** 2220,2226 ****
typedef enum {
ESTACK_NONE,
ESTACK_SFILE,
! ESTACK_STACK
} estack_arg_T;

// Flags for assignment functions.
--- 2220,2227 ----
typedef enum {
ESTACK_NONE,
ESTACK_SFILE,
! ESTACK_STACK,
! ESTACK_SCRIPT,
} estack_arg_T;

// Flags for assignment functions.
*** ../vim-8.2.4725/src/testdir/test_expand.vim 2022-04-03 21:30:25.022559205 +0100
--- src/testdir/test_expand.vim 2022-04-09 21:38:00.391514370 +0100
***************
*** 159,162 ****
--- 159,212 ----
call assert_equal('$*', expandcmd('$*'))
endfunc

+ func Test_expand_script_source()
+ let lines0 =<< trim [SCRIPT]
+ let g:script_level[0] = expand('<script>:t')
+ so Xscript1
+ func F0()
+ let g:func_level[0] = expand('<script>:t')
+ endfunc
+ [SCRIPT]
+
+ let lines1 =<< trim [SCRIPT]
+ let g:script_level[1] = expand('<script>:t')
+ so Xscript2
+ func F1()
+ let g:func_level[1] = expand('<script>:t')
+ endfunc
+ [SCRIPT]
+
+ let lines2 =<< trim [SCRIPT]
+ let g:script_level[2] = expand('<script>:t')
+ func F2()
+ let g:func_level[2] = expand('<script>:t')
+ endfunc
+ [SCRIPT]
+
+ call writefile(lines0, 'Xscript0')
+ call writefile(lines1, 'Xscript1')
+ call writefile(lines2, 'Xscript2')
+
+ " Check the expansion of <script> at script and function level.
+ let g:script_level = ['', '', '']
+ let g:func_level = ['', '', '']
+
+ so Xscript0
+ call F0()
+ call F1()
+ call F2()
+
+ call assert_equal(['Xscript0', 'Xscript1', 'Xscript2'], g:script_level)
+ call assert_equal(['Xscript0', 'Xscript1', 'Xscript2'], g:func_level)
+
+ unlet g:script_level g:func_level
+ delfunc F0
+ delfunc F1
+ delfunc F2
+
+ call delete('Xscript0')
+ call delete('Xscript1')
+ call delete('Xscript2')
+ endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
*** ../vim-8.2.4725/src/version.c 2022-04-09 21:13:47.177970155 +0100
--- src/version.c 2022-04-09 21:31:03.285478696 +0100
***************
*** 748,749 ****
--- 748,751 ----
{ /* Add new patch number below this line */
+ /**/
+ 4726,
/**/

--
CART DRIVER: Bring out your dead!
We follow the cart through a wretched, impoverished plague-ridden village.
A few starved mongrels run about in the mud scavenging. In the open
doorway of one house perhaps we jug glimpse a pair of legs dangling from
the ceiling. In another doorway an OLD WOMAN is beating a cat against a
wall rather like one does with a mat. The cart passes round a dead donkey
or cow in the mud. And a MAN tied to a cart is being hammered to death by
four NUNS with huge mallets.
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages