Patch 8.1.0037
Problem:    Cannot easily append lines to another buffer.
Solution:   Add appendbufline().
Files:      runtime/doc/eval.txt, src/evalfunc.c,
            src/testdir/test_bufline.vim, src/testdir/test_edit.vim


*** ../vim-8.1.0036/runtime/doc/eval.txt        2018-06-03 14:42:17.824505143 
+0200
--- runtime/doc/eval.txt        2018-06-06 20:58:47.732807369 +0200
***************
*** 2560,2565 ****
--- 2560,2580 ----
                0 for success.  Example: >
                        :let failed = append(line('$'), "# THE END")
                        :let failed = append(0, ["Chapter 1", "the beginning"])
+ 
+ appendbufline({expr}, {lnum}, {text})                 *appendbufline()*
+               Like |append()| but append the text in buffer {expr}.
+ 
+               For the use of {expr}, see |bufname()|.
+ 
+               {lnum} is used like with |append()|.  Note that using |line()|
+               would use the current buffer, not the one appending to.
+               Use "$" to append at the end of the buffer.
+ 
+               On success 0 is returned, on failure 1 is returned.
+ 
+               If {expr} is not a valid buffer or {lnum} is not valid, an
+               error message is given. Example: >
+                       :let failed = appendbufline(13, 0, "# THE START")
  <
                                                        *argc()*
  argc()                The result is the number of files in the argument list 
of the
*** ../vim-8.1.0036/src/evalfunc.c      2018-06-03 14:42:17.844505109 +0200
--- src/evalfunc.c      2018-06-06 20:58:47.740807362 +0200
***************
*** 40,45 ****
--- 40,46 ----
  static void f_add(typval_T *argvars, typval_T *rettv);
  static void f_and(typval_T *argvars, typval_T *rettv);
  static void f_append(typval_T *argvars, typval_T *rettv);
+ static void f_appendbufline(typval_T *argvars, typval_T *rettv);
  static void f_argc(typval_T *argvars, typval_T *rettv);
  static void f_argidx(typval_T *argvars, typval_T *rettv);
  static void f_arglistid(typval_T *argvars, typval_T *rettv);
***************
*** 487,492 ****
--- 488,494 ----
      {"add",           2, 2, f_add},
      {"and",           2, 2, f_and},
      {"append",                2, 2, f_append},
+     {"appendbufline", 3, 3, f_appendbufline},
      {"argc",          0, 0, f_argc},
      {"argidx",                0, 0, f_argidx},
      {"arglistid",     0, 2, f_arglistid},
***************
*** 1192,1261 ****
  }
  
  /*
!  * "append(lnum, string/list)" function
   */
      static void
! f_append(typval_T *argvars, typval_T *rettv)
  {
!     long      lnum;
!     char_u    *line;
      list_T    *l = NULL;
      listitem_T        *li = NULL;
-     typval_T  *tv;
      long      added = 0;
  
!     /* When coming here from Insert mode, sync undo, so that this can be
!      * undone separately from what was previously inserted. */
!     if (u_sync_once == 2)
      {
!       u_sync_once = 1; /* notify that u_sync() was called */
!       u_sync(TRUE);
      }
  
!     lnum = get_tv_lnum(argvars);
!     if (lnum >= 0
!           && lnum <= curbuf->b_ml.ml_line_count
!           && u_save(lnum, lnum + 1) == OK)
      {
!       if (argvars[1].v_type == VAR_LIST)
!       {
!           l = argvars[1].vval.v_list;
!           if (l == NULL)
!               return;
!           li = l->lv_first;
!       }
!       for (;;)
        {
!           if (l == NULL)
!               tv = &argvars[1];       /* append a string */
!           else if (li == NULL)
!               break;                  /* end of list */
!           else
!               tv = &li->li_tv;        /* append item from list */
!           line = get_tv_string_chk(tv);
!           if (line == NULL)           /* type error */
            {
!               rettv->vval.v_number = 1;       /* Failed */
                break;
            }
!           ml_append(lnum + added, line, (colnr_T)0, FALSE);
!           ++added;
!           if (l == NULL)
                break;
            li = li->li_next;
        }
  
!       appended_lines_mark(lnum, added);
!       if (curwin->w_cursor.lnum > lnum)
!           curwin->w_cursor.lnum += added;
  #ifdef FEAT_JOB_CHANNEL
        if (bt_prompt(curbuf) && (State & INSERT))
            // show the line with the prompt
            update_topline();
  #endif
      }
      else
!       rettv->vval.v_number = 1;       /* Failed */
  }
  
  /*
--- 1194,1378 ----
  }
  
  /*
!  * Get the lnum from the first argument.
!  * Also accepts "$", then "buf" is used.
!  * Returns 0 on error.
!  */
!     static linenr_T
! get_tv_lnum_buf(typval_T *argvars, buf_T *buf)
! {
!     if (argvars[0].v_type == VAR_STRING
!           && argvars[0].vval.v_string != NULL
!           && argvars[0].vval.v_string[0] == '$'
!           && buf != NULL)
!       return buf->b_ml.ml_line_count;
!     return (linenr_T)get_tv_number_chk(&argvars[0], NULL);
! }
! 
! /*
!  * Set line or list of lines in buffer "buf".
   */
      static void
