Skip to content

Commit

Permalink
patch 8.0.0846: cannot get the name of the pty of a job
Browse files Browse the repository at this point in the history
Problem:    Cannot get the name of the pty of a job.
Solution:   Add the "tty" entry to the job info. (Ozaki Kiichi, closes #1920)
            Add the term_gettty() function.
  • Loading branch information
brammool committed Aug 3, 2017
1 parent d8dc179 commit 7c9aec4
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 26 deletions.
19 changes: 14 additions & 5 deletions runtime/doc/eval.txt
@@ -1,4 +1,4 @@
*eval.txt* For Vim version 8.0. Last change: 2017 Aug 01 *eval.txt* For Vim version 8.0. Last change: 2017 Aug 03




VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
Expand Down Expand Up @@ -2376,6 +2376,7 @@ term_getline({buf}, {row}) String get a line of text from a terminal
term_getsize({buf}) List get the size of a terminal term_getsize({buf}) List get the size of a terminal
term_getstatus({buf}) String get the status of a terminal term_getstatus({buf}) String get the status of a terminal
term_gettitle({buf}) String get the title of a terminal term_gettitle({buf}) String get the title of a terminal
term_gettty({buf}) String get the tty name of a terminal
term_list() List get the list of terminal buffers term_list() List get the list of terminal buffers
term_scrape({buf}, {row}) List get row of a terminal screen term_scrape({buf}, {row}) List get row of a terminal screen
term_sendkeys({buf}, {keys}) none send keystrokes to a terminal term_sendkeys({buf}, {keys}) none send keystrokes to a terminal
Expand Down Expand Up @@ -5192,6 +5193,8 @@ job_info({job}) *job_info()*
Returns a Dictionary with information about {job}: Returns a Dictionary with information about {job}:
"status" what |job_status()| returns "status" what |job_status()| returns
"channel" what |job_getchannel()| returns "channel" what |job_getchannel()| returns
"process" process ID
"tty" controlling terminal name, empty when none
"exitval" only valid when "status" is "dead" "exitval" only valid when "status" is "dead"
"exit_cb" function to be called on exit "exit_cb" function to be called on exit
"stoponexit" |job-stoponexit| "stoponexit" |job-stoponexit|
Expand Down Expand Up @@ -7930,6 +7933,7 @@ term_getcursor({buf}) *term_getcursor()*
term_getjob({buf}) *term_getjob()* term_getjob({buf}) *term_getjob()*
Get the Job associated with terminal window {buf}. Get the Job associated with terminal window {buf}.
{buf} is used as with |term_getsize()|. {buf} is used as with |term_getsize()|.
Returns |v:null| when there is no job.


term_getline({buf}, {row}) *term_getline()* term_getline({buf}, {row}) *term_getline()*
Get a line of text from the terminal window of {buf}. Get a line of text from the terminal window of {buf}.
Expand All @@ -7943,9 +7947,9 @@ term_getsize({buf}) *term_getsize()*
numbers: [rows, cols]. This is the size of the terminal, not numbers: [rows, cols]. This is the size of the terminal, not
the window containing the terminal. the window containing the terminal.


{buf} must be the buffer number of a terminal window. If the {buf} must be the buffer number of a terminal window. Use an
buffer does not exist or is not a terminal window, an empty empty string for the current buffer. If the buffer does not
list is returned. exist or is not a terminal window, an empty list is returned.


term_getstatus({buf}) *term_getstatus()* term_getstatus({buf}) *term_getstatus()*
Get the status of terminal {buf}. This returns a comma Get the status of terminal {buf}. This returns a comma
Expand All @@ -7967,6 +7971,11 @@ term_gettitle({buf}) *term_gettitle()*
buffer does not exist or is not a terminal window, an empty buffer does not exist or is not a terminal window, an empty
string is returned. string is returned.


term_gettty({buf}) *term_gettty()*
Get the name of the controlling terminal associated with
terminal window {buf}.
{buf} is used as with |term_getsize()|.

term_list() *term_list()* term_list() *term_list()*
Return a list with the buffer numbers of all buffers for Return a list with the buffer numbers of all buffers for
terminal windows. terminal windows.
Expand All @@ -7982,7 +7991,7 @@ term_scrape({buf}, {row}) *term_scrape()*
"chars" character(s) at the cell "chars" character(s) at the cell
"fg" foreground color as #rrggbb "fg" foreground color as #rrggbb
"bg" background color as #rrggbb "bg" background color as #rrggbb
"attr" attributes of the cell, use term_getattr() "attr" attributes of the cell, use |term_getattr()|
to get the individual flags to get the individual flags
"width" cell width: 1 or 2 "width" cell width: 1 or 2


Expand Down
11 changes: 6 additions & 5 deletions src/channel.c
Expand Up @@ -1016,11 +1016,9 @@ ch_close_part(channel_T *channel, ch_part_T part)
{ {
/* When using a pty the same FD is set on multiple parts, only /* When using a pty the same FD is set on multiple parts, only
* close it when the last reference is closed. */ * close it when the last reference is closed. */
if ((part == PART_IN || channel->ch_part[PART_IN].ch_fd != *fd) if ((part == PART_IN || channel->CH_IN_FD != *fd)
&& (part == PART_OUT && (part == PART_OUT || channel->CH_OUT_FD != *fd)
|| channel->ch_part[PART_OUT].ch_fd != *fd) && (part == PART_ERR || channel->CH_ERR_FD != *fd))
&& (part == PART_ERR
|| channel->ch_part[PART_ERR].ch_fd != *fd))
fd_close(*fd); fd_close(*fd);
} }
*fd = INVALID_FD; *fd = INVALID_FD;
Expand Down Expand Up @@ -4592,6 +4590,7 @@ job_free_contents(job_T *job)
} }
mch_clear_job(job); mch_clear_job(job);


