comparison src/channel.c @ 8267:108d30ed34ba v7.4.1426

commit https://github.com/vim/vim/commit/187db50d0499aecf4cfd42fb4db0a1bebf61c8cd Author: Bram Moolenaar <Bram@vim.org> Date: Sat Feb 27 14:44:26 2016 +0100 patch 7.4.1426 Problem: The "out-io" option for jobs is not implemented yet. Solution: Implement the "buffer" value: append job output to a buffer.
author Christian Brabandt <cb@256bit.org>
date Sat, 27 Feb 2016 14:45:05 +0100
parents a412b466bedc
children ac0c43e7af20
comparison
equal deleted inserted replaced
8266:62545a8dec53 8267:108d30ed34ba
50 # define fd_read(fd, buf, len) read(fd, buf, len) 50 # define fd_read(fd, buf, len) read(fd, buf, len)
51 # define fd_write(sd, buf, len) write(sd, buf, len) 51 # define fd_write(sd, buf, len) write(sd, buf, len)
52 # define fd_close(sd) close(sd) 52 # define fd_close(sd) close(sd)
53 #endif 53 #endif
54 54
55 /* Whether a redraw is needed for appending a line to a buffer. */
56 static int channel_need_redraw = FALSE;
57
58
55 #ifdef WIN32 59 #ifdef WIN32
56 static int 60 static int
57 fd_read(sock_T fd, char *buf, size_t len) 61 fd_read(sock_T fd, char *buf, size_t len)
58 { 62 {
59 HANDLE h = (HANDLE)fd; 63 HANDLE h = (HANDLE)fd;
340 */ 344 */
341 void 345 void
342 channel_free(channel_T *channel) 346 channel_free(channel_T *channel)
343 { 347 {
344 channel_close(channel, TRUE); 348 channel_close(channel, TRUE);
349 channel_clear(channel);
345 if (channel->ch_next != NULL) 350 if (channel->ch_next != NULL)
346 channel->ch_next->ch_prev = channel->ch_prev; 351 channel->ch_next->ch_prev = channel->ch_prev;
347 if (channel->ch_prev == NULL) 352 if (channel->ch_prev == NULL)
348 first_channel = channel->ch_next; 353 first_channel = channel->ch_next;
349 else 354 else
775 { 780 {
776 channel->ch_job = job; 781 channel->ch_job = job;
777 } 782 }
778 783
779 /* 784 /*
785 * Find a buffer matching "name" or create a new one.
786 */
787 static buf_T *
788 find_buffer(char_u *name)
789 {
790 buf_T *buf = buflist_findname(name);
791 buf_T *save_curbuf = curbuf;
792
793 if (buf == NULL)
794 {
795 buf = buflist_new(name, NULL, (linenr_T)0, BLN_LISTED);
796 buf_copy_options(buf, BCO_ENTER);
797 #ifdef FEAT_QUICKFIX
798 clear_string_option(&buf->b_p_bt);
799 buf->b_p_bt = vim_strsave((char_u *)"nofile");
800 clear_string_option(&buf->b_p_bh);
801 buf->b_p_bh = vim_strsave((char_u *)"hide");
802 #endif
803 curbuf = buf;
804 ml_open(curbuf);
805 ml_replace(1, (char_u *)"Reading from channel output...", TRUE);
806 changed_bytes(1, 0);
807 curbuf = save_curbuf;
808 }
809
810 return buf;
811 }
812
813 /*
780 * Set various properties from an "opt" argument. 814 * Set various properties from an "opt" argument.
781 */ 815 */
782 void 816 void
783 channel_set_options(channel_T *channel, jobopt_T *opt) 817 channel_set_options(channel_T *channel, jobopt_T *opt)
784 { 818 {
836 vim_free(*cbp); 870 vim_free(*cbp);
837 if (opt->jo_close_cb != NULL && *opt->jo_close_cb != NUL) 871 if (opt->jo_close_cb != NULL && *opt->jo_close_cb != NUL)
838 *cbp = vim_strsave(opt->jo_close_cb); 872 *cbp = vim_strsave(opt->jo_close_cb);
839 else 873 else
840 *cbp = NULL; 874 *cbp = NULL;
875 }
876
877 if ((opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER)
878 {
879 /* writing output to a buffer. Force mode to NL. */
880 channel->ch_part[PART_OUT].ch_mode = MODE_NL;
881 channel->ch_part[PART_OUT].ch_buffer =
882 find_buffer(opt->jo_io_name[PART_OUT]);
883 ch_logs(channel, "writing to buffer %s",
884 (char *)channel->ch_part[PART_OUT].ch_buffer->b_ffname);
841 } 885 }
842 } 886 }
843 887
844 /* 888 /*
845 * Set the callback for "channel"/"part" for the response with "id". 889 * Set the callback for "channel"/"part" for the response with "id".
1301 typval_T *listtv = NULL; 1345 typval_T *listtv = NULL;
1302 typval_T argv[CH_JSON_MAX_ARGS]; 1346 typval_T argv[CH_JSON_MAX_ARGS];
1303 int seq_nr = -1; 1347 int seq_nr = -1;
1304 ch_mode_T ch_mode = channel->ch_part[part].ch_mode; 1348 ch_mode_T ch_mode = channel->ch_part[part].ch_mode;
1305 char_u *callback = NULL; 1349 char_u *callback = NULL;
1350 buf_T *buffer = NULL;
1306 1351
1307 if (channel->ch_nb_close_cb != NULL) 1352 if (channel->ch_nb_close_cb != NULL)
1308 /* this channel is handled elsewhere (netbeans) */ 1353 /* this channel is handled elsewhere (netbeans) */
1309 return FALSE; 1354 return FALSE;
1310 1355
1311 if (channel->ch_part[part].ch_callback != NULL) 1356 if (channel->ch_part[part].ch_callback != NULL)
1312 callback = channel->ch_part[part].ch_callback; 1357 callback = channel->ch_part[part].ch_callback;
1313 else 1358 else
1314 callback = channel->ch_callback; 1359 callback = channel->ch_callback;
1360 buffer = channel->ch_part[part].ch_buffer;
1315 1361
1316 if (ch_mode == MODE_JSON || ch_mode == MODE_JS) 1362 if (ch_mode == MODE_JSON || ch_mode == MODE_JS)
1317 { 1363 {
1318 listitem_T *item; 1364 listitem_T *item;
1319 int argc = 0; 1365 int argc = 0;
1359 /* nothing to read on RAW or NL channel */ 1405 /* nothing to read on RAW or NL channel */
1360 return FALSE; 1406 return FALSE;
1361 } 1407 }
1362 else 1408 else
1363 { 1409 {
1364 /* If there is no callback drop the message. */ 1410 /* If there is no callback or buffer drop the message. */
1365 if (callback == NULL) 1411 if (callback == NULL && buffer == NULL)
1366 { 1412 {
1367 while ((msg = channel_get(channel, part)) != NULL) 1413 while ((msg = channel_get(channel, part)) != NULL)
1368 vim_free(msg); 1414 vim_free(msg);
1369 return FALSE; 1415 return FALSE;
1370 } 1416 }
1384 break; 1430 break;
1385 if (channel_collapse(channel, part) == FAIL) 1431 if (channel_collapse(channel, part) == FAIL)
1386 return FALSE; /* incomplete message */ 1432 return FALSE; /* incomplete message */
1387 } 1433 }
1388 if (nl[1] == NUL) 1434 if (nl[1] == NUL)
1389 /* get the whole buffer */ 1435 {
1436 /* get the whole buffer, drop the NL */
1390 msg = channel_get(channel, part); 1437 msg = channel_get(channel, part);
1438 *nl = NUL;
1439 }
1391 else 1440 else
1392 { 1441 {
1393 /* Copy the message into allocated memory and remove it from 1442 /* Copy the message into allocated memory and remove it from
1394 * the buffer. */ 1443 * the buffer. */
1395 msg = vim_strnsave(buf, (int)(nl - buf)); 1444 msg = vim_strnsave(buf, (int)(nl - buf));
1429 item = item->cq_next; 1478 item = item->cq_next;
1430 } 1479 }
1431 if (!done) 1480 if (!done)
1432 ch_log(channel, "Dropping message without callback"); 1481 ch_log(channel, "Dropping message without callback");
1433 } 1482 }
1434 else if (callback != NULL) 1483 else if (callback != NULL || buffer != NULL)
1435 { 1484 {
1436 /* invoke the channel callback */ 1485 if (buffer != NULL)
1437 ch_log(channel, "Invoking channel callback"); 1486 {
1438 invoke_callback(channel, callback, argv); 1487 buf_T *save_curbuf = curbuf;
1488 linenr_T lnum = buffer->b_ml.ml_line_count;
1489
1490 /* Append to the buffer */
1491 ch_logn(channel, "appending line %d to buffer", (int)lnum + 1);
1492
1493 curbuf = buffer;
1494 u_sync(TRUE);
1495 u_save(lnum, lnum + 1);
1496
1497 ml_append(lnum, msg, 0, FALSE);
1498 appended_lines_mark(lnum, 1L);
1499 curbuf = save_curbuf;
1500
1501 if (buffer->b_nwindows > 0)
1502 {
1503 win_T *wp;
1504 win_T *save_curwin;
1505
1506 FOR_ALL_WINDOWS(wp)
1507 {
1508 if (wp->w_buffer == buffer
1509 && wp->w_cursor.lnum == lnum
1510 && wp->w_cursor.col == 0)
1511 {
1512 ++wp->w_cursor.lnum;
1513 save_curwin = curwin;
1514 curwin = wp;
1515 curbuf = curwin->w_buffer;
1516 scroll_cursor_bot(0, FALSE);
1517 curwin = save_curwin;
1518 curbuf = curwin->w_buffer;
1519 }
1520 }
1521 redraw_buf_later(buffer, VALID);
1522 channel_need_redraw = TRUE;
1523 }
1524 }
1525 if (callback != NULL)
1526 {
1527 /* invoke the channel callback */
1528 ch_log(channel, "Invoking channel callback");
1529 invoke_callback(channel, callback, argv);
1530 }
1439 } 1531 }
1440 else 1532 else
1441 ch_log(channel, "Dropping message"); 1533 ch_log(channel, "Dropping message");
1442 1534
1443 if (listtv != NULL) 1535 if (listtv != NULL)
1491 } 1583 }
1492 1584
1493 /* 1585 /*
1494 * Close channel "channel". 1586 * Close channel "channel".
1495 * Trigger the close callback if "invoke_close_cb" is TRUE. 1587 * Trigger the close callback if "invoke_close_cb" is TRUE.
1588 * Does not clear the buffers.
1496 */ 1589 */
1497 void 1590 void
1498 channel_close(channel_T *channel, int invoke_close_cb) 1591 channel_close(channel_T *channel, int invoke_close_cb)
1499 { 1592 {
1500 ch_log(channel, "Closing channel"); 1593 ch_log(channel, "Closing channel");
1546 vim_free(channel->ch_close_cb); 1639 vim_free(channel->ch_close_cb);
1547 channel->ch_close_cb = NULL; 1640 channel->ch_close_cb = NULL;
1548 } 1641 }
1549 1642
1550 channel->ch_nb_close_cb = NULL; 1643 channel->ch_nb_close_cb = NULL;
1551 channel_clear(channel);
1552 } 1644 }
1553 1645
1554 /* 1646 /*
1555 * Return the first buffer from "channel"/"part" without removing it. 1647 * Return the first buffer from "channel"/"part" without removing it.
1556 * Returns NULL if there is nothing. 1648 * Returns NULL if there is nothing.
2158 return ret; 2250 return ret;
2159 } 2251 }
2160 # endif /* !WIN32 && HAVE_SELECT */ 2252 # endif /* !WIN32 && HAVE_SELECT */
2161 2253
2162 /* 2254 /*
2255 * Return TRUE if "channel" has JSON or other typeahead.
2256 */
2257 static int
2258 channel_has_readahead(channel_T *channel, int part)
2259 {
2260 ch_mode_T ch_mode = channel->ch_part[part].ch_mode;
2261
2262 if (ch_mode == MODE_JSON || ch_mode == MODE_JS)
2263 {
2264 jsonq_T *head = &channel->ch_part[part].ch_json_head;
2265 jsonq_T *item = head->jq_next;
2266
2267 return item != NULL;
2268 }
2269 return channel_peek(channel, part) != NULL;
2270 }
2271
2272 /*
2163 * Execute queued up commands. 2273 * Execute queued up commands.
2164 * Invoked from the main loop when it's safe to execute received commands. 2274 * Invoked from the main loop when it's safe to execute received commands.
2165 * Return TRUE when something was done. 2275 * Return TRUE when something was done.
2166 */ 2276 */
2167 int 2277 int
2170 channel_T *channel = first_channel; 2280 channel_T *channel = first_channel;
2171 int ret = FALSE; 2281 int ret = FALSE;
2172 int r; 2282 int r;
2173 int part = PART_SOCK; 2283 int part = PART_SOCK;
2174 2284
2285 ch_log(NULL, "looking for messages on channels");
2175 while (channel != NULL) 2286 while (channel != NULL)
2176 { 2287 {
2177 if (channel->ch_refcount == 0 && !channel_still_useful(channel)) 2288 if (channel->ch_refcount == 0 && !channel_still_useful(channel))
2178 { 2289 {
2179 /* channel is no longer useful, free it */ 2290 /* channel is no longer useful, free it */
2180 channel_free(channel); 2291 channel_free(channel);
2181 channel = first_channel; 2292 channel = first_channel;
2182 part = PART_SOCK; 2293 part = PART_SOCK;
2183 continue; 2294 continue;
2184 } 2295 }
2185 if (channel->ch_part[part].ch_fd != INVALID_FD) 2296 if (channel->ch_part[part].ch_fd != INVALID_FD
2297 || channel_has_readahead(channel, part))
2186 { 2298 {
2187 /* Increase the refcount, in case the handler causes the channel 2299 /* Increase the refcount, in case the handler causes the channel
2188 * to be unreferenced or closed. */ 2300 * to be unreferenced or closed. */
2189 ++channel->ch_refcount; 2301 ++channel->ch_refcount;
2190 r = may_invoke_callback(channel, part); 2302 r = may_invoke_callback(channel, part);
2206 { 2318 {
2207 channel = channel->ch_next; 2319 channel = channel->ch_next;
2208 part = PART_SOCK; 2320 part = PART_SOCK;
2209 } 2321 }
2210 } 2322 }
2323
2324 if (channel_need_redraw && must_redraw)
2325 {
2326 channel_need_redraw = FALSE;
2327 update_screen(0);
2328 setcursor();
2329 cursor_on();
2330 out_flush();
2331 }
2332
2211 return ret; 2333 return ret;
2212 } 2334 }
2213 2335
2214 /* 2336 /*
2215 * Mark references to lists used in channels. 2337 * Mark references to lists used in channels.