diff options
| author | Roland Winkler | 2008-05-05 02:38:20 +0000 |
|---|---|---|
| committer | Roland Winkler | 2008-05-05 02:38:20 +0000 |
| commit | 615482527df5151c71b81a74dd0fb37cc3f8aacf (patch) | |
| tree | 4008b46ccc0f9f5dd9800eb919679dda0a21226b | |
| parent | 725aff3cad23f4370c7cb606d75e0f3306981886 (diff) | |
| download | emacs-615482527df5151c71b81a74dd0fb37cc3f8aacf.tar.gz emacs-615482527df5151c71b81a74dd0fb37cc3f8aacf.zip | |
(proced-command-alist): Fix system-type values. Fix defcustom.
(proced-sorting-schemes-alist, proced-sorting-scheme): New variables.
(proced-sort-pcpu, proced-sort-pmem, proced-sort-pid)
(proced-sort-start, proced-sort, proced-sort-time): New commands.
(proced-update): Use proced-sorting-scheme. Update modeline.
(proced-send-signal): Use nreverse.
(proced-sorting-scheme-p): New function.
| -rw-r--r-- | lisp/proced.el | 134 |
1 files changed, 120 insertions, 14 deletions
diff --git a/lisp/proced.el b/lisp/proced.el index f6e6c94e166..c9b1c62fb33 100644 --- a/lisp/proced.el +++ b/lisp/proced.el | |||
| @@ -30,7 +30,8 @@ | |||
| 30 | ;; on the processes listed. | 30 | ;; on the processes listed. |
| 31 | ;; | 31 | ;; |
| 32 | ;; To do: | 32 | ;; To do: |
| 33 | ;; - sort by CPU time or other criteria | 33 | ;; - sort the "cooked" values used in the output format fields |
| 34 | ;; if ps(1) doesn't support the requested sorting scheme | ||
| 34 | ;; - filter by user name or other criteria | 35 | ;; - filter by user name or other criteria |
| 35 | ;; - automatic update of process list | 36 | ;; - automatic update of process list |
| 36 | 37 | ||
| @@ -49,12 +50,12 @@ | |||
| 49 | (regexp :tag "regexp"))) | 50 | (regexp :tag "regexp"))) |
| 50 | 51 | ||
| 51 | (defcustom proced-command-alist | 52 | (defcustom proced-command-alist |
| 52 | (cond ((memq system-type '(berkeley-unix netbsd)) | 53 | (cond ((memq system-type '(berkeley-unix)) |
| 53 | '(("user" ("ps" "-uxgww") 2) | 54 | '(("user" ("ps" "-uxgww") 2) |
| 54 | ("user-running" ("ps" "-uxrgww") 2) | 55 | ("user-running" ("ps" "-uxrgww") 2) |
| 55 | ("all" ("ps" "-auxgww") 2) | 56 | ("all" ("ps" "-auxgww") 2) |
| 56 | ("all-running" ("ps" "-auxrgww") 2))) | 57 | ("all-running" ("ps" "-auxrgww") 2))) |
| 57 | ((memq system-type '(linux lignux gnu/linux)) | 58 | ((memq system-type '(gnu gnu/linux)) ; BSD syntax |
| 58 | `(("user" ("ps" "uxwww") 2) | 59 | `(("user" ("ps" "uxwww") 2) |
| 59 | ("user-running" ("ps" "uxrwww") 2) | 60 | ("user-running" ("ps" "uxrwww") 2) |
| 60 | ("all" ("ps" "auxwww") 2) | 61 | ("all" ("ps" "auxwww") 2) |
| @@ -65,7 +66,7 @@ | |||
| 65 | ((memq system-type '(darwin)) | 66 | ((memq system-type '(darwin)) |
| 66 | `(("user" ("ps" "-u" ,(number-to-string (user-uid))) 2) | 67 | `(("user" ("ps" "-u" ,(number-to-string (user-uid))) 2) |
| 67 | ("all" ("ps" "-Au") 2))) | 68 | ("all" ("ps" "-Au") 2))) |
| 68 | (t ; standard syntax doesn't allow us to list running processes only | 69 | (t ; standard UNIX syntax; doesn't allow to list running processes only |
| 69 | `(("user" ("ps" "-fu" ,(number-to-string (user-uid))) 2) | 70 | `(("user" ("ps" "-fu" ,(number-to-string (user-uid))) 2) |
| 70 | ("all" ("ps" "-ef") 2)))) | 71 | ("all" ("ps" "-ef") 2)))) |
| 71 | "Alist of commands to get list of processes. | 72 | "Alist of commands to get list of processes. |
| @@ -80,8 +81,42 @@ PID-COLUMN is the column number (starting from 1) of the process ID." | |||
| 80 | :type '(repeat (group (string :tag "name") | 81 | :type '(repeat (group (string :tag "name") |
| 81 | (cons (string :tag "command") | 82 | (cons (string :tag "command") |
| 82 | (repeat (string :tag "option"))) | 83 | (repeat (string :tag "option"))) |
| 83 | (integer :tag "PID column") | 84 | (integer :tag "PID column")))) |
| 84 | (option (integer :tag "sort column"))))) | 85 | |
| 86 | ;; Should we incorporate in NAME if sorting is done in descending order? | ||
| 87 | (defcustom proced-sorting-schemes-alist | ||
| 88 | (cond ((memq system-type '(gnu gnu/linux)) ; GNU long options | ||
| 89 | '(("%CPU" "--sort" "-pcpu") ; descending order | ||
| 90 | ("%MEM" "--sort" "-pmem") ; descending order | ||
| 91 | ("COMMAND" "--sort" "args") | ||
| 92 | ("PID" "--sort" "pid") | ||
| 93 | ("PGID,PID" "--sort" "pgid,pid") | ||
| 94 | ("PPID,PID" "--sort" "ppid,pid") | ||
| 95 | ("RSS" "--sort" "rss,pid") ; equal RSS's are rare | ||
| 96 | ("STAT,PID" "--sort" "stat,pid") | ||
| 97 | ("START" "--sort" "start_time") | ||
| 98 | ("TIME" "--sort" "cputime") | ||
| 99 | ("TTY,PID" "--sort" "tty,pid") | ||
| 100 | ("UID,PID" "--sort" "uid,pid") | ||
| 101 | ("USER,PID" "--sort" "user,pid") | ||
| 102 | ("VSZ,PID" "--sort" "vsz,pid")))) | ||
| 103 | "Alist of sorting schemes. | ||
| 104 | Each element is a list (NAME OPTION1 OPTION2 ...). | ||
| 105 | NAME denotes the sorting scheme and OPTION1, OPTION2, ... are options | ||
| 106 | defining the sorting scheme." | ||
| 107 | :group 'proced | ||
| 108 | :type '(repeat (cons (string :tag "name") | ||
| 109 | (repeat (string :tag "option"))))) | ||
| 110 | |||
| 111 | (defcustom proced-sorting-scheme nil | ||
| 112 | "Proced sorting type. | ||
| 113 | Must be the car of an element of `proced-sorting-schemes-alist' or nil." | ||
| 114 | :group 'proced | ||
| 115 | :type `(choice ,@(append '((const nil)) ; sorting type may be nil | ||
| 116 | (mapcar (lambda (item) | ||
| 117 | (list 'const (car item))) | ||
| 118 | proced-sorting-schemes-alist)))) | ||
| 119 | (make-variable-buffer-local 'proced-sorting-scheme) | ||
| 85 | 120 | ||
| 86 | (defcustom proced-command (if (zerop (user-real-uid)) "all" "user") | 121 | (defcustom proced-command (if (zerop (user-real-uid)) "all" "user") |
| 87 | "Name of process listing. | 122 | "Name of process listing. |
| @@ -186,6 +221,12 @@ Initialized based on `proced-procname-column-regexp'.") | |||
| 186 | (define-key km "l" 'proced-listing-type) | 221 | (define-key km "l" 'proced-listing-type) |
| 187 | (define-key km "g" 'revert-buffer) ; Dired compatibility | 222 | (define-key km "g" 'revert-buffer) ; Dired compatibility |
| 188 | (define-key km "q" 'quit-window) | 223 | (define-key km "q" 'quit-window) |
| 224 | (define-key km "sc" 'proced-sort-pcpu) | ||
| 225 | (define-key km "sm" 'proced-sort-pmem) | ||
| 226 | (define-key km "sp" 'proced-sort-pid) | ||
| 227 | (define-key km "ss" 'proced-sort-start) | ||
| 228 | (define-key km "sS" 'proced-sort) | ||
| 229 | (define-key km "st" 'proced-sort-time) | ||
| 189 | (define-key km [remap undo] 'proced-undo) | 230 | (define-key km [remap undo] 'proced-undo) |
| 190 | (define-key km [remap advertised-undo] 'proced-undo) | 231 | (define-key km [remap advertised-undo] 'proced-undo) |
| 191 | km) | 232 | km) |
| @@ -200,6 +241,13 @@ Initialized based on `proced-procname-column-regexp'.") | |||
| 200 | ["Unmark All" proced-unmark-all t] | 241 | ["Unmark All" proced-unmark-all t] |
| 201 | ["Toggle Marks" proced-unmark-all t] | 242 | ["Toggle Marks" proced-unmark-all t] |
| 202 | "--" | 243 | "--" |
| 244 | ["Sort" proced-sort t] | ||
| 245 | ["Sort by %CPU" proced-sort-pcpu (proced-sorting-scheme-p "%CPU")] | ||
| 246 | ["Sort by %MEM" proced-sort-pmem (proced-sorting-scheme-p "%MEM")] | ||
| 247 | ["Sort by PID" proced-sort-pid (proced-sorting-scheme-p "PID")] | ||
| 248 | ["Sort by START" proced-sort-start (proced-sorting-scheme-p "START")] | ||
| 249 | ["Sort by TIME" proced-sort-time (proced-sorting-scheme-p "TIME")] | ||
| 250 | "--" | ||
| 203 | ["Hide Marked Processes" proced-hide-processes t] | 251 | ["Hide Marked Processes" proced-hide-processes t] |
| 204 | "--" | 252 | "--" |
| 205 | ["Revert" revert-buffer t] | 253 | ["Revert" revert-buffer t] |
| @@ -211,9 +259,11 @@ Initialized based on `proced-procname-column-regexp'.") | |||
| 211 | "Help string for proced.") | 259 | "Help string for proced.") |
| 212 | 260 | ||
| 213 | (defun proced-marker-regexp () | 261 | (defun proced-marker-regexp () |
| 262 | "Return regexp matching `proced-marker-char'." | ||
| 214 | (concat "^" (regexp-quote (char-to-string proced-marker-char)))) | 263 | (concat "^" (regexp-quote (char-to-string proced-marker-char)))) |
| 215 | 264 | ||
| 216 | (defun proced-success-message (action count) | 265 | (defun proced-success-message (action count) |
| 266 | "Display success message for ACTION performed for COUNT processes." | ||
| 217 | (message "%s %s process%s" action count (if (= 1 count) "" "es"))) | 267 | (message "%s %s process%s" action count (if (= 1 count) "" "es"))) |
| 218 | 268 | ||
| 219 | (defun proced-move-to-procname () | 269 | (defun proced-move-to-procname () |
| @@ -258,21 +308,20 @@ information will be displayed but not selected. | |||
| 258 | 308 | ||
| 259 | \\{proced-mode-map}" | 309 | \\{proced-mode-map}" |
| 260 | (interactive "P") | 310 | (interactive "P") |
| 261 | (let ((proced-buffer (get-buffer-create "*Process Info*")) new) | 311 | (let ((buffer (get-buffer-create "*Process Info*")) new) |
| 262 | (set-buffer proced-buffer) | 312 | (set-buffer buffer) |
| 263 | (setq new (zerop (buffer-size))) | 313 | (setq new (zerop (buffer-size))) |
| 264 | (when new (proced-mode)) | 314 | (if new (proced-mode)) |
| 265 | 315 | ||
| 266 | (if (or new arg) | 316 | (if (or new arg) |
| 267 | (proced-update)) | 317 | (proced-update)) |
| 268 | 318 | ||
| 269 | (if arg | 319 | (if arg |
| 270 | (display-buffer proced-buffer) | 320 | (display-buffer buffer) |
| 271 | (pop-to-buffer proced-buffer) | 321 | (pop-to-buffer buffer) |
| 272 | (message (substitute-command-keys | 322 | (message (substitute-command-keys |
| 273 | "type \\[quit-window] to quit, \\[proced-help] for help"))))) | 323 | "type \\[quit-window] to quit, \\[proced-help] for help"))))) |
| 274 | 324 | ||
| 275 | |||
| 276 | (defun proced-mark (&optional count) | 325 | (defun proced-mark (&optional count) |
| 277 | "Mark the current (or next COUNT) processes." | 326 | "Mark the current (or next COUNT) processes." |
| 278 | (interactive "p") | 327 | (interactive "p") |
| @@ -285,6 +334,8 @@ information will be displayed but not selected. | |||
| 285 | 334 | ||
| 286 | (defun proced-unmark-backward (&optional count) | 335 | (defun proced-unmark-backward (&optional count) |
| 287 | "Unmark the previous (or COUNT previous) processes." | 336 | "Unmark the previous (or COUNT previous) processes." |
| 337 | ;; Analogous to `dired-unmark-backward', | ||
| 338 | ;; but `ibuffer-unmark-backward' behaves different. | ||
| 288 | (interactive "p") | 339 | (interactive "p") |
| 289 | (proced-do-mark nil (- (or count 1)))) | 340 | (proced-do-mark nil (- (or count 1)))) |
| 290 | 341 | ||
| @@ -396,7 +447,7 @@ Returns count of hidden lines." | |||
| 396 | ;; This is the main function that generates and updates the process listing. | 447 | ;; This is the main function that generates and updates the process listing. |
| 397 | (interactive) | 448 | (interactive) |
| 398 | (or quiet (message "Updating process information...")) | 449 | (or quiet (message "Updating process information...")) |
| 399 | (let* ((command (cdr (assoc proced-command proced-command-alist))) | 450 | (let* ((command (cadr (assoc proced-command proced-command-alist))) |
| 400 | (regexp (concat (proced-skip-regexp) "\\s-+\\([0-9]+\\>\\)")) | 451 | (regexp (concat (proced-skip-regexp) "\\s-+\\([0-9]+\\>\\)")) |
| 401 | (old-pos (if (save-excursion | 452 | (old-pos (if (save-excursion |
| 402 | (beginning-of-line) | 453 | (beginning-of-line) |
| @@ -411,7 +462,9 @@ Returns count of hidden lines." | |||
| 411 | (match-string-no-properties 1)) plist)) | 462 | (match-string-no-properties 1)) plist)) |
| 412 | ;; generate new listing | 463 | ;; generate new listing |
| 413 | (erase-buffer) | 464 | (erase-buffer) |
| 414 | (apply 'call-process (caar command) nil t nil (cdar command)) | 465 | (apply 'call-process (car command) nil t nil |
| 466 | (append (cdr command) (cdr (assoc proced-sorting-scheme | ||
| 467 | proced-sorting-schemes-alist)))) | ||
| 415 | (goto-char (point-min)) | 468 | (goto-char (point-min)) |
| 416 | (while (not (eobp)) | 469 | (while (not (eobp)) |
| 417 | (insert " ") | 470 | (insert " ") |
| @@ -447,6 +500,12 @@ Returns count of hidden lines." | |||
| 447 | (beginning-of-line) | 500 | (beginning-of-line) |
| 448 | (forward-char (cdr old-pos))) | 501 | (forward-char (cdr old-pos))) |
| 449 | (proced-move-to-procname)) | 502 | (proced-move-to-procname)) |
| 503 | ;; update modeline | ||
| 504 | (setq mode-name (if proced-sorting-scheme | ||
| 505 | (concat "Proced by " proced-sorting-scheme) | ||
| 506 | "Proced")) | ||
| 507 | (force-mode-line-update) | ||
| 508 | ;; done | ||
| 450 | (or quiet (input-pending-p) | 509 | (or quiet (input-pending-p) |
| 451 | (message "Updating process information...done.")))) | 510 | (message "Updating process information...done.")))) |
| 452 | 511 | ||
| @@ -476,6 +535,7 @@ If SIGNAL is nil display marked processes and query interactively for SIGNAL." | |||
| 476 | ;; and the command name? | 535 | ;; and the command name? |
| 477 | (substring (match-string-no-properties 0) 2)) | 536 | (substring (match-string-no-properties 0) 2)) |
| 478 | plist))) | 537 | plist))) |
| 538 | (setq plist (nreverse plist)) | ||
| 479 | (if (not plist) | 539 | (if (not plist) |
| 480 | (message "No processes marked") | 540 | (message "No processes marked") |
| 481 | (unless signal | 541 | (unless signal |
| @@ -555,6 +615,52 @@ buffer. You can use it to recover marks." | |||
| 555 | (message "Change in proced buffer undone. | 615 | (message "Change in proced buffer undone. |
| 556 | Killed processes cannot be recovered by Emacs.")) | 616 | Killed processes cannot be recovered by Emacs.")) |
| 557 | 617 | ||
| 618 | ;;; Sorting | ||
| 619 | (defun proced-sort (scheme) | ||
| 620 | "Sort Proced buffer using SCHEME. | ||
| 621 | When called interactively, an empty string means nil, i.e., no sorting." | ||
| 622 | (interactive | ||
| 623 | (list (let* ((completion-ignore-case t) | ||
| 624 | (scheme (completing-read "Sorting type: " | ||
| 625 | proced-sorting-schemes-alist nil t))) | ||
| 626 | (if (string= "" scheme) nil scheme)))) | ||
| 627 | (if (proced-sorting-scheme-p scheme) | ||
| 628 | (progn | ||
| 629 | (setq proced-sorting-scheme scheme) | ||
| 630 | (proced-update)) | ||
| 631 | (error "Proced sorting scheme %s undefined" scheme))) | ||
| 632 | |||
| 633 | (defun proced-sorting-scheme-p (scheme) | ||
| 634 | "Return non-nil if SCHEME is an applicable sorting scheme. | ||
| 635 | SCHEME must be a string or nil." | ||
| 636 | (or (not scheme) | ||
| 637 | (assoc scheme proced-sorting-schemes-alist))) | ||
| 638 | |||
| 639 | (defun proced-sort-pcpu () | ||
| 640 | "Sort Proced buffer by percentage CPU time (%CPU)." | ||
| 641 | (interactive) | ||
| 642 | (proced-sort "%CPU")) | ||
| 643 | |||
| 644 | (defun proced-sort-pmem () | ||
| 645 | "Sort Proced buffer by percentage memory usage (%MEM)." | ||
| 646 | (interactive) | ||
| 647 | (proced-sort "%MEM")) | ||
| 648 | |||
| 649 | (defun proced-sort-pid () | ||
| 650 | "Sort Proced buffer by PID." | ||
| 651 | (interactive) | ||
| 652 | (proced-sort "PID")) | ||
| 653 | |||
| 654 | (defun proced-sort-start () | ||
| 655 | "Sort Proced buffer by time the command started (START)." | ||
| 656 | (interactive) | ||
| 657 | (proced-sort "START")) | ||
| 658 | |||
| 659 | (defun proced-sort-time () | ||
| 660 | "Sort Proced buffer by cumulative CPU time (TIME)." | ||
| 661 | (interactive) | ||
| 662 | (proced-sort "TIME")) | ||
| 663 | |||
| 558 | (provide 'proced) | 664 | (provide 'proced) |
| 559 | 665 | ||
| 560 | ;; arch-tag: a6e312ad-9032-45aa-972d-31a8cfc545af | 666 | ;; arch-tag: a6e312ad-9032-45aa-972d-31a8cfc545af |