vim_free(job->jv_tty_name);
vim_free(job->jv_stoponexit); vim_free(job->jv_stoponexit);
free_callback(job->jv_exit_cb, job->jv_exit_partial); free_callback(job->jv_exit_cb, job->jv_exit_partial);
} }
Expand Down Expand Up @@ -5164,6 +5163,8 @@ job_info(job_T *job, dict_T *dict)
nr = job->jv_proc_info.dwProcessId; nr = job->jv_proc_info.dwProcessId;
#endif #endif
dict_add_nr_str(dict, "process", nr, NULL); dict_add_nr_str(dict, "process", nr, NULL);
dict_add_nr_str(dict, "tty", 0L,
job->jv_tty_name != NULL ? job->jv_tty_name : (char_u *)"");


dict_add_nr_str(dict, "exitval", job->jv_exitval, NULL); dict_add_nr_str(dict, "exitval", job->jv_exitval, NULL);
dict_add_nr_str(dict, "exit_cb", 0L, job->jv_exit_cb); dict_add_nr_str(dict, "exit_cb", 0L, job->jv_exit_cb);
Expand Down
1 change: 1 addition & 0 deletions src/evalfunc.c
Expand Up @@ -838,6 +838,7 @@ static struct fst
{"term_getsize", 1, 1, f_term_getsize}, {"term_getsize", 1, 1, f_term_getsize},
{"term_getstatus", 1, 1, f_term_getstatus}, {"term_getstatus", 1, 1, f_term_getstatus},
{"term_gettitle", 1, 1, f_term_gettitle}, {"term_gettitle", 1, 1, f_term_gettitle},
{"term_gettty", 1, 1, f_term_gettty},
{"term_list", 0, 0, f_term_list}, {"term_list", 0, 0, f_term_list},
{"term_scrape", 1, 2, f_term_scrape}, {"term_scrape", 1, 2, f_term_scrape},
{"term_sendkeys", 2, 2, f_term_sendkeys}, {"term_sendkeys", 2, 2, f_term_sendkeys},
Expand Down
20 changes: 8 additions & 12 deletions src/os_unix.c
Expand Up @@ -4170,7 +4170,7 @@ set_default_child_environment(void)
* When successful both file descriptors are stored. * When successful both file descriptors are stored.
*/ */
static void static void
open_pty(int *pty_master_fd, int *pty_slave_fd) open_pty(int *pty_master_fd, int *pty_slave_fd, char_u **namep)
{ {
char *tty_name; char *tty_name;


Expand All @@ -4190,6 +4190,8 @@ open_pty(int *pty_master_fd, int *pty_slave_fd)
close(*pty_master_fd); close(*pty_master_fd);
*pty_master_fd = -1; *pty_master_fd = -1;
} }
else if (namep != NULL)
*namep = vim_strsave((char_u *)tty_name);
} }
} }
#endif #endif
Expand Down Expand Up @@ -4384,7 +4386,7 @@ mch_call_shell(
* If the slave can't be opened, close the master pty. * If the slave can't be opened, close the master pty.
*/ */
if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE))) if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
open_pty(&pty_master_fd, &pty_slave_fd); open_pty(&pty_master_fd, &pty_slave_fd, NULL);
/* /*
* If not opening a pty or it didn't work, try using pipes. * If not opening a pty or it didn't work, try using pipes.
*/ */
Expand Down Expand Up @@ -5189,9 +5191,9 @@ mch_call_shell(
mch_job_start(char **argv, job_T *job, jobopt_T *options) mch_job_start(char **argv, job_T *job, jobopt_T *options)
{ {
pid_t pid; pid_t pid;
int fd_in[2]; /* for stdin */ int fd_in[2] = {-1, -1}; /* for stdin */
int fd_out[2]; /* for stdout */ int fd_out[2] = {-1, -1}; /* for stdout */
int fd_err[2]; /* for stderr */ int fd_err[2] = {-1, -1}; /* for stderr */
int pty_master_fd = -1; int pty_master_fd = -1;
int pty_slave_fd = -1; int pty_slave_fd = -1;
channel_T *channel = NULL; channel_T *channel = NULL;
Expand All @@ -5209,15 +5211,9 @@ mch_job_start(char **argv, job_T *job, jobopt_T *options)


/* default is to fail */ /* default is to fail */
job->jv_status = JOB_FAILED; job->jv_status = JOB_FAILED;
fd_in[0] = -1;
fd_in[1] = -1;
fd_out[0] = -1;
fd_out[1] = -1;
fd_err[0] = -1;
fd_err[1] = -1;


if (options->jo_pty) if (options->jo_pty)
open_pty(&pty_master_fd, &pty_slave_fd); open_pty(&pty_master_fd, &pty_slave_fd, &job->jv_tty_name);


/* TODO: without the channel feature connect the child to /dev/null? */ /* TODO: without the channel feature connect the child to /dev/null? */
/* Open pipes for stdin, stdout, stderr. */ /* Open pipes for stdin, stdout, stderr. */
Expand Down
1 change: 1 addition & 0 deletions src/proto/terminal.pro
Expand Up @@ -23,6 +23,7 @@ void f_term_getline(typval_T *argvars, typval_T *rettv);
void f_term_getsize(typval_T *argvars, typval_T *rettv); void f_term_getsize(typval_T *argvars, typval_T *rettv);
void f_term_getstatus(typval_T *argvars, typval_T *rettv); void f_term_getstatus(typval_T *argvars, typval_T *rettv);
void f_term_gettitle(typval_T *argvars, typval_T *rettv); void f_term_gettitle(typval_T *argvars, typval_T *rettv);
void f_term_gettty(typval_T *argvars, typval_T *rettv);
void f_term_list(typval_T *argvars, typval_T *rettv); void f_term_list(typval_T *argvars, typval_T *rettv);
void f_term_scrape(typval_T *argvars, typval_T *rettv); void f_term_scrape(typval_T *argvars, typval_T *rettv);
void f_term_sendkeys(typval_T *argvars, typval_T *rettv); void f_term_sendkeys(typval_T *argvars, typval_T *rettv);
Expand Down
11 changes: 7 additions & 4 deletions src/structs.h
Expand Up @@ -1478,6 +1478,7 @@ struct jobvar_S
PROCESS_INFORMATION jv_proc_info; PROCESS_INFORMATION jv_proc_info;
HANDLE jv_job_object; HANDLE jv_job_object;
#endif #endif
char_u *jv_tty_name; /* controlling tty, allocated */
jobstatus_T jv_status; jobstatus_T jv_status;
char_u *jv_stoponexit; /* allocated */ char_u *jv_stoponexit; /* allocated */
int jv_exitval; int jv_exitval;
Expand Down Expand Up @@ -1537,18 +1538,20 @@ typedef enum {
JIO_OUT JIO_OUT
} job_io_T; } job_io_T;


#define CH_PART_FD(part) ch_part[part].ch_fd

/* Ordering matters, it is used in for loops: IN is last, only SOCK/OUT/ERR /* Ordering matters, it is used in for loops: IN is last, only SOCK/OUT/ERR
* are polled. */ * are polled. */
typedef enum { typedef enum {
PART_SOCK = 0, PART_SOCK = 0,
#define CH_SOCK_FD ch_part[PART_SOCK].ch_fd #define CH_SOCK_FD CH_PART_FD(PART_SOCK)
#ifdef FEAT_JOB_CHANNEL #ifdef FEAT_JOB_CHANNEL
PART_OUT, PART_OUT,
# define CH_OUT_FD ch_part[PART_OUT].ch_fd # define CH_OUT_FD CH_PART_FD(PART_OUT)
PART_ERR, PART_ERR,
# define CH_ERR_FD ch_part[PART_ERR].ch_fd # define CH_ERR_FD CH_PART_FD(PART_ERR)
PART_IN, PART_IN,
# define CH_IN_FD ch_part[PART_IN].ch_fd # define CH_IN_FD CH_PART_FD(PART_IN)
#endif #endif
PART_COUNT PART_COUNT
} ch_part_T; } ch_part_T;
Expand Down
30 changes: 30 additions & 0 deletions src/terminal.c
Expand Up @@ -57,12 +57,16 @@
* - add 't' to mode() * - add 't' to mode()
* - set 'filetype' to "terminal"? * - set 'filetype' to "terminal"?
* - use win_del_lines() to make scroll-up efficient. * - use win_del_lines() to make scroll-up efficient.
* - Make StatusLineTerm adjust UserN highlighting like StatusLineNC does, see
* use of hightlight_stlnc[].
* - implement term_setsize() * - implement term_setsize()
* - add test for giving error for invalid 'termsize' value. * - add test for giving error for invalid 'termsize' value.
* - support minimal size when 'termsize' is "rows*cols". * - support minimal size when 'termsize' is "rows*cols".
* - support minimal size when 'termsize' is empty? * - support minimal size when 'termsize' is empty?
* - implement "term" for job_start(): more job options when starting a * - implement "term" for job_start(): more job options when starting a
* terminal. * terminal.
* - support ":term NONE" to open a terminal with a pty but not running a job
* in it. The pty can be passed to gdb to run the executable in.
* - if the job in the terminal does not support the mouse, we can use the * - if the job in the terminal does not support the mouse, we can use the
* mouse in the Terminal window for copy/paste. * mouse in the Terminal window for copy/paste.
* - when 'encoding' is not utf-8, or the job is using another encoding, setup * - when 'encoding' is not utf-8, or the job is using another encoding, setup
Expand Down Expand Up @@ -97,6 +101,10 @@ struct terminal_S {
job_T *tl_job; job_T *tl_job;
buf_T *tl_buffer; buf_T *tl_buffer;


/* used when tl_job is NULL and only a pty was created */
int tl_tty_fd;
char_u *tl_tty_name;

int tl_terminal_mode; int tl_terminal_mode;
int tl_channel_closed; int tl_channel_closed;


Expand Down Expand Up @@ -1924,6 +1932,26 @@ f_term_gettitle(typval_T *argvars, typval_T *rettv)
rettv->vval.v_string = vim_strsave(buf->b_term->tl_title); rettv->vval.v_string = vim_strsave(buf->b_term->tl_title);
} }


/*
* "term_gettty(buf)" function
*/
void
f_term_gettty(typval_T *argvars, typval_T *rettv)
{
buf_T *buf = term_get_buf(argvars);
char_u *p;

rettv->v_type = VAR_STRING;
if (buf == NULL)
return;
if (buf->b_term->tl_job != NULL)
p = buf->b_term->tl_job->jv_tty_name;
else
p = buf->b_term->tl_tty_name;
if (p != NULL)
rettv->vval.v_string = vim_strsave(p);
}

/* /*
* "term_list()" function * "term_list()" function
*/ */
Expand Down Expand Up @@ -2216,6 +2244,7 @@ term_and_job_init(term_T *term, int rows, int cols, char_u *cmd)
if (term->tl_winpty == NULL) if (term->tl_winpty == NULL)
goto failed; goto failed;


/* TODO: if the command is "NONE" only create a pty. */
spawn_config = winpty_spawn_config_new( spawn_config = winpty_spawn_config_new(
WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN | WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN |
WINPTY_SPAWN_FLAG_EXIT_AFTER_SHUTDOWN, WINPTY_SPAWN_FLAG_EXIT_AFTER_SHUTDOWN,
Expand Down Expand Up @@ -2359,6 +2388,7 @@ term_and_job_init(term_T *term, int rows, int cols, char_u *cmd)


create_vterm(term, rows, cols); create_vterm(term, rows, cols);


/* TODO: if the command is "NONE" only create a pty. */
argvars[0].v_type = VAR_STRING; argvars[0].v_type = VAR_STRING;
argvars[0].vval.v_string = cmd; argvars[0].vval.v_string = cmd;
setup_job_options(&opt, rows, cols); setup_job_options(&opt, rows, cols);
Expand Down
6 changes: 6 additions & 0 deletions src/testdir/test_terminal.vim
Expand Up @@ -30,6 +30,12 @@ endfunc


func Test_terminal_basic() func Test_terminal_basic()
let buf = Run_shell_in_terminal() let buf = Run_shell_in_terminal()
if has("unix")
call assert_match("^/dev/", job_info(g:job).tty)
call assert_match("^/dev/", term_gettty(''))
else
call assert_equal("", job_info(g:job).tty)
endif
call Stop_shell_in_terminal(buf) call Stop_shell_in_terminal(buf)
call term_wait(buf) call term_wait(buf)


Expand Down
2 changes: 2 additions & 0 deletions src/version.c
Expand Up @@ -769,6 +769,8 @@ static char *(features[]) =


static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
846,
/**/ /**/
845, 845,
/**/ /**/
Expand Down

0 comments on commit 7c9aec4

Please sign in to comment.