! set_buffer_lines(
!       buf_T       *buf,
!       linenr_T    lnum_arg,
!       int         append,
!       typval_T    *lines,
!       typval_T    *rettv)
  {
!     linenr_T    lnum = lnum_arg + (append ? 1 : 0);
!     char_u    *line = NULL;
      list_T    *l = NULL;
      listitem_T        *li = NULL;
      long      added = 0;
+     linenr_T  append_lnum;
+     buf_T     *curbuf_save = NULL;
+     win_T     *curwin_save = NULL;
+     int               is_curbuf = buf == curbuf;
  
!     /* When using the current buffer ml_mfp will be set if needed.  Useful 
when
!      * setline() is used on startup.  For other buffers the buffer must be
!      * loaded. */
!     if (buf == NULL || (!is_curbuf && buf->b_ml.ml_mfp == NULL) || lnum < 1)
      {
!       rettv->vval.v_number = 1;       /* FAIL */
!       return;
      }
  
!     if (!is_curbuf)
      {
!       wininfo_T *wip;
! 
!       curbuf_save = curbuf;
!       curwin_save = curwin;
!       curbuf = buf;
!       for (wip = buf->b_wininfo; wip != NULL; wip = wip->wi_next)
        {
!           if (wip->wi_win != NULL)
            {
!               curwin = wip->wi_win;
                break;
            }
!       }
!     }
! 
!     if (append)
!       // appendbufline() uses the line number below which we insert
!       append_lnum = lnum - 1;
!     else
!       // setbufline() uses the line number above which we insert, we only
!       // append if it's below the last line
!       append_lnum = curbuf->b_ml.ml_line_count;
! 
!     if (lines->v_type == VAR_LIST)
!     {
!       l = lines->vval.v_list;
!       li = l->lv_first;
!     }
!     else
!       line = get_tv_string_chk(lines);
! 
!     /* default result is zero == OK */
!     for (;;)
!     {
!       if (l != NULL)
!       {
!           /* list argument, get next string */
!           if (li == NULL)
                break;
+           line = get_tv_string_chk(&li->li_tv);
            li = li->li_next;
        }
  
!       rettv->vval.v_number = 1;       /* FAIL */
!       if (line == NULL || lnum > curbuf->b_ml.ml_line_count + 1)
!           break;
! 
!       /* When coming here from Insert mode, sync undo, so that this can be
!        * undone separately from what was previously inserted. */
!       if (u_sync_once == 2)
!       {
!           u_sync_once = 1; /* notify that u_sync() was called */
!           u_sync(TRUE);
!       }
! 
!       if (!append && lnum <= curbuf->b_ml.ml_line_count)
!       {
!           /* existing line, replace it */
!           if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK)
!           {
!               changed_bytes(lnum, 0);
!               if (is_curbuf && lnum == curwin->w_cursor.lnum)
!                   check_cursor_col();
!               rettv->vval.v_number = 0;       /* OK */
!           }
!       }
!       else if (added > 0 || u_save(lnum - 1, lnum) == OK)
!       {
!           /* append the line */
!           ++added;
!           if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK)
!               rettv->vval.v_number = 0;       /* OK */
!       }
! 
!       if (l == NULL)                  /* only one string argument */
!           break;
!       ++lnum;
!     }
! 
!     if (added > 0)
!     {
!       win_T       *wp;
!       tabpage_T   *tp;
! 
!       appended_lines_mark(append_lnum, added);
!       FOR_ALL_TAB_WINDOWS(tp, wp)
!           if (wp->w_buffer == buf && wp->w_cursor.lnum > append_lnum)
!               wp->w_cursor.lnum += added;
!       check_cursor_col();
! 
  #ifdef FEAT_JOB_CHANNEL
        if (bt_prompt(curbuf) && (State & INSERT))
            // show the line with the prompt
            update_topline();
  #endif
      }
