# HG changeset patch # User Christian Brabandt # Date 1504357204 -7200 # Node ID e1f44e4afe674d24c1c3267fda38a2f484b0d8f6 # Parent 30acf035d5c237b54199447254b041ef88c8e0c7 patch 8.0.1034: sending buffer lines to terminal doesn't work on MS-Windows commit https://github.com/vim/vim/commit/3346cc4ffb459ecddb97a8c19bcc5834afa4dead Author: Bram Moolenaar Date: Sat Sep 2 14:54:21 2017 +0200 patch 8.0.1034: sending buffer lines to terminal doesn't work on MS-Windows Problem: Sending buffer lines to terminal doesn't work on MS-Windows. Solution: Send CTRL-D to mark the end of the text. (Yasuhiro Matsumoto, closes #2043) Add the "eof_chars" option. diff --git a/src/channel.c b/src/channel.c --- a/src/channel.c +++ b/src/channel.c @@ -1417,6 +1417,13 @@ channel_write_in(channel_T *channel) in_part->ch_buf_top = lnum; if (lnum > buf->b_ml.ml_line_count || lnum > in_part->ch_buf_bot) { +#if defined(WIN32) && defined(FEAT_TERMINAL) + /* Send CTRL-D or "eof_chars" to close stdin on Windows. A console + * application doesn't treat closing stdin like UNIX. */ + if (channel->ch_job != NULL) + term_send_eof(channel); +#endif + /* Writing is done, no longer need the buffer. */ in_part->ch_bufref.br_buf = NULL; ch_log(channel, "Finished writing all lines to channel"); @@ -4626,6 +4633,22 @@ get_job_options(typval_T *tv, jobopt_T * return FAIL; } } + else if (STRCMP(hi->hi_key, "eof_chars") == 0) + { +# ifdef WIN3264 + char_u *p; + + if (!(supported2 & JO2_EOF_CHARS)) + break; + opt->jo_set2 |= JO2_EOF_CHARS; + p = opt->jo_eof_chars = get_tv_string_chk(item); + if (p == NULL) + { + EMSG2(_(e_invarg2), "term_opencmd"); + return FAIL; + } +# endif + } else if (STRCMP(hi->hi_key, "term_rows") == 0) { if (!(supported2 & JO2_TERM_ROWS)) diff --git a/src/proto/terminal.pro b/src/proto/terminal.pro --- a/src/proto/terminal.pro +++ b/src/proto/terminal.pro @@ -16,6 +16,7 @@ int term_update_window(win_T *wp); int term_is_finished(buf_T *buf); int term_show_buffer(buf_T *buf); void term_change_in_curbuf(void); +void term_send_eof(channel_T *ch); int term_get_attr(buf_T *buf, linenr_T lnum, int col); char_u *term_get_status_text(term_T *term); int set_ref_in_term(int copyID); diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -1713,7 +1713,8 @@ struct channel_S { #define JO2_CURWIN 0x0200 /* "curwin" */ #define JO2_HIDDEN 0x0400 /* "hidden" */ #define JO2_TERM_OPENCMD 0x0800 /* "term_opencmd" */ -#define JO2_ALL 0x0FFF +#define JO2_EOF_CHARS 0x1000 /* "eof_chars" */ +#define JO2_ALL 0x1FFF #define JO_MODE_ALL (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE) #define JO_CB_ALL \ @@ -1779,6 +1780,9 @@ typedef struct char_u *jo_term_name; char_u *jo_term_opencmd; int jo_term_finish; +# ifdef WIN3264 + char_u *jo_eof_chars; +# endif #endif } jobopt_T; diff --git a/src/terminal.c b/src/terminal.c --- a/src/terminal.c +++ b/src/terminal.c @@ -114,6 +114,7 @@ struct terminal_S { #ifdef WIN3264 void *tl_winpty_config; void *tl_winpty; + char_u *tl_eof_chars; #endif /* last known vterm size */ @@ -389,6 +390,11 @@ term_start(typval_T *argvar, jobopt_T *o if (opt->jo_term_opencmd != NULL) term->tl_opencmd = vim_strsave(opt->jo_term_opencmd); +# ifdef WIN3264 + if (opt->jo_eof_chars != NULL) + term->tl_eof_chars = vim_strsave(opt->jo_eof_chars); +# endif + set_string_option_direct((char_u *)"buftype", -1, (char_u *)"terminal", OPT_FREE|OPT_LOCAL, 0); @@ -570,6 +576,9 @@ free_terminal(buf_T *buf) vim_free(term->tl_title); vim_free(term->tl_status_text); vim_free(term->tl_opencmd); +# ifdef WIN3264 + vim_free(term->tl_eof_chars); +# endif vim_free(term->tl_cursor_color); vim_free(term); buf->b_term = NULL; @@ -2821,7 +2830,7 @@ f_term_start(typval_T *argvars, typval_T + JO_EXIT_CB + JO_CLOSE_CALLBACK, JO2_TERM_NAME + JO2_TERM_FINISH + JO2_HIDDEN + JO2_TERM_OPENCMD + JO2_TERM_COLS + JO2_TERM_ROWS + JO2_VERTICAL + JO2_CURWIN - + JO2_CWD + JO2_ENV) == FAIL) + + JO2_CWD + JO2_ENV + JO2_EOF_CHARS) == FAIL) return; if (opt.jo_vertical) @@ -3188,6 +3197,20 @@ terminal_enabled(void) return dyn_winpty_init(FALSE) == OK; } +/* + * Called when a channel has sent all the lines to a terminal. + * Send a CTRL-D to mark the end of the text. + */ + void +term_send_eof(channel_T *ch) +{ + term_T *term; + + for (term = first_term; term != NULL; term = term->tl_next) + if (term->tl_job == ch->ch_job) + channel_send(ch, PART_IN, term->tl_eof_chars != NULL + ? term->tl_eof_chars : (char_u *)"\004\r\n", 3, NULL); +} # else diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -489,22 +489,22 @@ func Test_terminal_noblock() endfunc func Test_terminal_write_stdin() - " Todo: make this work on all systems. - if !has('unix') + if !executable('wc') + call ch_log('Test_terminal_write_stdin() is skipped because system doesn''t have wc command') return endif new call setline(1, ['one', 'two', 'three']) %term wc call WaitFor('getline(1) != ""') - let nrs = split(getline(1)) + let nrs = split(getline('$')) call assert_equal(['3', '3', '14'], nrs) bwipe call setline(1, ['one', 'two', 'three', 'four']) 2,3term wc call WaitFor('getline(1) != ""') - let nrs = split(getline(1)) + let nrs = split(getline('$')) call assert_equal(['2', '2', '10'], nrs) bwipe diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -770,6 +770,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1034, +/**/ 1033, /**/ 1032,