emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 47e0e31: Generalize start-process with keyword args


From: Daiki Ueno
Subject: [Emacs-diffs] master 47e0e31: Generalize start-process with keyword args
Date: Mon, 23 Mar 2015 07:36:02 +0000

branch: master
commit 47e0e319329a1ecf9da4fa1afd2b9f2738fada67
Author: Daiki Ueno <address@hidden>
Commit: Daiki Ueno <address@hidden>

    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'.
---
 doc/lispref/ChangeLog      |    4 +
 doc/lispref/processes.texi |   55 ++++++++++++++
 etc/ChangeLog              |    4 +
 etc/NEWS                   |    5 +
 lisp/ChangeLog             |    5 +
 lisp/subr.el               |   24 ++++++
 src/ChangeLog              |    8 ++
 src/process.c              |  175 +++++++++++++++++++++++++++++++++-----------
 8 files changed, 237 insertions(+), 43 deletions(-)

diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog
index 3644d40..ff1f814 100644
--- a/doc/lispref/ChangeLog
+++ b/doc/lispref/ChangeLog
@@ -1,3 +1,7 @@
+2015-03-23  Daiki Ueno  <address@hidden>
+
+       * processes.texi (Asynchronous Processes): Mention `make-process'.
+
 2015-03-18  Eli Zaretskii  <address@hidden>
 
        * minibuf.texi (Basic Completion): Fix a typo.  (Bug#20108)
diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi
index 177cd68..3e9cc50 100644
--- a/doc/lispref/processes.texi
+++ b/doc/lispref/processes.texi
@@ -692,6 +692,61 @@ use the function @code{process-tty-name} (@pxref{Process
 Information}).
 @end defvar
 
address@hidden 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
address@hidden  Here are the meaningful keywords:
+
address@hidden @asis
address@hidden :name @var{name}
+Use the string @var{name} as the process name.  It is modified if
+necessary to make it unique.
+
address@hidden :buffer @var{buffer}
+Use @var{buffer} as the process buffer.
+
address@hidden :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.
+
address@hidden :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
address@hidden@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}.
+
address@hidden :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.
+
address@hidden :noquery @var{query-flag}
+Initialize the process query flag to @var{query-flag}.
address@hidden Before Exit}.
+
address@hidden :stop @var{stopped}
+If @var{stopped} is address@hidden, start the process in the
+``stopped'' state.
+
address@hidden :filter @var{filter}
+Initialize the process filter to @var{filter}.
+
address@hidden :sentinel @var{sentinel}
+Initialize the process sentinel to @var{sentinel}.
address@hidden table
+
+The original argument list, modified with the actual connection
+information, is available via the @code{process-contact} function.
address@hidden defun
+
 @node Deleting Processes
 @section Deleting Processes
 @cindex deleting processes
diff --git a/etc/ChangeLog b/etc/ChangeLog
index c94e122..e146f78 100644
--- a/etc/ChangeLog
+++ b/etc/ChangeLog
@@ -1,3 +1,7 @@
+2015-03-23  Daiki Ueno  <address@hidden>
+
+       * NEWS: Mention `make-process'.
+
 2015-03-21  Titus von der Malsburg  <address@hidden>
 
        * NEWS: Mention `default-font-width', `window-font-height',
diff --git a/etc/NEWS b/etc/NEWS
index 7cdb24b..3b848dc 100644
--- a/etc/NEWS
+++ b/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.
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 596b6e2..8f1534a 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,8 @@
+2015-03-23  Daiki Ueno  <address@hidden>
+
+       * subr.el (start-process): New function, ported from the C
+       implementation.
+
 2015-03-23  Daniel Colascione  <address@hidden>
 
        Automatically adjust process window sizes.
diff --git a/lisp/subr.el b/lisp/subr.el
index deadca6..163a1c4 100644
--- a/lisp/subr.el
+++ b/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."
diff --git a/src/ChangeLog b/src/ChangeLog
index 79feb61..6c7955a 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
+2015-03-23  Daiki Ueno  <address@hidden>
+
+       * 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  <address@hidden>
 
        * fontset.c (fontset_pattern_regexp): Replace + 1 with + 3 for
diff --git a/src/process.c b/src/process.c
index 1d935ba..5abe748 100644
--- a/src/process.c
+++ b/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.
+
+: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.
 
-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.
+: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.
 
-usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)  */)
+: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);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]