+ 
+     if (!is_curbuf)
+     {
+       curbuf = curbuf_save;
+       curwin = curwin_save;
+     }
+ }
+ 
+ /*
+  * "append(lnum, string/list)" function
+  */
+     static void
+ f_append(typval_T *argvars, typval_T *rettv)
+ {
+     linenr_T  lnum = get_tv_lnum(&argvars[0]);
+ 
+     set_buffer_lines(curbuf, lnum, TRUE, &argvars[1], rettv);
+ }
+ 
+ /*
+  * "appendbufline(buf, lnum, string/list)" function
+  */
+     static void
+ f_appendbufline(typval_T *argvars, typval_T *rettv)
+ {
+     linenr_T  lnum;
+     buf_T     *buf;
+ 
+     buf = get_buf_tv(&argvars[0], FALSE);
+     if (buf == NULL)
+       rettv->vval.v_number = 1; /* FAIL */
      else
!     {
!       lnum = get_tv_lnum_buf(&argvars[1], buf);
!       set_buffer_lines(buf, lnum, TRUE, &argvars[2], rettv);
!     }
  }
  
  /*
***************
*** 4276,4297 ****
  }
  
  /*
-  * Get the lnum from the first argument.
-  * Also accepts "$", then "buf" is used.
-  * Returns 0 on error.
-  */
-     static linenr_T
- get_tv_lnum_buf(typval_T *argvars, buf_T *buf)
- {
-     if (argvars[0].v_type == VAR_STRING
-           && argvars[0].vval.v_string != NULL
-           && argvars[0].vval.v_string[0] == '$'
-           && buf != NULL)
-       return buf->b_ml.ml_line_count;
-     return (linenr_T)get_tv_number_chk(&argvars[0], NULL);
- }
- 
- /*
   * "getbufline()" function
   */
      static void
--- 4393,4398 ----
***************
*** 10226,10340 ****
  }
  
  /*
-  * Set line or list of lines in buffer "buf".
-  */
-     static void
- set_buffer_lines(buf_T *buf, linenr_T lnum, typval_T *lines, typval_T *rettv)
- {
-     char_u    *line = NULL;
-     list_T    *l = NULL;
-     listitem_T        *li = NULL;
-     long      added = 0;
-     linenr_T  lcount;
-     buf_T     *curbuf_save = NULL;
-     win_T     *curwin_save = NULL;
-     int               is_curbuf = buf == curbuf;
- 
-     /* When using the current buffer ml_mfp will be set if needed.  Useful 
when
-      * setline() is used on startup.  For other buffers the buffer must be
-      * loaded. */
-     if (buf == NULL || (!is_curbuf && buf->b_ml.ml_mfp == NULL) || lnum < 1)
-     {
-       rettv->vval.v_number = 1;       /* FAIL */
-       return;
-     }
- 
-     if (!is_curbuf)
-     {
-       wininfo_T *wip;
- 
-       curbuf_save = curbuf;
-       curwin_save = curwin;
-       curbuf = buf;
-       for (wip = buf->b_wininfo; wip != NULL; wip = wip->wi_next)
-       {
-           if (wip->wi_win != NULL)
-           {
-               curwin = wip->wi_win;
-               break;
-           }
-       }
-     }
- 
-     lcount = curbuf->b_ml.ml_line_count;
- 
-     if (lines->v_type == VAR_LIST)
-     {
-       l = lines->vval.v_list;
-       li = l->lv_first;
-     }
-     else
-       line = get_tv_string_chk(lines);
- 
-     /* default result is zero == OK */
-     for (;;)
-     {
-       if (l != NULL)
-       {
-           /* list argument, get next string */
-           if (li == NULL)
-               break;
-           line = get_tv_string_chk(&li->li_tv);
-           li = li->li_next;
-       }
- 
-       rettv->vval.v_number = 1;       /* FAIL */
-       if (line == NULL || lnum > curbuf->b_ml.ml_line_count + 1)
-           break;
- 
-       /* When coming here from Insert mode, sync undo, so that this can be
-        * undone separately from what was previously inserted. */
-       if (u_sync_once == 2)
-       {
-           u_sync_once = 1; /* notify that u_sync() was called */
-           u_sync(TRUE);
-       }
- 
-       if (lnum <= curbuf->b_ml.ml_line_count)
-       {
-           /* existing line, replace it */
-           if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK)
-           {
-               changed_bytes(lnum, 0);
-               if (is_curbuf && lnum == curwin->w_cursor.lnum)
-                   check_cursor_col();
-               rettv->vval.v_number = 0;       /* OK */
-           }
-       }
-       else if (added > 0 || u_save(lnum - 1, lnum) == OK)
-       {
-           /* lnum is one past the last line, append the line */
-           ++added;
-           if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK)
-               rettv->vval.v_number = 0;       /* OK */
-       }
- 
-       if (l == NULL)                  /* only one string argument */
-           break;
-       ++lnum;
-     }
- 
-     if (added > 0)
-       appended_lines_mark(lcount, added);
- 
-     if (!is_curbuf)
-     {
-       curbuf = curbuf_save;
-       curwin = curwin_save;
-     }
- }
- 
- /*
   * "setbufline()" function
   */
      static void
