mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-15 10:30:25 -08:00
Generalize start-process with keyword args
* src/process.c (Fmake_process): New function. (create_process, create_pty): Check p->pty_flag instead of Vprocess_connection_type. (syms_of_process): Register QCcommand, QCconnection_type, Qpty, Qpipe, and Smake_process. Unregister Sstart_process. * lisp/subr.el (start-process): New function, ported from the C implementation. * doc/lispref/processes.texi (Asynchronous Processes): Mention `make-process'. * etc/NEWS: Mention `make-process'.
This commit is contained in:
parent
165bea7800
commit
47e0e31932
8 changed files with 237 additions and 43 deletions
|
|
@ -1,3 +1,7 @@
|
|||
2015-03-23 Daiki Ueno <ueno@gnu.org>
|
||||
|
||||
* processes.texi (Asynchronous Processes): Mention `make-process'.
|
||||
|
||||
2015-03-18 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* minibuf.texi (Basic Completion): Fix a typo. (Bug#20108)
|
||||
|
|
|
|||
|
|
@ -692,6 +692,61 @@ use the function @code{process-tty-name} (@pxref{Process
|
|||
Information}).
|
||||
@end defvar
|
||||
|
||||
@defun make-process &rest args
|
||||
This function is like @code{start-process}, but takes keyword arguments.
|
||||
|
||||
The arguments @var{args} are a list of keyword/argument pairs.
|
||||
Omitting a keyword is always equivalent to specifying it with value
|
||||
@code{nil}. Here are the meaningful keywords:
|
||||
|
||||
@table @asis
|
||||
@item :name @var{name}
|
||||
Use the string @var{name} as the process name. It is modified if
|
||||
necessary to make it unique.
|
||||
|
||||
@item :buffer @var{buffer}
|
||||
Use @var{buffer} as the process buffer.
|
||||
|
||||
@item :command @var{command}
|
||||
Use @var{command} as the command line of the process. @var{command}
|
||||
is a list starting with the program's executable file name, followed
|
||||
by strings to give to program as arguments.
|
||||
|
||||
@item :coding @var{coding}
|
||||
If @var{coding} is a symbol, it specifies the coding system to be
|
||||
used for both reading and writing of data from and to the
|
||||
connection. If @var{coding} is a cons cell
|
||||
@w{@code{(@var{decoding} . @var{encoding})}}, then @var{decoding}
|
||||
will be used for reading and @var{encoding} for writing.
|
||||
|
||||
If @var{coding} is @code{nil}, the default rules for finding the
|
||||
coding system will apply. @xref{Default Coding Systems}.
|
||||
|
||||
@item :connection-type @var{TYPE}
|
||||
Initialize the type of device used to communicate with the subprocess.
|
||||
Possible values are @code{pty} to use a pty, @code{pipe} to use a
|
||||
pipe, or @code{nil} to use the default derived from the value of
|
||||
the @code{process-connection-type} variable.
|
||||
|
||||
@item :noquery @var{query-flag}
|
||||
Initialize the process query flag to @var{query-flag}.
|
||||
@xref{Query Before Exit}.
|
||||
|
||||
@item :stop @var{stopped}
|
||||
If @var{stopped} is non-@code{nil}, start the process in the
|
||||
``stopped'' state.
|
||||
|
||||
@item :filter @var{filter}
|
||||
Initialize the process filter to @var{filter}.
|
||||
|
||||
@item :sentinel @var{sentinel}
|
||||
Initialize the process sentinel to @var{sentinel}.
|
||||
@end table
|
||||
|
||||
The original argument list, modified with the actual connection
|
||||
information, is available via the @code{process-contact} function.
|
||||
@end defun
|
||||
|
||||
@node Deleting Processes
|
||||
@section Deleting Processes
|
||||
@cindex deleting processes
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
2015-03-23 Daiki Ueno <ueno@gnu.org>
|
||||
|
||||
* NEWS: Mention `make-process'.
|
||||
|
||||
2015-03-21 Titus von der Malsburg <malsburg@posteo.de>
|
||||
|
||||
* NEWS: Mention `default-font-width', `window-font-height',
|
||||
|
|
|
|||
5
etc/NEWS
5
etc/NEWS
|
|
@ -651,6 +651,11 @@ word syntax, use `\sw' instead.
|
|||
|
||||
* Lisp Changes in Emacs 25.1
|
||||
|
||||
** New function `make-process' provides an alternative interface to
|
||||
`start-process'. It allows programs to set process parameters such as
|
||||
process filter, sentinel, etc., through keyword arguments (similar to
|
||||
`make-network-process').
|
||||
|
||||
** `read-buffer' takes a new `predicate' argument.
|
||||
|
||||
** Emacs Lisp now supports generators.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
2015-03-23 Daiki Ueno <ueno@gnu.org>
|
||||
|
||||
* subr.el (start-process): New function, ported from the C
|
||||
implementation.
|
||||
|
||||
2015-03-23 Daniel Colascione <dancol@dancol.org>
|
||||
|
||||
Automatically adjust process window sizes.
|
||||
|
|
|
|||
24
lisp/subr.el
24
lisp/subr.el
|
|
@ -1901,6 +1901,30 @@ and the file name is displayed in the echo area."
|
|||
|
||||
;;;; Process stuff.
|
||||
|
||||
(defun start-process (name buffer program &rest program-args)
|
||||
"Start a program in a subprocess. Return the process object for it.
|
||||
NAME is name for process. It is modified if necessary to make it unique.
|
||||
BUFFER is the buffer (or buffer name) to associate with the process.
|
||||
|
||||
Process output (both standard output and standard error streams) goes
|
||||
at end of BUFFER, unless you specify an output stream or filter
|
||||
function to handle the output. BUFFER may also be nil, meaning that
|
||||
this process is not associated with any buffer.
|
||||
|
||||
PROGRAM is the program file name. It is searched for in `exec-path'
|
||||
\(which see). If nil, just associate a pty with the buffer. Remaining
|
||||
arguments are strings to give program as arguments.
|
||||
|
||||
If you want to separate standard output from standard error, invoke
|
||||
the command through a shell and redirect one of them using the shell
|
||||
syntax."
|
||||
(unless (fboundp 'make-process)
|
||||
(error "Emacs was compiled without subprocess support"))
|
||||
(apply #'make-process
|
||||
(append (list :name name :buffer buffer)
|
||||
(if program
|
||||
(list :command (cons program program-args))))))
|
||||
|
||||
(defun process-lines (program &rest args)
|
||||
"Execute PROGRAM with ARGS, returning its output as a list of lines.
|
||||
Signal an error if the program returns with a non-zero exit status."
|
||||
|
|
|
|||
|
|
@ -1,3 +1,11 @@
|
|||
2015-03-23 Daiki Ueno <ueno@gnu.org>
|
||||
|
||||
* process.c (Fmake_process): New function.
|
||||
(create_process, create_pty): Check p->pty_flag instead of
|
||||
Vprocess_connection_type.
|
||||
(syms_of_process): Register QCcommand, QCconnection_type, Qpty,
|
||||
Qpipe, and Smake_process. Unregister Sstart_process.
|
||||
|
||||
2015-03-22 Jan Djärv <jan.h.d@swipnet.se>
|
||||
|
||||
* fontset.c (fontset_pattern_regexp): Replace + 1 with + 3 for
|
||||
|
|
|
|||
175
src/process.c
175
src/process.c
|
|
@ -1355,34 +1355,63 @@ DEFUN ("process-list", Fprocess_list, Sprocess_list, 0, 0, 0,
|
|||
|
||||
static void start_process_unwind (Lisp_Object proc);
|
||||
|
||||
DEFUN ("start-process", Fstart_process, Sstart_process, 3, MANY, 0,
|
||||
DEFUN ("make-process", Fmake_process, Smake_process, 0, MANY, 0,
|
||||
doc: /* Start a program in a subprocess. Return the process object for it.
|
||||
NAME is name for process. It is modified if necessary to make it unique.
|
||||
BUFFER is the buffer (or buffer name) to associate with the process.
|
||||
|
||||
Process output (both standard output and standard error streams) goes
|
||||
at end of BUFFER, unless you specify an output stream or filter
|
||||
function to handle the output. BUFFER may also be nil, meaning that
|
||||
this process is not associated with any buffer.
|
||||
This is similar to `start-process', but arguments are specified as
|
||||
keyword/argument pairs. The following arguments are defined:
|
||||
|
||||
PROGRAM is the program file name. It is searched for in `exec-path'
|
||||
(which see). If nil, just associate a pty with the buffer. Remaining
|
||||
arguments are strings to give program as arguments.
|
||||
:name NAME -- NAME is name for process. It is modified if necessary
|
||||
to make it unique.
|
||||
|
||||
If you want to separate standard output from standard error, invoke
|
||||
the command through a shell and redirect one of them using the shell
|
||||
syntax.
|
||||
:buffer BUFFER -- BUFFER is the buffer (or buffer-name) to associate
|
||||
with the process. Process output goes at end of that buffer, unless
|
||||
you specify an output stream or filter function to handle the output.
|
||||
BUFFER may be also nil, meaning that this process is not associated
|
||||
with any buffer.
|
||||
|
||||
usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
|
||||
:command COMMAND -- COMMAND is a list starting with the program file
|
||||
name, followed by strings to give to the program as arguments.
|
||||
|
||||
:coding CODING -- If CODING is a symbol, it specifies the coding
|
||||
system used for both reading and writing for this process. If CODING
|
||||
is a cons (DECODING . ENCODING), DECODING is used for reading, and
|
||||
ENCODING is used for writing.
|
||||
|
||||
:noquery BOOL -- When exiting Emacs, query the user if BOOL is nil and
|
||||
the process is running. If BOOL is not given, query before exiting.
|
||||
|
||||
:stop BOOL -- Start process in the `stopped' state if BOOL non-nil.
|
||||
In the stopped state, a process does not accept incoming data, but you
|
||||
can send outgoing data. The stopped state is cleared by
|
||||
`continue-process' and set by `stop-process'.
|
||||
|
||||
:connection-type TYPE -- TYPE is control type of device used to
|
||||
communicate with subprocesses. Values are `pipe' to use a pipe, `pty'
|
||||
to use a pty, or nil to use the default specified through
|
||||
`process-connection-type'.
|
||||
|
||||
:filter FILTER -- Install FILTER as the process filter.
|
||||
|
||||
:sentinel SENTINEL -- Install SENTINEL as the process sentinel.
|
||||
|
||||
usage: (make-process &rest ARGS) */)
|
||||
(ptrdiff_t nargs, Lisp_Object *args)
|
||||
{
|
||||
Lisp_Object buffer, name, program, proc, current_dir, tem;
|
||||
unsigned char **new_argv;
|
||||
Lisp_Object buffer, name, command, program, proc, contact, current_dir, tem;
|
||||
ptrdiff_t i;
|
||||
ptrdiff_t count = SPECPDL_INDEX ();
|
||||
struct gcpro gcpro1;
|
||||
USE_SAFE_ALLOCA;
|
||||
|
||||
buffer = args[1];
|
||||
if (nargs == 0)
|
||||
return Qnil;
|
||||
|
||||
/* Save arguments for process-contact and clone-process. */
|
||||
contact = Flist (nargs, args);
|
||||
GCPRO1 (contact);
|
||||
|
||||
buffer = Fplist_get (contact, QCbuffer);
|
||||
if (!NILP (buffer))
|
||||
buffer = Fget_buffer_create (buffer);
|
||||
|
||||
|
|
@ -1402,10 +1431,14 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
|
|||
UNGCPRO;
|
||||
}
|
||||
|
||||
name = args[0];
|
||||
name = Fplist_get (contact, QCname);
|
||||
CHECK_STRING (name);
|
||||
|
||||
program = args[2];
|
||||
command = Fplist_get (contact, QCcommand);
|
||||
if (CONSP (command))
|
||||
program = XCAR (command);
|
||||
else
|
||||
program = Qnil;
|
||||
|
||||
if (!NILP (program))
|
||||
CHECK_STRING (program);
|
||||
|
|
@ -1423,7 +1456,22 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
|
|||
pset_buffer (XPROCESS (proc), buffer);
|
||||
pset_sentinel (XPROCESS (proc), Qinternal_default_process_sentinel);
|
||||
pset_filter (XPROCESS (proc), Qinternal_default_process_filter);
|
||||
pset_command (XPROCESS (proc), Flist (nargs - 2, args + 2));
|
||||
pset_command (XPROCESS (proc), Fcopy_sequence (command));
|
||||
|
||||
if (tem = Fplist_get (contact, QCnoquery), !NILP (tem))
|
||||
XPROCESS (proc)->kill_without_query = 1;
|
||||
if (tem = Fplist_get (contact, QCstop), !NILP (tem))
|
||||
pset_command (XPROCESS (proc), Qt);
|
||||
|
||||
tem = Fplist_get (contact, QCconnection_type);
|
||||
if (EQ (tem, Qpty))
|
||||
XPROCESS (proc)->pty_flag = true;
|
||||
else if (EQ (tem, Qpipe))
|
||||
XPROCESS (proc)->pty_flag = false;
|
||||
else if (NILP (tem))
|
||||
XPROCESS (proc)->pty_flag = !NILP (Vprocess_connection_type);
|
||||
else
|
||||
report_file_error ("Unknown connection type", tem);
|
||||
|
||||
#ifdef HAVE_GNUTLS
|
||||
/* AKA GNUTLS_INITSTAGE(proc). */
|
||||
|
|
@ -1453,15 +1501,29 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
|
|||
Lisp_Object val, *args2;
|
||||
struct gcpro gcpro1, gcpro2;
|
||||
|
||||
val = Vcoding_system_for_read;
|
||||
tem = Fplist_get (contact, QCcoding);
|
||||
if (!NILP (tem))
|
||||
{
|
||||
val = tem;
|
||||
if (CONSP (val))
|
||||
val = XCAR (val);
|
||||
}
|
||||
else
|
||||
val = Vcoding_system_for_read;
|
||||
if (NILP (val))
|
||||
{
|
||||
SAFE_ALLOCA_LISP (args2, nargs + 1);
|
||||
args2[0] = Qstart_process;
|
||||
for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
|
||||
ptrdiff_t nargs2 = 3 + XINT (Flength (command));
|
||||
Lisp_Object tem2;
|
||||
SAFE_ALLOCA_LISP (args2, nargs2);
|
||||
i = 0;
|
||||
args2[i++] = Qstart_process;
|
||||
args2[i++] = name;
|
||||
args2[i++] = buffer;
|
||||
for (tem2 = command; CONSP (tem2); tem2 = XCDR (tem2))
|
||||
args2[i++] = XCAR (tem2);
|
||||
GCPRO2 (proc, current_dir);
|
||||
if (!NILP (program))
|
||||
coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
|
||||
coding_systems = Ffind_operation_coding_system (nargs2, args2);
|
||||
UNGCPRO;
|
||||
if (CONSP (coding_systems))
|
||||
val = XCAR (coding_systems);
|
||||
|
|
@ -1470,17 +1532,30 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
|
|||
}
|
||||
pset_decode_coding_system (XPROCESS (proc), val);
|
||||
|
||||
val = Vcoding_system_for_write;
|
||||
if (!NILP (tem))
|
||||
{
|
||||
val = tem;
|
||||
if (CONSP (val))
|
||||
val = XCDR (val);
|
||||
}
|
||||
else
|
||||
val = Vcoding_system_for_write;
|
||||
if (NILP (val))
|
||||
{
|
||||
if (EQ (coding_systems, Qt))
|
||||
{
|
||||
SAFE_ALLOCA_LISP (args2, nargs + 1);
|
||||
args2[0] = Qstart_process;
|
||||
for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
|
||||
ptrdiff_t nargs2 = 3 + XINT (Flength (command));
|
||||
Lisp_Object tem2;
|
||||
SAFE_ALLOCA_LISP (args2, nargs2);
|
||||
i = 0;
|
||||
args2[i++] = Qstart_process;
|
||||
args2[i++] = name;
|
||||
args2[i++] = buffer;
|
||||
for (tem2 = command; CONSP (tem2); tem2 = XCDR (tem2))
|
||||
args2[i++] = XCAR (tem2);
|
||||
GCPRO2 (proc, current_dir);
|
||||
if (!NILP (program))
|
||||
coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
|
||||
coding_systems = Ffind_operation_coding_system (nargs2, args2);
|
||||
UNGCPRO;
|
||||
}
|
||||
if (CONSP (coding_systems))
|
||||
|
|
@ -1506,16 +1581,20 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
|
|||
|
||||
if (!NILP (program))
|
||||
{
|
||||
Lisp_Object program_args = XCDR (command);
|
||||
unsigned char **new_argv;
|
||||
ptrdiff_t new_argc;
|
||||
|
||||
/* If program file name is not absolute, search our path for it.
|
||||
Put the name we will really use in TEM. */
|
||||
if (!IS_DIRECTORY_SEP (SREF (program, 0))
|
||||
&& !(SCHARS (program) > 1
|
||||
&& IS_DEVICE_SEP (SREF (program, 1))))
|
||||
{
|
||||
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
|
||||
struct gcpro gcpro1, gcpro2;
|
||||
|
||||
tem = Qnil;
|
||||
GCPRO4 (name, program, buffer, current_dir);
|
||||
GCPRO2 (buffer, current_dir);
|
||||
openp (Vexec_path, program, Vexec_suffixes, &tem,
|
||||
make_number (X_OK), false);
|
||||
UNGCPRO;
|
||||
|
|
@ -1534,7 +1613,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
|
|||
tem = remove_slash_colon (tem);
|
||||
|
||||
{
|
||||
Lisp_Object arg_encoding = Qnil;
|
||||
Lisp_Object arg_encoding = Qnil, tem2;
|
||||
struct gcpro gcpro1;
|
||||
GCPRO1 (tem);
|
||||
|
||||
|
|
@ -1547,9 +1626,9 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
|
|||
systems for encoding arguments and for encoding data sent to the
|
||||
process. */
|
||||
|
||||
for (i = 3; i < nargs; i++)
|
||||
for (tem2 = program_args; CONSP (tem2); tem2 = XCDR (tem2))
|
||||
{
|
||||
tem = Fcons (args[i], tem);
|
||||
tem = Fcons (XCAR (tem2), tem);
|
||||
CHECK_STRING (XCAR (tem));
|
||||
if (STRING_MULTIBYTE (XCAR (tem)))
|
||||
{
|
||||
|
|
@ -1567,10 +1646,11 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
|
|||
|
||||
/* Now that everything is encoded we can collect the strings into
|
||||
NEW_ARGV. */
|
||||
SAFE_NALLOCA (new_argv, 1, nargs - 1);
|
||||
new_argv[nargs - 2] = 0;
|
||||
new_argc = XINT (Flength (tem));
|
||||
SAFE_NALLOCA (new_argv, 1, new_argc + 1);
|
||||
new_argv[new_argc] = 0;
|
||||
|
||||
for (i = nargs - 2; i-- != 0; )
|
||||
for (i = new_argc - 1; i >= 0; i--)
|
||||
{
|
||||
new_argv[i] = SDATA (XCAR (tem));
|
||||
tem = XCDR (tem);
|
||||
|
|
@ -1581,6 +1661,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
|
|||
else
|
||||
create_pty (proc);
|
||||
|
||||
UNGCPRO;
|
||||
SAFE_FREE ();
|
||||
return unbind_to (count, proc);
|
||||
}
|
||||
|
|
@ -1648,7 +1729,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
|
|||
|
||||
inchannel = outchannel = -1;
|
||||
|
||||
if (!NILP (Vprocess_connection_type))
|
||||
if (p->pty_flag)
|
||||
outchannel = inchannel = allocate_pty (pty_name);
|
||||
|
||||
if (inchannel >= 0)
|
||||
|
|
@ -1701,8 +1782,12 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
|
|||
p->pty_flag = pty_flag;
|
||||
pset_status (p, Qrun);
|
||||
|
||||
FD_SET (inchannel, &input_wait_mask);
|
||||
FD_SET (inchannel, &non_keyboard_wait_mask);
|
||||
if (!EQ (p->command, Qt))
|
||||
{
|
||||
FD_SET (inchannel, &input_wait_mask);
|
||||
FD_SET (inchannel, &non_keyboard_wait_mask);
|
||||
}
|
||||
|
||||
if (inchannel > max_process_desc)
|
||||
max_process_desc = inchannel;
|
||||
|
||||
|
|
@ -1894,7 +1979,7 @@ create_pty (Lisp_Object process)
|
|||
{
|
||||
struct Lisp_Process *p = XPROCESS (process);
|
||||
char pty_name[PTY_NAME_SIZE];
|
||||
int pty_fd = NILP (Vprocess_connection_type) ? -1 : allocate_pty (pty_name);
|
||||
int pty_fd = !p->pty_flag ? -1 : allocate_pty (pty_name);
|
||||
|
||||
if (pty_fd >= 0)
|
||||
{
|
||||
|
|
@ -7269,6 +7354,10 @@ syms_of_process (void)
|
|||
DEFSYM (QCstop, ":stop");
|
||||
DEFSYM (QCoptions, ":options");
|
||||
DEFSYM (QCplist, ":plist");
|
||||
DEFSYM (QCcommand, ":command");
|
||||
DEFSYM (QCconnection_type, ":connection-type");
|
||||
DEFSYM (Qpty, "pty");
|
||||
DEFSYM (Qpipe, "pipe");
|
||||
|
||||
DEFSYM (Qlast_nonmenu_event, "last-nonmenu-event");
|
||||
|
||||
|
|
@ -7371,7 +7460,7 @@ The variable takes effect when `start-process' is called. */);
|
|||
defsubr (&Sprocess_plist);
|
||||
defsubr (&Sset_process_plist);
|
||||
defsubr (&Sprocess_list);
|
||||
defsubr (&Sstart_process);
|
||||
defsubr (&Smake_process);
|
||||
defsubr (&Sserial_process_configure);
|
||||
defsubr (&Smake_serial_process);
|
||||
defsubr (&Sset_network_process_option);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue