To: vim_dev@googlegroups.com Subject: Patch 7.4.1502 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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. Files: src/channel.c, src/structs.h, src/memline.c, src/proto/channel.pro *** ../vim-7.4.1501/src/channel.c 2016-03-05 22:19:37.278622998 +0100 --- src/channel.c 2016-03-06 20:07:22.013564002 +0100 *************** *** 837,843 **** ch_logs(channel, "reading from buffer '%s'", (char *)in_part->ch_buffer->b_ffname); if (options->jo_set & JO_IN_TOP) ! in_part->ch_buf_top = options->jo_in_top; else in_part->ch_buf_top = 1; if (options->jo_set & JO_IN_BOT) --- 837,854 ---- ch_logs(channel, "reading from buffer '%s'", (char *)in_part->ch_buffer->b_ffname); if (options->jo_set & JO_IN_TOP) ! { ! if (options->jo_in_top == 0 && !(options->jo_set & JO_IN_BOT)) ! { ! /* Special mode: send last-but-one line when appending a line ! * to the buffer. */ ! in_part->ch_buffer->b_write_to_channel = TRUE; ! in_part->ch_buf_top = ! in_part->ch_buffer->b_ml.ml_line_count + 1; ! } ! else ! in_part->ch_buf_top = options->jo_in_top; ! } else in_part->ch_buf_top = 1; if (options->jo_set & JO_IN_BOT) *************** *** 864,876 **** NULL, (linenr_T)0, BLN_LISTED); buf_copy_options(buf, BCO_ENTER); #ifdef FEAT_QUICKFIX ! clear_string_option(&buf->b_p_bt); ! buf->b_p_bt = vim_strsave((char_u *)"nofile"); ! clear_string_option(&buf->b_p_bh); ! buf->b_p_bh = vim_strsave((char_u *)"hide"); #endif curbuf = buf; ! ml_open(curbuf); ml_replace(1, (char_u *)"Reading from channel output...", TRUE); changed_bytes(1, 0); curbuf = save_curbuf; --- 875,886 ---- NULL, (linenr_T)0, BLN_LISTED); buf_copy_options(buf, BCO_ENTER); #ifdef FEAT_QUICKFIX ! set_option_value((char_u *)"bt", 0L, (char_u *)"nofile", OPT_LOCAL); ! set_option_value((char_u *)"bh", 0L, (char_u *)"hide", OPT_LOCAL); #endif curbuf = buf; ! if (curbuf->b_ml.ml_mfp == NULL) ! ml_open(curbuf); ml_replace(1, (char_u *)"Reading from channel output...", TRUE); changed_bytes(1, 0); curbuf = save_curbuf; *************** *** 982,989 **** } } /* ! * Write any lines to the in channel. */ void channel_write_in(channel_T *channel) --- 992,1016 ---- } } + static void + write_buf_line(buf_T *buf, linenr_T lnum, channel_T *channel) + { + char_u *line = ml_get_buf(buf, lnum, FALSE); + int len = STRLEN(line); + char_u *p; + + /* TODO: check if channel can be written to, do not block on write */ + if ((p = alloc(len + 2)) == NULL) + return; + STRCPY(p, line); + p[len] = NL; + p[len + 1] = NUL; + channel_send(channel, PART_IN, p, "write_buf_line()"); + vim_free(p); + } + /* ! * Write any lines to the input channel. */ void channel_write_in(channel_T *channel) *************** *** 991,996 **** --- 1018,1024 ---- chanpart_T *in_part = &channel->ch_part[PART_IN]; linenr_T lnum; buf_T *buf = in_part->ch_buffer; + int written = 0; if (buf == NULL) return; *************** *** 1007,1029 **** for (lnum = in_part->ch_buf_top; lnum <= in_part->ch_buf_bot && lnum <= buf->b_ml.ml_line_count; ++lnum) { ! char_u *line = ml_get_buf(buf, lnum, FALSE); ! int len = STRLEN(line); ! char_u *p; ! ! /* TODO: check if channel can be written to */ ! if ((p = alloc(len + 2)) == NULL) ! break; ! STRCPY(p, line); ! p[len] = NL; ! p[len + 1] = NUL; ! channel_send(channel, PART_IN, p, "channel_write_in()"); ! vim_free(p); } in_part->ch_buf_top = lnum; } /* * Invoke the "callback" on channel "channel". */ static void --- 1035,1095 ---- for (lnum = in_part->ch_buf_top; lnum <= in_part->ch_buf_bot && lnum <= buf->b_ml.ml_line_count; ++lnum) { ! write_buf_line(buf, lnum, channel); ! ++written; } + + if (written == 1) + ch_logn(channel, "written line %d to channel", (int)lnum - 1); + else if (written > 1) + ch_logn(channel, "written %d lines to channel", written); + in_part->ch_buf_top = lnum; } /* + * Write appended lines above the last one in "buf" to the channel. + */ + void + channel_write_new_lines(buf_T *buf) + { + channel_T *channel; + int found_one = FALSE; + + /* There could be more than one channel for the buffer, loop over all of + * them. */ + for (channel = first_channel; channel != NULL; channel = channel->ch_next) + { + chanpart_T *in_part = &channel->ch_part[PART_IN]; + linenr_T lnum; + int written = 0; + + if (in_part->ch_buffer == buf) + { + if (in_part->ch_fd == INVALID_FD) + /* pipe was closed */ + continue; + found_one = TRUE; + for (lnum = in_part->ch_buf_bot; lnum < buf->b_ml.ml_line_count; + ++lnum) + { + write_buf_line(buf, lnum, channel); + ++written; + } + + if (written == 1) + ch_logn(channel, "written line %d to channel", (int)lnum - 1); + else if (written > 1) + ch_logn(channel, "written %d lines to channel", written); + + in_part->ch_buf_bot = lnum; + } + } + if (!found_one) + buf->b_write_to_channel = FALSE; + } + + /* * Invoke the "callback" on channel "channel". */ static void *************** *** 1470,1475 **** --- 1536,1611 ---- vim_free(item); } + static void + append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel) + { + buf_T *save_curbuf = curbuf; + linenr_T lnum = buffer->b_ml.ml_line_count; + int save_write_to = buffer->b_write_to_channel; + + /* If the buffer is also used as input insert above the last + * line. Don't write these lines. */ + if (save_write_to) + { + --lnum; + buffer->b_write_to_channel = FALSE; + } + + /* Append to the buffer */ + ch_logn(channel, "appending line %d to buffer", (int)lnum + 1); + + curbuf = buffer; + u_sync(TRUE); + /* ignore undo failure, undo is not very useful here */ + ignored = u_save(lnum, lnum + 1); + + ml_append(lnum, msg, 0, FALSE); + appended_lines_mark(lnum, 1L); + curbuf = save_curbuf; + + if (buffer->b_nwindows > 0) + { + win_T *wp; + win_T *save_curwin; + + FOR_ALL_WINDOWS(wp) + { + if (wp->w_buffer == buffer + && (save_write_to + ? wp->w_cursor.lnum == lnum + 1 + : (wp->w_cursor.lnum == lnum + && wp->w_cursor.col == 0))) + { + ++wp->w_cursor.lnum; + save_curwin = curwin; + curwin = wp; + curbuf = curwin->w_buffer; + scroll_cursor_bot(0, FALSE); + curwin = save_curwin; + curbuf = curwin->w_buffer; + } + } + redraw_buf_later(buffer, VALID); + channel_need_redraw = TRUE; + } + + if (save_write_to) + { + channel_T *ch; + + /* Find channels reading from this buffer and adjust their + * next-to-read line number. */ + buffer->b_write_to_channel = TRUE; + for (ch = first_channel; ch != NULL; ch = ch->ch_next) + { + chanpart_T *in_part = &ch->ch_part[PART_IN]; + + if (in_part->ch_buffer == buffer) + in_part->ch_buf_bot = buffer->b_ml.ml_line_count; + } + } + } + /* * Invoke a callback for "channel"/"part" if needed. * Return TRUE when a message was handled, there might be another one. *************** *** 1634,1679 **** /* JSON or JS mode: re-encode the message. */ msg = json_encode(listtv, ch_mode); if (msg != NULL) ! { ! buf_T *save_curbuf = curbuf; ! linenr_T lnum = buffer->b_ml.ml_line_count; ! ! /* Append to the buffer */ ! ch_logn(channel, "appending line %d to buffer", (int)lnum + 1); ! ! curbuf = buffer; ! u_sync(TRUE); ! /* ignore undo failure, undo is not very useful here */ ! ignored = u_save(lnum, lnum + 1); ! ! ml_append(lnum, msg, 0, FALSE); ! appended_lines_mark(lnum, 1L); ! curbuf = save_curbuf; ! ! if (buffer->b_nwindows > 0) ! { ! win_T *wp; ! win_T *save_curwin; ! ! FOR_ALL_WINDOWS(wp) ! { ! if (wp->w_buffer == buffer ! && wp->w_cursor.lnum == lnum ! && wp->w_cursor.col == 0) ! { ! ++wp->w_cursor.lnum; ! save_curwin = curwin; ! curwin = wp; ! curbuf = curwin->w_buffer; ! scroll_cursor_bot(0, FALSE); ! curwin = save_curwin; ! curbuf = curwin->w_buffer; ! } ! } ! redraw_buf_later(buffer, VALID); ! channel_need_redraw = TRUE; ! } ! } } if (callback != NULL) --- 1770,1776 ---- /* JSON or JS mode: re-encode the message. */ msg = json_encode(listtv, ch_mode); if (msg != NULL) ! append_to_buffer(buffer, msg, channel); } if (callback != NULL) *** ../vim-7.4.1501/src/structs.h 2016-03-03 22:51:36.125809792 +0100 --- src/structs.h 2016-03-06 18:03:57.346135772 +0100 *************** *** 2051,2056 **** --- 2051,2060 ---- int b_netbeans_file; /* TRUE when buffer is owned by NetBeans */ int b_was_netbeans_file;/* TRUE if b_netbeans_file was once set */ #endif + #ifdef FEAT_CHANNEL + int b_write_to_channel; /* TRUE when appended lines are written to + * a channel. */ + #endif #ifdef FEAT_CRYPT cryptstate_T *b_cryptstate; /* Encryption state while reading or writing *** ../vim-7.4.1501/src/memline.c 2016-02-23 14:52:31.885232171 +0100 --- src/memline.c 2016-03-06 18:17:40.697666562 +0100 *************** *** 3059,3064 **** --- 3059,3069 ---- (char_u *)"\n", 1); } #endif + #ifdef FEAT_CHANNEL + if (buf->b_write_to_channel) + channel_write_new_lines(buf); + #endif + return OK; } *** ../vim-7.4.1501/src/proto/channel.pro 2016-03-03 22:51:36.133809707 +0100 --- src/proto/channel.pro 2016-03-06 18:21:38.671221230 +0100 *************** *** 14,19 **** --- 14,20 ---- void channel_set_options(channel_T *channel, jobopt_T *opt); void channel_set_req_callback(channel_T *channel, int part, char_u *callback, int id); void channel_write_in(channel_T *channel); + void channel_write_new_lines(buf_T *buf); char_u *channel_get(channel_T *channel, int part); int channel_collapse(channel_T *channel, int part); int channel_can_write_to(channel_T *channel); *** ../vim-7.4.1501/src/version.c 2016-03-06 16:38:23.123062145 +0100 --- src/version.c 2016-03-06 20:10:22.255688403 +0100 *************** *** 745,746 **** --- 745,748 ---- { /* Add new patch number below this line */ + /**/ + 1502, /**/ -- Imagine a world without hypothetical situations. /// Bram Moolenaar -- Bram@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 ///