From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Daiki Ueno Newsgroups: gmane.emacs.devel Subject: [PATCH] Generalize start-process with keyword args Date: Mon, 16 Mar 2015 14:42:24 +0900 Message-ID: References: <87d24d3uwz.fsf-ueno@gnu.org> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1426484574 29863 80.91.229.3 (16 Mar 2015 05:42:54 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 16 Mar 2015 05:42:54 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Mar 16 06:42:49 2015 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1YXNnc-0002T6-Bk for ged-emacs-devel@m.gmane.org; Mon, 16 Mar 2015 06:42:48 +0100 Original-Received: from localhost ([::1]:47344 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YXNnb-00043x-98 for ged-emacs-devel@m.gmane.org; Mon, 16 Mar 2015 01:42:47 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:50071) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YXNnL-00043p-Uc for emacs-devel@gnu.org; Mon, 16 Mar 2015 01:42:33 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YXNnJ-0006ch-RX for emacs-devel@gnu.org; Mon, 16 Mar 2015 01:42:31 -0400 Original-Received: from fencepost.gnu.org ([2001:4830:134:3::e]:51859) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YXNnJ-0006cd-NL for emacs-devel@gnu.org; Mon, 16 Mar 2015 01:42:29 -0400 Original-Received: from du-a.org ([2001:e41:db5e:fb14::1]:34441 helo=localhost.localdomain) by fencepost.gnu.org with esmtpsa (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1YXNnI-00072f-QC for emacs-devel@gnu.org; Mon, 16 Mar 2015 01:42:29 -0400 In-Reply-To: <87d24d3uwz.fsf-ueno@gnu.org> (Daiki Ueno's message of "Fri, 13 Mar 2015 22:10:20 +0900") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.4 (gnu/linux) X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:4830:134:3::e X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:183893 Archived-At: --=-=-= Content-Type: text/plain Daiki Ueno writes: >> BTW, what happened with your earlier `make-process' suggestion? > > I'm still willing to work on that, but just wanted to be sure that my > desired feature (additional pipes) could be implemented atop of it, So here it is. This merely adds a new function `make-process' as an alternative form of `start-process', and use it in the `start-process' implementation. No extra feature has been added by now. All tests succeeded with this, except file-notify-tests, which is failing without the patch. Reviews appreciated. Thanks, -- Daiki Ueno --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=0001-Generalize-start-process-with-keyword-args.patch >From 100b268e02cba94afa40948c54a7a3def47ce1d3 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Mon, 16 Mar 2015 11:38:05 +0900 Subject: [PATCH] Generalize start-process with keyword args * src/process.c (Fmake_process): New function. (Fstart_process): Define as a wrapper around Fmake_process. (create_process, create_pty): Check p->pty_flag instead of Vprocess_connection_type. (syms_of_process): Register QCcommand, QCconnection_type, and Smake_process. * doc/lispref/processes.texi (Asynchronous Processes): Mention `make-process'. --- doc/lispref/ChangeLog | 4 ++ doc/lispref/processes.texi | 48 +++++++++++++ src/ChangeLog | 9 +++ src/process.c | 168 +++++++++++++++++++++++++++++++++++++-------- 4 files changed, 199 insertions(+), 30 deletions(-) diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index 260656c..06d4630 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,7 @@ +2015-03-16 Daiki Ueno + + * processes.texi (Asynchronous Processes): Mention `make-process'. + 2015-03-09 Nicolas Petton * sequences.texi (seq-into): Add documentation for the new diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index 177cd68..c386696 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -692,6 +692,54 @@ 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}, except for @code{:coding} and @code{:connection-type}. +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 name, followed by strings to give +to program as arguments. + +@item :coding @var{coding} +Use @var{coding} as the coding system for this process. To specify +different coding systems for decoding data from the connection and for +encoding data sent to it, specify @code{(@var{decoding} . +@var{encoding})} for @var{coding}. + +If you don't specify this keyword at all, the default +is to determine the coding systems from the data. + +@item :connection-type @var{TYPE} +Initialize the type of device used to communicate with the subprocess. + +If you don't specify this keyword at all, the default is 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 :filter @var{filter} +Initialize the process filter to @var{filter}. + +@item :sentinel @var{sentinel} +Initialize the process sentinel to @var{sentinel}. + +@end defun + @node Deleting Processes @section Deleting Processes @cindex deleting processes diff --git a/src/ChangeLog b/src/ChangeLog index e328afc..d8ac459 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2015-03-16 Daiki Ueno + + * process.c (Fmake_process): New function. + (Fstart_process): Define as a wrapper around Fmake_process. + (create_process, create_pty): Check p->pty_flag instead of + Vprocess_connection_type. + (syms_of_process): Register QCcommand, QCconnection_type, and + Smake_process. + 2015-03-15 Eli Zaretskii * xdisp.c (handle_invisible_prop): Fix up it->position even when diff --git a/src/process.c b/src/process.c index 1d935ba..44b7a2d 100644 --- a/src/process.c +++ b/src/process.c @@ -1376,13 +1376,73 @@ syntax. usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) (ptrdiff_t nargs, Lisp_Object *args) { - Lisp_Object buffer, name, program, proc, current_dir, tem; + Lisp_Object plist[6]; + + plist[0] = QCname; + plist[1] = args[0]; + plist[2] = QCbuffer; + plist[3] = args[1]; + plist[4] = QCcommand; + plist[5] = Flist (nargs - 2, args + 2); + + /* Don't need to GCPRO each element of PLIST, since PLIST will be + protected as a whole in Fmake_process. */ + return CALLMANY (Fmake_process, plist); +} + +DEFUN ("make-process", Fmake_process, Smake_process, 0, MANY, 0, + doc: /* Start a program in a subprocess. Return the process object for it. + +This is similar to `start-process', but arguments are specified as +keyword/argument pairs. The following arguments are defined: + +:name NAME -- NAME is name for process. It is modified if necessary +to make it unique. + +: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. + +: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. + +:connection-type TYPE -- TYPE is control type of device used to +communicate with subprocesses. Values are nil to use a pipe, or t or +`pty' to use a pty. + +: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, command, program, proc, contact, current_dir, tem; unsigned char **new_argv; + ptrdiff_t new_argc; 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 +1462,11 @@ 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); + program = XCAR (command); if (!NILP (program)) CHECK_STRING (program); @@ -1423,7 +1484,16 @@ 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; + + tem = Fplist_member (contact, QCconnection_type); + if (!NILP (tem)) + XPROCESS (proc)->pty_flag = !NILP (XCAR (tem)); + else + XPROCESS (proc)->pty_flag = !NILP (Vprocess_connection_type); #ifdef HAVE_GNUTLS /* AKA GNUTLS_INITSTAGE(proc). */ @@ -1453,15 +1523,33 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) Lisp_Object val, *args2; struct gcpro gcpro1, gcpro2; - val = Vcoding_system_for_read; + tem = Fplist_member (contact, QCcoding); + if (!NILP (tem) && (!CONSP (tem) || !CONSP (XCDR (tem)))) + tem = Qnil; + + val = Qnil; + if (!NILP (tem)) + { + val = XCAR (XCDR (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 +1558,31 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) } pset_decode_coding_system (XPROCESS (proc), val); - val = Vcoding_system_for_write; + val = Qnil; + if (!NILP (tem)) + { + val = XCAR (XCDR (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)) @@ -1512,10 +1614,10 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) && !(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,31 +1636,32 @@ 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; + + tem = Fcons (tem, Fcopy_sequence (XCDR (command))); GCPRO1 (tem); /* Encode the file name and put it in NEW_ARGV. That's where the child will use it to execute the program. */ - tem = list1 (ENCODE_FILE (tem)); + XSETCAR (tem, ENCODE_FILE (XCAR (tem))); /* Here we encode arguments by the coding system used for sending data to the process. We don't support using different coding systems for encoding arguments and for encoding data sent to the process. */ - for (i = 3; i < nargs; i++) + for (tem2 = XCDR (tem); CONSP (tem2); tem2 = XCDR (tem2)) { - tem = Fcons (args[i], tem); - CHECK_STRING (XCAR (tem)); - if (STRING_MULTIBYTE (XCAR (tem))) + CHECK_STRING (XCAR (tem2)); + if (STRING_MULTIBYTE (XCAR (tem2))) { if (NILP (arg_encoding)) arg_encoding = (complement_process_encoding_system (XPROCESS (proc)->encode_coding_system)); - XSETCAR (tem, + XSETCAR (tem2, code_convert_string_norecord - (XCAR (tem), arg_encoding, 1)); + (XCAR (tem2), arg_encoding, 1)); } } @@ -1567,10 +1670,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 = 0; i < new_argc; i++) { new_argv[i] = SDATA (XCAR (tem)); tem = XCDR (tem); @@ -1581,6 +1685,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) else create_pty (proc); + UNGCPRO; SAFE_FREE (); return unbind_to (count, proc); } @@ -1648,7 +1753,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) @@ -1894,7 +1999,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 +7374,8 @@ syms_of_process (void) DEFSYM (QCstop, ":stop"); DEFSYM (QCoptions, ":options"); DEFSYM (QCplist, ":plist"); + DEFSYM (QCcommand, ":command"); + DEFSYM (QCconnection_type, ":connection-type"); DEFSYM (Qlast_nonmenu_event, "last-nonmenu-event"); @@ -7372,6 +7479,7 @@ The variable takes effect when `start-process' is called. */); 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); -- 2.1.0 --=-=-=--