mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.0.0846: cannot get the name of the pty of a job
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.
This commit is contained in:
parent
d8dc179937
commit
7c9aec4ac8
@ -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
|
||||||
@ -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
|
||||||
@ -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|
|
||||||
@ -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}.
|
||||||
@ -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
|
||||||
@ -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.
|
||||||
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
@ -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);
|
||||||
|
@ -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},
|
||||||
|
@ -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;
|
||||||
|
|
||||||
@ -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
|
||||||
@ -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.
|
||||||
*/
|
*/
|
||||||
@ -5189,9 +5191,9 @@ error:
|
|||||||
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;
|
||||||
@ -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. */
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
@ -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;
|
||||||
|
@ -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
|
||||||
@ -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;
|
||||||
|
|
||||||
@ -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
|
||||||
*/
|
*/
|
||||||
@ -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,
|
||||||
@ -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);
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user