Mercurial > emacs
comparison lisp/proced.el @ 98249:538f59dc1be8
(proced-grammar-alist, proced-custom-attributes)
(proced-format-alist, proced-format, proced-filter-alist)
(proced-filter, proced-sort): Use defcustom.
(proced-mode): Fix docstring.
(proced-process-attributes): Handle return value nil of functions
in proced-custom-attributes.
author | Roland Winkler <Roland.Winkler@physik.uni-erlangen.de> |
---|---|
date | Sat, 20 Sep 2008 03:01:50 +0000 |
parents | 87d64c3d48ac |
children | 38b176122f90 |
comparison
equal
deleted
inserted
replaced
98248:215a88f14455 | 98249:538f59dc1be8 |
---|---|
26 ;; system processes. You can use the normal Emacs commands to move around | 26 ;; system processes. You can use the normal Emacs commands to move around |
27 ;; in this buffer, and special Proced commands to operate on the processes | 27 ;; in this buffer, and special Proced commands to operate on the processes |
28 ;; listed. See `proced-mode' for getting started. | 28 ;; listed. See `proced-mode' for getting started. |
29 ;; | 29 ;; |
30 ;; To do: | 30 ;; To do: |
31 ;; - use defcustom where appropriate | |
32 ;; - interactive temporary customizability of flags in `proced-grammar-alist' | 31 ;; - interactive temporary customizability of flags in `proced-grammar-alist' |
33 ;; - allow "sudo kill PID", "renice PID" | 32 ;; - allow "sudo kill PID", "renice PID" |
34 ;; | 33 ;; |
35 ;; Wishlist | 34 ;; Wishlist |
36 ;; - tree view like pstree(1) | 35 ;; - tree view like pstree(1) |
82 ;; predicate like `<'. Otherwise, a list of proced predicates can be used | 81 ;; predicate like `<'. Otherwise, a list of proced predicates can be used |
83 ;; to refine the sort. | 82 ;; to refine the sort. |
84 ;; | 83 ;; |
85 ;; It would be neat if one could temporarily override the following | 84 ;; It would be neat if one could temporarily override the following |
86 ;; predefined rules. | 85 ;; predefined rules. |
87 (defvar proced-grammar-alist | 86 (defcustom proced-grammar-alist |
88 '( ;; attributes defined in `system-process-attributes' | 87 '( ;; attributes defined in `system-process-attributes' |
89 (euid "EUID" "%d" right proced-< nil (euid pid) (nil t nil)) | 88 (euid "EUID" "%d" right proced-< nil (euid pid) (nil t nil)) |
90 (user "USER" nil left proced-string-lessp nil (user pid) (nil t nil)) | 89 (user "USER" nil left proced-string-lessp nil (user pid) (nil t nil)) |
91 (egid "EGID" "%d" right proced-< nil (egid euid pid) (nil t nil)) | 90 (egid "EGID" "%d" right proced-< nil (egid euid pid) (nil t nil)) |
92 (group "GROUP" nil left proced-string-lessp nil (group user pid) (nil t nil)) | 91 (group "GROUP" nil left proced-string-lessp nil (group user pid) (nil t nil)) |
126 | 125 |
127 Each element has the form | 126 Each element has the form |
128 | 127 |
129 (KEY NAME FORMAT JUSTIFY PREDICATE REVERSE SORT-SCHEME REFINE-FLAGS). | 128 (KEY NAME FORMAT JUSTIFY PREDICATE REVERSE SORT-SCHEME REFINE-FLAGS). |
130 | 129 |
131 KEY is the car of a process attribute. | 130 Symbol KEY is the car of a process attribute. |
132 | 131 |
133 NAME appears in the header line. | 132 String NAME appears in the header line. |
134 | 133 |
135 FORMAT specifies the format for displaying the attribute values. | 134 FORMAT specifies the format for displaying the attribute values. |
136 It can be a string passed to `format'. It can be a function called | 135 It can be a string passed to `format'. It can be a function called |
137 with one argument, the value of the attribute. Nil means take as is. | 136 with one argument, the value of the attribute. Nil means take as is. |
138 | 137 |
163 This command compares the value of attribute KEY of every process with | 162 This command compares the value of attribute KEY of every process with |
164 the value of attribute KEY of the process at the position of point | 163 the value of attribute KEY of the process at the position of point |
165 using PREDICATE. | 164 using PREDICATE. |
166 If PREDICATE yields non-nil, the process is accepted if LESS-B is non-nil. | 165 If PREDICATE yields non-nil, the process is accepted if LESS-B is non-nil. |
167 If PREDICATE yields 'equal, the process is accepted if EQUAL-B is non-nil. | 166 If PREDICATE yields 'equal, the process is accepted if EQUAL-B is non-nil. |
168 If PREDICATE yields nil, the process is accepted if LARGER-B is non-nil.") | 167 If PREDICATE yields nil, the process is accepted if LARGER-B is non-nil." |
169 | 168 :group 'proced |
170 (defvar proced-custom-attributes nil | 169 :type '(repeat (list :tag "Attribute" |
170 (symbol :tag "Key") | |
171 (string :tag "Header") | |
172 (choice :tag "Format" | |
173 (const :tag "None" nil) | |
174 (string :tag "Format String") | |
175 (function :tag "Formatting Function")) | |
176 (choice :tag "Justification" | |
177 (const :tag "left" left) | |
178 (const :tag "right" right) | |
179 (integer :tag "width")) | |
180 (function :tag "Predicate") | |
181 (boolean :tag "Reverse Sort Order") | |
182 (repeat :tag "Sort Scheme" (symbol :tag "Key")) | |
183 (list :tag "Refine Flags" | |
184 (boolean :tag "Less") | |
185 (boolean :tag "Equal") | |
186 (boolean :tag "Larger"))))) | |
187 | |
188 (defcustom proced-custom-attributes nil | |
171 "List of functions defining custom attributes. | 189 "List of functions defining custom attributes. |
172 This variable extends the functionality of `proced-process-attributes'. | 190 This variable extends the functionality of `proced-process-attributes'. |
173 Each function is called with one argument, the list of attributes | 191 Each function is called with one argument, the list of attributes |
174 of a system process. It returns a cons cell of the form (KEY . VALUE) | 192 of a system process. It returns a cons cell of the form (KEY . VALUE) |
175 like `system-process-attributes'.") | 193 like `system-process-attributes'. This cons cell is appended to the list |
194 returned by `proced-process-attributes'. | |
195 If the function returns nil, the value is ignored." | |
196 :group 'proced | |
197 :type '(repeat (function :tag "Attribute"))) | |
176 | 198 |
177 ;; Formatting and sorting rules are defined "per attribute". If formatting | 199 ;; Formatting and sorting rules are defined "per attribute". If formatting |
178 ;; and / or sorting should use more than one attribute, it appears more | 200 ;; and / or sorting should use more than one attribute, it appears more |
179 ;; transparent to define a new derived attribute, so that formatting and | 201 ;; transparent to define a new derived attribute, so that formatting and |
180 ;; sorting can use them consistently. (Are there exceptions to this rule? | 202 ;; sorting can use them consistently. (Are there exceptions to this rule? |
181 ;; Would it be advantageous to have yet more general methods available?) | 203 ;; Would it be advantageous to have yet more general methods available?) |
182 ;; Sorting can also be based on attributes that are invisible in the listing. | 204 ;; Sorting can also be based on attributes that are invisible in the listing. |
183 | 205 |
184 (defvar proced-format-alist | 206 (defcustom proced-format-alist |
185 '((short user pid pcpu pmem start time args) | 207 '((short user pid pcpu pmem start time args) |
186 (medium user pid pcpu pmem vsize rss ttname state start time args) | 208 (medium user pid pcpu pmem vsize rss ttname state start time args) |
187 (long user euid group pid pri nice pcpu pmem vsize rss ttname state | 209 (long user euid group pid pri nice pcpu pmem vsize rss ttname state |
188 start time args) | 210 start time args) |
189 (verbose user euid group egid pid ppid pgrp sess comm pri nice pcpu pmem | 211 (verbose user euid group egid pid ppid pgrp sess comm pri nice pcpu pmem |
190 state thcount vsize rss ttname tpgid minflt majflt cminflt cmajflt | 212 state thcount vsize rss ttname tpgid minflt majflt cminflt cmajflt |
191 start time utime stime ctime cutime cstime etime args)) | 213 start time utime stime ctime cutime cstime etime args)) |
192 "Alist of formats of listing. | 214 "Alist of formats of listing. |
193 The car of each element is a symbol, the name of the format. | 215 The car of each element is a symbol, the name of the format. |
194 The cdr is a list of keys appearing in `proced-grammar-alist'.") | 216 The cdr is a list of keys appearing in `proced-grammar-alist'." |
195 | 217 :group 'proced |
196 (defvar proced-format 'short | 218 :type '(alist :key-type (symbol :tag "Format Name") |
219 :value-type (repeat :tag "Keys" (symbol :tag "")))) | |
220 | |
221 (defcustom proced-format 'short | |
197 "Current format of Proced listing. | 222 "Current format of Proced listing. |
198 It can be the car of an element of `proced-format-alist'. | 223 It can be the car of an element of `proced-format-alist'. |
199 It can also be a list of keys appearing in `proced-grammar-alist'.") | 224 It can also be a list of keys appearing in `proced-grammar-alist'." |
225 :group 'proced | |
226 :type '(choice (symbol :tag "Format Name") | |
227 (repeat :tag "Keys" (symbol :tag "")))) | |
200 (make-variable-buffer-local 'proced-format) | 228 (make-variable-buffer-local 'proced-format) |
201 | 229 |
202 ;; FIXME: is there a better name for filter `user' that does not coincide | 230 ;; FIXME: is there a better name for filter `user' that does not coincide |
203 ;; with an attribute key? | 231 ;; with an attribute key? |
204 (defvar proced-filter-alist | 232 (defcustom proced-filter-alist |
205 `((user (user . ,(concat "\\`" (user-real-login-name) "\\'"))) | 233 `((user (user . ,(concat "\\`" (user-real-login-name) "\\'"))) |
206 (user-running (user . ,(concat "\\`" (user-real-login-name) "\\'")) | 234 (user-running (user . ,(concat "\\`" (user-real-login-name) "\\'")) |
207 (state . "\\`[Rr]\\'")) | 235 (state . "\\`[Rr]\\'")) |
208 (all) | 236 (all) |
209 (all-running (state . "\\`[Rr]\\'")) | 237 (all-running (state . "\\`[Rr]\\'")) |
221 \(KEY . FUN) Apply function FUN to attribute KEY. Accept this process, | 249 \(KEY . FUN) Apply function FUN to attribute KEY. Accept this process, |
222 if FUN returns non-nil. | 250 if FUN returns non-nil. |
223 \(function . FUN) For each process, apply function FUN to list of attributes | 251 \(function . FUN) For each process, apply function FUN to list of attributes |
224 of each. Accept the process if FUN returns non-nil. | 252 of each. Accept the process if FUN returns non-nil. |
225 \(fun-all . FUN) Apply function FUN to entire process list. | 253 \(fun-all . FUN) Apply function FUN to entire process list. |
226 FUN must return the filtered list.") | 254 FUN must return the filtered list." |
227 | 255 :group 'proced |
228 (defvar proced-filter 'user | 256 :type '(repeat (cons :tag "Filter" |
257 (symbol :tag "Filter Name") | |
258 (repeat :tag "Filters" | |
259 (choice (cons :tag "Key . Regexp" (symbol :tag "Key") regexp) | |
260 (cons :tag "Key . Function" (symbol :tag "Key") function) | |
261 (cons :tag "Function" (const :tag "Key: function" function) function) | |
262 (cons :tag "Fun-all" (const :tag "Key: fun-all" fun-all) function)))))) | |
263 | |
264 (defcustom proced-filter 'user | |
229 "Current filter of proced listing. | 265 "Current filter of proced listing. |
230 It can be the car of an element of `proced-filter-alist'. | 266 It can be the car of an element of `proced-filter-alist'. |
231 It can also be a list of elementary filters as in the cdrs of the elements | 267 It can also be a list of elementary filters as in the cdrs of the elements |
232 of `proced-filter-alist'.") | 268 of `proced-filter-alist'." |
269 :group 'proced | |
270 :type '(choice (symbol :tag "Filter Name") | |
271 (repeat :tag "Filters" | |
272 (choice (cons :tag "Key . Regexp" (symbol :tag "Key") regexp) | |
273 (cons :tag "Key . Function" (symbol :tag "Key") function) | |
274 (cons :tag "Function" (const :tag "Key: function" function) function) | |
275 (cons :tag "Fun-all" (const :tag "Key: fun-all" fun-all) function))))) | |
233 (make-variable-buffer-local 'proced-filter) | 276 (make-variable-buffer-local 'proced-filter) |
234 | 277 |
235 (defvar proced-sort 'pcpu | 278 (defcustom proced-sort 'pcpu |
236 "Current sort scheme for proced listing. | 279 "Current sort scheme for proced listing. |
237 It must be the KEY of an element of `proced-grammar-alist'. | 280 It must be the KEY of an element of `proced-grammar-alist'. |
238 It can also be a list of KEYs as in the SORT-SCHEMEs of the elements | 281 It can also be a list of KEYs as in the SORT-SCHEMEs of the elements |
239 of `proced-grammar-alist'.") | 282 of `proced-grammar-alist'." |
283 :group 'proced | |
284 :type '(choice (symbol :tag "Sort Scheme") | |
285 (repeat :tag "Key List" (symbol :tag "Key")))) | |
240 (make-variable-buffer-local 'proced-format) | 286 (make-variable-buffer-local 'proced-format) |
241 | 287 |
242 (defcustom proced-goal-attribute 'args | 288 (defcustom proced-goal-attribute 'args |
243 "If non-nil, key of the attribute that defines the `goal-column'." | 289 "If non-nil, key of the attribute that defines the `goal-column'." |
244 :group 'proced | 290 :group 'proced |
245 :type '(choice (const :tag "none" nil) | 291 :type '(choice (const :tag "none" nil) |
246 (symbol :tag "key"))) | 292 (symbol :tag "key"))) |
247 | 293 |
248 (defcustom proced-timer-interval 5 | 294 (defcustom proced-timer-interval 5 |
249 "Time interval in seconds for updating Proced buffers." | 295 "Time interval in seconds for auto updating Proced buffers." |
250 :group 'proced | 296 :group 'proced |
251 :type 'integer) | 297 :type 'integer) |
252 | 298 |
253 (defcustom proced-timer-flag nil | 299 (defcustom proced-timer-flag nil |
254 "Non-nil for auto update of a Proced buffer. | 300 "Non-nil for auto update of a Proced buffer. |
299 | 345 |
300 (defvar proced-header-line nil | 346 (defvar proced-header-line nil |
301 "Headers in Proced buffer as a string.") | 347 "Headers in Proced buffer as a string.") |
302 (make-variable-buffer-local 'proced-header-line) | 348 (make-variable-buffer-local 'proced-header-line) |
303 | 349 |
350 (defvar proced-process-tree nil | |
351 "Process tree of listing (internal variable).") | |
352 | |
353 (defvar proced-timer nil | |
354 "Stores if Proced timer is already installed.") | |
355 | |
304 (defvar proced-log-buffer "*Proced log*" | 356 (defvar proced-log-buffer "*Proced log*" |
305 "Name of Proced Log buffer.") | 357 "Name of Proced Log buffer.") |
306 | |
307 (defvar proced-process-tree nil | |
308 "Process tree of listing (internal variable).") | |
309 | |
310 (defvar proced-timer nil | |
311 "Stores if Proced timer is already installed.") | |
312 | 358 |
313 (defconst proced-help-string | 359 (defconst proced-help-string |
314 "(n)ext, (p)revious, (m)ark, (u)nmark, (k)ill, (q)uit (type ? for more help)" | 360 "(n)ext, (p)revious, (m)ark, (u)nmark, (k)ill, (q)uit (type ? for more help)" |
315 "Help string for proced.") | 361 "Help string for proced.") |
316 | 362 |
485 | 531 |
486 ;; proced mode | 532 ;; proced mode |
487 | 533 |
488 (define-derived-mode proced-mode nil "Proced" | 534 (define-derived-mode proced-mode nil "Proced" |
489 "Mode for displaying UNIX system processes and sending signals to them. | 535 "Mode for displaying UNIX system processes and sending signals to them. |
490 Type \\<proced-mode-map>\\[proced-mark] to mark a process for later commands. | 536 Type \\[proced] to start a Proced session. In a Proced buffer |
537 type \\<proced-mode-map>\\[proced-mark] to mark a process for later commands. | |
491 Type \\[proced-send-signal] to send signals to marked processes. | 538 Type \\[proced-send-signal] to send signals to marked processes. |
492 | 539 |
493 The initial content of a listing is defined by the variable `proced-filter' | 540 The initial content of a listing is defined by the variable `proced-filter' |
494 and the variable `proced-format'. | 541 and the variable `proced-format'. |
495 The variable `proced-filter' specifies which system processes are displayed. | 542 The variable `proced-filter' specifies which system processes are displayed. |
1189 (mapcar (lambda (pid) | 1236 (mapcar (lambda (pid) |
1190 (let* ((attributes (system-process-attributes pid)) | 1237 (let* ((attributes (system-process-attributes pid)) |
1191 (utime (cdr (assq 'utime attributes))) | 1238 (utime (cdr (assq 'utime attributes))) |
1192 (stime (cdr (assq 'stime attributes))) | 1239 (stime (cdr (assq 'stime attributes))) |
1193 (cutime (cdr (assq 'cutime attributes))) | 1240 (cutime (cdr (assq 'cutime attributes))) |
1194 (cstime (cdr (assq 'cstime attributes)))) | 1241 (cstime (cdr (assq 'cstime attributes))) |
1242 attr) | |
1195 (setq attributes | 1243 (setq attributes |
1196 (append (list (cons 'pid pid)) | 1244 (append (list (cons 'pid pid)) |
1197 (if (and utime stime) | 1245 (if (and utime stime) |
1198 (list (cons 'time (time-add utime stime)))) | 1246 (list (cons 'time (time-add utime stime)))) |
1199 (if (and cutime cstime) | 1247 (if (and cutime cstime) |
1200 (list (cons 'ctime (time-add cutime cstime)))) | 1248 (list (cons 'ctime (time-add cutime cstime)))) |
1201 attributes)) | 1249 attributes)) |
1202 (dolist (fun proced-custom-attributes) | 1250 (dolist (fun proced-custom-attributes) |
1203 (push (funcall fun attributes) attributes)) | 1251 (if (setq attr (funcall fun attributes)) |
1252 (push attr attributes))) | |
1204 (cons pid attributes))) | 1253 (cons pid attributes))) |
1205 (list-system-processes))) | 1254 (list-system-processes))) |
1206 | 1255 |
1207 (defun proced-update (&optional revert quiet) | 1256 (defun proced-update (&optional revert quiet) |
1208 "Update the `proced' process information. Preserves point and marks. | 1257 "Update the `proced' process information. Preserves point and marks. |
1264 proced-header-line)) | 1313 proced-header-line)) |
1265 (if (nth 3 grammar) | 1314 (if (nth 3 grammar) |
1266 (match-beginning 0) | 1315 (match-beginning 0) |
1267 (match-end 0))))) | 1316 (match-end 0))))) |
1268 | 1317 |
1269 ;; restore process marks and buffer position (if possible) | 1318 ;; Restore process marks and buffer position (if possible). |
1270 ;; FIXME: sometimes this puts point in the middle of the proced buffer | 1319 ;; Sometimes this puts point in the middle of the proced buffer |
1271 ;; where it is not interesting. Is there a better / more flexible solution? | 1320 ;; where it is not interesting. Is there a better / more flexible solution? |
1272 (goto-char (point-min)) | 1321 (goto-char (point-min)) |
1273 (let (pid mark new-pos) | 1322 (let (pid mark new-pos) |
1274 (if (or mp-list (car old-pos)) | 1323 (if (or mp-list (car old-pos)) |
1275 (while (not (eobp)) | 1324 (while (not (eobp)) |