Skip to content

Commit 99ef062

Browse files
committed
patch 7.4.1502
Problem: Writing last-but-one line of buffer to a channel isn't implemented yet. Solution: Implement it. Fix leaving a swap file behind.
1 parent 38fd4bb commit 99ef062

5 files changed

Lines changed: 168 additions & 59 deletions

File tree

src/channel.c

Lines changed: 156 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -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
9891016
channel_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)

src/memline.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3059,6 +3059,11 @@ ml_append_int(
30593059
(char_u *)"\n", 1);
30603060
}
30613061
#endif
3062+
#ifdef FEAT_CHANNEL
3063+
if (buf->b_write_to_channel)
3064+
channel_write_new_lines(buf);
3065+
#endif
3066+
30623067
return OK;
30633068
}
30643069

src/proto/channel.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ void channel_set_job(channel_T *channel, job_T *job, jobopt_T *options);
1414
void channel_set_options(channel_T *channel, jobopt_T *opt);
1515
void channel_set_req_callback(channel_T *channel, int part, char_u *callback, int id);
1616
void channel_write_in(channel_T *channel);
17+
void channel_write_new_lines(buf_T *buf);
1718
char_u *channel_get(channel_T *channel, int part);
1819
int channel_collapse(channel_T *channel, int part);
1920
int channel_can_write_to(channel_T *channel);

src/structs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2051,6 +2051,10 @@ struct file_buffer
20512051
int b_netbeans_file; /* TRUE when buffer is owned by NetBeans */
20522052
int b_was_netbeans_file;/* TRUE if b_netbeans_file was once set */
20532053
#endif
2054+
#ifdef FEAT_CHANNEL
2055+
int b_write_to_channel; /* TRUE when appended lines are written to
2056+
* a channel. */
2057+
#endif
20542058

20552059
#ifdef FEAT_CRYPT
20562060
cryptstate_T *b_cryptstate; /* Encryption state while reading or writing

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,8 @@ static char *(features[]) =
743743

744744
static int included_patches[] =
745745
{ /* Add new patch number below this line */
746+
/**/
747+
1502,
746748
/**/
747749
1501,
748750
/**/

0 commit comments

Comments
 (0)