diff options
| author | Roland Winkler | 2008-08-18 00:47:12 +0000 |
|---|---|---|
| committer | Roland Winkler | 2008-08-18 00:47:12 +0000 |
| commit | 9f583d141ffe6198a69c57491fb4f1349f020b22 (patch) | |
| tree | a225c21e8220696d5873fc56e372accad8021d05 | |
| parent | e56d3af5f0f28aea89004fcce2c140c8a4d5b468 (diff) | |
| download | emacs-9f583d141ffe6198a69c57491fb4f1349f020b22.tar.gz emacs-9f583d141ffe6198a69c57491fb4f1349f020b22.zip | |
(proced-signal-list): Add POSIX 1003.1-2001 signals.
(proced-mode-map): Add tooltips for menus. Use radio buttons for
listing types.
(proced-log-buffer): New variable.
(proced-mark-all, proced-unmark-all, proced-do-mark-al): Operate
on region if transient-mark-mode is turned on and the region is
active.
(proced-omit-processes): Renamed from proced-hide-processes to
avoid key clash with describe-mode (bound to h). Search for
marked processes starting from point-min.
(proced-header-space): Removed.
(proced-send-signal): Handle errors. Operate on current process
if no process is marked.
(proced-why): New command.
(proced-log, proced-log-summary): New functions.
(proced-help): Use proced-why.
| -rw-r--r-- | lisp/ChangeLog | 21 | ||||
| -rw-r--r-- | lisp/proced.el | 358 |
2 files changed, 261 insertions, 118 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 801920d06a4..08cafe3853f 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,24 @@ | |||
| 1 | 2008-08-17 Roland Winkler <Roland.Winkler@physik.uni-erlangen.de> | ||
| 2 | |||
| 3 | * proced.el (proced-signal-list): Add POSIX 1003.1-2001 signals. | ||
| 4 | (proced-mode-map): Add tooltips for menus. Use radio buttons for | ||
| 5 | listing types. | ||
| 6 | (proced-log-buffer): New variable. | ||
| 7 | (proced-mark-all, proced-unmark-all, proced-do-mark-al): Operate | ||
| 8 | on region if transient-mark-mode is turned on and the region is | ||
| 9 | active. | ||
| 10 | (proced-omit-processes): Renamed from proced-hide-processes to | ||
| 11 | avoid key clash with describe-mode (bound to h). Search for | ||
| 12 | marked processes starting from point-min. | ||
| 13 | (proced-header-space): Removed. | ||
| 14 | (proced-send-signal): Handle errors. Operate on current process | ||
| 15 | if no process is marked. | ||
| 16 | (proced-why): New command. | ||
| 17 | (proced-log, proced-log-summary): New functions. | ||
| 18 | (proced-help): Use proced-why. | ||
| 19 | * textmodes/bibtex.el (bibtex-entry-format): Mark as safe. | ||
| 20 | (bibtex-autokey-year-title-separator): Fix doscstring. | ||
| 21 | |||
| 1 | 2008-08-17 Michael Albinus <michael.albinus@gmx.de> | 22 | 2008-08-17 Michael Albinus <michael.albinus@gmx.de> |
| 2 | 23 | ||
| 3 | * net/xesam.el (xesam-vendor, xesam-notify-function): New local | 24 | * net/xesam.el (xesam-vendor, xesam-notify-function): New local |
diff --git a/lisp/proced.el b/lisp/proced.el index 436189d8f6a..0df3b9a9792 100644 --- a/lisp/proced.el +++ b/lisp/proced.el | |||
| @@ -28,14 +28,15 @@ | |||
| 28 | ;; on the processes listed. | 28 | ;; on the processes listed. |
| 29 | ;; | 29 | ;; |
| 30 | ;; To do: | 30 | ;; To do: |
| 31 | ;; - decompose ps(1) output into columns (for `proced-header-alist') | 31 | ;; - use list-system-processes and system-process-attributes |
| 32 | ;; How can we identify columns that may contain whitespace | 32 | ;; - sort and filter by user name or other criteria |
| 33 | ;; and that can be either right or left justified? | 33 | ;; - make fields clickable for marking / filtering / sorting: |
| 34 | ;; Use a "grammar table"? | 34 | ;; clicking on a USER field marks all processes of this user etc |
| 35 | ;; - sort the "cooked" values used in the output format fields | 35 | ;; clicking on a %MEM field marks all processes with at least this %MEM. |
| 36 | ;; if ps(1) doesn't support the requested sorting scheme | 36 | ;; clicking on a header field sorts according to this header |
| 37 | ;; - filter by user name or other criteria | 37 | ;; - mark parent and children PIDs (or both) |
| 38 | ;; - automatic update of process list | 38 | ;; - automatic update of process list |
| 39 | ;; - allow "sudo kill PID", "renice PID" | ||
| 39 | 40 | ||
| 40 | ;;; Code: | 41 | ;;; Code: |
| 41 | 42 | ||
| @@ -143,13 +144,20 @@ the external command (usually \"kill\")." | |||
| 143 | (string :tag "command"))) | 144 | (string :tag "command"))) |
| 144 | 145 | ||
| 145 | (defcustom proced-signal-list | 146 | (defcustom proced-signal-list |
| 146 | '(("HUP (1. Hangup)") | 147 | '(;; signals supported on all POSIX compliant systems |
| 148 | ("HUP (1. Hangup)") | ||
| 147 | ("INT (2. Terminal interrupt)") | 149 | ("INT (2. Terminal interrupt)") |
| 148 | ("QUIT (3. Terminal quit)") | 150 | ("QUIT (3. Terminal quit)") |
| 149 | ("ABRT (6. Process abort)") | 151 | ("ABRT (6. Process abort)") |
| 150 | ("KILL (9. Kill -- cannot be caught or ignored)") | 152 | ("KILL (9. Kill - cannot be caught or ignored)") |
| 151 | ("ALRM (14. Alarm Clock)") | 153 | ("ALRM (14. Alarm Clock)") |
| 152 | ("TERM (15. Termination)")) | 154 | ("TERM (15. Termination)") |
| 155 | ;; POSIX 1003.1-2001 | ||
| 156 | ;; Which systems do not support these signals so that we can | ||
| 157 | ;; exclude them from `proced-signal-list'? | ||
| 158 | ("CONT (Continue executing)") | ||
| 159 | ("STOP (Stop executing / pause - cannot be caught or ignored)") | ||
| 160 | ("TSTP (Terminal stop / pause)")) | ||
| 153 | "List of signals, used for minibuffer completion." | 161 | "List of signals, used for minibuffer completion." |
| 154 | :group 'proced | 162 | :group 'proced |
| 155 | :type '(repeat (string :tag "signal"))) | 163 | :type '(repeat (string :tag "signal"))) |
| @@ -223,7 +231,7 @@ Important: the match ends just after the marker.") | |||
| 223 | (define-key km "sS" 'proced-sort) | 231 | (define-key km "sS" 'proced-sort) |
| 224 | (define-key km "st" 'proced-sort-time) | 232 | (define-key km "st" 'proced-sort-time) |
| 225 | ;; operate | 233 | ;; operate |
| 226 | (define-key km "h" 'proced-hide-processes) | 234 | (define-key km "o" 'proced-omit-processes) |
| 227 | (define-key km "x" 'proced-send-signal) ; Dired compatibility | 235 | (define-key km "x" 'proced-send-signal) ; Dired compatibility |
| 228 | (define-key km "k" 'proced-send-signal) ; kill processes | 236 | (define-key km "k" 'proced-send-signal) ; kill processes |
| 229 | ;; misc | 237 | ;; misc |
| @@ -235,29 +243,45 @@ Important: the match ends just after the marker.") | |||
| 235 | (define-key km [remap undo] 'proced-undo) | 243 | (define-key km [remap undo] 'proced-undo) |
| 236 | (define-key km [remap advertised-undo] 'proced-undo) | 244 | (define-key km [remap advertised-undo] 'proced-undo) |
| 237 | km) | 245 | km) |
| 238 | "Keymap for proced commands") | 246 | "Keymap for proced commands.") |
| 239 | 247 | ||
| 240 | (easy-menu-define | 248 | (easy-menu-define |
| 241 | proced-menu proced-mode-map "Proced Menu" | 249 | proced-menu proced-mode-map "Proced Menu" |
| 242 | '("Proced" | 250 | `("Proced" |
| 243 | ["Mark" proced-mark t] | 251 | ["Mark" proced-mark |
| 244 | ["Unmark" proced-unmark t] | 252 | :help "Mark Current Process"] |
| 245 | ["Mark All" proced-mark-all t] | 253 | ["Unmark" proced-unmark |
| 246 | ["Unmark All" proced-unmark-all t] | 254 | :help "Unmark Current Process"] |
| 247 | ["Toggle Marks" proced-toggle-marks t] | 255 | ["Mark All" proced-mark-all |
| 256 | :help "Mark All Processes"] | ||
| 257 | ["Unmark All" proced-unmark-all | ||
| 258 | :help "Unmark All Process"] | ||
| 259 | ["Toggle Marks" proced-toggle-marks | ||
| 260 | :help "Marked Processes Become Unmarked, and Vice Versa"] | ||
| 248 | "--" | 261 | "--" |
| 249 | ["Sort" proced-sort t] | 262 | ["Sort..." proced-sort |
| 263 | :help "Sort Process List"] | ||
| 250 | ["Sort by %CPU" proced-sort-pcpu (proced-sorting-scheme-p "%CPU")] | 264 | ["Sort by %CPU" proced-sort-pcpu (proced-sorting-scheme-p "%CPU")] |
| 251 | ["Sort by %MEM" proced-sort-pmem (proced-sorting-scheme-p "%MEM")] | 265 | ["Sort by %MEM" proced-sort-pmem (proced-sorting-scheme-p "%MEM")] |
| 252 | ["Sort by PID" proced-sort-pid (proced-sorting-scheme-p "PID")] | 266 | ["Sort by PID" proced-sort-pid (proced-sorting-scheme-p "PID")] |
| 253 | ["Sort by START" proced-sort-start (proced-sorting-scheme-p "START")] | 267 | ["Sort by START" proced-sort-start (proced-sorting-scheme-p "START")] |
| 254 | ["Sort by TIME" proced-sort-time (proced-sorting-scheme-p "TIME")] | 268 | ["Sort by TIME" proced-sort-time (proced-sorting-scheme-p "TIME")] |
| 255 | "--" | 269 | "--" |
| 256 | ["Hide Marked Processes" proced-hide-processes t] | 270 | ["Omit Marked Processes" proced-omit-processes |
| 271 | :help "Omit Marked Processes in Process Listing."] | ||
| 257 | "--" | 272 | "--" |
| 258 | ["Revert" revert-buffer t] | 273 | ["Revert" revert-buffer |
| 259 | ["Send signal" proced-send-signal t] | 274 | :help "Revert Process Listing"] |
| 260 | ["Change listing" proced-listing-type t])) | 275 | ["Send signal" proced-send-signal |
| 276 | :help "Send Signal to Marked Processes"] | ||
| 277 | ("Listing Type" | ||
| 278 | :help "Select Type of Process Listing" | ||
| 279 | ,@(mapcar (lambda (el) | ||
| 280 | (let ((command (car el))) | ||
| 281 | `[,command (proced-listing-type ,command) | ||
| 282 | :style radio | ||
| 283 | :selected (string= proced-command ,command)])) | ||
| 284 | proced-command-alist)))) | ||
| 261 | 285 | ||
| 262 | (defconst proced-help-string | 286 | (defconst proced-help-string |
| 263 | "(n)ext, (p)revious, (m)ark, (u)nmark, (k)ill, (q)uit (type ? for more help)" | 287 | "(n)ext, (p)revious, (m)ark, (u)nmark, (k)ill, (q)uit (type ? for more help)" |
| @@ -280,6 +304,9 @@ JUSTIFY is 'left or 'right for left or right-justified output of ps(1).") | |||
| 280 | "Regexp to match valid sorting schemes.") | 304 | "Regexp to match valid sorting schemes.") |
| 281 | (make-variable-buffer-local 'proced-sorting-schemes-re) | 305 | (make-variable-buffer-local 'proced-sorting-schemes-re) |
| 282 | 306 | ||
| 307 | (defvar proced-log-buffer "*Proced log*" | ||
| 308 | "Name of Proced Log buffer.") | ||
| 309 | |||
| 283 | ;; helper functions | 310 | ;; helper functions |
| 284 | (defun proced-marker-regexp () | 311 | (defun proced-marker-regexp () |
| 285 | "Return regexp matching `proced-marker-char'." | 312 | "Return regexp matching `proced-marker-char'." |
| @@ -339,10 +366,8 @@ information will be displayed but not selected. | |||
| 339 | (set-buffer buffer) | 366 | (set-buffer buffer) |
| 340 | (setq new (zerop (buffer-size))) | 367 | (setq new (zerop (buffer-size))) |
| 341 | (if new (proced-mode)) | 368 | (if new (proced-mode)) |
| 342 | |||
| 343 | (if (or new arg) | 369 | (if (or new arg) |
| 344 | (proced-update)) | 370 | (proced-update)) |
| 345 | |||
| 346 | (if arg | 371 | (if arg |
| 347 | (display-buffer buffer) | 372 | (display-buffer buffer) |
| 348 | (pop-to-buffer buffer) | 373 | (pop-to-buffer buffer) |
| @@ -382,7 +407,7 @@ Optional prefix ARG says how many lines to move; default is one line." | |||
| 382 | (proced-do-mark nil (- (or count 1)))) | 407 | (proced-do-mark nil (- (or count 1)))) |
| 383 | 408 | ||
| 384 | (defun proced-do-mark (mark &optional count) | 409 | (defun proced-do-mark (mark &optional count) |
| 385 | "Mark the current (or next ARG) processes using MARK." | 410 | "Mark the current (or next COUNT) processes using MARK." |
| 386 | (or count (setq count 1)) | 411 | (or count (setq count 1)) |
| 387 | (let ((backward (< count 0)) | 412 | (let ((backward (< count 0)) |
| 388 | buffer-read-only) | 413 | buffer-read-only) |
| @@ -394,22 +419,40 @@ Optional prefix ARG says how many lines to move; default is one line." | |||
| 394 | (proced-move-to-goal-column))) | 419 | (proced-move-to-goal-column))) |
| 395 | 420 | ||
| 396 | (defun proced-mark-all () | 421 | (defun proced-mark-all () |
| 397 | "Mark all processes." | 422 | "Mark all processes. |
| 423 | If `transient-mark-mode' is turned on and the region is active, | ||
| 424 | mark the region." | ||
| 398 | (interactive) | 425 | (interactive) |
| 399 | (proced-do-mark-all t)) | 426 | (proced-do-mark-all t)) |
| 400 | 427 | ||
| 401 | (defun proced-unmark-all () | 428 | (defun proced-unmark-all () |
| 402 | "Unmark all processes." | 429 | "Unmark all processes. |
| 430 | If `transient-mark-mode' is turned on and the region is active, | ||
| 431 | unmark the region." | ||
| 403 | (interactive) | 432 | (interactive) |
| 404 | (proced-do-mark-all nil)) | 433 | (proced-do-mark-all nil)) |
| 405 | 434 | ||
| 406 | (defun proced-do-mark-all (mark) | 435 | (defun proced-do-mark-all (mark) |
| 407 | "Mark all processes using MARK." | 436 | "Mark all processes using MARK. |
| 437 | If `transient-mark-mode' is turned on and the region is active, | ||
| 438 | mark the region." | ||
| 408 | (let (buffer-read-only) | 439 | (let (buffer-read-only) |
| 409 | (save-excursion | 440 | (save-excursion |
| 410 | (goto-char (point-min)) | 441 | (if (and transient-mark-mode mark-active) |
| 411 | (while (not (eobp)) | 442 | ;; Operate even on those lines that are only partially a part |
| 412 | (proced-insert-mark mark))))) | 443 | ;; of region. This appears most consistent with |
| 444 | ;; `proced-move-to-goal-column'. | ||
| 445 | (let ((end (save-excursion | ||
| 446 | (goto-char (region-end)) | ||
| 447 | (unless (looking-at "^") (forward-line)) | ||
| 448 | (point)))) | ||
| 449 | (goto-char (region-beginning)) | ||
| 450 | (unless (looking-at "^") (beginning-of-line)) | ||
| 451 | (while (< (point) end) | ||
| 452 | (proced-insert-mark mark))) | ||
| 453 | (goto-char (point-min)) | ||
| 454 | (while (not (eobp)) | ||
| 455 | (proced-insert-mark mark)))))) | ||
| 413 | 456 | ||
| 414 | (defun proced-toggle-marks () | 457 | (defun proced-toggle-marks () |
| 415 | "Toggle marks: marked processes become unmarked, and vice versa." | 458 | "Toggle marks: marked processes become unmarked, and vice versa." |
| @@ -439,35 +482,36 @@ Otherwise move one line forward after inserting the mark." | |||
| 439 | ;; However, for negative args the target lines of `dired-do-kill-lines' | 482 | ;; However, for negative args the target lines of `dired-do-kill-lines' |
| 440 | ;; include the current line, whereas `dired-mark' for negative args operates | 483 | ;; include the current line, whereas `dired-mark' for negative args operates |
| 441 | ;; on the preceding lines. Here we are consistent with `dired-mark'. | 484 | ;; on the preceding lines. Here we are consistent with `dired-mark'. |
| 442 | (defun proced-hide-processes (&optional arg quiet) | 485 | (defun proced-omit-processes (&optional arg quiet) |
| 443 | "Hide marked processes. | 486 | "Omit marked processes. |
| 444 | With prefix ARG, hide that many lines starting with the current line. | 487 | With prefix ARG, omit that many lines starting with the current line. |
| 445 | \(A negative argument hides backward.) | 488 | \(A negative argument omits backward.) |
| 446 | If QUIET is non-nil suppress status message. | 489 | If QUIET is non-nil suppress status message. |
| 447 | Returns count of hidden lines." | 490 | Returns count of omitted lines." |
| 448 | (interactive "P") | 491 | (interactive "P") |
| 449 | (let ((mark-re (proced-marker-regexp)) | 492 | (let ((mark-re (proced-marker-regexp)) |
| 450 | (count 0) | 493 | (count 0) |
| 451 | buffer-read-only) | 494 | buffer-read-only) |
| 452 | (save-excursion | 495 | (if arg |
| 453 | (if arg | 496 | ;; Omit ARG lines starting with the current line. |
| 454 | ;; Hide ARG lines starting with the current line. | 497 | (delete-region (line-beginning-position) |
| 455 | (delete-region (line-beginning-position) | 498 | (save-excursion |
| 456 | (save-excursion | 499 | (if (<= 0 arg) |
| 457 | (if (<= 0 arg) | 500 | (setq count (- arg (forward-line arg))) |
| 458 | (setq count (- arg (forward-line arg))) | 501 | (setq count (min (1- (line-number-at-pos)) |
| 459 | (setq count (min (1- (line-number-at-pos)) | 502 | (abs arg))) |
| 460 | (abs arg))) | 503 | (forward-line (- count))) |
| 461 | (forward-line (- count))) | 504 | (point))) |
| 462 | (point))) | 505 | ;; Omit marked lines |
| 463 | ;; Hide marked lines | 506 | (save-excursion |
| 507 | (goto-char (point-min)) | ||
| 464 | (while (and (not (eobp)) | 508 | (while (and (not (eobp)) |
| 465 | (re-search-forward mark-re nil t)) | 509 | (re-search-forward mark-re nil t)) |
| 466 | (delete-region (match-beginning 0) | 510 | (delete-region (match-beginning 0) |
| 467 | (save-excursion (forward-line) (point))) | 511 | (save-excursion (forward-line) (point))) |
| 468 | (setq count (1+ count))))) | 512 | (setq count (1+ count))))) |
| 469 | (unless (zerop count) (proced-move-to-goal-column)) | 513 | (unless (zerop count) (proced-move-to-goal-column)) |
| 470 | (unless quiet (proced-success-message "Hid" count)) | 514 | (unless quiet (proced-success-message "Omitted" count)) |
| 471 | count)) | 515 | count)) |
| 472 | 516 | ||
| 473 | (defun proced-listing-type (command) | 517 | (defun proced-listing-type (command) |
| @@ -477,12 +521,6 @@ Returns count of hidden lines." | |||
| 477 | (setq proced-command command) | 521 | (setq proced-command command) |
| 478 | (proced-update)) | 522 | (proced-update)) |
| 479 | 523 | ||
| 480 | ;; adopted from `ruler-mode-space' | ||
| 481 | (defsubst proced-header-space (width) | ||
| 482 | "Return a single space string of WIDTH times the normal character width." | ||
| 483 | (propertize " " 'display (list 'space :width width))) | ||
| 484 | |||
| 485 | ;; header line: code inspired by `ruler-mode-ruler' | ||
| 486 | (defun proced-header-line () | 524 | (defun proced-header-line () |
| 487 | "Return header line for Proced buffer." | 525 | "Return header line for Proced buffer." |
| 488 | (list (propertize " " 'display '(space :align-to 0)) | 526 | (list (propertize " " 'display '(space :align-to 0)) |
| @@ -490,7 +528,8 @@ Returns count of hidden lines." | |||
| 490 | "%" "%%" (substring proced-header-line (window-hscroll))))) | 528 | "%" "%%" (substring proced-header-line (window-hscroll))))) |
| 491 | 529 | ||
| 492 | (defun proced-update (&optional quiet) | 530 | (defun proced-update (&optional quiet) |
| 493 | "Update the `proced' process information. Preserves point and marks." | 531 | "Update the `proced' process information. Preserves point and marks. |
| 532 | Suppress status information if QUIET is nil." | ||
| 494 | ;; This is the main function that generates and updates the process listing. | 533 | ;; This is the main function that generates and updates the process listing. |
| 495 | (interactive) | 534 | (interactive) |
| 496 | (or quiet (message "Updating process information...")) | 535 | (or quiet (message "Updating process information...")) |
| @@ -594,6 +633,7 @@ Returns count of hidden lines." | |||
| 594 | 633 | ||
| 595 | (defun proced-send-signal (&optional signal) | 634 | (defun proced-send-signal (&optional signal) |
| 596 | "Send a SIGNAL to the marked processes. | 635 | "Send a SIGNAL to the marked processes. |
| 636 | If no process is marked, operate on current process. | ||
| 597 | SIGNAL may be a string (HUP, INT, TERM, etc.) or a number. | 637 | SIGNAL may be a string (HUP, INT, TERM, etc.) or a number. |
| 598 | If SIGNAL is nil display marked processes and query interactively for SIGNAL." | 638 | If SIGNAL is nil display marked processes and query interactively for SIGNAL." |
| 599 | (interactive) | 639 | (interactive) |
| @@ -610,71 +650,153 @@ If SIGNAL is nil display marked processes and query interactively for SIGNAL." | |||
| 610 | ;; and the command name? | 650 | ;; and the command name? |
| 611 | (substring (match-string-no-properties 0) 2)) | 651 | (substring (match-string-no-properties 0) 2)) |
| 612 | process-list))) | 652 | process-list))) |
| 613 | (setq process-list (nreverse process-list)) | 653 | (setq process-list |
| 614 | (if (not process-list) | 654 | (if process-list |
| 615 | (message "No processes marked") | 655 | (nreverse process-list) |
| 616 | (unless signal | 656 | ;; take current process |
| 617 | ;; Display marked processes (code taken from `dired-mark-pop-up'). | 657 | (save-excursion |
| 618 | (let ((bufname " *Marked Processes*") | 658 | (line-beginning-position) |
| 619 | (header proced-header-line)) ; inherit header line | 659 | (looking-at (concat "^" (proced-skip-regexp) |
| 620 | (with-current-buffer (get-buffer-create bufname) | 660 | "\\s-+\\([0-9]+\\>\\).*$")) |
| 621 | (setq truncate-lines t | 661 | (list (cons (match-string-no-properties 1) |
| 622 | proced-header-line header | 662 | (substring (match-string-no-properties 0) 2)))))) |
| 623 | header-line-format '(:eval (proced-header-line))) | 663 | (unless signal |
| 624 | (add-hook 'post-command-hook 'force-mode-line-update nil t) | 664 | ;; Display marked processes (code taken from `dired-mark-pop-up'). |
| 625 | (erase-buffer) | 665 | (let ((bufname " *Marked Processes*") |
| 626 | (dolist (process process-list) | 666 | (header proced-header-line)) ; inherit header line |
| 627 | (insert " " (cdr process) "\n")) | 667 | (with-current-buffer (get-buffer-create bufname) |
| 628 | (save-window-excursion | 668 | (setq truncate-lines t |
| 629 | (dired-pop-to-buffer bufname) ; all we need | 669 | proced-header-line header |
| 630 | (let* ((completion-ignore-case t) | 670 | header-line-format '(:eval (proced-header-line))) |
| 631 | (pnum (if (= 1 (length process-list)) | 671 | (add-hook 'post-command-hook 'force-mode-line-update nil t) |
| 632 | "1 process" | 672 | (erase-buffer) |
| 633 | (format "%d processes" (length process-list)))) | 673 | (dolist (process process-list) |
| 634 | ;; The following is an ugly hack. Is there a better way | 674 | (insert " " (cdr process) "\n")) |
| 635 | ;; to help people like me to remember the signals and | 675 | (save-window-excursion |
| 636 | ;; their meanings? | 676 | (dired-pop-to-buffer bufname) ; all we need |
| 637 | (tmp (completing-read (concat "Send signal [" pnum | 677 | (let* ((completion-ignore-case t) |
| 638 | "] (default TERM): ") | 678 | (pnum (if (= 1 (length process-list)) |
| 639 | proced-signal-list | 679 | "1 process" |
| 640 | nil nil nil nil "TERM"))) | 680 | (format "%d processes" (length process-list)))) |
| 641 | (setq signal (if (string-match "^\\(\\S-+\\)\\s-" tmp) | 681 | ;; The following is an ugly hack. Is there a better way |
| 642 | (match-string 1 tmp) tmp)))))) | 682 | ;; to help people like me to remember the signals and |
| 643 | ;; send signal | 683 | ;; their meanings? |
| 644 | (let ((count 0) | 684 | (tmp (completing-read (concat "Send signal [" pnum |
| 645 | err-list) | 685 | "] (default TERM): ") |
| 646 | (if (functionp proced-signal-function) | 686 | proced-signal-list |
| 647 | ;; use built-in `signal-process' | 687 | nil nil nil nil "TERM"))) |
| 648 | (let ((signal (if (stringp signal) | 688 | (setq signal (if (string-match "^\\(\\S-+\\)\\s-" tmp) |
| 649 | (if (string-match "\\`[0-9]+\\'" signal) | 689 | (match-string 1 tmp) tmp)))))) |
| 650 | (string-to-number signal) | 690 | ;; send signal |
| 651 | (make-symbol signal)) | 691 | (let ((count 0) |
| 652 | signal))) ; number | 692 | failures) |
| 653 | (dolist (process process-list) | 693 | ;; Why not always use `signal-process'? See |
| 654 | (if (zerop (funcall | 694 | ;; http://lists.gnu.org/archive/html/emacs-devel/2008-03/msg02955.html |
| 655 | proced-signal-function | 695 | (if (functionp proced-signal-function) |
| 656 | (string-to-number (car process)) signal)) | 696 | ;; use built-in `signal-process' |
| 657 | (setq count (1+ count)) | 697 | (let ((signal (if (stringp signal) |
| 658 | (push (cdr process) err-list)))) | 698 | (if (string-match "\\`[0-9]+\\'" signal) |
| 659 | ;; use external system call | 699 | (string-to-number signal) |
| 660 | (let ((signal (concat "-" (if (numberp signal) | 700 | (make-symbol signal)) |
| 661 | (number-to-string signal) signal)))) | 701 | signal))) ; number |
| 662 | (dolist (process process-list) | 702 | (dolist (process process-list) |
| 663 | (if (zerop (call-process | 703 | (condition-case err |
| 664 | proced-signal-function nil 0 nil | 704 | (if (zerop (funcall |
| 665 | signal (car process))) | 705 | proced-signal-function |
| 666 | (setq count (1+ count)) | 706 | (string-to-number (car process)) signal)) |
| 667 | (push (cdr process) err-list))))) | 707 | (setq count (1+ count)) |
| 668 | (if err-list | 708 | (proced-log "%s\n" (cdr process)) |
| 669 | ;; FIXME: that's not enough to display the errors. | 709 | (push (cdr process) failures)) |
| 670 | (message "%s: %s" signal err-list) | 710 | (error ;; catch errors from failed signals |
| 671 | (proced-success-message "Sent signal to" count))) | 711 | (proced-log "%s\n" err) |
| 672 | ;; final clean-up | 712 | (proced-log "%s\n" (cdr process)) |
| 673 | (run-hooks 'proced-after-send-signal-hook))))) | 713 | (push (cdr process) failures))))) |
| 714 | ;; use external system call | ||
| 715 | (let ((signal (concat "-" (if (numberp signal) | ||
| 716 | (number-to-string signal) signal)))) | ||
| 717 | (dolist (process process-list) | ||
| 718 | (with-temp-buffer | ||
| 719 | (condition-case err | ||
| 720 | (if (zerop (call-process | ||
| 721 | proced-signal-function nil t nil | ||
| 722 | signal (car process))) | ||
| 723 | (setq count (1+ count)) | ||
| 724 | (proced-log (current-buffer)) | ||
| 725 | (proced-log "%s\n" (cdr process)) | ||
| 726 | (push (cdr process) failures)) | ||
| 727 | (error ;; catch errors from failed signals | ||
| 728 | (proced-log (current-buffer)) | ||
| 729 | (proced-log "%s\n" (cdr process)) | ||
| 730 | (push (cdr process) failures))))))) | ||
| 731 | (if failures | ||
| 732 | (proced-log-summary | ||
| 733 | signal | ||
| 734 | (format "%d of %d signal%s failed" | ||
| 735 | (length failures) (length process-list) | ||
| 736 | (if (= 1 (length process-list)) "" "s"))) | ||
| 737 | (proced-success-message "Sent signal to" count))) | ||
| 738 | ;; final clean-up | ||
| 739 | (run-hooks 'proced-after-send-signal-hook)))) | ||
| 740 | |||
| 741 | ;; just like `dired-why' | ||
| 742 | (defun proced-why () | ||
| 743 | "Pop up a buffer with error log output from Proced. | ||
| 744 | A group of errors from a single command ends with a formfeed. | ||
| 745 | Thus, use \\[backward-page] to find the beginning of a group of errors." | ||
| 746 | (interactive) | ||
| 747 | (if (get-buffer proced-log-buffer) | ||
| 748 | (let ((owindow (selected-window)) | ||
| 749 | (window (display-buffer (get-buffer proced-log-buffer)))) | ||
| 750 | (unwind-protect | ||
| 751 | (progn | ||
| 752 | (select-window window) | ||
| 753 | (goto-char (point-max)) | ||
| 754 | (forward-line -1) | ||
| 755 | (backward-page 1) | ||
| 756 | (recenter 0)) | ||
| 757 | (select-window owindow))))) | ||
| 758 | |||
| 759 | ;; similar to `dired-log' | ||
| 760 | (defun proced-log (log &rest args) | ||
| 761 | "Log a message or the contents of a buffer. | ||
| 762 | If LOG is a string and there are more args, it is formatted with | ||
| 763 | those ARGS. Usually the LOG string ends with a \\n. | ||
| 764 | End each bunch of errors with (proced-log t signal): | ||
| 765 | this inserts the current time, buffer and signal at the start of the page, | ||
| 766 | and \f (formfeed) at the end." | ||
| 767 | (let ((obuf (current-buffer))) | ||
| 768 | (with-current-buffer (get-buffer-create proced-log-buffer) | ||
| 769 | (goto-char (point-max)) | ||
| 770 | (let ((inhibit-read-only t)) | ||
| 771 | (cond ((stringp log) | ||
| 772 | (insert (if args | ||
| 773 | (apply 'format log args) | ||
| 774 | log))) | ||
| 775 | ((bufferp log) | ||
| 776 | (insert-buffer-substring log)) | ||
| 777 | ((eq t log) | ||
| 778 | (backward-page 1) | ||
| 779 | (unless (bolp) | ||
| 780 | (insert "\n")) | ||
| 781 | (insert (current-time-string) | ||
| 782 | "\tBuffer `" (buffer-name obuf) "', " | ||
| 783 | (format "signal `%s'\n" (car args))) | ||
| 784 | (goto-char (point-max)) | ||
| 785 | (insert "\f\n"))))))) | ||
| 786 | |||
| 787 | ;; similar to `dired-log-summary' | ||
| 788 | (defun proced-log-summary (signal string) | ||
| 789 | "State a summary of SIGNAL's failures, in echo area and log buffer. | ||
| 790 | STRING is an overall summary of the failures." | ||
| 791 | (message "Signal %s: %s--type ? for details" signal string) | ||
| 792 | ;; Log a summary describing a bunch of errors. | ||
| 793 | (proced-log (concat "\n" string "\n")) | ||
| 794 | (proced-log t signal)) | ||
| 674 | 795 | ||
| 675 | (defun proced-help () | 796 | (defun proced-help () |
| 676 | "Provide help for the `proced' user." | 797 | "Provide help for the `proced' user." |
| 677 | (interactive) | 798 | (interactive) |
| 799 | (proced-why) | ||
| 678 | (if (eq last-command 'proced-help) | 800 | (if (eq last-command 'proced-help) |
| 679 | (describe-mode) | 801 | (describe-mode) |
| 680 | (message proced-help-string))) | 802 | (message proced-help-string))) |
| @@ -747,4 +869,4 @@ SCHEME must be a string or nil." | |||
| 747 | (provide 'proced) | 869 | (provide 'proced) |
| 748 | 870 | ||
| 749 | ;; arch-tag: a6e312ad-9032-45aa-972d-31a8cfc545af | 871 | ;; arch-tag: a6e312ad-9032-45aa-972d-31a8cfc545af |
| 750 | ;;; proced.el ends here. | 872 | ;;; proced.el ends here |