Mercurial > hg > xemacs-beta
comparison lisp/custom/cus-edit.el @ 28:1917ad0d78d7 r19-15b97
Import from CVS: tag r19-15b97
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:51:55 +0200 |
parents | |
children | ec9a17fef872 |
comparison
equal
deleted
inserted
replaced
27:0a3286277d9b | 28:1917ad0d78d7 |
---|---|
1 ;;; cus-edit.el --- Tools for customization Emacs. | |
2 ;; | |
3 ;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. | |
4 ;; | |
5 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk> | |
6 ;; Keywords: help, faces | |
7 ;; Version: 1.50 | |
8 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ | |
9 | |
10 ;;; Commentary: | |
11 ;; | |
12 ;; See `custom.el'. | |
13 | |
14 ;;; Code: | |
15 | |
16 (require 'cus-face) | |
17 (require 'wid-edit) | |
18 (require 'easymenu) | |
19 | |
20 (define-widget-keywords :custom-prefixes :custom-menu :custom-show | |
21 :custom-magic :custom-state :custom-level :custom-form | |
22 :custom-set :custom-save :custom-reset-current :custom-reset-saved | |
23 :custom-reset-factory) | |
24 | |
25 ;;; Customization Groups. | |
26 | |
27 (defgroup emacs nil | |
28 "Customization of the One True Editor." | |
29 :link '(custom-manual "(emacs)Top")) | |
30 | |
31 ;; Most of these groups are stolen from `finder.el', | |
32 (defgroup editing nil | |
33 "Basic text editing facilities." | |
34 :group 'emacs) | |
35 | |
36 (defgroup abbrev nil | |
37 "Abbreviation handling, typing shortcuts, macros." | |
38 :tag "Abbreviations" | |
39 :group 'editing) | |
40 | |
41 (defgroup matching nil | |
42 "Various sorts of searching and matching." | |
43 :group 'editing) | |
44 | |
45 (defgroup emulations nil | |
46 "Emulations of other editors." | |
47 :group 'editing) | |
48 | |
49 (defgroup mouse nil | |
50 "Mouse support." | |
51 :group 'editing) | |
52 | |
53 (defgroup outlines nil | |
54 "Support for hierarchical outlining." | |
55 :group 'editing) | |
56 | |
57 (defgroup external nil | |
58 "Interfacing to external utilities." | |
59 :group 'emacs) | |
60 | |
61 (defgroup bib nil | |
62 "Code related to the `bib' bibliography processor." | |
63 :tag "Bibliography" | |
64 :group 'external) | |
65 | |
66 (defgroup processes nil | |
67 "Process, subshell, compilation, and job control support." | |
68 :group 'external | |
69 :group 'development) | |
70 | |
71 (defgroup programming nil | |
72 "Support for programming in other languages." | |
73 :group 'emacs) | |
74 | |
75 (defgroup languages nil | |
76 "Specialized modes for editing programming languages." | |
77 :group 'programming) | |
78 | |
79 (defgroup lisp nil | |
80 "Lisp support, including Emacs Lisp." | |
81 :group 'languages | |
82 :group 'development) | |
83 | |
84 (defgroup c nil | |
85 "Support for the C language and related languages." | |
86 :group 'languages) | |
87 | |
88 (defgroup tools nil | |
89 "Programming tools." | |
90 :group 'programming) | |
91 | |
92 (defgroup oop nil | |
93 "Support for object-oriented programming." | |
94 :group 'programming) | |
95 | |
96 (defgroup applications nil | |
97 "Applications written in Emacs." | |
98 :group 'emacs) | |
99 | |
100 (defgroup calendar nil | |
101 "Calendar and time management support." | |
102 :group 'applications) | |
103 | |
104 (defgroup mail nil | |
105 "Modes for electronic-mail handling." | |
106 :group 'applications) | |
107 | |
108 (defgroup news nil | |
109 "Support for netnews reading and posting." | |
110 :group 'applications) | |
111 | |
112 (defgroup games nil | |
113 "Games, jokes and amusements." | |
114 :group 'applications) | |
115 | |
116 (defgroup development nil | |
117 "Support for further development of Emacs." | |
118 :group 'emacs) | |
119 | |
120 (defgroup docs nil | |
121 "Support for Emacs documentation." | |
122 :group 'development) | |
123 | |
124 (defgroup extensions nil | |
125 "Emacs Lisp language extensions." | |
126 :group 'development) | |
127 | |
128 (defgroup internal nil | |
129 "Code for Emacs internals, build process, defaults." | |
130 :group 'development) | |
131 | |
132 (defgroup maint nil | |
133 "Maintenance aids for the Emacs development group." | |
134 :tag "Maintenance" | |
135 :group 'development) | |
136 | |
137 (defgroup environment nil | |
138 "Fitting Emacs with its environment." | |
139 :group 'emacs) | |
140 | |
141 (defgroup comm nil | |
142 "Communications, networking, remote access to files." | |
143 :tag "Communication" | |
144 :group 'environment) | |
145 | |
146 (defgroup hardware nil | |
147 "Support for interfacing with exotic hardware." | |
148 :group 'environment) | |
149 | |
150 (defgroup terminals nil | |
151 "Support for terminal types." | |
152 :group 'environment) | |
153 | |
154 (defgroup unix nil | |
155 "Front-ends/assistants for, or emulators of, UNIX features." | |
156 :group 'environment) | |
157 | |
158 (defgroup vms nil | |
159 "Support code for vms." | |
160 :group 'environment) | |
161 | |
162 (defgroup i18n nil | |
163 "Internationalization and alternate character-set support." | |
164 :group 'environment | |
165 :group 'editing) | |
166 | |
167 (defgroup frames nil | |
168 "Support for Emacs frames and window systems." | |
169 :group 'environment) | |
170 | |
171 (defgroup data nil | |
172 "Support editing files of data." | |
173 :group 'emacs) | |
174 | |
175 (defgroup wp nil | |
176 "Word processing." | |
177 :group 'emacs) | |
178 | |
179 (defgroup tex nil | |
180 "Code related to the TeX formatter." | |
181 :group 'wp) | |
182 | |
183 (defgroup faces nil | |
184 "Support for multiple fonts." | |
185 :group 'emacs) | |
186 | |
187 (defgroup hypermedia nil | |
188 "Support for links between text or other media types." | |
189 :group 'emacs) | |
190 | |
191 (defgroup help nil | |
192 "Support for on-line help systems." | |
193 :group 'emacs) | |
194 | |
195 (defgroup local nil | |
196 "Code local to your site." | |
197 :group 'emacs) | |
198 | |
199 (defgroup customize '((widgets custom-group)) | |
200 "Customization of the Customization support." | |
201 :link '(custom-manual "(custom)Top") | |
202 :link '(url-link :tag "Development Page" | |
203 "http://www.dina.kvl.dk/~abraham/custom/") | |
204 :prefix "custom-" | |
205 :group 'help | |
206 :group 'faces) | |
207 | |
208 ;;; Utilities. | |
209 | |
210 (defun custom-quote (sexp) | |
211 "Quote SEXP iff it is not self quoting." | |
212 (if (or (memq sexp '(t nil)) | |
213 (and (symbolp sexp) | |
214 (eq (aref (symbol-name sexp) 0) ?:)) | |
215 (and (listp sexp) | |
216 (memq (car sexp) '(lambda))) | |
217 (stringp sexp) | |
218 (numberp sexp) | |
219 (and (fboundp 'characterp) | |
220 (characterp sexp))) | |
221 sexp | |
222 (list 'quote sexp))) | |
223 | |
224 (defun custom-split-regexp-maybe (regexp) | |
225 "If REGEXP is a string, split it to a list at `\\|'. | |
226 You can get the original back with from the result with: | |
227 (mapconcat 'identity result \"\\|\") | |
228 | |
229 IF REGEXP is not a string, return it unchanged." | |
230 (if (stringp regexp) | |
231 (let ((start 0) | |
232 all) | |
233 (while (string-match "\\\\|" regexp start) | |
234 (setq all (cons (substring regexp start (match-beginning 0)) all) | |
235 start (match-end 0))) | |
236 (nreverse (cons (substring regexp start) all))) | |
237 regexp)) | |
238 | |
239 (defvar custom-prefix-list nil | |
240 "List of prefixes that should be ignored by `custom-unlispify'") | |
241 | |
242 (defcustom custom-unlispify-menu-entries t | |
243 "Display menu entries as words instead of symbols if non nil." | |
244 :group 'customize | |
245 :type 'boolean) | |
246 | |
247 (defun custom-unlispify-menu-entry (symbol &optional no-suffix) | |
248 "Convert symbol into a menu entry." | |
249 (cond ((not custom-unlispify-menu-entries) | |
250 (symbol-name symbol)) | |
251 ((get symbol 'custom-tag) | |
252 (if no-suffix | |
253 (get symbol 'custom-tag) | |
254 (concat (get symbol 'custom-tag) "..."))) | |
255 (t | |
256 (save-excursion | |
257 (set-buffer (get-buffer-create " *Custom-Work*")) | |
258 (erase-buffer) | |
259 (princ symbol (current-buffer)) | |
260 (goto-char (point-min)) | |
261 (let ((prefixes custom-prefix-list) | |
262 prefix) | |
263 (while prefixes | |
264 (setq prefix (car prefixes)) | |
265 (if (search-forward prefix (+ (point) (length prefix)) t) | |
266 (progn | |
267 (setq prefixes nil) | |
268 (delete-region (point-min) (point))) | |
269 (setq prefixes (cdr prefixes))))) | |
270 (subst-char-in-region (point-min) (point-max) ?- ?\ t) | |
271 (capitalize-region (point-min) (point-max)) | |
272 (unless no-suffix | |
273 (goto-char (point-max)) | |
274 (insert "...")) | |
275 (buffer-string))))) | |
276 | |
277 (defcustom custom-unlispify-tag-names t | |
278 "Display tag names as words instead of symbols if non nil." | |
279 :group 'customize | |
280 :type 'boolean) | |
281 | |
282 (defun custom-unlispify-tag-name (symbol) | |
283 "Convert symbol into a menu entry." | |
284 (let ((custom-unlispify-menu-entries custom-unlispify-tag-names)) | |
285 (custom-unlispify-menu-entry symbol t))) | |
286 | |
287 (defun custom-prefix-add (symbol prefixes) | |
288 ;; Addd SYMBOL to list of ignored PREFIXES. | |
289 (cons (or (get symbol 'custom-prefix) | |
290 (concat (symbol-name symbol) "-")) | |
291 prefixes)) | |
292 | |
293 ;;; The Custom Mode. | |
294 | |
295 (defvar custom-options nil | |
296 "Customization widgets in the current buffer.") | |
297 | |
298 (defvar custom-mode-map nil | |
299 "Keymap for `custom-mode'.") | |
300 | |
301 (unless custom-mode-map | |
302 (setq custom-mode-map (make-sparse-keymap)) | |
303 (set-keymap-parent custom-mode-map widget-keymap)) | |
304 | |
305 (easy-menu-define custom-mode-menu | |
306 custom-mode-map | |
307 "Menu used in customization buffers." | |
308 '("Custom" | |
309 ["Set" custom-set t] | |
310 ["Save" custom-save t] | |
311 ["Reset to Current" custom-reset-current t] | |
312 ["Reset to Saved" custom-reset-saved t] | |
313 ["Reset to Factory Settings" custom-reset-factory t] | |
314 ["Info" (Info-goto-node "(custom)The Customization Buffer") t])) | |
315 | |
316 (defcustom custom-mode-hook nil | |
317 "Hook called when entering custom-mode." | |
318 :type 'hook | |
319 :group 'customize) | |
320 | |
321 (defun custom-mode () | |
322 "Major mode for editing customization buffers. | |
323 | |
324 The following commands are available: | |
325 | |
326 \\[widget-forward] Move to next button or editable field. | |
327 \\[widget-backward] Move to previous button or editable field. | |
328 \\[widget-button-click] Activate button under the mouse pointer. | |
329 \\[widget-button-press] Activate button under point. | |
330 \\[custom-set] Set all modifications. | |
331 \\[custom-save] Make all modifications default. | |
332 \\[custom-reset-current] Reset all modified options. | |
333 \\[custom-reset-saved] Reset all modified or set options. | |
334 \\[custom-reset-factory] Reset all options. | |
335 | |
336 Entry to this mode calls the value of `custom-mode-hook' | |
337 if that value is non-nil." | |
338 (kill-all-local-variables) | |
339 (setq major-mode 'custom-mode | |
340 mode-name "Custom") | |
341 (use-local-map custom-mode-map) | |
342 (easy-menu-add custom-mode-menu) | |
343 (make-local-variable 'custom-options) | |
344 (run-hooks 'custom-mode-hook)) | |
345 | |
346 ;;; Custom Mode Commands. | |
347 | |
348 (defun custom-set () | |
349 "Set changes in all modified options." | |
350 (interactive) | |
351 (let ((children custom-options)) | |
352 (mapcar (lambda (child) | |
353 (when (eq (widget-get child :custom-state) 'modified) | |
354 (widget-apply child :custom-set))) | |
355 children))) | |
356 | |
357 (defun custom-save () | |
358 "Set all modified group members and save them." | |
359 (interactive) | |
360 (let ((children custom-options)) | |
361 (mapcar (lambda (child) | |
362 (when (memq (widget-get child :custom-state) '(modified set)) | |
363 (widget-apply child :custom-save))) | |
364 children)) | |
365 (custom-save-all)) | |
366 | |
367 (defvar custom-reset-menu | |
368 '(("Current" . custom-reset-current) | |
369 ("Saved" . custom-reset-saved) | |
370 ("Factory Settings" . custom-reset-factory)) | |
371 "Alist of actions for the `Reset' button. | |
372 The key is a string containing the name of the action, the value is a | |
373 lisp function taking the widget as an element which will be called | |
374 when the action is chosen.") | |
375 | |
376 (defun custom-reset (event) | |
377 "Select item from reset menu." | |
378 (let* ((completion-ignore-case t) | |
379 (answer (widget-choose "Reset to" | |
380 custom-reset-menu | |
381 event))) | |
382 (if answer | |
383 (funcall answer)))) | |
384 | |
385 (defun custom-reset-current () | |
386 "Reset all modified group members to their current value." | |
387 (interactive) | |
388 (let ((children custom-options)) | |
389 (mapcar (lambda (child) | |
390 (when (eq (widget-get child :custom-state) 'modified) | |
391 (widget-apply child :custom-reset-current))) | |
392 children))) | |
393 | |
394 (defun custom-reset-saved () | |
395 "Reset all modified or set group members to their saved value." | |
396 (interactive) | |
397 (let ((children custom-options)) | |
398 (mapcar (lambda (child) | |
399 (when (eq (widget-get child :custom-state) 'modified) | |
400 (widget-apply child :custom-reset-current))) | |
401 children))) | |
402 | |
403 (defun custom-reset-factory () | |
404 "Reset all modified, set, or saved group members to their factory settings." | |
405 (interactive) | |
406 (let ((children custom-options)) | |
407 (mapcar (lambda (child) | |
408 (when (eq (widget-get child :custom-state) 'modified) | |
409 (widget-apply child :custom-reset-current))) | |
410 children))) | |
411 | |
412 ;;; The Customize Commands | |
413 | |
414 ;;;###autoload | |
415 (defun customize (symbol) | |
416 "Customize SYMBOL, which must be a customization group." | |
417 (interactive (list (completing-read "Customize group: (default emacs) " | |
418 obarray | |
419 (lambda (symbol) | |
420 (get symbol 'custom-group)) | |
421 t))) | |
422 | |
423 (when (stringp symbol) | |
424 (if (string-equal "" symbol) | |
425 (setq symbol 'emacs) | |
426 (setq symbol (intern symbol)))) | |
427 (custom-buffer-create (list (list symbol 'custom-group)))) | |
428 | |
429 ;;;###autoload | |
430 (defun customize-variable (symbol) | |
431 "Customize SYMBOL, which must be a variable." | |
432 (interactive | |
433 ;; Code stolen from `help.el'. | |
434 (let ((v (variable-at-point)) | |
435 (enable-recursive-minibuffers t) | |
436 val) | |
437 (setq val (completing-read | |
438 (if v | |
439 (format "Customize variable (default %s): " v) | |
440 "Customize variable: ") | |
441 obarray 'boundp t)) | |
442 (list (if (equal val "") | |
443 v (intern val))))) | |
444 (custom-buffer-create (list (list symbol 'custom-variable)))) | |
445 | |
446 ;;;###autoload | |
447 (defun customize-face (&optional symbol) | |
448 "Customize SYMBOL, which should be a face name or nil. | |
449 If SYMBOL is nil, customize all faces." | |
450 (interactive (list (completing-read "Customize face: (default all) " | |
451 obarray 'custom-facep))) | |
452 (if (or (null symbol) (and (stringp symbol) (zerop (length symbol)))) | |
453 (let ((found nil)) | |
454 (message "Looking for faces...") | |
455 (mapcar (lambda (symbol) | |
456 (setq found (cons (list symbol 'custom-face) found))) | |
457 (face-list)) | |
458 (message "Creating customization buffer...") | |
459 (custom-buffer-create found)) | |
460 (if (stringp symbol) | |
461 (setq symbol (intern symbol))) | |
462 (unless (symbolp symbol) | |
463 (error "Should be a symbol %S" symbol)) | |
464 (custom-buffer-create (list (list symbol 'custom-face))))) | |
465 | |
466 ;;;###autoload | |
467 (defun customize-customized () | |
468 "Customize all already customized user options." | |
469 (interactive) | |
470 (let ((found nil)) | |
471 (mapatoms (lambda (symbol) | |
472 (and (get symbol 'saved-face) | |
473 (custom-facep symbol) | |
474 (setq found (cons (list symbol 'custom-face) found))) | |
475 (and (get symbol 'saved-value) | |
476 (boundp symbol) | |
477 (setq found | |
478 (cons (list symbol 'custom-variable) found))))) | |
479 (if found | |
480 (custom-buffer-create found) | |
481 (error "No customized user options")))) | |
482 | |
483 ;;;###autoload | |
484 (defun customize-apropos (regexp &optional all) | |
485 "Customize all user options matching REGEXP. | |
486 If ALL (e.g., started with a prefix key), include options which are not | |
487 user-settable." | |
488 (interactive "sCustomize regexp: \nP") | |
489 (let ((found nil)) | |
490 (mapatoms (lambda (symbol) | |
491 (when (string-match regexp (symbol-name symbol)) | |
492 (when (get symbol 'custom-group) | |
493 (setq found (cons (list symbol 'custom-group) found))) | |
494 (when (custom-facep symbol) | |
495 (setq found (cons (list symbol 'custom-face) found))) | |
496 (when (and (boundp symbol) | |
497 (or (get symbol 'saved-value) | |
498 (get symbol 'factory-value) | |
499 (if all | |
500 (get symbol 'variable-documentation) | |
501 (user-variable-p symbol)))) | |
502 (setq found | |
503 (cons (list symbol 'custom-variable) found)))))) | |
504 (if found | |
505 (custom-buffer-create found) | |
506 (error "No matches")))) | |
507 | |
508 ;;;###autoload | |
509 (defun custom-buffer-create (options) | |
510 "Create a buffer containing OPTIONS. | |
511 OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where | |
512 SYMBOL is a customization option, and WIDGET is a widget for editing | |
513 that option." | |
514 (kill-buffer (get-buffer-create "*Customization*")) | |
515 (switch-to-buffer (get-buffer-create "*Customization*")) | |
516 (custom-mode) | |
517 (widget-insert "This is a customization buffer. | |
518 Push RET or click mouse-2 on the word ") | |
519 (widget-create 'info-link | |
520 :tag "help" | |
521 :help-echo "Push me for help." | |
522 "(custom)The Customization Buffer") | |
523 (widget-insert " for more information.\n\n") | |
524 (setq custom-options | |
525 (mapcar (lambda (entry) | |
526 (prog1 | |
527 (if (> (length options) 1) | |
528 (widget-create (nth 1 entry) | |
529 :tag (custom-unlispify-tag-name | |
530 (nth 0 entry)) | |
531 :value (nth 0 entry)) | |
532 ;; If there is only one entry, don't hide it! | |
533 (widget-create (nth 1 entry) | |
534 :custom-state 'unknown | |
535 :tag (custom-unlispify-tag-name | |
536 (nth 0 entry)) | |
537 :value (nth 0 entry))) | |
538 (unless (eq (preceding-char) ?\n) | |
539 (widget-insert "\n")) | |
540 (widget-insert "\n"))) | |
541 options)) | |
542 (mapcar 'custom-magic-reset custom-options) | |
543 (widget-create 'push-button | |
544 :tag "Set" | |
545 :help-echo "Push me to set all modifications." | |
546 :action (lambda (widget &optional event) | |
547 (custom-set))) | |
548 (widget-insert " ") | |
549 (widget-create 'push-button | |
550 :tag "Save" | |
551 :help-echo "Push me to make the modifications default." | |
552 :action (lambda (widget &optional event) | |
553 (custom-save))) | |
554 (widget-insert " ") | |
555 (widget-create 'push-button | |
556 :tag "Reset" | |
557 :help-echo "Push me to undo all modifications." | |
558 :action (lambda (widget &optional event) | |
559 (custom-reset event))) | |
560 (widget-insert " ") | |
561 (widget-create 'push-button | |
562 :tag "Done" | |
563 :help-echo "Push me to bury the buffer." | |
564 :action (lambda (widget &optional event) | |
565 (bury-buffer) | |
566 ;; Steal button release event. | |
567 (if (and (fboundp 'button-press-event-p) | |
568 (fboundp 'next-command-event)) | |
569 ;; XEmacs | |
570 (and event | |
571 (button-press-event-p event) | |
572 (next-command-event)) | |
573 ;; Emacs | |
574 (when (memq 'down (event-modifiers event)) | |
575 (read-event))))) | |
576 (widget-insert "\n") | |
577 (widget-setup)) | |
578 | |
579 ;;; Modification of Basic Widgets. | |
580 ;; | |
581 ;; We add extra properties to the basic widgets needed here. This is | |
582 ;; fine, as long as we are careful to stay within out own namespace. | |
583 ;; | |
584 ;; We want simple widgets to be displayed by default, but complex | |
585 ;; widgets to be hidden. | |
586 | |
587 (widget-put (get 'item 'widget-type) :custom-show t) | |
588 (widget-put (get 'editable-field 'widget-type) | |
589 :custom-show (lambda (widget value) | |
590 (let ((pp (pp-to-string value))) | |
591 (cond ((string-match "\n" pp) | |
592 nil) | |
593 ((> (length pp) 40) | |
594 nil) | |
595 (t t))))) | |
596 (widget-put (get 'menu-choice 'widget-type) :custom-show t) | |
597 | |
598 ;;; The `custom-manual' Widget. | |
599 | |
600 (define-widget 'custom-manual 'info-link | |
601 "Link to the manual entry for this customization option." | |
602 :help-echo "Push me to read the manual." | |
603 :tag "Manual") | |
604 | |
605 ;;; The `custom-magic' Widget. | |
606 | |
607 (defface custom-invalid-face '((((class color)) | |
608 (:foreground "yellow" :background "red")) | |
609 (t | |
610 (:bold t :italic t :underline t))) | |
611 "Face used when the customize item is invalid.") | |
612 | |
613 (defface custom-rogue-face '((((class color)) | |
614 (:foreground "pink" :background "black")) | |
615 (t | |
616 (:underline t))) | |
617 "Face used when the customize item is not defined for customization.") | |
618 | |
619 (defface custom-modified-face '((((class color)) | |
620 (:foreground "white" :background "blue")) | |
621 (t | |
622 (:italic t :bold))) | |
623 "Face used when the customize item has been modified.") | |
624 | |
625 (defface custom-set-face '((((class color)) | |
626 (:foreground "blue" :background "white")) | |
627 (t | |
628 (:italic t))) | |
629 "Face used when the customize item has been set.") | |
630 | |
631 (defface custom-changed-face '((((class color)) | |
632 (:foreground "white" :background "blue")) | |
633 (t | |
634 (:italic t))) | |
635 "Face used when the customize item has been changed.") | |
636 | |
637 (defface custom-saved-face '((t (:underline t))) | |
638 "Face used when the customize item has been saved.") | |
639 | |
640 (defcustom custom-magic-alist '((nil "#" underline "\ | |
641 uninitialized, you should not see this.") | |
642 (unknown "?" italic "\ | |
643 unknown, you should not see this.") | |
644 (hidden "-" default "\ | |
645 hidden, press the state button to show.") | |
646 (invalid "x" custom-invalid-face "\ | |
647 the value displayed for this item is invalid and cannot be set.") | |
648 (modified "*" custom-modified-face "\ | |
649 you have edited the item, and can now set it.") | |
650 (set "+" custom-set-face "\ | |
651 you have set this item, but not saved it.") | |
652 (changed ":" custom-changed-face "\ | |
653 this item has been changed outside customize.") | |
654 (saved "!" custom-saved-face "\ | |
655 this item has been saved.") | |
656 (rogue "@" custom-rogue-face "\ | |
657 this item is not prepared for customization.") | |
658 (factory " " nil "\ | |
659 this item is unchanged from its factory setting.")) | |
660 "Alist of customize option states. | |
661 Each entry is of the form (STATE MAGIC FACE DESCRIPTION), where | |
662 | |
663 STATE is one of the following symbols: | |
664 | |
665 `nil' | |
666 For internal use, should never occur. | |
667 `unknown' | |
668 For internal use, should never occur. | |
669 `hidden' | |
670 This item is not being displayed. | |
671 `invalid' | |
672 This item is modified, but has an invalid form. | |
673 `modified' | |
674 This item is modified, and has a valid form. | |
675 `set' | |
676 This item has been set but not saved. | |
677 `changed' | |
678 The current value of this item has been changed temporarily. | |
679 `saved' | |
680 This item is marked for saving. | |
681 `rogue' | |
682 This item has no customization information. | |
683 `factory' | |
684 This item is unchanged from the factory default. | |
685 | |
686 MAGIC is a string used to present that state. | |
687 | |
688 FACE is a face used to present the state. | |
689 | |
690 DESCRIPTION is a string describing the state. | |
691 | |
692 The list should be sorted most significant first." | |
693 :type '(list (checklist :inline t | |
694 (group (const nil) | |
695 (string :tag "Magic") | |
696 face | |
697 (string :tag "Description")) | |
698 (group (const unknown) | |
699 (string :tag "Magic") | |
700 face | |
701 (string :tag "Description")) | |
702 (group (const hidden) | |
703 (string :tag "Magic") | |
704 face | |
705 (string :tag "Description")) | |
706 (group (const invalid) | |
707 (string :tag "Magic") | |
708 face | |
709 (string :tag "Description")) | |
710 (group (const modified) | |
711 (string :tag "Magic") | |
712 face | |
713 (string :tag "Description")) | |
714 (group (const set) | |
715 (string :tag "Magic") | |
716 face | |
717 (string :tag "Description")) | |
718 (group (const changed) | |
719 (string :tag "Magic") | |
720 face | |
721 (string :tag "Description")) | |
722 (group (const saved) | |
723 (string :tag "Magic") | |
724 face | |
725 (string :tag "Description")) | |
726 (group (const rogue) | |
727 (string :tag "Magic") | |
728 face | |
729 (string :tag "Description")) | |
730 (group (const factory) | |
731 (string :tag "Magic") | |
732 face | |
733 (string :tag "Description"))) | |
734 (editable-list :inline t | |
735 (group symbol | |
736 (string :tag "Magic") | |
737 face | |
738 (string :tag "Description")))) | |
739 :group 'customize) | |
740 | |
741 (defcustom custom-magic-show 'long | |
742 "Show long description of the state of each customization option." | |
743 :type '(choice (const :tag "no" nil) | |
744 (const short) | |
745 (const long)) | |
746 :group 'customize) | |
747 | |
748 (defcustom custom-magic-show-button t | |
749 "Show a magic button indicating the state of each customization option." | |
750 :type 'boolean | |
751 :group 'customize) | |
752 | |
753 (define-widget 'custom-magic 'default | |
754 "Show and manipulate state for a customization option." | |
755 :format "%v" | |
756 :action 'widget-choice-item-action | |
757 :value-get 'ignore | |
758 :value-create 'custom-magic-value-create | |
759 :value-delete 'widget-children-value-delete) | |
760 | |
761 (defun custom-magic-value-create (widget) | |
762 ;; Create compact status report for WIDGET. | |
763 (let* ((parent (widget-get widget :parent)) | |
764 (state (widget-get parent :custom-state)) | |
765 (entry (assq state custom-magic-alist)) | |
766 (magic (nth 1 entry)) | |
767 (face (nth 2 entry)) | |
768 (text (nth 3 entry)) | |
769 (lisp (eq (widget-get parent :custom-form) 'lisp)) | |
770 children) | |
771 (when custom-magic-show | |
772 (push (widget-create-child-and-convert widget 'choice-item | |
773 :help-echo "\ | |
774 Push me to change the state of this item." | |
775 :format "%[%t%]" | |
776 :tag "State") | |
777 children) | |
778 (insert ": ") | |
779 (if (eq custom-magic-show 'long) | |
780 (insert text) | |
781 (insert (symbol-name state))) | |
782 (when lisp | |
783 (insert " (lisp)")) | |
784 (insert "\n")) | |
785 (when custom-magic-show-button | |
786 (when custom-magic-show | |
787 (let ((indent (widget-get parent :indent))) | |
788 (when indent | |
789 (insert-char ? indent)))) | |
790 (push (widget-create-child-and-convert widget 'choice-item | |
791 :button-face face | |
792 :help-echo "\ | |
793 Push me to change the state." | |
794 :format "%[%t%]" | |
795 :tag (if lisp | |
796 (concat "(" magic ")") | |
797 (concat "[" magic "]"))) | |
798 children) | |
799 (insert " ")) | |
800 (widget-put widget :children children))) | |
801 | |
802 (defun custom-magic-reset (widget) | |
803 "Redraw the :custom-magic property of WIDGET." | |
804 (let ((magic (widget-get widget :custom-magic))) | |
805 (widget-value-set magic (widget-value magic)))) | |
806 | |
807 ;;; The `custom-level' Widget. | |
808 | |
809 (define-widget 'custom-level 'item | |
810 "The custom level buttons." | |
811 :format "%[%t%]" | |
812 :help-echo "Push me to expand or collapse this item." | |
813 :action 'custom-level-action) | |
814 | |
815 (defun custom-level-action (widget &optional event) | |
816 "Toggle visibility for parent to WIDGET." | |
817 (let* ((parent (widget-get widget :parent)) | |
818 (state (widget-get parent :custom-state))) | |
819 (cond ((memq state '(invalid modified)) | |
820 (error "There are unset changes")) | |
821 ((eq state 'hidden) | |
822 (widget-put parent :custom-state 'unknown)) | |
823 (t | |
824 (widget-put parent :custom-state 'hidden))) | |
825 (custom-redraw parent))) | |
826 | |
827 ;;; The `custom' Widget. | |
828 | |
829 (define-widget 'custom 'default | |
830 "Customize a user option." | |
831 :convert-widget 'custom-convert-widget | |
832 :format "%l%[%t%]: %v%m%h%a" | |
833 :format-handler 'custom-format-handler | |
834 :notify 'custom-notify | |
835 :custom-level 1 | |
836 :custom-state 'hidden | |
837 :documentation-property 'widget-subclass-responsibility | |
838 :value-create 'widget-subclass-responsibility | |
839 :value-delete 'widget-children-value-delete | |
840 :value-get 'widget-item-value-get | |
841 :validate 'widget-editable-list-validate | |
842 :match (lambda (widget value) (symbolp value))) | |
843 | |
844 (defun custom-convert-widget (widget) | |
845 ;; Initialize :value and :tag from :args in WIDGET. | |
846 (let ((args (widget-get widget :args))) | |
847 (when args | |
848 (widget-put widget :value (widget-apply widget | |
849 :value-to-internal (car args))) | |
850 (widget-put widget :tag (custom-unlispify-tag-name (car args))) | |
851 (widget-put widget :args nil))) | |
852 widget) | |
853 | |
854 (defun custom-format-handler (widget escape) | |
855 ;; We recognize extra escape sequences. | |
856 (let* ((buttons (widget-get widget :buttons)) | |
857 (state (widget-get widget :custom-state)) | |
858 (level (widget-get widget :custom-level))) | |
859 (cond ((eq escape ?l) | |
860 (when level | |
861 (push (widget-create-child-and-convert | |
862 widget 'custom-level (make-string level ?*)) | |
863 buttons) | |
864 (widget-insert " ") | |
865 (widget-put widget :buttons buttons))) | |
866 ((eq escape ?L) | |
867 (when (eq state 'hidden) | |
868 (widget-insert " ..."))) | |
869 ((eq escape ?m) | |
870 (and (eq (preceding-char) ?\n) | |
871 (widget-get widget :indent) | |
872 (insert-char ? (widget-get widget :indent))) | |
873 (let ((magic (widget-create-child-and-convert | |
874 widget 'custom-magic nil))) | |
875 (widget-put widget :custom-magic magic) | |
876 (push magic buttons) | |
877 (widget-put widget :buttons buttons))) | |
878 ((eq escape ?a) | |
879 (let* ((symbol (widget-get widget :value)) | |
880 (links (get symbol 'custom-links)) | |
881 (many (> (length links) 2))) | |
882 (when links | |
883 (and (eq (preceding-char) ?\n) | |
884 (widget-get widget :indent) | |
885 (insert-char ? (widget-get widget :indent))) | |
886 (insert "See also ") | |
887 (while links | |
888 (push (widget-create-child-and-convert widget (car links)) | |
889 buttons) | |
890 (setq links (cdr links)) | |
891 (cond ((null links) | |
892 (insert ".\n")) | |
893 ((null (cdr links)) | |
894 (if many | |
895 (insert ", and ") | |
896 (insert " and "))) | |
897 (t | |
898 (insert ", ")))) | |
899 (widget-put widget :buttons buttons)))) | |
900 (t | |
901 (widget-default-format-handler widget escape))))) | |
902 | |
903 (defun custom-notify (widget &rest args) | |
904 "Keep track of changes." | |
905 (widget-put widget :custom-state 'modified) | |
906 (let ((buffer-undo-list t)) | |
907 (custom-magic-reset widget)) | |
908 (apply 'widget-default-notify widget args)) | |
909 | |
910 (defun custom-redraw (widget) | |
911 "Redraw WIDGET with current settings." | |
912 (let ((pos (point)) | |
913 (from (marker-position (widget-get widget :from))) | |
914 (to (marker-position (widget-get widget :to)))) | |
915 (save-excursion | |
916 (widget-value-set widget (widget-value widget)) | |
917 (custom-redraw-magic widget)) | |
918 (when (and (>= pos from) (<= pos to)) | |
919 (goto-char pos)))) | |
920 | |
921 (defun custom-redraw-magic (widget) | |
922 "Redraw WIDGET state with current settings." | |
923 (while widget | |
924 (let ((magic (widget-get widget :custom-magic))) | |
925 (unless magic | |
926 (debug)) | |
927 (widget-value-set magic (widget-value magic)) | |
928 (when (setq widget (widget-get widget :group)) | |
929 (custom-group-state-update widget)))) | |
930 (widget-setup)) | |
931 | |
932 (defun custom-show (widget value) | |
933 "Non-nil if WIDGET should be shown with VALUE by default." | |
934 (let ((show (widget-get widget :custom-show))) | |
935 (cond ((null show) | |
936 nil) | |
937 ((eq t show) | |
938 t) | |
939 (t | |
940 (funcall show widget value))))) | |
941 | |
942 (defun custom-load-symbol (symbol) | |
943 "Load all dependencies for SYMBOL." | |
944 (let ((loads (get symbol 'custom-loads)) | |
945 load) | |
946 (while loads | |
947 (setq load (car loads) | |
948 loads (cdr loads)) | |
949 (cond ((symbolp load) | |
950 (condition-case nil | |
951 (require load) | |
952 (error nil))) | |
953 ((assoc load load-history)) | |
954 (t | |
955 (condition-case nil | |
956 (load-library load) | |
957 (error nil))))))) | |
958 | |
959 (defun custom-load-widget (widget) | |
960 "Load all dependencies for WIDGET." | |
961 (custom-load-symbol (widget-value widget))) | |
962 | |
963 ;;; The `custom-variable' Widget. | |
964 | |
965 (defface custom-variable-sample-face '((t (:underline t))) | |
966 "Face used for unpushable variable tags." | |
967 :group 'customize) | |
968 | |
969 (defface custom-variable-button-face '((t (:underline t :bold t))) | |
970 "Face used for pushable variable tags." | |
971 :group 'customize) | |
972 | |
973 (define-widget 'custom-variable 'custom | |
974 "Customize variable." | |
975 :format "%l%v%m%h%a" | |
976 :help-echo "Push me to set or reset this variable." | |
977 :documentation-property 'variable-documentation | |
978 :custom-state nil | |
979 :custom-menu 'custom-variable-menu-create | |
980 :custom-form 'edit | |
981 :value-create 'custom-variable-value-create | |
982 :action 'custom-variable-action | |
983 :custom-set 'custom-variable-set | |
984 :custom-save 'custom-variable-save | |
985 :custom-reset-current 'custom-redraw | |
986 :custom-reset-saved 'custom-variable-reset-saved | |
987 :custom-reset-factory 'custom-variable-reset-factory) | |
988 | |
989 (defun custom-variable-value-create (widget) | |
990 "Here is where you edit the variables value." | |
991 (custom-load-widget widget) | |
992 (let* ((buttons (widget-get widget :buttons)) | |
993 (children (widget-get widget :children)) | |
994 (form (widget-get widget :custom-form)) | |
995 (state (widget-get widget :custom-state)) | |
996 (symbol (widget-get widget :value)) | |
997 (options (get symbol 'custom-options)) | |
998 (child-type (or (get symbol 'custom-type) 'sexp)) | |
999 (tag (widget-get widget :tag)) | |
1000 (type (let ((tmp (if (listp child-type) | |
1001 (copy-list child-type) | |
1002 (list child-type)))) | |
1003 (when options | |
1004 (widget-put tmp :options options)) | |
1005 tmp)) | |
1006 (conv (widget-convert type)) | |
1007 (value (if (default-boundp symbol) | |
1008 (default-value symbol) | |
1009 (widget-get conv :value)))) | |
1010 ;; If the widget is new, the child determine whether it is hidden. | |
1011 (cond (state) | |
1012 ((custom-show type value) | |
1013 (setq state 'unknown)) | |
1014 (t | |
1015 (setq state 'hidden))) | |
1016 ;; If we don't know the state, see if we need to edit it in lisp form. | |
1017 (when (eq state 'unknown) | |
1018 (unless (widget-apply conv :match value) | |
1019 ;; (widget-apply (widget-convert type) :match value) | |
1020 (setq form 'lisp))) | |
1021 ;; Now we can create the child widget. | |
1022 (cond ((eq state 'hidden) | |
1023 ;; Indicate hidden value. | |
1024 (push (widget-create-child-and-convert | |
1025 widget 'item | |
1026 :format "%{%t%}: ..." | |
1027 :sample-face 'custom-variable-sample-face | |
1028 :tag tag | |
1029 :parent widget) | |
1030 children)) | |
1031 ((eq form 'lisp) | |
1032 ;; In lisp mode edit the saved value when possible. | |
1033 (let* ((value (cond ((get symbol 'saved-value) | |
1034 (car (get symbol 'saved-value))) | |
1035 ((get symbol 'factory-value) | |
1036 (car (get symbol 'factory-value))) | |
1037 ((default-boundp symbol) | |
1038 (custom-quote (default-value symbol))) | |
1039 (t | |
1040 (custom-quote (widget-get conv :value)))))) | |
1041 (push (widget-create-child-and-convert | |
1042 widget 'sexp | |
1043 :button-face 'custom-variable-button-face | |
1044 :tag (symbol-name symbol) | |
1045 :parent widget | |
1046 :value value) | |
1047 children))) | |
1048 (t | |
1049 ;; Edit mode. | |
1050 (push (widget-create-child-and-convert | |
1051 widget type | |
1052 :tag tag | |
1053 :button-face 'custom-variable-button-face | |
1054 :sample-face 'custom-variable-sample-face | |
1055 :value value) | |
1056 children))) | |
1057 ;; Now update the state. | |
1058 (unless (eq (preceding-char) ?\n) | |
1059 (widget-insert "\n")) | |
1060 (if (eq state 'hidden) | |
1061 (widget-put widget :custom-state state) | |
1062 (custom-variable-state-set widget)) | |
1063 (widget-put widget :custom-form form) | |
1064 (widget-put widget :buttons buttons) | |
1065 (widget-put widget :children children))) | |
1066 | |
1067 (defun custom-variable-state-set (widget) | |
1068 "Set the state of WIDGET." | |
1069 (let* ((symbol (widget-value widget)) | |
1070 (value (if (default-boundp symbol) | |
1071 (default-value symbol) | |
1072 (widget-get widget :value))) | |
1073 tmp | |
1074 (state (cond ((setq tmp (get symbol 'customized-value)) | |
1075 (if (condition-case nil | |
1076 (equal value (eval (car tmp))) | |
1077 (error nil)) | |
1078 'set | |
1079 'changed)) | |
1080 ((setq tmp (get symbol 'saved-value)) | |
1081 (if (condition-case nil | |
1082 (equal value (eval (car tmp))) | |
1083 (error nil)) | |
1084 'saved | |
1085 'changed)) | |
1086 ((setq tmp (get symbol 'factory-value)) | |
1087 (if (condition-case nil | |
1088 (equal value (eval (car tmp))) | |
1089 (error nil)) | |
1090 'factory | |
1091 'changed)) | |
1092 (t 'rogue)))) | |
1093 (widget-put widget :custom-state state))) | |
1094 | |
1095 (defvar custom-variable-menu | |
1096 '(("Edit" . custom-variable-edit) | |
1097 ("Edit Lisp" . custom-variable-edit-lisp) | |
1098 ("Set" . custom-variable-set) | |
1099 ("Save" . custom-variable-save) | |
1100 ("Reset to Current" . custom-redraw) | |
1101 ("Reset to Saved" . custom-variable-reset-saved) | |
1102 ("Reset to Factory Settings" . custom-variable-reset-factory)) | |
1103 "Alist of actions for the `custom-variable' widget. | |
1104 The key is a string containing the name of the action, the value is a | |
1105 lisp function taking the widget as an element which will be called | |
1106 when the action is chosen.") | |
1107 | |
1108 (defun custom-variable-action (widget &optional event) | |
1109 "Show the menu for `custom-variable' WIDGET. | |
1110 Optional EVENT is the location for the menu." | |
1111 (if (eq (widget-get widget :custom-state) 'hidden) | |
1112 (progn | |
1113 (widget-put widget :custom-state 'unknown) | |
1114 (custom-redraw widget)) | |
1115 (let* ((completion-ignore-case t) | |
1116 (answer (widget-choose (custom-unlispify-tag-name | |
1117 (widget-get widget :value)) | |
1118 custom-variable-menu | |
1119 event))) | |
1120 (if answer | |
1121 (funcall answer widget))))) | |
1122 | |
1123 (defun custom-variable-edit (widget) | |
1124 "Edit value of WIDGET." | |
1125 (widget-put widget :custom-state 'unknown) | |
1126 (widget-put widget :custom-form 'edit) | |
1127 (custom-redraw widget)) | |
1128 | |
1129 (defun custom-variable-edit-lisp (widget) | |
1130 "Edit the lisp representation of the value of WIDGET." | |
1131 (widget-put widget :custom-state 'unknown) | |
1132 (widget-put widget :custom-form 'lisp) | |
1133 (custom-redraw widget)) | |
1134 | |
1135 (defun custom-variable-set (widget) | |
1136 "Set the current value for the variable being edited by WIDGET." | |
1137 (let ((form (widget-get widget :custom-form)) | |
1138 (state (widget-get widget :custom-state)) | |
1139 (child (car (widget-get widget :children))) | |
1140 (symbol (widget-value widget)) | |
1141 val) | |
1142 (cond ((eq state 'hidden) | |
1143 (error "Cannot set hidden variable.")) | |
1144 ((setq val (widget-apply child :validate)) | |
1145 (goto-char (widget-get val :from)) | |
1146 (error "%s" (widget-get val :error))) | |
1147 ((eq form 'lisp) | |
1148 (set symbol (eval (setq val (widget-value child)))) | |
1149 (put symbol 'customized-value (list val))) | |
1150 (t | |
1151 (set symbol (setq val (widget-value child))) | |
1152 (put symbol 'customized-value (list (custom-quote val))))) | |
1153 (custom-variable-state-set widget) | |
1154 (custom-redraw-magic widget))) | |
1155 | |
1156 (defun custom-variable-save (widget) | |
1157 "Set the default value for the variable being edited by WIDGET." | |
1158 (let ((form (widget-get widget :custom-form)) | |
1159 (state (widget-get widget :custom-state)) | |
1160 (child (car (widget-get widget :children))) | |
1161 (symbol (widget-value widget)) | |
1162 val) | |
1163 (cond ((eq state 'hidden) | |
1164 (error "Cannot set hidden variable.")) | |
1165 ((setq val (widget-apply child :validate)) | |
1166 (goto-char (widget-get val :from)) | |
1167 (error "%s" (widget-get val :error))) | |
1168 ((eq form 'lisp) | |
1169 (put symbol 'saved-value (list (widget-value child))) | |
1170 (set symbol (eval (widget-value child)))) | |
1171 (t | |
1172 (put symbol | |
1173 'saved-value (list (custom-quote (widget-value | |
1174 child)))) | |
1175 (set symbol (widget-value child)))) | |
1176 (put symbol 'customized-value nil) | |
1177 (custom-save-all) | |
1178 (custom-variable-state-set widget) | |
1179 (custom-redraw-magic widget))) | |
1180 | |
1181 (defun custom-variable-reset-saved (widget) | |
1182 "Restore the saved value for the variable being edited by WIDGET." | |
1183 (let ((symbol (widget-value widget))) | |
1184 (if (get symbol 'saved-value) | |
1185 (condition-case nil | |
1186 (set symbol (eval (car (get symbol 'saved-value)))) | |
1187 (error nil)) | |
1188 (error "No saved value for %s" symbol)) | |
1189 (put symbol 'customized-value nil) | |
1190 (widget-put widget :custom-state 'unknown) | |
1191 (custom-redraw widget))) | |
1192 | |
1193 (defun custom-variable-reset-factory (widget) | |
1194 "Restore the factory setting for the variable being edited by WIDGET." | |
1195 (let ((symbol (widget-value widget))) | |
1196 (if (get symbol 'factory-value) | |
1197 (set symbol (eval (car (get symbol 'factory-value)))) | |
1198 (error "No factory default for %S" symbol)) | |
1199 (put symbol 'customized-value nil) | |
1200 (when (get symbol 'saved-value) | |
1201 (put symbol 'saved-value nil) | |
1202 (custom-save-all)) | |
1203 (widget-put widget :custom-state 'unknown) | |
1204 (custom-redraw widget))) | |
1205 | |
1206 ;;; The `custom-face-edit' Widget. | |
1207 | |
1208 (defvar custom-face-edit-args | |
1209 (mapcar (lambda (att) | |
1210 (list 'group | |
1211 :inline t | |
1212 (list 'const :format "" :value (nth 0 att)) | |
1213 (nth 1 att))) | |
1214 custom-face-attributes)) | |
1215 | |
1216 (define-widget 'custom-face-edit 'checklist | |
1217 "Edit face attributes." | |
1218 :format "%t: %v" | |
1219 :tag "Attributes" | |
1220 :extra-offset 12 | |
1221 :args (mapcar (lambda (att) | |
1222 (list 'group | |
1223 :inline t | |
1224 (list 'const :format "" :value (nth 0 att)) | |
1225 (nth 1 att))) | |
1226 custom-face-attributes)) | |
1227 | |
1228 ;;; The `custom-display' Widget. | |
1229 | |
1230 (define-widget 'custom-display 'menu-choice | |
1231 "Select a display type." | |
1232 :tag "Display" | |
1233 :value t | |
1234 :args '((const :tag "all" t) | |
1235 (checklist :offset 0 | |
1236 :extra-offset 9 | |
1237 :args ((group (const :format "Type: " type) | |
1238 (checklist :inline t | |
1239 :offset 0 | |
1240 (const :format "X " | |
1241 x) | |
1242 (const :format "PM " | |
1243 pm) | |
1244 (const :format "Win32 " | |
1245 win32) | |
1246 (const :format "DOS " | |
1247 pc) | |
1248 (const :format "TTY%n" | |
1249 tty))) | |
1250 (group (const :format "Class: " class) | |
1251 (checklist :inline t | |
1252 :offset 0 | |
1253 (const :format "Color " | |
1254 color) | |
1255 (const :format | |
1256 "Grayscale " | |
1257 grayscale) | |
1258 (const :format "Monochrome%n" | |
1259 mono))) | |
1260 (group (const :format "Background: " background) | |
1261 (checklist :inline t | |
1262 :offset 0 | |
1263 (const :format "Light " | |
1264 light) | |
1265 (const :format "Dark\n" | |
1266 dark))))))) | |
1267 | |
1268 ;;; The `custom-face' Widget. | |
1269 | |
1270 (defface custom-face-tag-face '((t (:underline t))) | |
1271 "Face used for face tags." | |
1272 :group 'customize) | |
1273 | |
1274 (define-widget 'custom-face 'custom | |
1275 "Customize face." | |
1276 :format "%l%{%t%}: %s%m%h%a%v" | |
1277 :format-handler 'custom-face-format-handler | |
1278 :sample-face 'custom-face-tag-face | |
1279 :help-echo "Push me to set or reset this face." | |
1280 :documentation-property '(lambda (face) | |
1281 (face-documentation face)) | |
1282 :value-create 'custom-face-value-create | |
1283 :action 'custom-face-action | |
1284 :custom-set 'custom-face-set | |
1285 :custom-save 'custom-face-save | |
1286 :custom-reset-current 'custom-redraw | |
1287 :custom-reset-saved 'custom-face-reset-saved | |
1288 :custom-reset-factory 'custom-face-reset-factory | |
1289 :custom-menu 'custom-face-menu-create) | |
1290 | |
1291 (defun custom-face-format-handler (widget escape) | |
1292 ;; We recognize extra escape sequences. | |
1293 (let (child | |
1294 (symbol (widget-get widget :value))) | |
1295 (cond ((eq escape ?s) | |
1296 (and (string-match "XEmacs" emacs-version) | |
1297 ;; XEmacs cannot display initialized faces. | |
1298 (not (custom-facep symbol)) | |
1299 (copy-face 'custom-face-empty symbol)) | |
1300 (setq child (widget-create-child-and-convert | |
1301 widget 'item | |
1302 :format "(%{%t%})\n" | |
1303 :sample-face symbol | |
1304 :tag "sample"))) | |
1305 (t | |
1306 (custom-format-handler widget escape))) | |
1307 (when child | |
1308 (widget-put widget | |
1309 :buttons (cons child (widget-get widget :buttons)))))) | |
1310 | |
1311 (defun custom-face-value-create (widget) | |
1312 ;; Create a list of the display specifications. | |
1313 (unless (eq (preceding-char) ?\n) | |
1314 (insert "\n")) | |
1315 (when (not (eq (widget-get widget :custom-state) 'hidden)) | |
1316 (custom-load-widget widget) | |
1317 (let* ((symbol (widget-value widget)) | |
1318 (edit (widget-create-child-and-convert | |
1319 widget 'editable-list | |
1320 :entry-format "%i %d %v" | |
1321 :value (or (get symbol 'saved-face) | |
1322 (get symbol 'factory-face)) | |
1323 '(group :format "%v" | |
1324 custom-display custom-face-edit)))) | |
1325 (custom-face-state-set widget) | |
1326 (widget-put widget :children (list edit))))) | |
1327 | |
1328 (defvar custom-face-menu | |
1329 '(("Set" . custom-face-set) | |
1330 ("Save" . custom-face-save) | |
1331 ("Reset to Saved" . custom-face-reset-saved) | |
1332 ("Reset to Factory Setting" . custom-face-reset-factory)) | |
1333 "Alist of actions for the `custom-face' widget. | |
1334 The key is a string containing the name of the action, the value is a | |
1335 lisp function taking the widget as an element which will be called | |
1336 when the action is chosen.") | |
1337 | |
1338 (defun custom-face-state-set (widget) | |
1339 "Set the state of WIDGET." | |
1340 (let ((symbol (widget-value widget))) | |
1341 (widget-put widget :custom-state (cond ((get symbol 'customized-face) | |
1342 'set) | |
1343 ((get symbol 'saved-face) | |
1344 'saved) | |
1345 ((get symbol 'factory-face) | |
1346 'factory) | |
1347 (t | |
1348 'rogue))))) | |
1349 | |
1350 (defun custom-face-action (widget &optional event) | |
1351 "Show the menu for `custom-face' WIDGET. | |
1352 Optional EVENT is the location for the menu." | |
1353 (if (eq (widget-get widget :custom-state) 'hidden) | |
1354 (progn | |
1355 (widget-put widget :custom-state 'unknown) | |
1356 (custom-redraw widget)) | |
1357 (let* ((completion-ignore-case t) | |
1358 (symbol (widget-get widget :value)) | |
1359 (answer (widget-choose (custom-unlispify-tag-name symbol) | |
1360 custom-face-menu event))) | |
1361 (if answer | |
1362 (funcall answer widget))))) | |
1363 | |
1364 (defun custom-face-set (widget) | |
1365 "Make the face attributes in WIDGET take effect." | |
1366 (let* ((symbol (widget-value widget)) | |
1367 (child (car (widget-get widget :children))) | |
1368 (value (widget-value child))) | |
1369 (put symbol 'customized-face value) | |
1370 (when (fboundp 'copy-face) | |
1371 (copy-face 'custom-face-empty symbol)) | |
1372 (custom-face-display-set symbol value) | |
1373 (custom-face-state-set widget) | |
1374 (custom-redraw-magic widget))) | |
1375 | |
1376 (defun custom-face-save (widget) | |
1377 "Make the face attributes in WIDGET default." | |
1378 (let* ((symbol (widget-value widget)) | |
1379 (child (car (widget-get widget :children))) | |
1380 (value (widget-value child))) | |
1381 (when (fboundp 'copy-face) | |
1382 (copy-face 'custom-face-empty symbol)) | |
1383 (custom-face-display-set symbol value) | |
1384 (put symbol 'saved-face value) | |
1385 (put symbol 'customized-face nil) | |
1386 (custom-face-state-set widget) | |
1387 (custom-redraw-magic widget))) | |
1388 | |
1389 (defun custom-face-reset-saved (widget) | |
1390 "Restore WIDGET to the face's default attributes." | |
1391 (let* ((symbol (widget-value widget)) | |
1392 (child (car (widget-get widget :children))) | |
1393 (value (get symbol 'saved-face))) | |
1394 (unless value | |
1395 (error "No saved value for this face")) | |
1396 (put symbol 'customized-face nil) | |
1397 (when (fboundp 'copy-face) | |
1398 (copy-face 'custom-face-empty symbol)) | |
1399 (custom-face-display-set symbol value) | |
1400 (widget-value-set child value) | |
1401 (custom-face-state-set widget) | |
1402 (custom-redraw-magic widget))) | |
1403 | |
1404 (defun custom-face-reset-factory (widget) | |
1405 "Restore WIDGET to the face's factory settings." | |
1406 (let* ((symbol (widget-value widget)) | |
1407 (child (car (widget-get widget :children))) | |
1408 (value (get symbol 'factory-face))) | |
1409 (unless value | |
1410 (error "No factory default for this face")) | |
1411 (put symbol 'customized-face nil) | |
1412 (when (get symbol 'saved-face) | |
1413 (put symbol 'saved-face nil) | |
1414 (custom-save-all)) | |
1415 (when (fboundp 'copy-face) | |
1416 (copy-face 'custom-face-empty symbol)) | |
1417 (custom-face-display-set symbol value) | |
1418 (widget-value-set child value) | |
1419 (custom-face-state-set widget) | |
1420 (custom-redraw-magic widget))) | |
1421 | |
1422 ;;; The `face' Widget. | |
1423 | |
1424 (define-widget 'face 'default | |
1425 "Select and customize a face." | |
1426 :convert-widget 'widget-item-convert-widget | |
1427 :format "%[%t%]: %v" | |
1428 :tag "Face" | |
1429 :value 'default | |
1430 :value-create 'widget-face-value-create | |
1431 :value-delete 'widget-face-value-delete | |
1432 :value-get 'widget-item-value-get | |
1433 :validate 'widget-editable-list-validate | |
1434 :action 'widget-face-action | |
1435 :match '(lambda (widget value) (symbolp value))) | |
1436 | |
1437 (defun widget-face-value-create (widget) | |
1438 ;; Create a `custom-face' child. | |
1439 (let* ((symbol (widget-value widget)) | |
1440 (child (widget-create-child-and-convert | |
1441 widget 'custom-face | |
1442 :format "%t %s%m%h%v" | |
1443 :custom-level nil | |
1444 :value symbol))) | |
1445 (custom-magic-reset child) | |
1446 (setq custom-options (cons child custom-options)) | |
1447 (widget-put widget :children (list child)))) | |
1448 | |
1449 (defun widget-face-value-delete (widget) | |
1450 ;; Remove the child from the options. | |
1451 (let ((child (car (widget-get widget :children)))) | |
1452 (setq custom-options (delq child custom-options)) | |
1453 (widget-children-value-delete widget))) | |
1454 | |
1455 (defvar face-history nil | |
1456 "History of entered face names.") | |
1457 | |
1458 (defun widget-face-action (widget &optional event) | |
1459 "Prompt for a face." | |
1460 (let ((answer (completing-read "Face: " | |
1461 (mapcar (lambda (face) | |
1462 (list (symbol-name face))) | |
1463 (face-list)) | |
1464 nil nil nil | |
1465 'face-history))) | |
1466 (unless (zerop (length answer)) | |
1467 (widget-value-set widget (intern answer)) | |
1468 (widget-apply widget :notify widget event) | |
1469 (widget-setup)))) | |
1470 | |
1471 ;;; The `hook' Widget. | |
1472 | |
1473 (define-widget 'hook 'list | |
1474 "A emacs lisp hook" | |
1475 :convert-widget 'custom-hook-convert-widget | |
1476 :tag "Hook") | |
1477 | |
1478 (defun custom-hook-convert-widget (widget) | |
1479 ;; Handle `:custom-options'. | |
1480 (let* ((options (widget-get widget :options)) | |
1481 (other `(editable-list :inline t | |
1482 :entry-format "%i %d%v" | |
1483 (function :format " %v"))) | |
1484 (args (if options | |
1485 (list `(checklist :inline t | |
1486 ,@(mapcar (lambda (entry) | |
1487 `(function-item ,entry)) | |
1488 options)) | |
1489 other) | |
1490 (list other)))) | |
1491 (widget-put widget :args args) | |
1492 widget)) | |
1493 | |
1494 ;;; The `custom-group' Widget. | |
1495 | |
1496 (defcustom custom-group-tag-faces '(custom-group-tag-face-1) | |
1497 ;; In XEmacs, this ought to play games with font size. | |
1498 "Face used for group tags. | |
1499 The first member is used for level 1 groups, the second for level 2, | |
1500 and so forth. The remaining group tags are shown with | |
1501 `custom-group-tag-face'." | |
1502 :type '(repeat face) | |
1503 :group 'customize) | |
1504 | |
1505 (defface custom-group-tag-face-1 '((((class color) | |
1506 (background dark)) | |
1507 (:foreground "pink" :underline t)) | |
1508 (((class color) | |
1509 (background light)) | |
1510 (:foreground "red" :underline t)) | |
1511 (t (:underline t))) | |
1512 "Face used for group tags.") | |
1513 | |
1514 (defface custom-group-tag-face '((((class color) | |
1515 (background dark)) | |
1516 (:foreground "light blue" :underline t)) | |
1517 (((class color) | |
1518 (background light)) | |
1519 (:foreground "blue" :underline t)) | |
1520 (t (:underline t))) | |
1521 "Face used for low level group tags." | |
1522 :group 'customize) | |
1523 | |
1524 (define-widget 'custom-group 'custom | |
1525 "Customize group." | |
1526 :format "%l%{%t%}:%L\n%m%h%a%v" | |
1527 :sample-face-get 'custom-group-sample-face-get | |
1528 :documentation-property 'group-documentation | |
1529 :help-echo "Push me to set or reset all members of this group." | |
1530 :value-create 'custom-group-value-create | |
1531 :action 'custom-group-action | |
1532 :custom-set 'custom-group-set | |
1533 :custom-save 'custom-group-save | |
1534 :custom-reset-current 'custom-group-reset-current | |
1535 :custom-reset-saved 'custom-group-reset-saved | |
1536 :custom-reset-factory 'custom-group-reset-factory | |
1537 :custom-menu 'custom-group-menu-create) | |
1538 | |
1539 (defun custom-group-sample-face-get (widget) | |
1540 ;; Use :sample-face. | |
1541 (or (nth (1- (widget-get widget :custom-level)) custom-group-tag-faces) | |
1542 'custom-group-tag-face)) | |
1543 | |
1544 (defun custom-group-value-create (widget) | |
1545 (let ((state (widget-get widget :custom-state))) | |
1546 (unless (eq state 'hidden) | |
1547 (custom-load-widget widget) | |
1548 (let* ((level (widget-get widget :custom-level)) | |
1549 (symbol (widget-value widget)) | |
1550 (members (get symbol 'custom-group)) | |
1551 (prefixes (widget-get widget :custom-prefixes)) | |
1552 (custom-prefix-list (custom-prefix-add symbol prefixes)) | |
1553 (children (mapcar (lambda (entry) | |
1554 (widget-insert "\n") | |
1555 (prog1 | |
1556 (widget-create-child-and-convert | |
1557 widget (nth 1 entry) | |
1558 :group widget | |
1559 :tag (custom-unlispify-tag-name | |
1560 (nth 0 entry)) | |
1561 :custom-prefixes custom-prefix-list | |
1562 :custom-level (1+ level) | |
1563 :value (nth 0 entry)) | |
1564 (unless (eq (preceding-char) ?\n) | |
1565 (widget-insert "\n")))) | |
1566 members))) | |
1567 (mapcar 'custom-magic-reset children) | |
1568 (widget-put widget :children children) | |
1569 (custom-group-state-update widget))))) | |
1570 | |
1571 (defvar custom-group-menu | |
1572 '(("Set" . custom-group-set) | |
1573 ("Save" . custom-group-save) | |
1574 ("Reset to Current" . custom-group-reset-current) | |
1575 ("Reset to Saved" . custom-group-reset-saved) | |
1576 ("Reset to Factory" . custom-group-reset-factory)) | |
1577 "Alist of actions for the `custom-group' widget. | |
1578 The key is a string containing the name of the action, the value is a | |
1579 lisp function taking the widget as an element which will be called | |
1580 when the action is chosen.") | |
1581 | |
1582 (defun custom-group-action (widget &optional event) | |
1583 "Show the menu for `custom-group' WIDGET. | |
1584 Optional EVENT is the location for the menu." | |
1585 (if (eq (widget-get widget :custom-state) 'hidden) | |
1586 (progn | |
1587 (widget-put widget :custom-state 'unknown) | |
1588 (custom-redraw widget)) | |
1589 (let* ((completion-ignore-case t) | |
1590 (answer (widget-choose (custom-unlispify-tag-name | |
1591 (widget-get widget :value)) | |
1592 custom-group-menu | |
1593 event))) | |
1594 (if answer | |
1595 (funcall answer widget))))) | |
1596 | |
1597 (defun custom-group-set (widget) | |
1598 "Set changes in all modified group members." | |
1599 (let ((children (widget-get widget :children))) | |
1600 (mapcar (lambda (child) | |
1601 (when (eq (widget-get child :custom-state) 'modified) | |
1602 (widget-apply child :custom-set))) | |
1603 children ))) | |
1604 | |
1605 (defun custom-group-save (widget) | |
1606 "Save all modified group members." | |
1607 (let ((children (widget-get widget :children))) | |
1608 (mapcar (lambda (child) | |
1609 (when (memq (widget-get child :custom-state) '(modified set)) | |
1610 (widget-apply child :custom-save))) | |
1611 children ))) | |
1612 | |
1613 (defun custom-group-reset-current (widget) | |
1614 "Reset all modified group members." | |
1615 (let ((children (widget-get widget :children))) | |
1616 (mapcar (lambda (child) | |
1617 (when (eq (widget-get child :custom-state) 'modified) | |
1618 (widget-apply child :custom-reset-current))) | |
1619 children ))) | |
1620 | |
1621 (defun custom-group-reset-saved (widget) | |
1622 "Reset all modified or set group members." | |
1623 (let ((children (widget-get widget :children))) | |
1624 (mapcar (lambda (child) | |
1625 (when (memq (widget-get child :custom-state) '(modified set)) | |
1626 (widget-apply child :custom-reset-saved))) | |
1627 children ))) | |
1628 | |
1629 (defun custom-group-reset-factory (widget) | |
1630 "Reset all modified, set, or saved group members." | |
1631 (let ((children (widget-get widget :children))) | |
1632 (mapcar (lambda (child) | |
1633 (when (memq (widget-get child :custom-state) | |
1634 '(modified set saved)) | |
1635 (widget-apply child :custom-reset-factory))) | |
1636 children ))) | |
1637 | |
1638 (defun custom-group-state-update (widget) | |
1639 "Update magic." | |
1640 (unless (eq (widget-get widget :custom-state) 'hidden) | |
1641 (let* ((children (widget-get widget :children)) | |
1642 (states (mapcar (lambda (child) | |
1643 (widget-get child :custom-state)) | |
1644 children)) | |
1645 (magics custom-magic-alist) | |
1646 (found 'factory)) | |
1647 (while magics | |
1648 (let ((magic (car (car magics)))) | |
1649 (if (and (not (eq magic 'hidden)) | |
1650 (memq magic states)) | |
1651 (setq found magic | |
1652 magics nil) | |
1653 (setq magics (cdr magics))))) | |
1654 (widget-put widget :custom-state found))) | |
1655 (custom-magic-reset widget)) | |
1656 | |
1657 ;;; The `custom-save-all' Function. | |
1658 | |
1659 (defcustom custom-file "~/.emacs" | |
1660 "File used for storing customization information. | |
1661 If you change this from the default \"~/.emacs\" you need to | |
1662 explicitly load that file for the settings to take effect." | |
1663 :type 'file | |
1664 :group 'customize) | |
1665 | |
1666 (defun custom-save-delete (symbol) | |
1667 "Delete the call to SYMBOL form `custom-file'. | |
1668 Leave point at the location of the call, or after the last expression." | |
1669 (set-buffer (find-file-noselect custom-file)) | |
1670 (goto-char (point-min)) | |
1671 (catch 'found | |
1672 (while t | |
1673 (let ((sexp (condition-case nil | |
1674 (read (current-buffer)) | |
1675 (end-of-file (throw 'found nil))))) | |
1676 (when (and (listp sexp) | |
1677 (eq (car sexp) symbol)) | |
1678 (delete-region (save-excursion | |
1679 (backward-sexp) | |
1680 (point)) | |
1681 (point)) | |
1682 (throw 'found nil)))))) | |
1683 | |
1684 (defun custom-save-variables () | |
1685 "Save all customized variables in `custom-file'." | |
1686 (save-excursion | |
1687 (custom-save-delete 'custom-set-variables) | |
1688 (let ((standard-output (current-buffer))) | |
1689 (unless (bolp) | |
1690 (princ "\n")) | |
1691 (princ "(custom-set-variables") | |
1692 (mapatoms (lambda (symbol) | |
1693 (let ((value (get symbol 'saved-value))) | |
1694 (when value | |
1695 (princ "\n '(") | |
1696 (princ symbol) | |
1697 (princ " ") | |
1698 (prin1 (car value)) | |
1699 (if (or (get symbol 'factory-value) | |
1700 (and (not (boundp symbol)) | |
1701 (not (get symbol 'force-value)))) | |
1702 (princ ")") | |
1703 (princ " t)")))))) | |
1704 (princ ")") | |
1705 (unless (eolp) | |
1706 (princ "\n"))))) | |
1707 | |
1708 (defun custom-save-faces () | |
1709 "Save all customized faces in `custom-file'." | |
1710 (save-excursion | |
1711 (custom-save-delete 'custom-set-faces) | |
1712 (let ((standard-output (current-buffer))) | |
1713 (unless (bolp) | |
1714 (princ "\n")) | |
1715 (princ "(custom-set-faces") | |
1716 (mapatoms (lambda (symbol) | |
1717 (let ((value (get symbol 'saved-face))) | |
1718 (when value | |
1719 (princ "\n '(") | |
1720 (princ symbol) | |
1721 (princ " ") | |
1722 (prin1 value) | |
1723 (if (or (get symbol 'factory-face) | |
1724 (and (not (custom-facep symbol)) | |
1725 (not (get symbol 'force-face)))) | |
1726 (princ ")") | |
1727 (princ " t)")))))) | |
1728 (princ ")") | |
1729 (unless (eolp) | |
1730 (princ "\n"))))) | |
1731 | |
1732 (defun custom-save-all () | |
1733 "Save all customizations in `custom-file'." | |
1734 (custom-save-variables) | |
1735 (custom-save-faces) | |
1736 (save-excursion | |
1737 (set-buffer (find-file-noselect custom-file)) | |
1738 (save-buffer))) | |
1739 | |
1740 ;;; The Customize Menu. | |
1741 | |
1742 (defcustom custom-menu-nesting 2 | |
1743 "Maximum nesting in custom menus." | |
1744 :type 'integer | |
1745 :group 'customize) | |
1746 | |
1747 (defun custom-face-menu-create (widget symbol) | |
1748 "Ignoring WIDGET, create a menu entry for customization face SYMBOL." | |
1749 (vector (custom-unlispify-menu-entry symbol) | |
1750 `(custom-buffer-create '((,symbol custom-face))) | |
1751 t)) | |
1752 | |
1753 (defun custom-variable-menu-create (widget symbol) | |
1754 "Ignoring WIDGET, create a menu entry for customization variable SYMBOL." | |
1755 (let ((type (get symbol 'custom-type))) | |
1756 (unless (listp type) | |
1757 (setq type (list type))) | |
1758 (if (and type (widget-get type :custom-menu)) | |
1759 (widget-apply type :custom-menu symbol) | |
1760 (vector (custom-unlispify-menu-entry symbol) | |
1761 `(custom-buffer-create '((,symbol custom-variable))) | |
1762 t)))) | |
1763 | |
1764 (widget-put (get 'boolean 'widget-type) | |
1765 :custom-menu (lambda (widget symbol) | |
1766 (vector (custom-unlispify-menu-entry symbol) | |
1767 `(custom-buffer-create | |
1768 '((,symbol custom-variable))) | |
1769 ':style 'toggle | |
1770 ':selected symbol))) | |
1771 | |
1772 (defun custom-group-menu-create (widget symbol) | |
1773 "Ignoring WIDGET, create a menu entry for customization group SYMBOL." | |
1774 (custom-menu-create symbol)) | |
1775 | |
1776 (defun custom-menu-create (symbol &optional name) | |
1777 "Create menu for customization group SYMBOL. | |
1778 If optional NAME is given, use that as the name of the menu. | |
1779 Otherwise make up a name from SYMBOL. | |
1780 The menu is in a format applicable to `easy-menu-define'." | |
1781 (unless name | |
1782 (setq name (custom-unlispify-menu-entry symbol))) | |
1783 (let ((item (vector name | |
1784 `(custom-buffer-create '((,symbol custom-group))) | |
1785 t))) | |
1786 (if (and (> custom-menu-nesting 0) | |
1787 (< (length (get symbol 'custom-group)) widget-menu-max-size)) | |
1788 (let ((custom-menu-nesting (1- custom-menu-nesting)) | |
1789 (custom-prefix-list (custom-prefix-add symbol | |
1790 custom-prefix-list))) | |
1791 (custom-load-symbol symbol) | |
1792 `(,(custom-unlispify-menu-entry symbol t) | |
1793 ,item | |
1794 "--" | |
1795 ,@(mapcar (lambda (entry) | |
1796 (widget-apply (if (listp (nth 1 entry)) | |
1797 (nth 1 entry) | |
1798 (list (nth 1 entry))) | |
1799 :custom-menu (nth 0 entry))) | |
1800 (get symbol 'custom-group)))) | |
1801 item))) | |
1802 | |
1803 ;;;###autoload | |
1804 (defun custom-menu-update () | |
1805 "Update customize menu." | |
1806 (interactive) | |
1807 (add-hook 'custom-define-hook 'custom-menu-reset) | |
1808 (let ((menu `(,(car custom-help-menu) | |
1809 ,(widget-apply '(custom-group) :custom-menu 'emacs) | |
1810 ,@(cdr (cdr custom-help-menu))))) | |
1811 (if (fboundp 'add-submenu) | |
1812 (add-submenu '("Help") menu) | |
1813 (define-key global-map [menu-bar help-menu customize-menu] | |
1814 (cons (car menu) (easy-menu-create-keymaps (car menu) (cdr menu))))))) | |
1815 | |
1816 ;;; Dependencies. | |
1817 | |
1818 ;;;###autoload | |
1819 (defun custom-make-dependencies () | |
1820 "Batch function to extract custom dependencies from .el files. | |
1821 Usage: emacs -batch *.el -f custom-make-dependencies > deps.el" | |
1822 (let ((buffers (buffer-list))) | |
1823 (while buffers | |
1824 (set-buffer (car buffers)) | |
1825 (setq buffers (cdr buffers)) | |
1826 (let ((file (buffer-file-name))) | |
1827 (when (and file (string-match "\\`\\(.*\\)\\.el\\'" file)) | |
1828 (goto-char (point-min)) | |
1829 (condition-case nil | |
1830 (let ((name (file-name-nondirectory (match-string 1 file)))) | |
1831 (while t | |
1832 (let ((expr (read (current-buffer)))) | |
1833 (when (and (listp expr) | |
1834 (memq (car expr) '(defcustom defface defgroup))) | |
1835 (eval expr) | |
1836 (put (nth 1 expr) 'custom-where name))))) | |
1837 (error nil)))))) | |
1838 (mapatoms (lambda (symbol) | |
1839 (let ((members (get symbol 'custom-group)) | |
1840 item where found) | |
1841 (when members | |
1842 (princ "(put '") | |
1843 (princ symbol) | |
1844 (princ " 'custom-loads '(") | |
1845 (while members | |
1846 (setq item (car (car members)) | |
1847 members (cdr members) | |
1848 where (get item 'custom-where)) | |
1849 (unless (or (null where) | |
1850 (member where found)) | |
1851 (when found | |
1852 (princ " ")) | |
1853 (prin1 where) | |
1854 (push where found))) | |
1855 (princ "))\n")))))) | |
1856 | |
1857 ;;; The End. | |
1858 | |
1859 (provide 'cus-edit) | |
1860 | |
1861 ;; cus-edit.el ends here |