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 -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20220409204246.2FA101C0917%40moolenaar.net.

Raspunde prin e-mail lui