@@ -837,7 +837,18 @@ channel_set_job(channel_T *channel, job_T *job, jobopt_T *options)
837837 ch_logs (channel , "reading from buffer '%s'" ,
838838 (char * )in_part -> ch_buffer -> b_ffname );
839839 if (options -> jo_set & JO_IN_TOP )
840- in_part -> ch_buf_top = options -> jo_in_top ;
840+ {
841+ if (options -> jo_in_top == 0 && !(options -> jo_set & JO_IN_BOT ))
842+ {
843+ /* Special mode: send last-but-one line when appending a line
844+ * to the buffer. */
845+ in_part -> ch_buffer -> b_write_to_channel = TRUE;
846+ in_part -> ch_buf_top =
847+ in_part -> ch_buffer -> b_ml .ml_line_count + 1 ;
848+ }
849+ else
850+ in_part -> ch_buf_top = options -> jo_in_top ;
851+ }
841852 else
842853 in_part -> ch_buf_top = 1 ;
843854 if (options -> jo_set & JO_IN_BOT )
@@ -864,13 +875,12 @@ find_buffer(char_u *name)
864875 NULL , (linenr_T )0 , BLN_LISTED );
865876 buf_copy_options (buf , BCO_ENTER );
866877#ifdef FEAT_QUICKFIX
867- clear_string_option (& buf -> b_p_bt );
868- buf -> b_p_bt = vim_strsave ((char_u * )"nofile" );
869- clear_string_option (& buf -> b_p_bh );
870- buf -> b_p_bh = vim_strsave ((char_u * )"hide" );
878+ set_option_value ((char_u * )"bt" , 0L , (char_u * )"nofile" , OPT_LOCAL );
879+ set_option_value ((char_u * )"bh" , 0L , (char_u * )"hide" , OPT_LOCAL );
871880#endif
872881 curbuf = buf ;
873- ml_open (curbuf );
882+ if (curbuf -> b_ml .ml_mfp == NULL )
883+ ml_open (curbuf );
874884 ml_replace (1 , (char_u * )"Reading from channel output..." , TRUE);
875885 changed_bytes (1 , 0 );
876886 curbuf = save_curbuf ;
@@ -982,15 +992,33 @@ channel_set_req_callback(
982992 }
983993}
984994
995+ static void
996+ write_buf_line (buf_T * buf , linenr_T lnum , channel_T * channel )
997+ {
998+ char_u * line = ml_get_buf (buf , lnum , FALSE);
999+ int len = STRLEN (line );
1000+ char_u * p ;
1001+
1002+ /* TODO: check if channel can be written to, do not block on write */
1003+ if ((p = alloc (len + 2 )) == NULL )
1004+ return ;
1005+ STRCPY (p , line );
1006+ p [len ] = NL ;
1007+ p [len + 1 ] = NUL ;
1008+ channel_send (channel , PART_IN , p , "write_buf_line()" );
1009+ vim_free (p );
1010+ }
1011+
9851012/*
986- * Write any lines to the in channel.
1013+ * Write any lines to the input channel.
9871014 */
9881015 void
9891016channel_write_in (channel_T * channel )
9901017{
9911018 chanpart_T * in_part = & channel -> ch_part [PART_IN ];
9921019 linenr_T lnum ;
9931020 buf_T * buf = in_part -> ch_buffer ;
1021+ int written = 0 ;
9941022
9951023 if (buf == NULL )
9961024 return ;
@@ -1007,22 +1035,60 @@ channel_write_in(channel_T *channel)
10071035 for (lnum = in_part -> ch_buf_top ; lnum <= in_part -> ch_buf_bot
10081036 && lnum <= buf -> b_ml .ml_line_count ; ++ lnum )
10091037 {
1010- char_u * line = ml_get_buf (buf , lnum , FALSE);
1011- int len = STRLEN (line );
1012- char_u * p ;
1013-
1014- /* TODO: check if channel can be written to */
1015- if ((p = alloc (len + 2 )) == NULL )
1016- break ;
1017- STRCPY (p , line );
1018- p [len ] = NL ;
1019- p [len + 1 ] = NUL ;
1020- channel_send (channel , PART_IN , p , "channel_write_in()" );
1021- vim_free (p );
1038+ write_buf_line (buf , lnum , channel );
1039+ ++ written ;
10221040 }
1041+
1042+ if (written == 1 )
1043+ ch_logn (channel , "written line %d to channel" , (int )lnum - 1 );
1044+ else if (written > 1 )
1045+ ch_logn (channel , "written %d lines to channel" , written );
1046+
10231047 in_part -> ch_buf_top = lnum ;
10241048}
10251049
1050+ /*
1051+ * Write appended lines above the last one in "buf" to the channel.
1052+ */
1053+ void
1054+ channel_write_new_lines (buf_T * buf )
1055+ {
1056+ channel_T * channel ;
1057+ int found_one = FALSE;
1058+
1059+ /* There could be more than one channel for the buffer, loop over all of
1060+ * them. */
1061+ for (channel = first_channel ; channel != NULL ; channel = channel -> ch_next )
1062+ {
1063+ chanpart_T * in_part = & channel -> ch_part [PART_IN ];
1064+ linenr_T lnum ;
1065+ int written = 0 ;
1066+
1067+ if (in_part -> ch_buffer == buf )
1068+ {
1069+ if (in_part -> ch_fd == INVALID_FD )
1070+ /* pipe was closed */
1071+ continue ;
1072+ found_one = TRUE;
1073+ for (lnum = in_part -> ch_buf_bot ; lnum < buf -> b_ml .ml_line_count ;
1074+ ++ lnum )
1075+ {
1076+ write_buf_line (buf , lnum , channel );
1077+ ++ written ;
1078+ }
1079+
1080+ if (written == 1 )
1081+ ch_logn (channel , "written line %d to channel" , (int )lnum - 1 );
1082+ else if (written > 1 )
1083+ ch_logn (channel , "written %d lines to channel" , written );
1084+
1085+ in_part -> ch_buf_bot = lnum ;
1086+ }
1087+ }
1088+ if (!found_one )
1089+ buf -> b_write_to_channel = FALSE;
1090+ }
1091+
10261092/*
10271093 * Invoke the "callback" on channel "channel".
10281094 */
@@ -1470,6 +1536,76 @@ invoke_one_time_callback(
14701536 vim_free (item );
14711537}
14721538
1539+ static void
1540+ append_to_buffer (buf_T * buffer , char_u * msg , channel_T * channel )
1541+ {
1542+ buf_T * save_curbuf = curbuf ;
1543+ linenr_T lnum = buffer -> b_ml .ml_line_count ;
1544+ int save_write_to = buffer -> b_write_to_channel ;
1545+
1546+ /* If the buffer is also used as input insert above the last
1547+ * line. Don't write these lines. */
1548+ if (save_write_to )
1549+ {
1550+ -- lnum ;
1551+ buffer -> b_write_to_channel = FALSE;
1552+ }
1553+
1554+ /* Append to the buffer */
1555+ ch_logn (channel , "appending line %d to buffer" , (int )lnum + 1 );
1556+
1557+ curbuf = buffer ;
1558+ u_sync (TRUE);
1559+ /* ignore undo failure, undo is not very useful here */
1560+ ignored = u_save (lnum , lnum + 1 );
1561+
1562+ ml_append (lnum , msg , 0 , FALSE);
1563+ appended_lines_mark (lnum , 1L );
1564+ curbuf = save_curbuf ;
1565+
1566+ if (buffer -> b_nwindows > 0 )
1567+ {
1568+ win_T * wp ;
1569+ win_T * save_curwin ;
1570+
1571+ FOR_ALL_WINDOWS (wp )
1572+ {
1573+ if (wp -> w_buffer == buffer
1574+ && (save_write_to
1575+ ? wp -> w_cursor .lnum == lnum + 1
1576+ : (wp -> w_cursor .lnum == lnum
1577+ && wp -> w_cursor .col == 0 )))
1578+ {
1579+ ++ wp -> w_cursor .lnum ;
1580+ save_curwin = curwin ;
1581+ curwin = wp ;
1582+ curbuf = curwin -> w_buffer ;
1583+ scroll_cursor_bot (0 , FALSE);
1584+ curwin = save_curwin ;
1585+ curbuf = curwin -> w_buffer ;
1586+ }
1587+ }
1588+ redraw_buf_later (buffer , VALID );
1589+ channel_need_redraw = TRUE;
1590+ }
1591+
1592+ if (save_write_to )
1593+ {
1594+ channel_T * ch ;
1595+
1596+ /* Find channels reading from this buffer and adjust their
1597+ * next-to-read line number. */
1598+ buffer -> b_write_to_channel = TRUE;
1599+ for (ch = first_channel ; ch != NULL ; ch = ch -> ch_next )
1600+ {
1601+ chanpart_T * in_part = & ch -> ch_part [PART_IN ];
1602+
1603+ if (in_part -> ch_buffer == buffer )
1604+ in_part -> ch_buf_bot = buffer -> b_ml .ml_line_count ;
1605+ }
1606+ }
1607+ }
1608+
14731609/*
14741610 * Invoke a callback for "channel"/"part" if needed.
14751611 * Return TRUE when a message was handled, there might be another one.
@@ -1634,46 +1770,7 @@ may_invoke_callback(channel_T *channel, int part)
16341770 /* JSON or JS mode: re-encode the message. */
16351771 msg = json_encode (listtv , ch_mode );
16361772 if (msg != NULL )
1637- {
1638- buf_T * save_curbuf = curbuf ;
1639- linenr_T lnum = buffer -> b_ml .ml_line_count ;
1640-
1641- /* Append to the buffer */
1642- ch_logn (channel , "appending line %d to buffer" , (int )lnum + 1 );
1643-
1644- curbuf = buffer ;
1645- u_sync (TRUE);
1646- /* ignore undo failure, undo is not very useful here */
1647- ignored = u_save (lnum , lnum + 1 );
1648-
1649- ml_append (lnum , msg , 0 , FALSE);
1650- appended_lines_mark (lnum , 1L );
1651- curbuf = save_curbuf ;
1652-
1653- if (buffer -> b_nwindows > 0 )
1654- {
1655- win_T * wp ;
1656- win_T * save_curwin ;
1657-
1658- FOR_ALL_WINDOWS (wp )
1659- {
1660- if (wp -> w_buffer == buffer
1661- && wp -> w_cursor .lnum == lnum
1662- && wp -> w_cursor .col == 0 )
1663- {
1664- ++ wp -> w_cursor .lnum ;
1665- save_curwin = curwin ;
1666- curwin = wp ;
1667- curbuf = curwin -> w_buffer ;
1668- scroll_cursor_bot (0 , FALSE);
1669- curwin = save_curwin ;
1670- curbuf = curwin -> w_buffer ;
1671- }
1672- }
1673- redraw_buf_later (buffer , VALID );
1674- channel_need_redraw = TRUE;
1675- }
1676- }
1773+ append_to_buffer (buffer , msg , channel );
16771774 }
16781775
16791776 if (callback != NULL )
0 commit comments