What is list-processes?

list-processes is an emacs-lisp function which displays daemons running as subprocesses under emacs.

The trouble with list-processes

  • It doesn’t format the command string
    • Commands with multiline arguments are printed verbatim
    • Arguments are not quoted

This means that commands may flow several lines (as many as it takes to print out the full command).

Also, 90% of the time you can’t copy the command and paste in the terminal because individual parameters with spaces are split into separate arguments.

The thing that tipped me over the edge

anaconda-mode takes up the entire process list with one big, paunchy command.

The fix

This code quotes each argument and replaces actual newlines with escape codes

(let* ((fullcmd (mapconcat 'e/q (process-command p) " "))
                  (oneliner (replace-regexp-in-string "\n" "\\n" fullcmd t t))
                  ;; This works but instead of trimming i want to turn everything into one line
                  ;; (fullcmdlen (length fullcmd))
                  ;; (shortcmd (substring fullcmd 0 (min fullcmdlen (window-total-width))))
                  )
             (concat "{" oneliner "}") ; Surround with braces to allow selecting the command easily. Braces are also valid shell.
             ;; shortcmd
             )

Place the above fix into the list-processes--refresh function

(defun list-processes--refresh ()
  "Recompute the list of processes for the Process List buffer.
Also, delete any process that is exited or signaled."
  (setq tabulated-list-entries nil)
  (dolist (p (process-list))
    (cond ((memq (process-status p) '(exit signal closed))
     (delete-process p))
    ((or (not process-menu-query-only)
         (process-query-on-exit-flag p))
     (let* ((buf (process-buffer p))
      (type (process-type p))
      (pid  (if (process-id p) (format "%d" (process-id p)) "--"))
      (name (process-name p))
      (status (symbol-name (process-status p)))
      (buf-label (if (buffer-live-p buf)
         `(,(buffer-name buf)
           face link
           help-echo ,(format-message
                 "Visit buffer `%s'"
                 (buffer-name buf))
           follow-link t
           process-buffer ,buf
           action process-menu-visit-buffer)
             "--"))
      (tty (or (process-tty-name p) "--"))
      (cmd
       (if (memq type '(network serial))
           (let ((contact (process-contact p t)))
             (if (eq type 'network)
                 (format "(%s %s)"
                         (if (plist-get contact :type)
                             "datagram"
                           "network")
                         (if (plist-get contact :server)
                             (format "server on %s"
                                     (or
                                      (plist-get contact :host)
                                      (plist-get contact :local)))
                           (format "connection to %s"
                                   (plist-get contact :host))))
               (format "(serial port %s%s)"
                       (or (plist-get contact :port) "?")
                       (let ((speed (plist-get contact :speed)))
                         (if speed
                             (format " at %s b/s" speed)
                           "")))))
         (let* ((fullcmd (mapconcat 'e/q (process-command p) " "))
                (oneliner (replace-regexp-in-string "\n" "\\n" fullcmd t t))
                ;; This works but instead of trimming i want to turn everything into one line
                ;; (fullcmdlen (length fullcmd))
                ;; (shortcmd (substring fullcmd 0 (min fullcmdlen (window-total-width))))
                )
           (concat "{" oneliner "}") ; Surround with braces to allow selecting the command easily. Braces are also valid shell.
           ;; shortcmd
           ))))
       (push (list p (vector name pid status buf-label tty cmd))
             tabulated-list-entries)))))
  (tabulated-list-init-header))