Mercurial > hg > xemacs-beta
comparison lisp/custom/custom.el @ 98:0d2f883870bc r20-1b1
Import from CVS: tag r20-1b1
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:13:56 +0200 |
parents | |
children | 4be1180a9e89 |
comparison
equal
deleted
inserted
replaced
97:498bf5da1c90 | 98:0d2f883870bc |
---|---|
1 ;;; custom.el -- Tools for declaring and initializing options. | |
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.40 | |
8 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ | |
9 | |
10 ;;; Commentary: | |
11 ;; | |
12 ;; If you want to use this code, please visit the URL above. | |
13 ;; | |
14 ;; This file only contain the code needed to declare and initialize | |
15 ;; user options. The code to customize options is autoloaded from | |
16 ;; `custom-edit.el'. | |
17 | |
18 ;;; Code: | |
19 | |
20 (require 'widget) | |
21 | |
22 (define-widget-keywords :prefix :tag :load :link :options :type :group) | |
23 | |
24 ;; These autoloads should be deleted when the file is added to Emacs | |
25 | |
26 (unless (fboundp 'load-gc) | |
27 (autoload 'customize "custom-edit" nil t) | |
28 (autoload 'customize-variable "custom-edit" nil t) | |
29 (autoload 'customize-face "custom-edit" nil t) | |
30 (autoload 'customize-apropos "custom-edit" nil t) | |
31 (autoload 'customize-customized "custom-edit" nil t) | |
32 (autoload 'custom-buffer-create "custom-edit") | |
33 (autoload 'custom-menu-update "custom-edit") | |
34 (autoload 'custom-make-dependencies "custom-edit")) | |
35 | |
36 ;;; Compatibility. | |
37 | |
38 (unless (fboundp 'x-color-values) | |
39 ;; Emacs function missing in XEmacs 19.14. | |
40 (defun x-color-values (color) | |
41 "Return a description of the color named COLOR on frame FRAME. | |
42 The value is a list of integer RGB values--(RED GREEN BLUE). | |
43 These values appear to range from 0 to 65280 or 65535, depending | |
44 on the system; white is (65280 65280 65280) or (65535 65535 65535). | |
45 If FRAME is omitted or nil, use the selected frame." | |
46 (color-instance-rgb-components (make-color-instance color)))) | |
47 | |
48 (unless (fboundp 'frame-property) | |
49 ;; XEmacs function missing in Emacs 19.34. | |
50 (defun frame-property (frame property &optional default) | |
51 "Return FRAME's value for property PROPERTY." | |
52 (or (cdr (assq property (frame-parameters frame))) | |
53 default))) | |
54 | |
55 (defun custom-background-mode () | |
56 "Kludge to detext background mode." | |
57 (let* ((bg-resource | |
58 (condition-case () | |
59 (x-get-resource ".backgroundMode" "BackgroundMode" 'string) | |
60 (error nil))) | |
61 color | |
62 (mode (cond (bg-resource | |
63 (intern (downcase bg-resource))) | |
64 ((and (setq color (condition-case () | |
65 (or (frame-property | |
66 (selected-frame) | |
67 'background-color) | |
68 (color-instance-name | |
69 (specifier-instance | |
70 (face-background 'default)))) | |
71 (error nil))) | |
72 (< (apply '+ (x-color-values color)) | |
73 (/ (apply '+ (x-color-values "white")) | |
74 3))) | |
75 'dark) | |
76 (t 'light)))) | |
77 (modify-frame-parameters (selected-frame) | |
78 (list (cons 'background-mode mode))) | |
79 mode)) | |
80 | |
81 ;; XEmacs and Emacs have different definitions of `facep'. | |
82 ;; The Emacs definition is the useful one, so emulate that. | |
83 (cond ((not (fboundp 'facep)) | |
84 (defun custom-facep (face) | |
85 "No faces" | |
86 nil)) | |
87 ((string-match "XEmacs" emacs-version) | |
88 (defun custom-facep (face) | |
89 "Face symbol or object." | |
90 (or (facep face) | |
91 (find-face face)))) | |
92 (t | |
93 (defalias 'custom-facep 'facep))) | |
94 | |
95 ;;; The `defcustom' Macro. | |
96 | |
97 (defun custom-declare-variable (symbol value doc &rest args) | |
98 "Like `defcustom', but SYMBOL and VALUE are evaluated as notmal arguments." | |
99 (unless (and (default-boundp symbol) | |
100 (not (get symbol 'saved-value))) | |
101 (set-default symbol (if (get symbol 'saved-value) | |
102 (eval (car (get symbol 'saved-value))) | |
103 (eval value)))) | |
104 (put symbol 'factory-value (list value)) | |
105 (when doc | |
106 (put symbol 'variable-documentation doc)) | |
107 (while args | |
108 (let ((arg (car args))) | |
109 (setq args (cdr args)) | |
110 (unless (symbolp arg) | |
111 (error "Junk in args %S" args)) | |
112 (let ((keyword arg) | |
113 (value (car args))) | |
114 (unless args | |
115 (error "Keyword %s is missing an argument" keyword)) | |
116 (setq args (cdr args)) | |
117 (cond ((eq keyword :type) | |
118 (put symbol 'custom-type value)) | |
119 ((eq keyword :options) | |
120 (if (get symbol 'custom-options) | |
121 ;; Slow safe code to avoid duplicates. | |
122 (mapcar (lambda (option) | |
123 (custom-add-option symbol option)) | |
124 value) | |
125 ;; Fast code for the common case. | |
126 (put symbol 'custom-options (copy-list value)))) | |
127 (t | |
128 (custom-handle-keyword symbol keyword value | |
129 'custom-variable)))))) | |
130 (run-hooks 'custom-define-hook) | |
131 symbol) | |
132 | |
133 (defmacro defcustom (symbol value doc &rest args) | |
134 "Declare SYMBOL as a customizable variable that defaults to VALUE. | |
135 DOC is the variable documentation. | |
136 | |
137 Neither SYMBOL nor VALUE needs to be quoted. | |
138 If SYMBOL is not already bound, initialize it to VALUE. | |
139 The remaining arguments should have the form | |
140 | |
141 [KEYWORD VALUE]... | |
142 | |
143 The following KEYWORD's are defined: | |
144 | |
145 :type VALUE should be a widget type. | |
146 :options VALUE should be a list of valid members of the widget type. | |
147 :group VALUE should be a customization group. | |
148 Add SYMBOL to that group. | |
149 | |
150 Read the section about customization in the emacs lisp manual for more | |
151 information." | |
152 `(eval-and-compile | |
153 (custom-declare-variable (quote ,symbol) (quote ,value) ,doc ,@args))) | |
154 | |
155 ;;; The `defface' Macro. | |
156 | |
157 (defun custom-declare-face (face spec doc &rest args) | |
158 "Like `defface', but FACE is evaluated as a normal argument." | |
159 (put face 'factory-face spec) | |
160 (when (fboundp 'facep) | |
161 (unless (and (custom-facep face) | |
162 (not (get face 'saved-face))) | |
163 ;; If the user has already created the face, respect that. | |
164 (let ((value (or (get face 'saved-face) spec))) | |
165 (custom-face-display-set face value)))) | |
166 (when doc | |
167 (put face 'face-documentation doc)) | |
168 (custom-handle-all-keywords face args 'custom-face) | |
169 (run-hooks 'custom-define-hook) | |
170 face) | |
171 | |
172 (defmacro defface (face spec doc &rest args) | |
173 "Declare FACE as a customizable face that defaults to SPEC. | |
174 FACE does not need to be quoted. | |
175 | |
176 Third argument DOC is the face documentation. | |
177 | |
178 If FACE has been set with `custom-set-face', set the face attributes | |
179 as specified by that function, otherwise set the face attributes | |
180 according to SPEC. | |
181 | |
182 The remaining arguments should have the form | |
183 | |
184 [KEYWORD VALUE]... | |
185 | |
186 The following KEYWORD's are defined: | |
187 | |
188 :group VALUE should be a customization group. | |
189 Add FACE to that group. | |
190 | |
191 SPEC should be an alist of the form ((DISPLAY ATTS)...). | |
192 | |
193 ATTS is a list of face attributes and their values. The possible | |
194 attributes are defined in the variable `custom-face-attributes'. | |
195 Alternatively, ATTS can be a face in which case the attributes of that | |
196 face is used. | |
197 | |
198 The ATTS of the first entry in SPEC where the DISPLAY matches the | |
199 frame should take effect in that frame. DISPLAY can either be the | |
200 symbol `t', which will match all frames, or an alist of the form | |
201 \((REQ ITEM...)...) | |
202 | |
203 For the DISPLAY to match a FRAME, the REQ property of the frame must | |
204 match one of the ITEM. The following REQ are defined: | |
205 | |
206 `type' (the value of (window-system)) | |
207 Should be one of `x' or `tty'. | |
208 | |
209 `class' (the frame's color support) | |
210 Should be one of `color', `grayscale', or `mono'. | |
211 | |
212 `background' (what color is used for the background text) | |
213 Should be one of `light' or `dark'. | |
214 | |
215 Read the section about customization in the emacs lisp manual for more | |
216 information." | |
217 `(custom-declare-face (quote ,face) ,spec ,doc ,@args)) | |
218 | |
219 ;;; The `defgroup' Macro. | |
220 | |
221 (defun custom-declare-group (symbol members doc &rest args) | |
222 "Like `defgroup', but SYMBOL is evaluated as a normal argument." | |
223 (put symbol 'custom-group (nconc members (get symbol 'custom-group))) | |
224 (when doc | |
225 (put symbol 'group-documentation doc)) | |
226 (while args | |
227 (let ((arg (car args))) | |
228 (setq args (cdr args)) | |
229 (unless (symbolp arg) | |
230 (error "Junk in args %S" args)) | |
231 (let ((keyword arg) | |
232 (value (car args))) | |
233 (unless args | |
234 (error "Keyword %s is missing an argument" keyword)) | |
235 (setq args (cdr args)) | |
236 (cond ((eq keyword :prefix) | |
237 (put symbol 'custom-prefix value)) | |
238 (t | |
239 (custom-handle-keyword symbol keyword value | |
240 'custom-group)))))) | |
241 (run-hooks 'custom-define-hook) | |
242 symbol) | |
243 | |
244 (defmacro defgroup (symbol members doc &rest args) | |
245 "Declare SYMBOL as a customization group containing MEMBERS. | |
246 SYMBOL does not need to be quoted. | |
247 | |
248 Third arg DOC is the group documentation. | |
249 | |
250 MEMBERS should be an alist of the form ((NAME WIDGET)...) where | |
251 NAME is a symbol and WIDGET is a widget is a widget for editing that | |
252 symbol. Useful widgets are `custom-variable' for editing variables, | |
253 `custom-face' for edit faces, and `custom-group' for editing groups. | |
254 | |
255 The remaining arguments should have the form | |
256 | |
257 [KEYWORD VALUE]... | |
258 | |
259 The following KEYWORD's are defined: | |
260 | |
261 :group VALUE should be a customization group. | |
262 Add SYMBOL to that group. | |
263 | |
264 Read the section about customization in the emacs lisp manual for more | |
265 information." | |
266 `(custom-declare-group (quote ,symbol) ,members ,doc ,@args)) | |
267 | |
268 (defun custom-add-to-group (group option widget) | |
269 "To existing GROUP add a new OPTION of type WIDGET, | |
270 If there already is an entry for that option, overwrite it." | |
271 (let* ((members (get group 'custom-group)) | |
272 (old (assq option members))) | |
273 (if old | |
274 (setcar (cdr old) widget) | |
275 (put group 'custom-group (nconc members (list (list option widget))))))) | |
276 | |
277 ;;; Properties. | |
278 | |
279 (defun custom-handle-all-keywords (symbol args type) | |
280 "For customization option SYMBOL, handle keyword arguments ARGS. | |
281 Third argument TYPE is the custom option type." | |
282 (while args | |
283 (let ((arg (car args))) | |
284 (setq args (cdr args)) | |
285 (unless (symbolp arg) | |
286 (error "Junk in args %S" args)) | |
287 (let ((keyword arg) | |
288 (value (car args))) | |
289 (unless args | |
290 (error "Keyword %s is missing an argument" keyword)) | |
291 (setq args (cdr args)) | |
292 (custom-handle-keyword symbol keyword value type))))) | |
293 | |
294 (defun custom-handle-keyword (symbol keyword value type) | |
295 "For customization option SYMBOL, handle KEYWORD with VALUE. | |
296 Fourth argument TYPE is the custom option type." | |
297 (cond ((eq keyword :group) | |
298 (custom-add-to-group value symbol type)) | |
299 ((eq keyword :link) | |
300 (custom-add-link symbol value)) | |
301 ((eq keyword :load) | |
302 (custom-add-load symbol value)) | |
303 ((eq keyword :tag) | |
304 (put symbol 'custom-tag value)) | |
305 (t | |
306 (error "Unknown keyword %s" symbol)))) | |
307 | |
308 (defun custom-add-option (symbol option) | |
309 "To the variable SYMBOL add OPTION. | |
310 | |
311 If SYMBOL is a hook variable, OPTION should be a hook member. | |
312 For other types variables, the effect is undefined." | |
313 (let ((options (get symbol 'custom-options))) | |
314 (unless (member option options) | |
315 (put symbol 'custom-options (cons option options))))) | |
316 | |
317 (defun custom-add-link (symbol widget) | |
318 "To the custom option SYMBOL add the link WIDGET." | |
319 (let ((links (get symbol 'custom-links))) | |
320 (unless (member widget links) | |
321 (put symbol 'custom-links (cons widget links))))) | |
322 | |
323 (defun custom-add-load (symbol load) | |
324 "To the custom option SYMBOL add the dependency LOAD. | |
325 LOAD should be either a library file name, or a feature name." | |
326 (let ((loads (get symbol 'custom-loads))) | |
327 (unless (member load loads) | |
328 (put symbol 'custom-loads (cons load loads))))) | |
329 | |
330 ;;; Face Utilities. | |
331 | |
332 (and (fboundp 'make-face) | |
333 (make-face 'custom-face-empty)) | |
334 | |
335 (defun custom-face-display-set (face spec &optional frame) | |
336 "Set FACE to the attributes to the first matching entry in SPEC. | |
337 Iff optional FRAME is non-nil, set it for that frame only. | |
338 See `defface' for information about SPEC." | |
339 (when (fboundp 'copy-face) | |
340 (copy-face 'custom-face-empty face) | |
341 (while spec | |
342 (let* ((entry (car spec)) | |
343 (display (nth 0 entry)) | |
344 (atts (nth 1 entry))) | |
345 (setq spec (cdr spec)) | |
346 (when (custom-display-match-frame display frame) | |
347 (apply 'custom-face-attribites-set face frame atts) | |
348 (setq spec nil)))))) | |
349 | |
350 (defcustom custom-background-mode nil | |
351 "The brightness of the background. | |
352 Set this to the symbol dark if your background color is dark, light if | |
353 your background is light, or nil (default) if you want Emacs to | |
354 examine the brightness for you." | |
355 :group 'customize | |
356 :type '(choice (choice-item dark) | |
357 (choice-item light) | |
358 (choice-item :tag "default" nil))) | |
359 | |
360 (defun custom-display-match-frame (display frame) | |
361 "Non-nil iff DISPLAY matches FRAME. | |
362 If FRAME is nil, the current FRAME is used." | |
363 ;; This is a kludge to get started, we really should use specifiers! | |
364 (unless frame | |
365 (setq frame (selected-frame))) | |
366 (if (eq display t) | |
367 t | |
368 (let ((match t)) | |
369 (while (and display match) | |
370 (let* ((entry (car display)) | |
371 (req (car entry)) | |
372 (options (cdr entry))) | |
373 (setq display (cdr display)) | |
374 (cond ((eq req 'type) | |
375 (let ((type (if (fboundp 'device-type) | |
376 (device-type (frame-device frame)) | |
377 window-system))) | |
378 (setq match (memq type options)))) | |
379 ((eq req 'class) | |
380 (let ((class (if (fboundp 'device-class) | |
381 (device-class (frame-device frame)) | |
382 (frame-property frame 'display-type)))) | |
383 (setq match (memq class options)))) | |
384 ((eq req 'background) | |
385 (let ((background (or custom-background-mode | |
386 (frame-property frame 'background-mode) | |
387 (custom-background-mode)))) | |
388 (setq match (memq background options)))) | |
389 (t | |
390 (error "Unknown req `%S' with options `%S'" req options))))) | |
391 match))) | |
392 | |
393 (defconst custom-face-attributes | |
394 '((:bold (toggle :format "Bold: %[%v%]\n") custom-set-face-bold) | |
395 (:italic (toggle :format "Italic: %[%v%]\n") custom-set-face-italic) | |
396 (:underline | |
397 (toggle :format "Underline: %[%v%]\n") set-face-underline-p) | |
398 (:foreground (color :tag "Foreground") set-face-foreground) | |
399 (:background (color :tag "Background") set-face-background) | |
400 (:stipple (editable-field :format "Stipple: %v") set-face-stipple)) | |
401 "Alist of face attributes. | |
402 | |
403 The elements are of the form (KEY TYPE SET) where KEY is a symbol | |
404 identifying the attribute, TYPE is a widget type for editing the | |
405 attibute, SET is a function for setting the attribute value. | |
406 | |
407 The SET function should take three arguments, the face to modify, the | |
408 value of the attribute, and optionally the frame where the face should | |
409 be changed.") | |
410 | |
411 (when (string-match "XEmacs" emacs-version) | |
412 ;; Support for special XEmacs font attributes. | |
413 (require 'font) | |
414 | |
415 (unless (fboundp 'face-font-name) | |
416 (defun face-font-name (face &rest args) | |
417 (apply 'face-font face args))) | |
418 | |
419 (defun set-face-font-size (face size &rest args) | |
420 "Set the font of FACE to SIZE" | |
421 (let* ((font (apply 'face-font-name face args)) | |
422 (fontobj (font-create-object font))) | |
423 (set-font-size fontobj size) | |
424 (apply 'set-face-font face fontobj args))) | |
425 | |
426 (defun set-face-font-family (face family &rest args) | |
427 "Set the font of FACE to FAMILY" | |
428 (let* ((font (apply 'face-font-name face args)) | |
429 (fontobj (font-create-object font))) | |
430 (set-font-family fontobj family) | |
431 (apply 'set-face-font face fontobj args))) | |
432 | |
433 (nconc custom-face-attributes | |
434 '((:family (editable-field :format "Family: %v") | |
435 set-face-font-family) | |
436 (:size (editable-field :format "Size: %v") | |
437 set-face-font-size)))) | |
438 | |
439 (defun custom-face-attribites-set (face frame &rest atts) | |
440 "For FACE on FRAME set the attributes [KEYWORD VALUE].... | |
441 Each keyword should be listed in `custom-face-attributes'. | |
442 | |
443 If FRAME is nil, set the default face." | |
444 (while atts | |
445 (let* ((name (nth 0 atts)) | |
446 (value (nth 1 atts)) | |
447 (fun (nth 2 (assq name custom-face-attributes)))) | |
448 (setq atts (cdr (cdr atts))) | |
449 (condition-case nil | |
450 (funcall fun face value) | |
451 (error nil))))) | |
452 | |
453 (defun custom-set-face-bold (face value &optional frame) | |
454 "Set the bold property of FACE to VALUE." | |
455 (if value | |
456 (make-face-bold face frame) | |
457 (make-face-unbold face frame))) | |
458 | |
459 (defun custom-set-face-italic (face value &optional frame) | |
460 "Set the italic property of FACE to VALUE." | |
461 (if value | |
462 (make-face-italic face frame) | |
463 (make-face-unitalic face frame))) | |
464 | |
465 (defun custom-initialize-faces (&optional frame) | |
466 "Initialize all custom faces for FRAME. | |
467 If FRAME is nil or omitted, initialize them for all frames." | |
468 (mapatoms (lambda (symbol) | |
469 (let ((spec (or (get symbol 'saved-face) | |
470 (get symbol 'factory-face)))) | |
471 (when spec | |
472 (custom-face-display-set symbol spec frame)))))) | |
473 | |
474 ;;; Initializing. | |
475 | |
476 (defun custom-set-variables (&rest args) | |
477 "Initialize variables according to user preferences. | |
478 | |
479 The arguments should be a list where each entry has the form: | |
480 | |
481 (SYMBOL VALUE [NOW]) | |
482 | |
483 The unevaluated VALUE is stored as the saved value for SYMBOL. | |
484 If NOW is present and non-nil, VALUE is also evaluated and bound as | |
485 the default value for the SYMBOL." | |
486 (while args | |
487 (let ((entry (car args))) | |
488 (if (listp entry) | |
489 (let ((symbol (nth 0 entry)) | |
490 (value (nth 1 entry)) | |
491 (now (nth 2 entry))) | |
492 (put symbol 'saved-value (list value)) | |
493 (when now | |
494 (put symbol 'force-value t) | |
495 (set-default symbol (eval value))) | |
496 (setq args (cdr args))) | |
497 ;; Old format, a plist of SYMBOL VALUE pairs. | |
498 (let ((symbol (nth 0 args)) | |
499 (value (nth 1 args))) | |
500 (put symbol 'saved-value (list value))) | |
501 (setq args (cdr (cdr args))))))) | |
502 | |
503 (defun custom-set-faces (&rest args) | |
504 "Initialize faces according to user preferences. | |
505 The arguments should be a list where each entry has the form: | |
506 | |
507 (FACE SPEC [NOW]) | |
508 | |
509 SPEC will be stored as the saved value for FACE. If NOW is present | |
510 and non-nil, FACE will also be created according to SPEC. | |
511 | |
512 See `defface' for the format of SPEC." | |
513 (while args | |
514 (let ((entry (car args))) | |
515 (if (listp entry) | |
516 (let ((face (nth 0 entry)) | |
517 (spec (nth 1 entry)) | |
518 (now (nth 2 entry))) | |
519 (put face 'saved-face spec) | |
520 (when now | |
521 (put face 'force-face t) | |
522 (custom-face-display-set face spec)) | |
523 (setq args (cdr args))) | |
524 ;; Old format, a plist of FACE SPEC pairs. | |
525 (let ((face (nth 0 args)) | |
526 (spec (nth 1 args))) | |
527 (put face 'saved-face spec)) | |
528 (setq args (cdr (cdr args))))))) | |
529 | |
530 ;;; Meta Customization | |
531 | |
532 (defgroup emacs nil | |
533 "Customization of the One True Editor." | |
534 :link '(custom-manual "(emacs)Top")) | |
535 | |
536 (defgroup customize '((widgets custom-group)) | |
537 "Customization of the Customization support." | |
538 :link '(custom-manual "(custom)Top") | |
539 :link '(url-link :tag "Development Page" | |
540 "http://www.dina.kvl.dk/~abraham/custom/") | |
541 :prefix "custom-" | |
542 :group 'emacs) | |
543 | |
544 (defcustom custom-define-hook nil | |
545 "Hook called after defining each customize option." | |
546 :group 'customize | |
547 :type 'hook) | |
548 | |
549 ;;; Menu support | |
550 | |
551 (defconst custom-help-menu '("Customize" | |
552 ["Update menu..." custom-menu-update t] | |
553 ["Group..." customize t] | |
554 ["Variable..." customize-variable t] | |
555 ["Face..." customize-face t] | |
556 ["Saved..." customize-customized t] | |
557 ["Apropos..." customize-apropos t]) | |
558 "Customize menu") | |
559 | |
560 (defun custom-menu-reset () | |
561 "Reset customize menu." | |
562 (remove-hook 'custom-define-hook 'custom-menu-reset) | |
563 (cond ((fboundp 'add-submenu) | |
564 ;; XEmacs with menus. | |
565 (add-submenu '("Help") custom-help-menu)) | |
566 ((string-match "XEmacs" emacs-version) | |
567 ;; XEmacs without menus. | |
568 ) | |
569 (t | |
570 ;; Emacs. | |
571 (define-key global-map [menu-bar help-menu customize-menu] | |
572 (cons (car custom-help-menu) | |
573 (easy-menu-create-keymaps (car custom-help-menu) | |
574 (cdr custom-help-menu))))))) | |
575 | |
576 (unless (fboundp 'load-gc) | |
577 (custom-menu-reset)) | |
578 | |
579 ;;; The End. | |
580 | |
581 (provide 'custom) | |
582 | |
583 ;; custom.el ends here |