[comp.emacs] I want more out of dired

george@scirtp.UUCP (Geo. R. Greene, Jr.) (11/06/87)

It seems to me that you ought to be able to edit process
trees the same way you edit directory trees.

-- 
A Self-Assessment of Julie Andrews:

Sometimes I'm so sweet even *I* can't stand it.

kyle@xanth.UUCP (Kyle Jones) (11/10/87)

In article <1071@scirtp.UUCP>, george@scirtp.UUCP (Geo. R. Greene, Jr.) writes:
> It seems to me that you ought to be able to edit process
> trees the same way you edit directory trees.

Give this a try.  "C-u M-x vkill" starts the show, "?" gets you online help.

kyle jones  <kyle@odu.edu>  old dominion university, norfolk, va  usa
---------------------------------------------------------------------------
;;; View and kill Unix processes from within Emacs
;;; Copyright (C) 1987 Kyle E. Jones
;;;
;;; This software may be redistributed provided this notice appears unchanged
;;; on all copies and that the further free redistribution of this software is
;;; not restricted in any way.
;;;
;;; This software is distributed 'as is', without warranties of any kind.

(defvar vkill-buffer-name "*Process Info*"
  "Buffer that the vkill command uses to store and show process information")

(defvar vkill-keymap nil
  "Keymap for vkill-buffer commands")

(if vkill-keymap
    ()
  (setq vkill-keymap (make-sparse-keymap))
  (define-key vkill-keymap " " 'next-line)
  (define-key vkill-keymap "?" 'vkill-help)
  (define-key vkill-keymap "k" 'vkill-send-signal)
  (define-key vkill-keymap "m" 'vkill-mark-process)
  (define-key vkill-keymap "M" 'vkill-mark-all-processes)
  (define-key vkill-keymap "p" 'vkill-show-processes)
  (define-key vkill-keymap "q" 'vkill-quit)
  (define-key vkill-keymap "u" 'vkill-unmark-process)
  (define-key vkill-keymap "U" 'vkill-unmark-all-processes))

(defconst vkill-quick-help-string
  (substitute-command-keys
   "\\<vkill-keymap>\\[vkill-send-signal], \\[vkill-mark-process], \\[vkill-mark-all-processes], \\[vkill-show-processes], \\[vkill-quit], \\[vkill-unmark-process], \\[vkill-unmark-all-processes] (type \\[vkill-help] for more help)")
  "Quick help string for vkill.")

(defun vkill (&optional activate)
  "Mode for displaying all the UNIX processes owned by the current user (all
the processes on the system if this is the super-user) and allowing
the user to mark processes to be sent a certain signal.  Processes are marked
by moving the cursor to the line with the displaying information about the
victim process and typing a key to mark the process.

If this command is invoked with a prefix arg (optional first arg non-nil from a
program) the window displaying the process information will be immediately
selected and all other windows will be deleted.

Commands:\\{vkill-keymap}"
  (interactive "P")
  (let ((vkill-buffer (get-buffer-create vkill-buffer-name)))
    (set-buffer vkill-buffer)
    (setq buffer-read-only t
	  truncate-lines t
	  major-mode 'vkill-mode
	  mode-name "Vkill"
	  mode-line-format '("        Process Info       "
			     global-mode-string "        %p"))
    (use-local-map vkill-keymap)
    (vkill-show-processes)
    (goto-line 2))

  (if activate
      (progn
	(switch-to-buffer vkill-buffer-name)
	(delete-other-windows))
    (display-buffer vkill-buffer-name)))

(fset 'vkill-mode (symbol-function 'vkill))

(defun vkill-mark-process ()
  "Mark the process listed on the current line and move forward a line"
  (interactive)
  (set-buffer vkill-buffer-name)
  (let (buffer-read-only)
    (beginning-of-line)
    (if (not (bobp))
	(progn
	  (insert "*")
	  (delete-char 1))))
  (forward-line))

(defun vkill-mark-all-processes ()
  "Mark all listed processes."
  (interactive)
  (set-buffer vkill-buffer-name)
  (save-excursion
    (let (buffer-read-only)
      (goto-line 2)
      (while (not (eobp))
	(insert "*")
	(delete-char 1)
	(forward-line)))))

(defun vkill-unmark-all-processes ()
  "Remove marks from all listed processes."
  (interactive)
  (set-buffer vkill-buffer-name)
  (save-excursion
    (let (buffer-read-only)
      (goto-line 2)
      (while (not (eobp))
	(insert " ")
	(delete-char 1)
	(forward-line)))))

(defun vkill-unmark-process ()
  "Remove the mark from the process listed on the current line and move
forward one line."
  (interactive)
  (set-buffer vkill-buffer-name)
  (let (buffer-read-only)
    (beginning-of-line)
    (if (not (bobp))
	(progn
	  (delete-char 1)
	  (insert " "))))
  (forward-line))

(defun vkill-quit ()
  "End current vkill session without sending a signal to any of the marked
processes."
  (interactive)
  (if (get-buffer-window vkill-buffer-name)
      (delete-window (get-buffer-window vkill-buffer-name)))
  (kill-buffer vkill-buffer-name))

(defun vkill-show-processes ()
  "Update the vkill process information.  This throws away all process marks."
  (interactive)
  (if (interactive-p)
      (message "Updating process information..."))
  (set-buffer vkill-buffer-name)
  (let (buffer-read-only)
    (erase-buffer)
    (shell-command-on-region
     (point-min) (point-max)
     (if (zerop (user-real-uid)) "ps auxg" "ps uxg") t)
    (goto-char (point-min))
    (while (not (eobp))
      (insert "  ")
      (forward-line))
    (goto-line 2))
  (if (interactive-p)
      (message "Updating process information... done.")))

(defun vkill-send-signal (signal)
  "Send a signal to the marked processes.  If a prefix arg is given it is used
as the signal number, otherwise the number is read from the minibuffer."
  (interactive "NSignal number: ")
  (set-buffer vkill-buffer-name)
  (copy-to-buffer " *workbuf*" (point-min) (point-max))
  (set-buffer " *workbuf*")
  (goto-char (point-min))
  (if (null (re-search-forward "^\\*" (point-max) t))
      (error "No processes marked."))
  (shell-command-on-region
   (point-min) (point-max)
   (concat "/bin/kill -" (int-to-string signal) " "
	   "`grep \"^\\*\" | awk '{ print $3 }'`") t)
  (kill-buffer " *workbuf*"))

(defun vkill-help ()
  "Provide help for the vkill user."
  (interactive)
  (if (eq last-command 'vkill-help)
      (describe-mode)
    (message vkill-quick-help-string)))