;; Make `kill-process' a command. ;; (put 'kill-process 'interactive-form '(interactive)) (put 'kill-process 'interactive-form '(interactive (kill-process-read-arg))) (defun kill-process-read-arg () "Obtain arguments interactively for `kill-process'." ;; Currently supports only the PROCESS argument. ;; Must either return a list containing a process, or signal an error. ;; (Returning `nil' would mean the current buffer's process.) (unless (fboundp 'process-list) (error "Asynchronous subprocesses are not supported on this system")) ;; Local function to return cons of a complete-able name, and the ;; associated process object, for use with `completing-read'. (cl-flet ((procitem (p) (when (process-live-p p) (let ((pid (process-id p)) (procname (process-name p)) (procbuf (process-buffer p))) (and (eq (process-type p) 'real) (cons (if procbuf (format "%s (%s) in buffer %s" procname pid (buffer-name procbuf)) (format "%s (%s)" procname pid)) p)))))) ;; Perform `completing-read' for a process. (let* ((currproc (get-buffer-process (current-buffer))) (proclist (or (process-list) (error "No processes found"))) (collection (delq nil (mapcar #'procitem proclist))) (selection (completing-read (if (and currproc (eq (process-type currproc) 'real)) (format "Kill process? (default %S (%s)): " currproc (process-id currproc)) "Kill process: ") collection nil :require-match nil nil (car (cl-find currproc collection :key #'cdr)))) (process (and selection (cdr (assoc selection collection))))) (unless process (error "No process selected")) ;; Return list of arguments for `kill-process'. (if (y-or-n-p (format "Kill %S? " process)) (list process) (error "Process not killed")))))