emacs-devel
[Top][All Lists]
Advanced

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

list-processes reimplementation, and list/menu buffers


From: Chong Yidong
Subject: list-processes reimplementation, and list/menu buffers
Date: Sun, 03 Apr 2011 20:48:56 -0400

I took a look at the list-processes reimplementation.  It looks OK, but
there's no real reason we should display the same buffer contents as the
old list-processes.  Instead, it seems to make sense to provide
something similar to the list-packages and list-buffers interface.

I took some code from your emacs-process.el, and reworked it using the
list-packages code from package.el.  Unlike emacs-process.el, this
doesn't use the CL package, so it can be added to simple.el.


However, it would be cleaner to make a new `list-menu-mode' major mode,
usable for general "list of stuff" buffers.  Then both the list-packages
and list-processes can derive from that major mode.  With a bit more
work, list-buffers could use it too.  I will investigate this approach.



=== modified file 'lisp/simple.el'
*** lisp/simple.el      2011-03-31 04:24:03 +0000
--- lisp/simple.el      2011-04-04 00:16:17 +0000
***************
*** 2692,2697 ****
--- 2692,2851 ----
        (apply 'start-process name buffer program program-args))))
  
  
+ (defvar process-menu-mode-map
+   (let ((map (make-sparse-keymap)))
+     (define-key map "\C-k" 'process-menu-delete)
+     (define-key map " " 'next-line)
+     (define-key map "n" 'next-line)
+     (define-key map "p" 'previous-line)
+     (define-key map "g" 'revert-buffer)
+     map)
+   "Keymap for `process-menu-mode'.")
+ 
+ (defvar process-menu--query-only nil)
+ 
+ (define-derived-mode process-menu-mode special-mode "Process List"
+   "Major mode for the buffer created by `list-processes'."
+   (setq truncate-lines t)
+   (setq buffer-read-only t)
+   (set (make-local-variable 'revert-buffer-function) 'list-processes-revert)
+   (setq header-line-format
+       (mapconcat
+        (lambda (pair)
+          (let ((column (car pair))
+                (name (cdr pair)))
+            (concat
+             ;; Insert a space that aligns the button properly.
+             (propertize " " 'display (list 'space :align-to column)
+                         'face 'fixed-pitch)
+             name)))
+        '((0 . "")
+          (2 . "Process")
+          (16 . "Status")
+          (24 . "Buffer")
+          (40 . "TTY")
+          (54 . "Command"))
+        "")))
+ 
+ (defun process-menu-delete ()
+   (interactive)
+   (let ((proc (get-text-property (point) 'process-list-process)))
+     (if (null (processp proc))
+       (message "No process on this line.")
+       (if (y-or-n-p (format "Delete process %s? " (process-name proc)))
+         (progn
+           (delete-process proc)
+           (revert-buffer))
+       (message "Aborted")))))
+ 
+ (defun list-processes-revert (&optional arg noconfirm)
+   "Update the list of processes.
+ This function is the `revert-buffer-function' for Process List
+ buffers.  The arguments are ignored."
+   (interactive)
+   (list-processes process-menu--query-only (current-buffer)))
+ 
+ (defun process-menu-info (&optional query-only)
+   "Return a list of plist of process information.
+ Each list element has the form (PROCESS NAME STATUS BUFFER TTY COMMAND)."
+   (let (proc-list buf type contact)
+     (dolist (p (process-list))
+       (when (or (not query-only)
+               (process-query-on-exit-flag p))
+       (setq buf  (process-buffer p)
+             type (process-type p))
+       (push
+        (list p ; The process itself
+              (process-name p)                 ; Name
+              (symbol-name (process-status p)) ; Status
+              (and (buffer-live-p buf) buf)    ; Buffer
+              (process-tty-name p)             ; TTY
+              (cond                            ; Command
+               ((eq type 'network)
+                (setq contact (process-contact p t))
+                (format "(network %s %s)"
+                        (if (plist-get contact :type) "datagram" "network")
+                        (if (plist-get contact :server)
+                            (format "server on %s"
+                                    (plist-get contact :server))
+                          (format "connection to %s"
+                                  (plist-get contact :host)))))
+               ((eq type 'serial)
+                (setq contact (process-contact p t))
+                (format "(serial port %s%s)"
+                        (or (plist-get contact :port) "?")
+                        (let ((speed (plist-get contact :speed)))
+                          (if speed
+                              (format " at %s b/s" speed)
+                            ""))))
+               (t (mapconcat 'identity (process-command p) " "))))
+        proc-list)))
+     proc-list))
+ 
+ (defun list-processes (&optional query-only buffer)
+   "Display a list of all processes.
+ If optional argument QUERY-ONLY is non-nil, only processes with
+ the query-on-exit flag set are listed.
+ Any process listed as exited or signaled is actually eliminated
+ after the listing is made.
+ Optional argument BUFFER specifies a buffer to use, instead of
+ \"*Process List\".
+ The return value is always nil."
+   (interactive)
+   (let ((info (process-menu-info query-only))
+         (inhibit-read-only t)
+       (buf (or buffer (get-buffer-create "*Process List*")))
+         line)
+     (with-current-buffer buf
+       (setq line (line-number-at-pos))
+       (process-menu-mode)
+       (erase-buffer)
+       (set (make-local-variable 'process-menu--query-only) query-only)
+       (if info
+         (progn
+           (dolist (pinfo info)
+             (apply 'process-menu-insert pinfo))
+           ;; Leave point at the same line as before.
+           (goto-char (point-min))
+           (forward-line (1- line)))
+       (message "No processes exist"))
+       (set-buffer-modified-p nil))
+     (display-buffer buf))
+   nil)
+ 
+ (defun process-menu-insert (process name status buffer tty command)
+   (let (str)
+     (insert (propertize "  " 'process-list-process process))
+     (setq str name)
+     (insert
+      (propertize
+       (if (> (length str) 15)
+         (concat (substring str 0 12) "...")
+       str)
+       'help-echo name))
+     (indent-to 16 1)
+     (insert status)
+     (indent-to 24 1)
+     (if (null buffer)
+       (insert "--")
+       (setq str (buffer-name buffer))
+       (insert-text-button (if (> (length str) 15)
+                             (concat (substring str 0 12) "...")
+                           str)
+                         'face 'link
+                         'help-echo (concat "Visit buffer `"
+                                            (buffer-name buffer)
+                                            "'")
+                         'follow-link t
+                         'process-buffer buffer
+                         'action (lambda (button)
+                                   (display-buffer
+                                    (button-get button 'process-buffer)))))
+     (indent-to 40 1)
+     (insert tty)
+     (indent-to 54 1)
+     (insert command)))
+ 
  (defvar universal-argument-map
    (let ((map (make-sparse-keymap)))
      (define-key map [t] 'universal-argument-other-key)

=== modified file 'src/process.c'
*** src/process.c       2011-03-27 02:32:40 +0000
--- src/process.c       2011-04-04 00:12:35 +0000
***************
*** 1239,1486 ****
  
    return Qnil;
  }
- 
- static Lisp_Object
- list_processes_1 (Lisp_Object query_only)
- {
-   register Lisp_Object tail;
-   Lisp_Object proc, minspace;
-   register struct Lisp_Process *p;
-   char tembuf[300];
-   int w_proc, w_buffer, w_tty;
-   int exited = 0;
-   Lisp_Object i_status, i_buffer, i_tty, i_command;
- 
-   w_proc = 4;    /* Proc   */
-   w_buffer = 6;  /* Buffer */
-   w_tty = 0;     /* Omit if no ttys */
- 
-   for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
-     {
-       int i;
- 
-       proc = Fcdr (XCAR (tail));
-       p = XPROCESS (proc);
-       if (NILP (p->type))
-       continue;
-       if (!NILP (query_only) && p->kill_without_query)
-       continue;
-       if (STRINGP (p->name)
-         && ( i = SCHARS (p->name), (i > w_proc)))
-       w_proc = i;
-       if (!NILP (p->buffer))
-       {
-         if (NILP (BVAR (XBUFFER (p->buffer), name)))
-           {
-             if (w_buffer < 8)
-               w_buffer = 8;  /* (Killed) */
-           }
-         else if ((i = SCHARS (BVAR (XBUFFER (p->buffer), name)), (i > 
w_buffer)))
-           w_buffer = i;
-       }
-       if (STRINGP (p->tty_name)
-         && (i = SCHARS (p->tty_name), (i > w_tty)))
-       w_tty = i;
-     }
- 
-   XSETFASTINT (i_status, w_proc + 1);
-   XSETFASTINT (i_buffer, XFASTINT (i_status) + 9);
-   if (w_tty)
-     {
-       XSETFASTINT (i_tty, XFASTINT (i_buffer) + w_buffer + 1);
-       XSETFASTINT (i_command, XFASTINT (i_tty) + w_tty + 1);
-     }
-   else
-     {
-       i_tty = Qnil;
-       XSETFASTINT (i_command, XFASTINT (i_buffer) + w_buffer + 1);
-     }
- 
-   XSETFASTINT (minspace, 1);
- 
-   set_buffer_internal (XBUFFER (Vstandard_output));
-   BVAR (current_buffer, undo_list) = Qt;
- 
-   BVAR (current_buffer, truncate_lines) = Qt;
- 
-   write_string ("Proc", -1);
-   Findent_to (i_status, minspace); write_string ("Status", -1);
-   Findent_to (i_buffer, minspace); write_string ("Buffer", -1);
-   if (!NILP (i_tty))
-     {
-       Findent_to (i_tty, minspace); write_string ("Tty", -1);
-     }
-   Findent_to (i_command, minspace); write_string ("Command", -1);
-   write_string ("\n", -1);
- 
-   write_string ("----", -1);
-   Findent_to (i_status, minspace); write_string ("------", -1);
-   Findent_to (i_buffer, minspace); write_string ("------", -1);
-   if (!NILP (i_tty))
-     {
-       Findent_to (i_tty, minspace); write_string ("---", -1);
-     }
-   Findent_to (i_command, minspace); write_string ("-------", -1);
-   write_string ("\n", -1);
- 
-   for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
-     {
-       Lisp_Object symbol;
- 
-       proc = Fcdr (XCAR (tail));
-       p = XPROCESS (proc);
-       if (NILP (p->type))
-       continue;
-       if (!NILP (query_only) && p->kill_without_query)
-       continue;
- 
-       Finsert (1, &p->name);
-       Findent_to (i_status, minspace);
- 
-       if (p->raw_status_new)
-       update_status (p);
-       symbol = p->status;
-       if (CONSP (p->status))
-       symbol = XCAR (p->status);
- 
-       if (EQ (symbol, Qsignal))
-       {
-         Lisp_Object tem;
-         tem = Fcar (Fcdr (p->status));
-         Fprinc (symbol, Qnil);
-       }
-       else if (NETCONN1_P (p) || SERIALCONN1_P (p))
-       {
-         if (EQ (symbol, Qexit))
-           write_string ("closed", -1);
-         else if (EQ (p->command, Qt))
-           write_string ("stopped", -1);
-         else if (EQ (symbol, Qrun))
-           write_string ("open", -1);
-         else
-           Fprinc (symbol, Qnil);
-       }
-       else if (SERIALCONN1_P (p))
-       {
-         write_string ("running", -1);
-       }
-       else
-       Fprinc (symbol, Qnil);
- 
-       if (EQ (symbol, Qexit))
-       {
-         Lisp_Object tem;
-         tem = Fcar (Fcdr (p->status));
-         if (XFASTINT (tem))
-           {
-             sprintf (tembuf, " %d", (int) XFASTINT (tem));
-             write_string (tembuf, -1);
-           }
-       }
- 
-       if (EQ (symbol, Qsignal) || EQ (symbol, Qexit) || EQ (symbol, Qclosed))
-       exited++;
- 
-       Findent_to (i_buffer, minspace);
-       if (NILP (p->buffer))
-       insert_string ("(none)");
-       else if (NILP (BVAR (XBUFFER (p->buffer), name)))
-       insert_string ("(Killed)");
-       else
-       Finsert (1, &BVAR (XBUFFER (p->buffer), name));
- 
-       if (!NILP (i_tty))
-       {
-         Findent_to (i_tty, minspace);
-         if (STRINGP (p->tty_name))
-           Finsert (1, &p->tty_name);
-       }
- 
-       Findent_to (i_command, minspace);
- 
-       if (EQ (p->status, Qlisten))
-       {
-         Lisp_Object port = Fplist_get (p->childp, QCservice);
-         if (INTEGERP (port))
-           port = Fnumber_to_string (port);
-         if (NILP (port))
-           port = Fformat_network_address (Fplist_get (p->childp, QClocal), 
Qnil);
-         sprintf (tembuf, "(network %s server on %s)\n",
-                  (DATAGRAM_CHAN_P (p->infd) ? "datagram" : "stream"),
-                  (STRINGP (port) ? SSDATA (port) : "?"));
-         insert_string (tembuf);
-       }
-       else if (NETCONN1_P (p))
-       {
-         /* For a local socket, there is no host name,
-            so display service instead.  */
-         Lisp_Object host = Fplist_get (p->childp, QChost);
-         if (!STRINGP (host))
-           {
-             host = Fplist_get (p->childp, QCservice);
-             if (INTEGERP (host))
-               host = Fnumber_to_string (host);
-           }
-         if (NILP (host))
-           host = Fformat_network_address (Fplist_get (p->childp, QCremote), 
Qnil);
-         sprintf (tembuf, "(network %s connection to %s)\n",
-                  (DATAGRAM_CHAN_P (p->infd) ? "datagram" : "stream"),
-                  (STRINGP (host) ? SSDATA (host) : "?"));
-         insert_string (tembuf);
-       }
-       else if (SERIALCONN1_P (p))
-       {
-         Lisp_Object port = Fplist_get (p->childp, QCport);
-         Lisp_Object speed = Fplist_get (p->childp, QCspeed);
-         insert_string ("(serial port ");
-         if (STRINGP (port))
-           insert_string (SSDATA (port));
-         else
-           insert_string ("?");
-         if (INTEGERP (speed))
-           {
-             sprintf (tembuf, " at %ld b/s", (long) XINT (speed));
-             insert_string (tembuf);
-           }
-         insert_string (")\n");
-       }
-       else
-       {
-         Lisp_Object tem = p->command;
-         while (1)
-           {
-             Lisp_Object tem1 = Fcar (tem);
-             if (NILP (tem1))
-               break;
-             Finsert (1, &tem1);
-             tem = Fcdr (tem);
-             if (NILP (tem))
-               break;
-             insert_string (" ");
-           }
-         insert_string ("\n");
-        }
-     }
-   if (exited)
-     {
-       status_notify (NULL);
-       redisplay_preserve_echo_area (13);
-     }
-   return Qnil;
- }
- 
- DEFUN ("list-processes", Flist_processes, Slist_processes, 0, 1, "P",
-        doc: /* Display a list of all processes.
- If optional argument QUERY-ONLY is non-nil, only processes with
- the query-on-exit flag set will be listed.
- Any process listed as exited or signaled is actually eliminated
- after the listing is made.  */)
-   (Lisp_Object query_only)
- {
-   internal_with_output_to_temp_buffer ("*Process List*",
-                                      list_processes_1, query_only);
-   return Qnil;
- }
  
  DEFUN ("process-list", Fprocess_list, Sprocess_list, 0, 0, 0,
         doc: /* Return a list of all processes.  */)
--- 1239,1244 ----
***************
*** 7679,7685 ****
    defsubr (&Sprocess_contact);
    defsubr (&Sprocess_plist);
    defsubr (&Sset_process_plist);
-   defsubr (&Slist_processes);
    defsubr (&Sprocess_list);
    defsubr (&Sstart_process);
    defsubr (&Sserial_process_configure);
--- 7437,7442 ----




reply via email to

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