summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-08-20 18:09:14 +0200
committerBram Moolenaar <Bram@vim.org>2017-08-20 18:09:14 +0200
commitb241208a13d3e9def36d749b1e824ae694aa85f8 (patch)
tree3b5544c1e0dfe300b4351b2934bf0ce87f84ac0a /src
parentedbc0d46cffe1766d0b330dc2842212cff644f8e (diff)
downloadvim-git-b241208a13d3e9def36d749b1e824ae694aa85f8.tar.gz
patch 8.0.0976: cannot send lines to a terminal jobv8.0.0976
Problem: Cannot send lines to a terminal job. Solution: Make [range]terminal send selected lines to the job. Use ++rows and ++cols for the terminal size.
Diffstat (limited to 'src')
-rw-r--r--src/ex_cmds.h4
-rw-r--r--src/os_unix.c14
-rw-r--r--src/terminal.c83
-rw-r--r--src/testdir/test_terminal.vim8
-rw-r--r--src/version.c2
5 files changed, 85 insertions, 26 deletions
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index 6fb528d58..161ba1d11 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -1484,8 +1484,8 @@ EX(CMD_tearoff, "tearoff", ex_tearoff,
NEEDARG|EXTRA|TRLBAR|NOTRLCOM|CMDWIN,
ADDR_LINES),
EX(CMD_terminal, "terminal", ex_terminal,
- RANGE|NOTADR|BANG|FILES|TRLBAR|CMDWIN,
- ADDR_OTHER),
+ RANGE|BANG|FILES|TRLBAR|CMDWIN,
+ ADDR_LINES),
EX(CMD_tfirst, "tfirst", ex_tag,
RANGE|NOTADR|BANG|TRLBAR|ZEROR,
ADDR_LINES),
diff --git a/src/os_unix.c b/src/os_unix.c
index 40e0762ea..57b0dcdd9 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -5238,6 +5238,7 @@ mch_job_start(char **argv, job_T *job, jobopt_T *options)
int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
int use_file_for_out = options->jo_io[PART_OUT] == JIO_FILE;
int use_file_for_err = options->jo_io[PART_ERR] == JIO_FILE;
+ int use_buffer_for_in = options->jo_io[PART_IN] == JIO_BUFFER;
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
SIGSET_DECL(curset)
@@ -5247,7 +5248,10 @@ mch_job_start(char **argv, job_T *job, jobopt_T *options)
/* default is to fail */
job->jv_status = JOB_FAILED;
- if (options->jo_pty)
+ if (options->jo_pty
+ && (!(use_file_for_in || use_null_for_in)
+ || !(use_file_for_in || use_null_for_out)
+ || !(use_out_for_err || use_file_for_err || use_null_for_err)))
open_pty(&pty_master_fd, &pty_slave_fd, &job->jv_tty_name);
/* TODO: without the channel feature connect the child to /dev/null? */
@@ -5263,8 +5267,12 @@ mch_job_start(char **argv, job_T *job, jobopt_T *options)
goto failed;
}
}
- else if (!use_null_for_in && pty_master_fd < 0 && pipe(fd_in) < 0)
- goto failed;
+ else
+ /* When writing buffer lines to the input don't use the pty, so that
+ * the pipe can be closed when all lines were written. */
+ if (!use_null_for_in && (pty_master_fd < 0 || use_buffer_for_in)
+ && pipe(fd_in) < 0)
+ goto failed;
if (use_file_for_out)
{
diff --git a/src/terminal.c b/src/terminal.c
index 08e0f9b93..344622a21 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -38,7 +38,7 @@
* in tl_scrollback are no longer used.
*
* TODO:
- * - make [range]terminal pipe [range] lines to the terminal
+ * - test writing lines to terminal job when implemented for MS-Windows
* - implement term_setsize()
* - add test for giving error for invalid 'termsize' value.
* - support minimal size when 'termsize' is "rows*cols".
@@ -447,10 +447,14 @@ ex_terminal(exarg_T *eap)
cmd = eap->arg;
while (*cmd && *cmd == '+' && *(cmd + 1) == '+')
{
- char_u *p;
+ char_u *p, *ep;
cmd += 2;
p = skiptowhite(cmd);
+ ep = vim_strchr(cmd, '=');
+ if (ep != NULL && ep < p)
+ p = ep;
+
if ((int)(p - cmd) == 5 && STRNICMP(cmd, "close", 5) == 0)
opt.jo_term_finish = 'c';
else if ((int)(p - cmd) == 4 && STRNICMP(cmd, "open", 4) == 0)
@@ -459,6 +463,20 @@ ex_terminal(exarg_T *eap)
opt.jo_curwin = 1;
else if ((int)(p - cmd) == 6 && STRNICMP(cmd, "hidden", 6) == 0)
opt.jo_hidden = 1;
+ else if ((int)(p - cmd) == 4 && STRNICMP(cmd, "rows", 4) == 0
+ && ep != NULL && isdigit(ep[1]))
+ {
+ opt.jo_set2 |= JO2_TERM_ROWS;
+ opt.jo_term_rows = atoi((char *)ep + 1);
+ p = skiptowhite(cmd);
+ }
+ else if ((int)(p - cmd) == 4 && STRNICMP(cmd, "cols", 4) == 0
+ && ep != NULL && isdigit(ep[1]))
+ {
+ opt.jo_set2 |= JO2_TERM_COLS;
+ opt.jo_term_cols = atoi((char *)ep + 1);
+ p = skiptowhite(cmd);
+ }
else
{
if (*p)
@@ -472,17 +490,14 @@ ex_terminal(exarg_T *eap)
/* Make a copy, an autocommand may set 'shell'. */
tofree = cmd = vim_strsave(p_sh);
- if (eap->addr_count == 2)
+ if (eap->addr_count > 0)
{
- opt.jo_term_rows = eap->line1;
- opt.jo_term_cols = eap->line2;
- }
- else if (eap->addr_count == 1)
- {
- if (cmdmod.split & WSP_VERT)
- opt.jo_term_cols = eap->line2;
- else
- opt.jo_term_rows = eap->line2;
+ /* Write lines from current buffer to the job. */
+ opt.jo_set |= JO_IN_IO | JO_IN_BUF | JO_IN_TOP | JO_IN_BOT;
+ opt.jo_io[PART_IN] = JIO_BUFFER;
+ opt.jo_io_buf[PART_IN] = curbuf->b_fnum;
+ opt.jo_in_top = eap->line1;
+ opt.jo_in_bot = eap->line2;
}
argvar.v_type = VAR_STRING;
@@ -1078,6 +1093,29 @@ term_vgetc()
}
/*
+ * Get the part that is connected to the tty. Normally this is PART_IN, but
+ * when writing buffer lines to the job it can be another. This makes it
+ * possible to do "1,5term vim -".
+ */
+ static ch_part_T
+get_tty_part(term_T *term)
+{
+#ifdef UNIX
+ ch_part_T parts[3] = {PART_IN, PART_OUT, PART_ERR};
+ int i;
+
+ for (i = 0; i < 3; ++i)
+ {
+ int fd = term->tl_job->jv_channel->ch_part[parts[i]].ch_fd;
+
+ if (isatty(fd))
+ return parts[i];
+ }
+#endif
+ return PART_IN;
+}
+
+/*
* Send keys to terminal.
* Return FAIL when the key needs to be handled in Normal mode.
* Return OK when the key was dropped or sent to the terminal.
@@ -1148,8 +1186,8 @@ send_keys_to_term(term_T *term, int c, int typed)
len = term_convert_key(term, c, msg);
if (len > 0)
/* TODO: if FAIL is returned, stop? */
- channel_send(term->tl_job->jv_channel, PART_IN,
- (char_u *)msg, (int)len, NULL);
+ channel_send(term->tl_job->jv_channel, get_tty_part(term),
+ (char_u *)msg, (int)len, NULL);
return OK;
}
@@ -1332,7 +1370,8 @@ terminal_loop(void)
#ifdef UNIX
{
- int fd = curbuf->b_term->tl_job->jv_channel->ch_part[PART_IN].ch_fd;
+ int part = get_tty_part(curbuf->b_term);
+ int fd = curbuf->b_term->tl_job->jv_channel->ch_part[part].ch_fd;
if (isatty(fd))
{
@@ -2823,7 +2862,12 @@ dyn_winpty_init(int verbose)
* Return OK or FAIL.
*/
static int
-term_and_job_init(term_T *term, int rows, int cols, typval_T *argvar, jobopt_T *opt)
+term_and_job_init(
+ term_T *term,
+ int rows,
+ int cols,
+ typval_T *argvar,
+ jobopt_T *opt)
{
WCHAR *p = NULL;
channel_T *channel = NULL;
@@ -3020,7 +3064,12 @@ terminal_enabled(void)
* Return OK or FAIL.
*/
static int
-term_and_job_init(term_T *term, int rows, int cols, typval_T *argvar, jobopt_T *opt)
+term_and_job_init(
+ term_T *term,
+ int rows,
+ int cols,
+ typval_T *argvar,
+ jobopt_T *opt)
{
create_vterm(term, rows, cols);
diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim
index e737aead9..a4041d725 100644
--- a/src/testdir/test_terminal.vim
+++ b/src/testdir/test_terminal.vim
@@ -251,7 +251,7 @@ endfunc
func Test_terminal_size()
let cmd = Get_cat_123_cmd()
- exe '5terminal ' . cmd
+ exe 'terminal ++rows=5 ' . cmd
let size = term_getsize('')
bwipe!
call assert_equal(5, size[0])
@@ -262,7 +262,7 @@ func Test_terminal_size()
call assert_equal(6, size[0])
vsplit
- exe '5,33terminal ' . cmd
+ exe 'terminal ++rows=5 ++cols=33 ' . cmd
let size = term_getsize('')
bwipe!
call assert_equal([5, 33], size)
@@ -272,7 +272,7 @@ func Test_terminal_size()
bwipe!
call assert_equal([6, 36], size)
- exe 'vertical 20terminal ' . cmd
+ exe 'vertical terminal ++cols=20 ' . cmd
let size = term_getsize('')
bwipe!
call assert_equal(20, size[1])
@@ -283,7 +283,7 @@ func Test_terminal_size()
call assert_equal(26, size[1])
split
- exe 'vertical 6,20terminal ' . cmd
+ exe 'vertical terminal ++rows=6 ++cols=20 ' . cmd
let size = term_getsize('')
bwipe!
call assert_equal([6, 20], size)
diff --git a/src/version.c b/src/version.c
index 36af20968..c191dc77d 100644
--- 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 */
/**/
+ 976,
+/**/
975,
/**/
974,