--- 10327,10332 ----
***************
*** 10351,10358 ****
      else
      {
        lnum = get_tv_lnum_buf(&argvars[1], buf);
! 
!       set_buffer_lines(buf, lnum, &argvars[2], rettv);
      }
  }
  
--- 10343,10349 ----
      else
      {
        lnum = get_tv_lnum_buf(&argvars[1], buf);
!       set_buffer_lines(buf, lnum, FALSE, &argvars[2], rettv);
      }
  }
  
***************
*** 10512,10518 ****
  {
      linenr_T  lnum = get_tv_lnum(&argvars[0]);
  
!     set_buffer_lines(curbuf, lnum, &argvars[1], rettv);
  }
  
  static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T 
*action_arg, typval_T *what_arg, typval_T *rettv);
--- 10503,10509 ----
  {
      linenr_T  lnum = get_tv_lnum(&argvars[0]);
  
!     set_buffer_lines(curbuf, lnum, FALSE, &argvars[1], rettv);
  }
  
  static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T 
*action_arg, typval_T *what_arg, typval_T *rettv);
*** ../vim-8.1.0036/src/testdir/test_bufline.vim        2017-11-06 
21:26:52.000000000 +0100
--- src/testdir/test_bufline.vim        2018-06-06 20:58:47.740807362 +0200
***************
*** 1,4 ****
! " Tests for setbufline() and getbufline()
  
  source shared.vim
  
--- 1,4 ----
! " Tests for setbufline(), getbufline(), appendbufline()
  
  source shared.vim
  
***************
*** 65,67 ****
--- 65,92 ----
    call delete('Xscript')
    call delete('Xtest')
  endfunc
+ 
+ func Test_appendbufline()
+   new
+   let b = bufnr('%')
+   hide
+   call assert_equal(0, appendbufline(b, 0, ['foo', 'bar']))
+   call assert_equal(['foo'], getbufline(b, 1))
+   call assert_equal(['bar'], getbufline(b, 2))
+   call assert_equal(['foo', 'bar'], getbufline(b, 1, 2))
+   exe "bd!" b
+   call assert_equal([], getbufline(b, 1, 2))
+ 
+   split Xtest
+   call setline(1, ['a', 'b', 'c'])
+   let b = bufnr('%')
+   wincmd w
+   call assert_equal(1, appendbufline(b, 4, ['x']))
+   call assert_equal(1, appendbufline(1234, 1, ['x']))
+   call assert_equal(0, appendbufline(b, 3, ['d', 'e']))
+   call assert_equal(['c'], getbufline(b, 3))
+   call assert_equal(['d'], getbufline(b, 4))
+   call assert_equal(['e'], getbufline(b, 5))
+   call assert_equal([], getbufline(b, 6))
+   exe "bwipe! " . b
+ endfunc
*** ../vim-8.1.0036/src/testdir/test_edit.vim   2018-06-04 20:34:07.607373577 
+0200
--- src/testdir/test_edit.vim   2018-06-06 20:58:47.740807362 +0200
***************
*** 527,533 ****
    " Tab in completion mode
    let path=expand("%:p:h")
    new
!   call setline(1, [path."/", ''])
    call feedkeys("Arunt\<c-x>\<c-f>\<tab>\<cr>\<esc>", 'tnix')
    call assert_match('runtest\.vim', getline(1))
    %d
--- 527,533 ----
    " Tab in completion mode
    let path=expand("%:p:h")
    new
!   call setline(1, [path. "/", ''])
    call feedkeys("Arunt\<c-x>\<c-f>\<tab>\<cr>\<esc>", 'tnix')
    call assert_match('runtest\.vim', getline(1))
    %d
*** ../vim-8.1.0036/src/version.c       2018-06-06 18:02:31.402773772 +0200
--- src/version.c       2018-06-06 21:00:46.040701324 +0200
***************
*** 763,764 ****
--- 763,766 ----
  {   /* Add new patch number below this line */
+ /**/
+     37,
  /**/

-- 
How To Keep A Healthy Level Of Insanity:
16. Have your coworkers address you by your wrestling name, Rock Hard Kim.

 /// Bram Moolenaar -- b...@moolenaar.net -- 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 vim_dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui