Patch 8.2.0997
Problem:    Cannot execute a register containing line continuation.
Solution:   Concatenate lines where needed. (Yegappan Lakshmanan,
            closes #6272)
Files:      runtime/doc/repeat.txt, src/register.c,
            src/testdir/test_registers.vim


*** ../vim-8.2.0996/runtime/doc/repeat.txt      2019-12-17 21:27:14.690319902 
+0100
--- runtime/doc/repeat.txt      2020-06-17 21:43:51.089410095 +0200
***************
*** 158,163 ****
--- 163,173 ----
                        result of evaluating the expression is executed as an
                        Ex command.
                        Mappings are not recognized in these commands.
+                       When the |line-continuation| character (\) is present
+                       at the beginning of a line in a linewise register,
+                       then it is combined with the previous line. This is
+                       useful for yanking and executing parts of a Vim
+                       script.
                        Future: Will execute the register for each line in the
                        address range.
  
*** ../vim-8.2.0996/src/register.c      2020-06-12 22:59:07.270097188 +0200
--- src/register.c      2020-06-17 21:43:51.089410095 +0200
***************
*** 474,479 ****
--- 474,546 ----
  }
  
  /*
+  * When executing a register as a series of ex-commands, if the
+  * line-continuation character is used for a line, then join it with one or
+  * more previous lines. Note that lines are processed backwards starting from
+  * the last line in the register.
+  *
+  * Arguments:
+  *   lines - list of lines in the register
+  *   idx - index of the line starting with \ or "\. Join this line with all 
the
+  *       immediate predecessor lines that start with a \ and the first line
+  *       that doesn't start with a \. Lines that start with a comment "\
+  *       character are ignored.
+  *
+  * Returns the concatenated line. The index of the line that should be
+  * processed next is returned in idx.
+  */
+     static char_u *
+ execreg_line_continuation(char_u **lines, long *idx)
+ {
+     garray_T  ga;
+     long      i = *idx;
+     char_u    *p;
+     int               cmd_start;
+     int               cmd_end = i;
+     int               j;
+     char_u    *str;
+ 
+     ga_init2(&ga, (int)sizeof(char_u), 400);
+ 
+     // search backwards to find the first line of this command.
+     // Any line not starting with \ or "\ is the start of the
+     // command.
+     while (--i > 0)
+     {
+       p = skipwhite(lines[i]);
+       if (*p != '\\' && (p[0] != '"' || p[1] != '\\' || p[2] != ' '))
+           break;
+     }
+     cmd_start = i;
+ 
+     // join all the lines
+     ga_concat(&ga, lines[cmd_start]);
+     for (j = cmd_start + 1; j <= cmd_end; j++)
+     {
+       p = skipwhite(lines[j]);
+       if (*p == '\\')
+       {
+           // Adjust the growsize to the current length to
+           // speed up concatenating many lines.
+           if (ga.ga_len > 400)
+           {
+               if (ga.ga_len > 8000)
+                   ga.ga_growsize = 8000;
+               else
+                   ga.ga_growsize = ga.ga_len;
+           }
+           ga_concat(&ga, p + 1);
+       }
+     }
+     ga_append(&ga, NUL);
+     str = vim_strsave(ga.ga_data);
+     ga_clear(&ga);
+ 
+     *idx = i;
+     return str;
+ }
+ 
+ /*
   * Execute a yank register: copy it into the stuff buffer.
   *
   * Return FAIL for failure, OK otherwise.
***************
*** 579,584 ****
--- 646,653 ----
        for (i = y_current->y_size; --i >= 0; )
        {
            char_u *escaped;
+           char_u *str;
+           int     free_str = FALSE;
  
            // insert NL between lines and after last line if type is MLINE
            if (y_current->y_type == MLINE || i < y_current->y_size - 1
***************
*** 587,593 ****
                if (ins_typebuf((char_u *)"\n", remap, 0, TRUE, silent) == FAIL)
                    return FAIL;
            }
!           escaped = vim_strsave_escape_csi(y_current->y_array[i]);
            if (escaped == NULL)
                return FAIL;
            retval = ins_typebuf(escaped, remap, 0, TRUE, silent);
--- 656,678 ----
                if (ins_typebuf((char_u *)"\n", remap, 0, TRUE, silent) == FAIL)
                    return FAIL;
            }
! 
!           // Handle line-continuation for :@<register>
!           str = y_current->y_array[i];
!           if (colon && i > 0)
!           {
!               p = skipwhite(str);
!               if (*p == '\\' || (p[0] == '"' && p[1] == '\\' && p[2] == ' '))
!               {
!                   str = execreg_line_continuation(y_current->y_array, &i);
!                   if (str == NULL)
!                       return FAIL;
!                   free_str = TRUE;
!               }
!           }
!           escaped = vim_strsave_escape_csi(str);
!           if (free_str)
!               vim_free(str);
            if (escaped == NULL)
                return FAIL;
            retval = ins_typebuf(escaped, remap, 0, TRUE, silent);
*** ../vim-8.2.0996/src/testdir/test_registers.vim      2020-06-07 
21:31:14.778405833 +0200
--- src/testdir/test_registers.vim      2020-06-17 21:43:51.089410095 +0200
***************
*** 557,560 ****
--- 557,636 ----
    bwipe!
  endfunc
  
+ " Test for executing the contents of a register as an Ex command with line
+ " continuation.
+ func Test_execute_reg_as_ex_cmd()
+   " Line continuation with just two lines
+   let code =<< trim END
+     let l = [
+       \ 1]
+   END
+   let @r = code->join("\n")
+   let l = []
+   @r
+   call assert_equal([1], l)
+ 
+   " Line continuation with more than two lines
+   let code =<< trim END
+     let l = [
+       \ 1,
+       \ 2,
+       \ 3]
+   END
+   let @r = code->join("\n")
+   let l = []
+   @r
+   call assert_equal([1, 2, 3], l)
+ 
+   " use comments interspersed with code
+   let code =<< trim END
+     let l = [
+       "\ one
+       \ 1,
+       "\ two
+       \ 2,
+       "\ three
+       \ 3]
+   END
+   let @r = code->join("\n")
+   let l = []
+   @r
+   call assert_equal([1, 2, 3], l)
+ 
+   " use line continuation in the middle
+   let code =<< trim END
+     let a = "one"
+     let l = [
+       \ 1,
+       \ 2]
+     let b = "two"
+   END
+   let @r = code->join("\n")
+   let l = []
+   @r
+   call assert_equal([1, 2], l)
+   call assert_equal("one", a)
+   call assert_equal("two", b)
+ 
+   " only one line with a \
+   let @r = "\\let l = 1"
+   call assert_fails('@r', 'E10:')
+ 
+   " only one line with a "\
+   let @r = '   "\ let i = 1'
+   @r
+   call assert_false(exists('i'))
+ 
+   " first line also begins with a \
+   let @r = "\\let l = [\n\\ 1]"
+   call assert_fails('@r', 'E10:')
+ 
+   " Test with a large number of lines
+   let @r = "let str = \n"
+   let @r ..= repeat("  \\ 'abcdefghijklmnopqrstuvwxyz' ..\n", 312)
+   let @r ..= '  \ ""'
+   @r
+   call assert_equal(repeat('abcdefghijklmnopqrstuvwxyz', 312), str)
+ endfunc
+ 
  " vim: shiftwidth=2 sts=2 expandtab
*** ../vim-8.2.0996/src/version.c       2020-06-17 21:41:31.973819210 +0200
--- src/version.c       2020-06-17 21:45:29.945120090 +0200
***************
*** 756,757 ****
--- 756,759 ----
  {   /* Add new patch number below this line */
+ /**/
+     997,
  /**/

-- 
GUEST:        He's killed the best man!
SECOND GUEST: (holding a limp WOMAN) He's killed my auntie.
FATHER:       No, please!  This is supposed to be a happy occasion!  Let's
              not bicker and argue about who killed who ...
                 "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/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            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/202006171947.05HJlwRm187650%40masaka.moolenaar.net.

Raspunde prin e-mail lui