use cooper theme -- end of git, I am trying livemesh
[srid.dotfiles.git] / emacs / external / color-theme.el
blob5c7d3a8b22ec39fe65d0d559f86ba66504564aab
1 ;;; color-theme.el --- install color themes
3 ;; Copyright (C) 1999, 2000 Jonadab the Unsightly One <jonadab@bright.net>
4 ;; Copyright (C) 2000, 2001, 2002, 2003 Alex Schroeder <alex@gnu.org>
5 ;; Copyright (C) 2003, 2004, 2005, 2006 Xavier Maillard <zedek@gnu.org>
7 ;; Version: 6.6.0
8 ;; Keywords: faces
9 ;; Author: Jonadab the Unsightly One <jonadab@bright.net>
10 ;; Maintainer: Xavier Maillard <zedek@gnu.org>
11 ;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ColorTheme
13 ;; This file is not (YET) part of GNU Emacs.
15 ;; This is free software; you can redistribute it and/or modify it under
16 ;; the terms of the GNU General Public License as published by the Free
17 ;; Software Foundation; either version 2, or (at your option) any later
18 ;; version.
20 ;; This is distributed in the hope that it will be useful, but WITHOUT
21 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 ;; for more details.
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with GNU Emacs; see the file COPYING. If not, write to the
27 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
28 ;; MA 02111-1307, USA.
30 ;;; Commentary:
32 ;; Please read README and BUGS files for any relevant help.
33 ;; Contributors (not themers) should also read HACKING file.
35 ;;; Thanks
37 ;; Deepak Goel <deego@glue.umd.edu>
38 ;; S. Pokrovsky <pok@nbsp.nsk.su> for ideas and discussion.
39 ;; Gordon Messmer <gordon@dragonsdawn.net> for ideas and discussion.
40 ;; Sriram Karra <karra@cs.utah.edu> for the color-theme-submit stuff.
41 ;; Olgierd `Kingsajz' Ziolko <kingsajz@rpg.pl> for the spec-filter idea.
42 ;; Brian Palmer for color-theme-library ideas and code
43 ;; All the users that contributed their color themes.
47 ;;; Code:
48 (eval-when-compile
49 (require 'easymenu)
50 (require 'reporter)
51 (require 'sendmail))
53 (require 'cl); set-difference is a function...
55 ;; for custom-face-attributes-get or face-custom-attributes-get
56 (require 'cus-face)
57 (require 'wid-edit); for widget-apply stuff in cus-face.el
59 (defconst color-theme-maintainer-address "zedek@gnu.org"
60 "Address used by `submit-color-theme'.")
62 ;; Emacs / XEmacs compatibility and workaround layer
64 (cond ((and (facep 'tool-bar)
65 (not (facep 'toolbar)))
66 (put 'toolbar 'face-alias 'tool-bar))
67 ((and (facep 'toolbar)
68 (not (facep 'tool-bar)))
69 (put 'tool-bar 'face-alias 'toolbar)))
71 (defvar color-theme-xemacs-p (and (featurep 'xemacs)
72 (string-match "XEmacs" emacs-version))
73 "Non-nil if running XEmacs.")
75 ;; Add this since it appears to miss in emacs-2x
76 (or (fboundp 'replace-in-string)
77 (defun replace-in-string (target old new)
78 (replace-regexp-in-string old new target)))
80 ;; face-attr-construct has a problem in Emacs 20.7 and older when
81 ;; dealing with inverse-video faces. Here is a short test to check
82 ;; wether you are affected.
84 ;; (set-background-color "wheat")
85 ;; (set-foreground-color "black")
86 ;; (setq a (make-face 'a-face))
87 ;; (face-spec-set a '((t (:background "white" :foreground "black" :inverse-video t))))
88 ;; (face-attr-construct a)
89 ;; => (:background "black" :inverse-video t)
91 ;; The expected response is the original specification:
92 ;; => (:background "white" :foreground "black" :inverse-video t)
94 ;; That's why we depend on cus-face.el functionality.
96 (cond ((fboundp 'custom-face-attributes-get)
97 (defun color-theme-face-attr-construct (face frame)
98 (if (atom face)
99 (custom-face-attributes-get face frame)
100 (if (and (consp face) (eq (car face) 'quote))
101 (custom-face-attributes-get (cadr face) frame)
102 (custom-face-attributes-get (car face) frame)))))
103 ((fboundp 'face-custom-attributes-get)
104 (defalias 'color-theme-face-attr-construct
105 'face-custom-attributes-get))
107 (defun color-theme-face-attr-construct (&rest ignore)
108 (error "Unable to construct face attributes"))))
110 (defun color-theme-alist (plist)
111 "Transform PLIST into an alist if it is a plist and return it.
112 If the first element of PLIST is a cons cell, we just return PLIST,
113 assuming PLIST to be an alist. If the first element of plist is not a
114 symbol, this is an error: We cannot distinguish a plist from an ordinary
115 list, but a list that doesn't start with a symbol is certainly no plist
116 and no alist.
118 This is used to make sure `default-frame-alist' really is an alist and not
119 a plist. In XEmacs, the alist is deprecated; a plist is used instead."
120 (cond ((consp (car plist))
121 plist)
122 ((not (symbolp (car plist)))
123 (error "Wrong type argument: plist, %S" plist))
124 ((featurep 'xemacs)
125 (plist-to-alist plist)))); XEmacs only
127 ;; Customization
129 (defgroup color-theme nil
130 "Color Themes for Emacs.
131 A color theme consists of frame parameter settings, variable settings,
132 and face definitions."
133 :version "20.6"
134 :group 'faces)
136 (defcustom color-theme-legal-frame-parameters "\\(color\\|mode\\)$"
137 "Regexp that matches frame parameter names.
138 Only frame parameter names that match this regexp can be changed as part
139 of a color theme."
140 :type '(choice (const :tag "Colors only" "\\(color\\|mode\\)$")
141 (const :tag "Colors, fonts, and size"
142 "\\(color\\|mode\\|font\\|height\\|width\\)$")
143 (regexp :tag "Custom regexp"))
144 :group 'color-theme
145 :link '(info-link "(elisp)Window Frame Parameters"))
147 (defcustom color-theme-legal-variables "\\(color\\|face\\)$"
148 "Regexp that matches variable names.
149 Only variables that match this regexp can be changed as part of a color
150 theme. In addition to matching this name, the variables have to be user
151 variables (see function `user-variable-p')."
152 :type 'regexp
153 :group 'color-theme)
155 (defcustom color-theme-illegal-faces "^w3-"
156 "Regexp that matches face names forbidden in themes.
157 The default setting \"^w3-\" excludes w3 faces since these
158 are created dynamically."
159 :type 'regexp
160 :group 'color-theme
161 :link '(info-link "(elisp)Faces for Font Lock")
162 :link '(info-link "(elisp)Standard Faces"))
164 (defcustom color-theme-illegal-default-attributes '(:family :height :width)
165 "A list of face properties to be ignored when installing faces.
166 This prevents Emacs from doing terrible things to your display just because
167 a theme author likes weird fonts."
168 :type '(repeat symbol)
169 :group 'color-theme)
171 (defcustom color-theme-is-global t
172 "*Determines wether a color theme is installed on all frames or not.
173 If non-nil, color themes will be installed for all frames.
174 If nil, color themes will be installed for the selected frame only.
176 A possible use for this variable is dynamic binding. Here is a larger
177 example to put in your ~/.emacs; it will make the Blue Sea color theme
178 the default used for the first frame, and it will create two additional
179 frames with different color themes.
181 setup:
182 \(require 'color-theme)
183 ;; set default color theme
184 \(color-theme-blue-sea)
185 ;; create some frames with different color themes
186 \(let ((color-theme-is-global nil))
187 \(select-frame (make-frame))
188 \(color-theme-gnome2)
189 \(select-frame (make-frame))
190 \(color-theme-standard))
192 Please note that using XEmacs and and a nil value for
193 color-theme-is-global will ignore any variable settings for the color
194 theme, since XEmacs doesn't have frame-local variable bindings.
196 Also note that using Emacs and a non-nil value for color-theme-is-global
197 will install a new color theme for all frames. Using XEmacs and a
198 non-nil value for color-theme-is-global will install a new color theme
199 only on those frames that are not using a local color theme."
200 :type 'boolean
201 :group 'color-theme)
203 (defcustom color-theme-is-cumulative t
204 "*Determines wether new color themes are installed on top of each other.
205 If non-nil, installing a color theme will undo all settings made by
206 previous color themes."
207 :type 'boolean
208 :group 'color-theme)
210 (defcustom color-theme-directory nil
211 "Directory where we can find additionnal themes (personnal).
212 Note that there is at least one directory shipped with the official
213 color-theme distribution where all contributed themes are located.
214 This official selection can't be changed with that variable.
215 However, you still can decide to turn it on or off and thus,
216 not be shown with all themes but yours."
217 :type '(repeat string)
218 :group 'color-theme)
220 (defcustom color-theme-libraries (directory-files
221 (concat
222 (file-name-directory (locate-library "color-theme"))
223 "/themes") t "^color-theme")
224 "A list of files, which will be loaded in color-theme-initialize depending
225 on `color-theme-load-all-themes' value.
226 This allows a user to prune the default color-themes (which can take a while
227 to load)."
228 :type '(repeat string)
229 :group 'color-theme)
231 (defcustom color-theme-load-all-themes t
232 "When t, load all color-theme theme files
233 as presented by `color-theme-libraries'. Else
234 do not load any of this themes."
235 :type 'boolean
236 :group 'color-theme)
238 (defcustom color-theme-mode-hook nil
239 "Hook for color-theme-mode."
240 :type 'hook
241 :group 'color-theme)
243 (defvar color-theme-mode-map
244 (let ((map (make-sparse-keymap)))
245 (define-key map (kbd "RET") 'color-theme-install-at-point)
246 (define-key map (kbd "c") 'list-colors-display)
247 (define-key map (kbd "d") 'color-theme-describe)
248 (define-key map (kbd "f") 'list-faces-display)
249 (define-key map (kbd "i") 'color-theme-install-at-point)
250 (define-key map (kbd "l") 'color-theme-install-at-point-for-current-frame)
251 (define-key map (kbd "p") 'color-theme-print)
252 (define-key map (kbd "q") 'bury-buffer)
253 (define-key map (kbd "?") 'color-theme-describe)
254 (if color-theme-xemacs-p
255 (define-key map (kbd "<button2>") 'color-theme-install-at-mouse)
256 (define-key map (kbd "<mouse-2>") 'color-theme-install-at-mouse))
257 map)
258 "Mode map used for the buffer created by `color-theme-select'.")
260 (defvar color-theme-initialized nil
261 "Internal variable determining whether color-theme-initialize has been invoked yet")
263 (defvar color-theme-buffer-name "*Color Theme Selection*"
264 "Name of the color theme selection buffer.")
266 (defvar color-theme-original-frame-alist nil
267 "nil until one of the color themes has been installed.")
269 (defvar color-theme-history nil
270 "List of color-themes called, in reverse order")
272 (defcustom color-theme-history-max-length nil
273 "Max length of history to maintain.
274 Two other values are acceptable: t means no limit, and
275 nil means that no history is maintained."
276 :type '(choice (const :tag "No history" nil)
277 (const :tag "Unlimited length" t)
278 integer)
279 :group 'color-theme)
281 (defvar color-theme-counter 0
282 "Counter for every addition to `color-theme-history'.
283 This counts how many themes were installed, regardless
284 of `color-theme-history-max-length'.")
286 (defvar color-theme-entry-path (cond
287 ;; Emacs 22.x and later
288 ((lookup-key global-map [menu-bar tools])
289 '("tools"))
290 ;; XEmacs
291 ((featurep 'xemacs)
292 (setq tool-entry '("Tools")))
293 ;; Emacs < 22
295 '("Tools")))
296 "Menu tool entry path.")
298 (defun color-theme-add-to-history (name)
299 "Add color-theme NAME to `color-theme-history'."
300 (setq color-theme-history
301 (cons (list name color-theme-is-cumulative)
302 color-theme-history)
303 color-theme-counter (+ 1 color-theme-counter))
304 ;; Truncate the list if necessary.
305 (when (and (integerp color-theme-history-max-length)
306 (>= (length color-theme-history)
307 color-theme-history-max-length))
308 (setcdr (nthcdr (1- color-theme-history-max-length)
309 color-theme-history)
310 nil)))
312 ;; (let ((l '(1 2 3 4 5)))
313 ;; (setcdr (nthcdr 2 l) nil)
314 ;; l)
318 ;; List of color themes used to create the *Color Theme Selection*
319 ;; buffer.
321 (defvar color-themes
322 '((color-theme-aalto-dark "Aalto Dark" "Jari Aalto <jari.aalto@poboxes.com>")
323 (color-theme-aalto-light "Aalto Light" "Jari Aalto <jari.aalto@poboxes.com>")
324 (color-theme-aliceblue "Alice Blue" "Girish Bharadwaj <girishb@gbvsoft.com>")
325 (color-theme-andreas "Andreas" "Andreas Busch <Andreas.Busch@politics.ox.ac.uk>")
326 (color-theme-arjen "Arjen" "Arjen Wiersma <arjen@wiersma.org>")
327 (color-theme-beige-diff "Beige Diff" "Alex Schroeder <alex@gnu.org>" t)
328 (color-theme-bharadwaj "Bharadwaj" "Girish Bharadwaj <girishb@gbvsoft.com>")
329 (color-theme-bharadwaj-slate "Bharadwaj Slate" "Girish Bharadwaj <girishb@gbvsoft.com>")
330 (color-theme-billw "Billw" "Bill White <billw@wolfram.com>")
331 (color-theme-black-on-gray "BlackOnGray" "Sudhir Bhojwani <sbhojwani@altoweb.com>")
332 (color-theme-blippblopp "Blipp Blopp" "Thomas Sicheritz-Ponten<thomas@biopython.org>")
333 (color-theme-simple-1 "Black" "Jonadab <jonadab@bright.net>")
334 (color-theme-blue-erc "Blue ERC" "Alex Schroeder <alex@gnu.org>" t)
335 (color-theme-blue-gnus "Blue Gnus" "Alex Schroeder <alex@gnu.org>" t)
336 (color-theme-blue-mood "Blue Mood" "Nelson Loyola <nloyola@yahoo.com>")
337 (color-theme-blue-sea "Blue Sea" "Alex Schroeder <alex@gnu.org>")
338 (color-theme-calm-forest "Calm Forest" "Artur Hefczyc <kobit@plusnet.pl>")
339 (color-theme-charcoal-black "Charcoal Black" "Lars Chr. Hausmann <jazz@zqz.dk>")
340 (color-theme-goldenrod "Cheap Goldenrod" "Alex Schroeder <alex@gnu.org>")
341 (color-theme-clarity "Clarity and Beauty" "Richard Wellum <rwellum@cisco.com>")
342 (color-theme-classic "Classic" "Frederic Giroud <postcard@worldonline.fr>")
343 (color-theme-comidia "Comidia" "Marcelo Dias de Toledo <mtole@ig.com.br>")
344 (color-theme-jsc-dark "Cooper Dark" "John S Cooper <John.Cooper@eu.citrix.com>")
345 (color-theme-jsc-light "Cooper Light" "John S Cooper <John.Cooper@eu.citrix.com>")
346 (color-theme-jsc-light2 "Cooper Light 2" "John S Cooper <John.Cooper@eu.citrix.com>")
347 (color-theme-dark-blue "Dark Blue" "Chris McMahan <cmcmahan@one.net>")
348 (color-theme-dark-blue2 "Dark Blue 2" "Chris McMahan <cmcmahan@one.net>")
349 (color-theme-dark-green "Dark Green" "eddy_woody@hotmail.com")
350 (color-theme-dark-laptop "Dark Laptop" "Laurent Michel <ldm@cs.brown.edu>")
351 (color-theme-deep-blue "Deep Blue" "Tomas Cerha <cerha@brailcom.org>")
352 (color-theme-digital-ofs1 "Digital OFS1" "Gareth Owen <gowen@gwowen.freeserve.co.uk>")
353 (color-theme-euphoria "Euphoria" "oGLOWo@oGLOWo.cjb.net")
354 (color-theme-feng-shui "Feng Shui" "Walter Higgins <walterh@rocketmail.com>")
355 (color-theme-fischmeister "Fischmeister"
356 "Sebastian Fischmeister <sfischme@nexus.lzk.tuwien.ac.at>")
357 (color-theme-gnome "Gnome" "Jonadab <jonadab@bright.net>")
358 (color-theme-gnome2 "Gnome 2" "Alex Schroeder <alex@gnu.org>")
359 (color-theme-gray1 "Gray1" "Paul Pulli <P.Pulli@motorola.com>")
360 (color-theme-gray30 "Gray30" "Girish Bharadwaj <girishb@gbvsoft.com>")
361 (color-theme-kingsajz "Green Kingsajz" "Olgierd `Kingsajz' Ziolko <kingsajz@rpg.pl>")
362 (color-theme-greiner "Greiner" "Kevin Greiner <kgreiner@mapquest.com>")
363 (color-theme-gtk-ide "GTK IDE" "Gordon Messmer <gordon@dragonsdawn.net>")
364 (color-theme-high-contrast "High Contrast" "Alex Schroeder <alex@gnu.org>")
365 (color-theme-hober "Hober" "Edward O'Connor <ted@oconnor.cx>")
366 (color-theme-infodoc "Infodoc" "Frederic Giroud <postcard@worldonline.fr>")
367 (color-theme-jb-simple "JB Simple" "jeff@dvns.com")
368 (color-theme-jedit-grey "Jedit Grey" "Gordon Messmer <gordon@dragonsdawn.net>")
369 (color-theme-jonadabian "Jonadab" "Jonadab <jonadab@bright.net>")
370 (color-theme-jonadabian-slate "Jonadabian Slate" "Jonadab <jonadab@bright.net>")
371 (color-theme-katester "Katester" "Higgins_Walter@emc.com")
372 (color-theme-late-night "Late Night" "Alex Schroeder <alex@gnu.org>")
373 (color-theme-lawrence "Lawrence" "lawrence mitchell <wence@gmx.li>")
374 (color-theme-lethe "Lethe" "Ivica Loncar <ivica.loncar@srk.fer.hr>")
375 (color-theme-ld-dark "Linh Dang Dark" "Linh Dang <linhd@nortelnetworks.com>")
376 (color-theme-marine "Marine" "Girish Bharadwaj <girishb@gbvsoft.com>")
377 (color-theme-matrix "Matrix" "Walter Higgins <walterh@rocketmail.com>")
378 (color-theme-marquardt "Marquardt" "Colin Marquardt <colin@marquardt-home.de>")
379 (color-theme-midnight "Midnight" "Gordon Messmer <gordon@dragonsdawn.net>")
380 (color-theme-mistyday "Misty Day" "Hari Kumar <Hari.Kumar@mtm.kuleuven.ac.be>")
381 (color-theme-montz "Montz" "Brady Montz <bradym@becomm.com>")
382 (color-theme-oswald "Oswald" "Tom Oswald <toswald@sharplabs.com>")
383 (color-theme-parus "Parus" "Jon K Hellan <hellan@acm.org>")
384 (color-theme-pierson "Pierson" "Dan L. Pierson <dan@sol.control.com>")
385 (color-theme-ramangalahy "Ramangalahy" "Solofo Ramangalahy <solofo@irisa.fr>")
386 (color-theme-raspopovic "Raspopovic" "Pedja Raspopovic <pedja@lsil.com>")
387 (color-theme-renegade "Renegade" "Dave Benjamin <ramen@ramenfest.com>")
388 (color-theme-resolve "Resolve" "Damien Elmes <resolve@repose.cx>")
389 (color-theme-retro-green "Retro Green" "Alex Schroeder <alex@gnu.org>")
390 (color-theme-retro-orange "Retro Orange" "Alex Schroeder <alex@gnu.org>")
391 (color-theme-robin-hood "Robin Hood" "Alex Schroeder <alex@gnu.org>")
392 (color-theme-rotor "Rotor" "Jinwei Shen <shenjw@wam.umd.edu>")
393 (color-theme-ryerson "Ryerson" "Luis Fernandes <elf@ee.ryerson.ca>")
394 (color-theme-salmon-diff "Salmon Diff" "Alex Schroeder <alex@gnu.org>" t)
395 (color-theme-salmon-font-lock "Salmon Font-Lock" "Alex Schroeder <alex@gnu.org>" t)
396 (color-theme-scintilla "Scintilla" "Gordon Messmer <gordon@dragonsdawn.net>")
397 (color-theme-shaman "Shaman" "shaman@interdon.net")
398 (color-theme-sitaramv-nt "Sitaram NT"
399 "Sitaram Venkatraman <sitaramv@loc251.tandem.com>")
400 (color-theme-sitaramv-solaris "Sitaram Solaris"
401 "Sitaram Venkatraman <sitaramv@loc251.tandem.com>")
402 (color-theme-snow "Snow" "Nicolas Rist <Nicolas.Rist@alcatel.de>")
403 (color-theme-snowish "Snowish" "Girish Bharadwaj <girishb@gbvsoft.com>")
404 (color-theme-standard-ediff "Standard Ediff" "Emacs Team, added by Alex Schroeder <alex@gnu.org>" t)
405 (color-theme-standard "Standard Emacs 20" "Emacs Team, added by Alex Schroeder <alex@gnu.org>")
406 (color-theme-emacs-21 "Standard Emacs 21" "Emacs Team, added by Alex Schroeder <alex@gnu.org>")
407 (color-theme-emacs-nw "Standard Emacs 21 No Window" "Emacs Team, added by D. Goel <deego@gnufans.org>")
408 (color-theme-xemacs "Standard XEmacs" "XEmacs Team, added by Alex Schroeder <alex@gnu.org>")
409 (color-theme-subtle-blue "Subtle Blue" "Chris McMahan <cmcmahan@one.net>")
410 (color-theme-subtle-hacker "Subtle Hacker" "Colin Walters <levanti@verbum.org>")
411 (color-theme-taming-mr-arneson "Taming Mr Arneson" "Erik Arneson <erik@aarg.net>")
412 (color-theme-taylor "Taylor" "Art Taylor <reeses@hemisphere.org>")
413 (color-theme-tty-dark "TTY Dark" "O Polite <m2@plusseven.com>")
414 (color-theme-vim-colors "Vim Colors" "Michael Soulier <msoulier@biryani.nssg.mitel.com>")
415 (color-theme-whateveryouwant "Whateveryouwant" "Fabien Penso <penso@linuxfr.org>, color by Scott Jaderholm <scott@jaderholm.com>")
416 (color-theme-wheat "Wheat" "Alex Schroeder <alex@gnu.org>")
417 (color-theme-pok-wob "White On Black" "S. Pokrovsky <pok@nbsp.nsk.su>")
418 (color-theme-pok-wog "White On Grey" "S. Pokrovsky <pok@nbsp.nsk.su>")
419 (color-theme-word-perfect "WordPerfect" "Thomas Gehrlein <Thomas.Gehrlein@t-online.de>")
420 (color-theme-xp "XP" "Girish Bharadwaj <girishb@gbvsoft.com>"))
421 "List of color themes.
423 Each THEME is itself a three element list (FUNC NAME MAINTAINER &optional LIBRARY).
425 FUNC is a color theme function which does the setup. The function
426 FUNC may call `color-theme-install'. The color theme function may be
427 interactive.
429 NAME is the name of the theme and MAINTAINER is the name and/or email of
430 the maintainer of the theme.
432 If LIBRARY is non-nil, the color theme will be considered a library and
433 may not be shown in the default menu.
435 If you defined your own color theme and want to add it to this list,
436 use something like this:
438 (add-to-list 'color-themes '(color-theme-gnome2 \"Gnome2\" \"Alex\"))")
440 ;;; Functions
442 (defun color-theme-backup-original-values ()
443 "Back up the original `default-frame-alist'.
444 The values are stored in `color-theme-original-frame-alist' on
445 startup."
446 (if (null color-theme-original-frame-alist)
447 (setq color-theme-original-frame-alist
448 (color-theme-filter (frame-parameters (selected-frame))
449 color-theme-legal-frame-parameters))))
450 (add-hook 'after-init-hook 'color-theme-backup-original-values)
452 ;;;###autoload
453 (defun color-theme-select (&optional arg)
454 "Displays a special buffer for selecting and installing a color theme.
455 With optional prefix ARG, this buffer will include color theme libraries
456 as well. A color theme library is in itself not complete, it must be
457 used as part of another color theme to be useful. Thus, color theme
458 libraries are mainly useful for color theme authors."
459 (interactive "P")
460 (unless color-theme-initialized (color-theme-initialize))
461 (switch-to-buffer (get-buffer-create color-theme-buffer-name))
462 (setq buffer-read-only nil)
463 (erase-buffer)
464 ;; recreate the snapshot if necessary
465 (when (or (not (assq 'color-theme-snapshot color-themes))
466 (not (commandp 'color-theme-snapshot)))
467 (fset 'color-theme-snapshot (color-theme-make-snapshot))
468 (setq color-themes (delq (assq 'color-theme-snapshot color-themes)
469 color-themes)
470 color-themes (delq (assq 'bury-buffer color-themes)
471 color-themes)
472 color-themes (append '((color-theme-snapshot
473 "[Reset]" "Undo changes, if possible.")
474 (bury-buffer
475 "[Quit]" "Bury this buffer."))
476 color-themes)))
477 (dolist (theme color-themes)
478 (let ((func (nth 0 theme))
479 (name (nth 1 theme))
480 (author (nth 2 theme))
481 (library (nth 3 theme))
482 (desc))
483 (when (or (not library) arg)
484 (setq desc (format "%-23s %s"
485 (if library (concat name " [lib]") name)
486 author))
487 (put-text-property 0 (length desc) 'color-theme func desc)
488 (put-text-property 0 (length name) 'face 'bold desc)
489 (put-text-property 0 (length name) 'mouse-face 'highlight desc)
490 (insert desc)
491 (newline))))
492 (goto-char (point-min))
493 (setq buffer-read-only t)
494 (set-buffer-modified-p nil)
495 (color-theme-mode))
497 (when (require 'easymenu)
498 (easy-menu-add-item nil color-theme-entry-path "--")
499 (easy-menu-add-item nil color-theme-entry-path
500 ["Color Themes" color-theme-select t]))
502 (defun color-theme-mode ()
503 "Major mode to select and install color themes.
505 Use \\[color-theme-install-at-point] to install a color theme on all frames.
506 Use \\[color-theme-install-at-point-for-current-frame] to install a color theme for the current frame only.
508 The changes are applied on top of your current setup. This is a
509 feature.
511 Some of the themes should be considered extensions to the standard color
512 theme: they modify only a limited number of faces and variables. To
513 verify the final look of a color theme, install the standard color
514 theme, then install the other color theme. This is a feature. It allows
515 you to mix several color themes.
517 Use \\[color-theme-describe] to read more about the color theme function at point.
518 If you want to install the color theme permanently, put the call to the
519 color theme function into your ~/.emacs:
521 \(require 'color-theme)
522 \(color-theme-gnome2)
524 If you worry about the size of color-theme.el: You are right. Use
525 \\[color-theme-print] to print the current color theme and save the resulting buffer
526 as ~/.emacs-color-theme. Now you can install only this specific color
527 theme in your .emacs:
529 \(load-file \"~/.emacs-color-theme\")
530 \(my-color-theme)
532 The Emacs menu is not affected by color themes within Emacs. Depending
533 on the toolkit you used to compile Emacs, you might have to set specific
534 X ressources. See the info manual for more information. Here is an
535 example ~/.Xdefaults fragment:
537 emacs*Background: DarkSlateGray
538 emacs*Foreground: wheat
540 \\{color-theme-mode-map}
542 The color themes are listed in `color-themes', which see."
543 (kill-all-local-variables)
544 (setq major-mode 'color-theme-mode)
545 (setq mode-name "Color Themes")
546 (use-local-map color-theme-mode-map)
547 (when (functionp 'goto-address); Emacs
548 (goto-address))
549 (run-hooks 'color-theme-mode-hook))
551 ;;; Commands in Color Theme Selection mode
553 ;;;###autoload
554 (defun color-theme-describe ()
555 "Describe color theme listed at point.
556 This shows the documentation of the value of text-property color-theme
557 at point. The text-property color-theme should be a color theme
558 function. See `color-themes'."
559 (interactive)
560 (describe-function (get-text-property (point) 'color-theme)))
562 ;;;###autoload
563 (defun color-theme-install-at-mouse (event)
564 "Install color theme clicked upon using the mouse.
565 First argument EVENT is used to set point. Then
566 `color-theme-install-at-point' is called."
567 (interactive "e")
568 (save-excursion
569 (mouse-set-point event)
570 (color-theme-install-at-point)))
572 ;;;autoload
573 (defun color-theme-install-at-point ()
574 "Install color theme at point.
575 This calls the value of the text-property `color-theme' at point.
576 The text-property `color-theme' should be a color theme function.
577 See `color-themes'."
578 (interactive)
579 (let ((func (get-text-property (point) 'color-theme)))
580 ;; install theme
581 (if func
582 (funcall func))
583 ;; If goto-address is being used, remove all overlays in the current
584 ;; buffer and run it again. The face used for the mail addresses in
585 ;; the the color theme selection buffer is based on the variable
586 ;; goto-address-mail-face. Changes in that variable will not affect
587 ;; existing overlays, however, thereby confusing users.
588 (when (functionp 'goto-address); Emacs
589 (dolist (o (overlays-in (point-min) (point-max)))
590 (delete-overlay o))
591 (goto-address))))
593 ;;;###autoload
594 (defun color-theme-install-at-point-for-current-frame ()
595 "Install color theme at point for current frame only.
596 Binds `color-theme-is-global' to nil and calls
597 `color-theme-install-at-point'."
598 (interactive)
599 (let ((color-theme-is-global nil))
600 (color-theme-install-at-point)))
604 ;; Taking a snapshot of the current color theme and pretty printing it.
606 (defun color-theme-filter (old-list regexp &optional exclude)
607 "Filter OLD-LIST.
608 The resulting list will be newly allocated and contains only elements
609 with names matching REGEXP. OLD-LIST may be a list or an alist. If you
610 want to filter a plist, use `color-theme-alist' to convert your plist to
611 an alist, first.
613 If the optional argument EXCLUDE is non-nil, then the sense is
614 reversed: only non-matching elements will be retained."
615 (let (elem new-list)
616 (dolist (elem old-list)
617 (setq name (symbol-name (if (listp elem) (car elem) elem)))
618 (when (or (and (not exclude)
619 (string-match regexp name))
620 (and exclude
621 (not (string-match regexp name))))
622 ;; Now make sure that if elem is a cons cell, and the cdr of
623 ;; that cons cell is a string, then we need a *new* string in
624 ;; the new list. Having a new cons cell is of no use because
625 ;; modify-frame-parameters will modify this string, thus
626 ;; modifying our color theme functions!
627 (when (and (consp elem)
628 (stringp (cdr elem)))
629 (setq elem (cons (car elem)
630 (copy-sequence (cdr elem)))))
631 ;; Now store elem
632 (setq new-list (cons elem new-list))))
633 new-list))
635 (defun color-theme-spec-filter (spec)
636 "Filter the attributes in SPEC.
637 This makes sure that SPEC has the form ((t (PLIST ...))).
638 Only properties not in `color-theme-illegal-default-attributes'
639 are included in the SPEC returned."
640 (let ((props (cadar spec))
641 result prop val)
642 (while props
643 (setq prop (nth 0 props)
644 val (nth 1 props)
645 props (nthcdr 2 props))
646 (unless (memq prop color-theme-illegal-default-attributes)
647 (setq result (cons val (cons prop result)))))
648 `((t ,(nreverse result)))))
650 ;; (color-theme-spec-filter '((t (:background "blue3"))))
651 ;; (color-theme-spec-filter '((t (:stipple nil :background "Black" :foreground "SteelBlue" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :width semi-condensed :family "misc-fixed"))))
653 (defun color-theme-plist-delete (plist prop)
654 "Delete property PROP from property list PLIST by side effect.
655 This modifies PLIST."
656 ;; deal with prop at the start
657 (while (eq (car plist) prop)
658 (setq plist (cddr plist)))
659 ;; deal with empty plist
660 (when plist
661 (let ((lastcell (cdr plist))
662 (l (cddr plist)))
663 (while l
664 (if (eq (car l) prop)
665 (progn
666 (setq l (cddr l))
667 (setcdr lastcell l))
668 (setq lastcell (cdr l)
669 l (cddr l))))))
670 plist)
672 ;; (color-theme-plist-delete '(a b c d e f g h) 'a)
673 ;; (color-theme-plist-delete '(a b c d e f g h) 'b)
674 ;; (color-theme-plist-delete '(a b c d e f g h) 'c)
675 ;; (color-theme-plist-delete '(a b c d e f g h) 'g)
676 ;; (color-theme-plist-delete '(a b c d c d e f g h) 'c)
677 ;; (color-theme-plist-delete '(a b c d e f c d g h) 'c)
679 (if (or (featurep 'xemacs)
680 (< emacs-major-version 21))
681 (defalias 'color-theme-spec-compat 'identity)
682 (defun color-theme-spec-compat (spec)
683 "Filter the attributes in SPEC such that is is never invalid.
684 Example: Eventhough :bold works in Emacs, it is not recognized by
685 `customize-face' -- and then the face is uncustomizable. This
686 function replaces a :bold attribute with the corresponding :weight
687 attribute, if there is no :weight, or deletes it. This undoes the
688 doings of `color-theme-spec-canonical-font', more or less."
689 (let ((props (cadar spec)))
690 (when (plist-member props :bold)
691 (setq props (color-theme-plist-delete props :bold))
692 (unless (plist-member props :weight)
693 (setq props (plist-put props :weight 'bold))))
694 (when (plist-member props :italic)
695 (setq props (color-theme-plist-delete props :italic))
696 (unless (plist-member props :slant)
697 (setq props (plist-put props :slant 'italic))))
698 `((t ,props)))))
700 ;; (color-theme-spec-compat '((t (:foreground "blue" :bold t))))
701 ;; (color-theme-spec-compat '((t (:bold t :foreground "blue" :weight extra-bold))))
702 ;; (color-theme-spec-compat '((t (:italic t :foreground "blue"))))
703 ;; (color-theme-spec-compat '((t (:slant oblique :italic t :foreground "blue"))))
705 (defun color-theme-spec-canonical-font (atts)
706 "Add :bold and :italic attributes if necessary."
707 ;; add these to the front of atts -- this will keept the old value for
708 ;; customize-face in Emacs 21.
709 (when (and (memq (plist-get atts :weight)
710 '(ultra-bold extra-bold bold semi-bold))
711 (not (plist-get atts :bold)))
712 (setq atts (cons :bold (cons t atts))))
713 (when (and (not (memq (plist-get atts :slant)
714 '(normal nil)))
715 (not (plist-get atts :italic)))
716 (setq atts (cons :italic (cons t atts))))
717 atts)
718 ;; (color-theme-spec-canonical-font (color-theme-face-attr-construct 'bold (selected-frame)))
719 ;; (defface foo '((t (:weight extra-bold))) "foo")
720 ;; (color-theme-spec-canonical-font (color-theme-face-attr-construct 'foo (selected-frame)))
721 ;; (face-spec-set 'foo '((t (:weight extra-bold))) nil)
722 ;; (face-spec-set 'foo '((t (:bold t))) nil)
723 ;; (face-spec-set 'foo '((t (:bold t :weight extra-bold))) nil)
725 ;; Handle :height according to NEWS file for Emacs 21
726 (defun color-theme-spec-resolve-height (old new)
727 "Return the new height given OLD and NEW height.
728 OLD is the current setting, NEW is the setting inherited from."
729 (cond ((not old)
730 new)
731 ((integerp old)
732 old)
733 ((and (floatp old)
734 (integerp new))
735 (round (* old new)))
736 ((and (floatp old)
737 (floatp new))
738 (* old new))
739 ((and (functionp old)
740 (integerp new))
741 (round (funcall old new)))
742 ((and (functionp old)
743 (float new))
744 `(lambda (f) (* (funcall ,old f) ,new)))
745 ((and (functionp old)
746 (functionp new))
747 `(lambda (f) (* (funcall ,old (funcall ,new f)))))
749 (error "Illegal :height attributes: %S or %S" old new))))
750 ;; (color-theme-spec-resolve-height 12 1.2)
751 ;; (color-theme-spec-resolve-height 1.2 1.2)
752 ;; (color-theme-spec-resolve-height 1.2 12)
753 ;; (color-theme-spec-resolve-height 1.2 'foo)
754 ;; (color-theme-spec-resolve-height (lambda (f) (* 2 f)) 5)
755 ;; (color-theme-spec-resolve-height (lambda (f) (* 2 f)) 2.0)
756 ;; the following lambda is the result from the above calculation
757 ;; (color-theme-spec-resolve-height (lambda (f) (* (funcall (lambda (f) (* 2 f)) f) 2.0)) 5)
759 (defun color-theme-spec-resolve-inheritance (atts)
760 "Resolve all occurences of the :inherit attribute."
761 (let ((face (plist-get atts :inherit)))
762 ;; From the Emacs 21 NEWS file: "Attributes from inherited faces are
763 ;; merged into the face like an underlying face would be." --
764 ;; therefore properties of the inherited face only add missing
765 ;; attributes.
766 (when face
767 ;; remove :inherit face from atts -- this assumes only one
768 ;; :inherit attribute.
769 (setq atts (delq ':inherit (delq face atts)))
770 (let ((more-atts (color-theme-spec-resolve-inheritance
771 (color-theme-face-attr-construct
772 face (selected-frame))))
773 att val)
774 (while more-atts
775 (setq att (car more-atts)
776 val (cadr more-atts)
777 more-atts (cddr more-atts))
778 ;; Color-theme assumes that no value is ever 'unspecified.
779 (cond ((eq att ':height); cumulative effect!
780 (setq atts (plist-put atts
781 ':height
782 (color-theme-spec-resolve-height
783 (plist-get atts att)
784 val))))
785 ;; Default: Only put if it has not been specified before.
786 ((not (plist-get atts att))
787 (setq atts (cons att (cons val atts))))
789 ))))
790 atts))
791 ;; (color-theme-spec-resolve-inheritance '(:bold t))
792 ;; (color-theme-spec-resolve-inheritance '(:bold t :foreground "blue"))
793 ;; (color-theme-face-attr-construct 'font-lock-comment-face (selected-frame))
794 ;; (color-theme-spec-resolve-inheritance '(:bold t :inherit font-lock-comment-face))
795 ;; (color-theme-spec-resolve-inheritance '(:bold t :foreground "red" :inherit font-lock-comment-face))
796 ;; (color-theme-face-attr-construct 'Info-title-2-face (selected-frame))
797 ;; (color-theme-face-attr-construct 'Info-title-3-face (selected-frame))
798 ;; (color-theme-face-attr-construct 'Info-title-4-face (selected-frame))
799 ;; (color-theme-spec-resolve-inheritance '(:inherit Info-title-2-face))
801 ;; The :inverse-video attribute causes Emacs to swap foreground and
802 ;; background colors, XEmacs does not. Therefore, if anybody chooses
803 ;; the inverse-video attribute, we 1. swap the colors ourselves in Emacs
804 ;; and 2. we remove the inverse-video attribute in Emacs and XEmacs.
805 ;; Inverse-video is only useful on a monochrome tty.
806 (defun color-theme-spec-maybe-invert (atts)
807 "Remove the :inverse-video attribute from ATTS.
808 If ATTS contains :inverse-video t, remove it and swap foreground and
809 background color. Return ATTS."
810 (let ((inv (plist-get atts ':inverse-video)))
811 (if inv
812 (let (result att)
813 (while atts
814 (setq att (car atts)
815 atts (cdr atts))
816 (cond ((and (eq att :foreground) (not color-theme-xemacs-p))
817 (setq result (cons :background result)))
818 ((and (eq att :background) (not color-theme-xemacs-p))
819 (setq result (cons :foreground result)))
820 ((eq att :inverse-video)
821 (setq atts (cdr atts))); this prevents using dolist
823 (setq result (cons att result)))))
824 (nreverse result))
825 ;; else
826 atts)))
827 ;; (color-theme-spec-maybe-invert '(:bold t))
828 ;; (color-theme-spec-maybe-invert '(:foreground "blue"))
829 ;; (color-theme-spec-maybe-invert '(:background "red"))
830 ;; (color-theme-spec-maybe-invert '(:inverse-video t))
831 ;; (color-theme-spec-maybe-invert '(:inverse-video t :foreground "red"))
832 ;; (color-theme-spec-maybe-invert '(:inverse-video t :background "red"))
833 ;; (color-theme-spec-maybe-invert '(:inverse-video t :background "red" :foreground "blue" :bold t))
834 ;; (color-theme-spec-maybe-invert '(:inverse-video nil :background "red" :foreground "blue" :bold t))
836 (defun color-theme-spec (face)
837 "Return a list for FACE which has the form (FACE SPEC).
838 See `defface' for the format of SPEC. In this case we use only one
839 DISPLAY, t, and determine ATTS using `color-theme-face-attr-construct'.
840 If ATTS is nil, (nil) is used instead.
842 If ATTS contains :inverse-video t, we remove it and swap foreground and
843 background color using `color-theme-spec-maybe-invert'. We do this
844 because :inverse-video is handled differently in Emacs and XEmacs. We
845 will loose on a tty without colors, because in that situation,
846 :inverse-video means something."
847 (let ((atts
848 (color-theme-spec-canonical-font
849 (color-theme-spec-maybe-invert
850 (color-theme-spec-resolve-inheritance
851 (color-theme-face-attr-construct face (selected-frame)))))))
852 (if atts
853 `(,face ((t ,atts)))
854 `(,face ((t (nil)))))))
856 (defun color-theme-get-params ()
857 "Return a list of frame parameter settings usable in a color theme.
858 Such an alist may be installed by `color-theme-install-frame-params'. The
859 frame parameters returned must match `color-theme-legal-frame-parameters'."
860 (let ((params (color-theme-filter (frame-parameters (selected-frame))
861 color-theme-legal-frame-parameters)))
862 (sort params (lambda (a b) (string< (symbol-name (car a))
863 (symbol-name (car b)))))))
865 (defun color-theme-get-vars ()
866 "Return a list of variable settings usable in a color theme.
867 Such an alist may be installed by `color-theme-install-variables'.
868 The variable names must match `color-theme-legal-variables', and the
869 variable must be a user variable according to `user-variable-p'."
870 (let ((vars)
871 (val))
872 (mapatoms (lambda (v)
873 (and (boundp v)
874 (user-variable-p v)
875 (string-match color-theme-legal-variables
876 (symbol-name v))
877 (setq val (eval v))
878 (add-to-list 'vars (cons v val)))))
879 (sort vars (lambda (a b) (string< (car a) (car b))))))
881 (defun color-theme-print-alist (alist)
882 "Print ALIST."
883 (insert "\n " (if alist "(" "nil"))
884 (dolist (elem alist)
885 (when (= (preceding-char) ?\))
886 (insert "\n "))
887 (prin1 elem (current-buffer)))
888 (when (= (preceding-char) ?\)) (insert ")")))
890 (defun color-theme-get-faces ()
891 "Return a list of faces usable in a color theme.
892 Such an alist may be installed by `color-theme-install-faces'. The
893 faces returned must not match `color-theme-illegal-faces'."
894 (let ((faces (color-theme-filter (face-list) color-theme-illegal-faces t)))
895 ;; default face must come first according to comments in
896 ;; custom-save-faces, the rest is to be sorted by name
897 (cons 'default (sort (delq 'default faces) 'string-lessp))))
899 (defun color-theme-get-face-definitions ()
900 "Return face settings usable in a color-theme."
901 (let ((faces (color-theme-get-faces)))
902 (mapcar 'color-theme-spec faces)))
904 (defun color-theme-print-faces (faces)
905 "Print face settings for all faces returned by `color-theme-get-faces'."
906 (when faces
907 (insert "\n "))
908 (dolist (face faces)
909 (when (= (preceding-char) ?\))
910 (insert "\n "))
911 (prin1 face (current-buffer))))
913 (defun color-theme-reset-faces ()
914 "Reset face settings for all faces returned by `color-theme-get-faces'."
915 (let ((faces (color-theme-get-faces))
916 (face) (spec) (entry)
917 (frame (if color-theme-is-global nil (selected-frame))))
918 (while faces
919 (setq entry (color-theme-spec (car faces)))
920 (setq face (nth 0 entry))
921 (setq spec '((t (nil))))
922 (setq faces (cdr faces))
923 (if (functionp 'face-spec-reset-face)
924 (face-spec-reset-face face frame)
925 (face-spec-set face spec frame)
926 (if color-theme-is-global
927 (put face 'face-defface-spec spec))))))
929 (defun color-theme-print-theme (func doc params vars faces)
930 "Print a theme into the current buffer.
931 FUNC is the function name, DOC the doc string, PARAMS the
932 frame parameters, VARS the variable bindings, and FACES
933 the list of faces and their specs."
934 (insert "(defun " (symbol-name func) " ()\n"
935 " \"" doc "\"\n"
936 " (interactive)\n"
937 " (color-theme-install\n"
938 " '(" (symbol-name func))
939 ;; alist of frame parameters
940 (color-theme-print-alist params)
941 ;; alist of variables
942 (color-theme-print-alist vars)
943 ;; remaining elements of snapshot: face specs
944 (color-theme-print-faces faces)
945 (insert ")))\n")
946 (insert "(add-to-list 'color-themes '(" (symbol-name func) " "
947 " \"THEME NAME\" \"YOUR NAME\"))")
948 (goto-char (point-min)))
950 ;;;###autoload
951 (defun color-theme-print (&optional buf)
952 "Print the current color theme function.
954 You can contribute this function to <URL:news:gnu.emacs.sources> or
955 paste it into your .emacs file and call it. That should recreate all
956 the settings necessary for your color theme.
958 Example:
960 \(require 'color-theme)
961 \(defun my-color-theme ()
962 \"Color theme by Alex Schroeder, created 2000-05-17.\"
963 \(interactive)
964 \(color-theme-install
965 '(...
967 ...)))
968 \(my-color-theme)
970 If you want to use a specific color theme function, you can call the
971 color theme function in your .emacs directly.
973 Example:
975 \(require 'color-theme)
976 \(color-theme-gnome2)"
977 (interactive)
978 (message "Pretty printing current color theme function...")
979 (switch-to-buffer (if buf
981 (get-buffer-create "*Color Theme*")))
982 (unless buf
983 (setq buffer-read-only nil)
984 (erase-buffer))
985 ;; insert defun
986 (insert "(eval-when-compile"
987 " (require 'color-theme))\n")
988 (color-theme-print-theme 'my-color-theme
989 (concat "Color theme by "
990 (if (string= "" user-full-name)
991 (user-login-name)
992 user-full-name)
993 ", created " (format-time-string "%Y-%m-%d") ".")
994 (color-theme-get-params)
995 (color-theme-get-vars)
996 (mapcar 'color-theme-spec (color-theme-get-faces)))
997 (unless buf
998 (emacs-lisp-mode))
999 (goto-char (point-min))
1000 (message "Pretty printing current color theme function... done"))
1002 (defun color-theme-analyze-find-theme (code)
1003 "Find the sexpr that calls `color-theme-install'."
1004 (let (theme)
1005 (while (and (not theme) code)
1006 (when (eq (car code) 'color-theme-install)
1007 (setq theme code))
1008 (when (listp (car code))
1009 (setq theme (color-theme-analyze-find-theme (car code))))
1010 (setq code (cdr code)))
1011 theme))
1013 ;; (equal (color-theme-analyze-find-theme
1014 ;; '(defun color-theme-blue-eshell ()
1015 ;; "Color theme for eshell faces only."
1016 ;; (color-theme-install
1017 ;; '(color-theme-blue-eshell
1018 ;; nil
1019 ;; (eshell-ls-archive-face ((t (:bold t :foreground "IndianRed"))))
1020 ;; (eshell-ls-backup-face ((t (:foreground "Grey"))))))))
1021 ;; '(color-theme-install
1022 ;; (quote
1023 ;; (color-theme-blue-eshell
1024 ;; nil
1025 ;; (eshell-ls-archive-face ((t (:bold t :foreground "IndianRed"))))
1026 ;; (eshell-ls-backup-face ((t (:foreground "Grey")))))))))
1028 (defun color-theme-analyze-add-face (a b regexp faces)
1029 "If only one of A or B are in FACES, the other is added, and FACES is returned.
1030 If REGEXP is given, this is only done if faces contains a match for regexps."
1031 (when (or (not regexp)
1032 (catch 'found
1033 (dolist (face faces)
1034 (when (string-match regexp (symbol-name (car face)))
1035 (throw 'found t)))))
1036 (let ((face-a (assoc a faces))
1037 (face-b (assoc b faces)))
1038 (if (and face-a (not face-b))
1039 (setq faces (cons (list b (nth 1 face-a))
1040 faces))
1041 (if (and (not face-a) face-b)
1042 (setq faces (cons (list a (nth 1 face-b))
1043 faces))))))
1044 faces)
1046 ;; (equal (color-theme-analyze-add-face
1047 ;; 'blue 'violet nil
1048 ;; '((blue ((t (:foreground "blue"))))
1049 ;; (bold ((t (:bold t))))))
1050 ;; '((violet ((t (:foreground "blue"))))
1051 ;; (blue ((t (:foreground "blue"))))
1052 ;; (bold ((t (:bold t))))))
1053 ;; (equal (color-theme-analyze-add-face
1054 ;; 'violet 'blue nil
1055 ;; '((blue ((t (:foreground "blue"))))
1056 ;; (bold ((t (:bold t))))))
1057 ;; '((violet ((t (:foreground "blue"))))
1058 ;; (blue ((t (:foreground "blue"))))
1059 ;; (bold ((t (:bold t))))))
1060 ;; (equal (color-theme-analyze-add-face
1061 ;; 'violet 'blue "foo"
1062 ;; '((blue ((t (:foreground "blue"))))
1063 ;; (bold ((t (:bold t))))))
1064 ;; '((blue ((t (:foreground "blue"))))
1065 ;; (bold ((t (:bold t))))))
1066 ;; (equal (color-theme-analyze-add-face
1067 ;; 'violet 'blue "blue"
1068 ;; '((blue ((t (:foreground "blue"))))
1069 ;; (bold ((t (:bold t))))))
1070 ;; '((violet ((t (:foreground "blue"))))
1071 ;; (blue ((t (:foreground "blue"))))
1072 ;; (bold ((t (:bold t))))))
1074 (defun color-theme-analyze-add-faces (faces)
1075 "Add missing faces to FACES and return it."
1076 ;; The most important thing is to add missing faces for the other
1077 ;; editor. These are the most important faces to check. The
1078 ;; following rules list two faces, A and B. If either of the two is
1079 ;; part of the theme, the other must be, too. The optional third
1080 ;; argument specifies a regexp. Only if an existing face name
1081 ;; matches this regexp, is the rule applied.
1082 (let ((rules '((font-lock-builtin-face font-lock-reference-face)
1083 (font-lock-doc-face font-lock-doc-string-face)
1084 (font-lock-constant-face font-lock-preprocessor-face)
1085 ;; In Emacs 21 `modeline' is just an alias for
1086 ;; `mode-line'. I recommend the use of
1087 ;; `modeline' until further notice.
1088 (modeline mode-line)
1089 (modeline modeline-buffer-id)
1090 (modeline modeline-mousable)
1091 (modeline modeline-mousable-minor-mode)
1092 (region primary-selection)
1093 (region zmacs-region)
1094 (font-lock-string-face dired-face-boring "^dired")
1095 (font-lock-function-name-face dired-face-directory "^dired")
1096 (default dired-face-executable "^dired")
1097 (font-lock-warning-face dired-face-flagged "^dired")
1098 (font-lock-warning-face dired-face-marked "^dired")
1099 (default dired-face-permissions "^dired")
1100 (default dired-face-setuid "^dired")
1101 (default dired-face-socket "^dired")
1102 (font-lock-keyword-face dired-face-symlink "^dired")
1103 (tool-bar menu))))
1104 (dolist (rule rules)
1105 (setq faces (color-theme-analyze-add-face
1106 (nth 0 rule) (nth 1 rule) (nth 2 rule) faces))))
1107 ;; The `fringe' face defines what the left and right borders of the
1108 ;; frame look like in Emacs 21. To give them default fore- and
1109 ;; background colors, use (fringe ((t (nil)))) in your color theme.
1110 ;; Usually it makes more sense to choose a color slightly lighter or
1111 ;; darker from the default background.
1112 (unless (assoc 'fringe faces)
1113 (setq faces (cons '(fringe ((t (nil)))) faces)))
1114 ;; The tool-bar should not be part of the frame-parameters, since it
1115 ;; should not appear or disappear depending on the color theme. The
1116 ;; apppearance of the toolbar, however, can be changed by the color
1117 ;; theme. For Emacs 21, use the `tool-bar' face. The easiest way
1118 ;; to do this is to give it the default fore- and background colors.
1119 ;; This can be achieved using (tool-bar ((t (nil)))) in the theme.
1120 ;; Usually it makes more sense, however, to provide the same colors
1121 ;; as used in the `menu' face, and to specify a :box attribute. In
1122 ;; order to alleviate potential Emacs/XEmacs incompatibilities,
1123 ;; `toolbar' will be defined as an alias for `tool-bar' if it does
1124 ;; not exist, and vice-versa. This is done eventhough the face
1125 ;; `toolbar' seems to have no effect on XEmacs. If you look at
1126 ;; XEmacs lisp/faces.el, however, you will find that it is in fact
1127 ;; referenced for XPM stuff.
1128 (unless (assoc 'tool-bar faces)
1129 (setq faces (cons '(tool-bar ((t (nil)))) faces)))
1130 ;; Move the default face back to the front, and sort the rest.
1131 (unless (eq (caar faces) 'default)
1132 (let ((face (assoc 'default faces)))
1133 (setq faces (cons face
1134 (sort (delete face faces)
1135 (lambda (a b)
1136 (string-lessp (car a) (car b))))))))
1137 faces)
1139 (defun color-theme-analyze-remove-heights (faces)
1140 "Remove :height property where it is an integer and return FACES."
1141 ;; I don't recommend making font sizes part of a color theme. Most
1142 ;; users would be surprised to see their font sizes change when they
1143 ;; install a color-theme. Therefore, remove all :height attributes
1144 ;; if the value is an integer. If the value is a float, this is ok
1145 ;; -- the value is relative to the default height. One notable
1146 ;; exceptions is for a color-theme created for visually impaired
1147 ;; people. These *must* use a larger font in order to be usable.
1148 (let (result)
1149 (dolist (face faces)
1150 (let ((props (cadar (nth 1 face))))
1151 (if (and (plist-member props :height)
1152 (integerp (plist-get props :height)))
1153 (setq props (color-theme-plist-delete props :height)
1154 result (cons (list (car face) `((t ,props)))
1155 result))
1156 (setq result (cons face result)))))
1157 (nreverse result)))
1159 ;; (equal (color-theme-analyze-remove-heights
1160 ;; '((blue ((t (:foreground "blue" :height 2))))
1161 ;; (bold ((t (:bold t :height 1.0))))))
1162 ;; '((blue ((t (:foreground "blue"))))
1163 ;; (bold ((t (:bold t :height 1.0))))))
1165 ;;;###autoload
1166 (defun color-theme-analyze-defun ()
1167 "Once you have a color-theme printed, check for missing faces.
1168 This is used by maintainers who receive a color-theme submission
1169 and want to make sure it follows the guidelines by the color-theme
1170 author."
1171 ;; The support for :foreground and :background attributes works for
1172 ;; Emacs 20 and 21 as well as for XEmacs. :inverse-video is taken
1173 ;; care of while printing color themes.
1174 (interactive)
1175 ;; Parse the stuff and find the call to color-theme-install
1176 (save-excursion
1177 (save-restriction
1178 (narrow-to-defun)
1179 ;; define the function
1180 (eval-defun nil)
1181 (goto-char (point-min))
1182 (let* ((code (read (current-buffer)))
1183 (theme (color-theme-canonic
1184 (eval
1185 (cadr
1186 (color-theme-analyze-find-theme
1187 code)))))
1188 (func (color-theme-function theme))
1189 (doc (documentation func t))
1190 (variables (color-theme-variables theme))
1191 (faces (color-theme-faces theme))
1192 (params (color-theme-frame-params theme)))
1193 (setq faces (color-theme-analyze-remove-heights
1194 (color-theme-analyze-add-faces faces)))
1195 ;; Remove any variable bindings of faces that point to their
1196 ;; symbol? Perhaps not, because another theme might want to
1197 ;; change this, so it is important to be able to reset them.
1198 ;; (let (result)
1199 ;; (dolist (var variables)
1200 ;; (unless (eq (car var) (cdr var))
1201 ;; (setq result (cons var result))))
1202 ;; (setq variables (nreverse result)))
1203 ;; Now modify the theme directly.
1204 (setq theme (color-theme-analyze-find-theme code))
1205 (setcdr (cadadr theme) (list params variables faces))
1206 (message "Pretty printing analysed color theme function...")
1207 (with-current-buffer (get-buffer-create "*Color Theme*")
1208 (setq buffer-read-only nil)
1209 (erase-buffer)
1210 ;; insert defun
1211 (color-theme-print-theme func doc params variables faces)
1212 (emacs-lisp-mode))
1213 (message "Pretty printing analysed color theme function... done")
1214 (ediff-buffers (current-buffer)
1215 (get-buffer "*Color Theme*"))))))
1217 ;;; Creating a snapshot of the current color theme
1219 (defun color-theme-snapshot nil)
1221 ;;;###autoload
1222 (defun color-theme-make-snapshot ()
1223 "Return the definition of the current color-theme.
1224 The function returned will recreate the color-theme in use at the moment."
1225 (eval `(lambda ()
1226 "The color theme in use when the selection buffer was created.
1227 \\[color-theme-select] creates the color theme selection buffer. At the
1228 same time, this snapshot is created as a very simple undo mechanism.
1229 The snapshot is created via `color-theme-snapshot'."
1230 (interactive)
1231 (color-theme-install
1232 '(color-theme-snapshot
1233 ;; alist of frame parameters
1234 ,(color-theme-get-params)
1235 ;; alist of variables
1236 ,(color-theme-get-vars)
1237 ;; remaining elements of snapshot: face specs
1238 ,@(color-theme-get-face-definitions))))))
1242 ;;; Handling the various parts of a color theme install
1244 (defvar color-theme-frame-param-frobbing-rules
1245 '((foreground-color default foreground)
1246 (background-color default background))
1247 "List of rules to use when frobbing faces based on frame parameters.
1248 This is only necessary for XEmacs, because in Emacs 21 changing the
1249 frame paramters automatically affects the relevant faces.")
1251 ;; fixme: silent the bytecompiler with set-face-property
1252 (defun color-theme-frob-faces (params)
1253 "Change certain faces according to PARAMS.
1254 This uses `color-theme-frame-param-frobbing-rules'."
1255 (dolist (rule color-theme-frame-param-frobbing-rules)
1256 (let* ((param (nth 0 rule))
1257 (face (nth 1 rule))
1258 (prop (nth 2 rule))
1259 (val (cdr (assq param params)))
1260 (frame (if color-theme-is-global nil (selected-frame))))
1261 (when val
1262 (set-face-property face prop val frame)))))
1264 (defun color-theme-alist-reduce (old-list)
1265 "Reduce OLD-LIST.
1266 The resulting list will be newly allocated and will not contain any elements
1267 with duplicate cars. This will speed the installation of new themes by
1268 only installing unique attributes."
1269 (let (new-list)
1270 (dolist (elem old-list)
1271 (when (not (assq (car elem) new-list))
1272 (setq new-list (cons elem new-list))))
1273 new-list))
1275 (defun color-theme-install-frame-params (params)
1276 "Change frame parameters using alist PARAMETERS.
1278 If `color-theme-is-global' is non-nil, all frames are modified using
1279 `modify-frame-parameters' and the PARAMETERS are prepended to
1280 `default-frame-alist'. The value of `initial-frame-alist' is not
1281 modified. If `color-theme-is-global' is nil, only the selected frame is
1282 modified. If `color-theme-is-cumulative' is nil, the frame parameters
1283 are restored from `color-theme-original-frame-alist'.
1285 If the current frame parameters have a parameter `minibuffer' with
1286 value `only', then the frame parameters are not installed, since this
1287 indicates a dedicated minibuffer frame.
1289 Called from `color-theme-install'."
1290 (setq params (color-theme-filter
1291 params color-theme-legal-frame-parameters))
1292 ;; We have a new list in params now, therefore we may use
1293 ;; destructive nconc.
1294 (if color-theme-is-global
1295 (let ((frames (frame-list)))
1296 (if (or color-theme-is-cumulative
1297 (null color-theme-original-frame-alist))
1298 (setq default-frame-alist
1299 (append params (color-theme-alist default-frame-alist))
1300 minibuffer-frame-alist
1301 (append params (color-theme-alist minibuffer-frame-alist)))
1302 (setq default-frame-alist
1303 (append params color-theme-original-frame-alist)
1304 minibuffer-frame-alist
1305 (append params (color-theme-alist minibuffer-frame-alist))))
1306 (setq default-frame-alist
1307 (color-theme-alist-reduce default-frame-alist)
1308 minibuffer-frame-alist
1309 (color-theme-alist-reduce minibuffer-frame-alist))
1310 (dolist (frame frames)
1311 (let ((params (if (eq 'only (cdr (assq 'minibuffer (frame-parameters frame))))
1312 minibuffer-frame-alist
1313 default-frame-alist)))
1314 (condition-case var
1315 (modify-frame-parameters frame params)
1316 (error (message "Error using params %S: %S" params var))))))
1317 (condition-case var
1318 (modify-frame-parameters (selected-frame) params)
1319 (error (message "Error using params %S: %S" params var))))
1320 (when color-theme-xemacs-p
1321 (color-theme-frob-faces params)))
1323 ;; (setq default-frame-alist (cons '(height . 30) default-frame-alist))
1325 (defun color-theme-install-variables (vars)
1326 "Change variables using alist VARS.
1327 All variables matching `color-theme-legal-variables' are set.
1329 If `color-theme-is-global' and `color-theme-xemacs-p' are nil, variables
1330 are made frame-local before setting them. Variables are set using `set'
1331 in either case. This may lead to problems if changing the variable
1332 requires the usage of the function specified with the :set tag in
1333 defcustom declarations.
1335 Called from `color-theme-install'."
1336 (let ((vars (color-theme-filter vars color-theme-legal-variables)))
1337 (dolist (var vars)
1338 (if (or color-theme-is-global color-theme-xemacs-p)
1339 (set (car var) (cdr var))
1340 (make-variable-frame-local (car var))
1341 (modify-frame-parameters (selected-frame) (list var))))))
1343 (defun color-theme-install-faces (faces)
1344 "Change faces using FACES.
1346 Change faces for all frames and create any faces listed in FACES which
1347 don't exist. The modified faces will be marked as \"unchanged from
1348 its standard setting\". This is OK, since the changes made by
1349 installing a color theme should never by saved in .emacs by
1350 customization code.
1352 FACES should be a list where each entry has the form:
1354 (FACE SPEC)
1356 See `defface' for the format of SPEC.
1358 If `color-theme-is-global' is non-nil, faces are modified on all frames
1359 using `face-spec-set'. If `color-theme-is-global' is nil, faces are
1360 only modified on the selected frame. Non-existing faces are created
1361 using `make-empty-face' in either case. If `color-theme-is-cumulative'
1362 is nil, all faces are reset before installing the new faces.
1364 Called from `color-theme-install'."
1365 ;; clear all previous faces
1366 (when (not color-theme-is-cumulative)
1367 (color-theme-reset-faces))
1368 ;; install new faces
1369 (let ((faces (color-theme-filter faces color-theme-illegal-faces t))
1370 (frame (if color-theme-is-global nil (selected-frame))))
1371 (dolist (entry faces)
1372 (let ((face (nth 0 entry))
1373 (spec (nth 1 entry)))
1374 (or (facep face)
1375 (make-empty-face face))
1376 ;; remove weird properties from the default face only
1377 (when (eq face 'default)
1378 (setq spec (color-theme-spec-filter spec)))
1379 ;; Emacs/XEmacs customization issues: filter out :bold when
1380 ;; the spec contains :weight, etc, such that the spec remains
1381 ;; "valid" for custom.
1382 (setq spec (color-theme-spec-compat spec))
1383 ;; using a spec of ((t (nil))) to reset a face doesn't work
1384 ;; in Emacs 21, we use the new function face-spec-reset-face
1385 ;; instead
1386 (if (and (functionp 'face-spec-reset-face)
1387 (equal spec '((t (nil)))))
1388 (face-spec-reset-face face frame)
1389 (condition-case var
1390 (progn
1391 (face-spec-set face spec frame)
1392 (if color-theme-is-global
1393 (put face 'face-defface-spec spec)))
1394 (error (message "Error using spec %S: %S" spec var))))))))
1396 ;; `custom-set-faces' is unusable here because it doesn't allow to set
1397 ;; the faces for one frame only.
1399 ;; Emacs `face-spec-set': If FRAME is nil, the face is created and
1400 ;; marked as a customized face. This is achieved by setting the
1401 ;; `face-defface-spec' property. If we don't, new frames will not be
1402 ;; created using the face we installed because `face-spec-set' is
1403 ;; broken: If given a FRAME of nil, it will not set the default faces;
1404 ;; instead it will walk through all the frames and set modify the faces.
1405 ;; If we do set a property (`saved-face' or `face-defface-spec'),
1406 ;; `make-frame' will correctly use the faces we defined with our color
1407 ;; theme. If we used the property `saved-face',
1408 ;; `customize-save-customized' will save all the faces installed as part
1409 ;; of a color-theme in .emacs. That's why we use the
1410 ;; `face-defface-spec' property.
1414 ;;; Theme accessor functions, canonicalization, merging, comparing
1416 (defun color-theme-canonic (theme)
1417 "Return the canonic form of THEME.
1418 This deals with all the backwards compatibility stuff."
1419 (let (function frame-params variables faces)
1420 (when (functionp (car theme))
1421 (setq function (car theme)
1422 theme (cdr theme)))
1423 (setq frame-params (car theme)
1424 theme (cdr theme))
1425 ;; optional variable defintions (for backwards compatibility)
1426 (when (listp (caar theme))
1427 (setq variables (car theme)
1428 theme (cdr theme)))
1429 ;; face definitions
1430 (setq faces theme)
1431 (list function frame-params variables faces)))
1433 (defun color-theme-function (theme)
1434 "Return function used to create THEME."
1435 (nth 0 theme))
1437 (defun color-theme-frame-params (theme)
1438 "Return frame-parameters defined by THEME."
1439 (nth 1 theme))
1441 (defun color-theme-variables (theme)
1442 "Return variables set by THEME."
1443 (nth 2 theme))
1445 (defun color-theme-faces (theme)
1446 "Return faces defined by THEME."
1447 (nth 3 theme))
1449 (defun color-theme-merge-alists (&rest alists)
1450 "Merges all the alist arguments into one alist.
1451 Only the first instance of every key will be part of the resulting
1452 alist. Membership will be tested using `assq'."
1453 (let (result)
1454 (dolist (l alists)
1455 (dolist (entry l)
1456 (unless (assq (car entry) result)
1457 (setq result (cons entry result)))))
1458 (nreverse result)))
1459 ;; (color-theme-merge-alists '((a . 1) (b . 2)))
1460 ;; (color-theme-merge-alists '((a . 1) (b . 2) (a . 3)))
1461 ;; (color-theme-merge-alists '((a . 1) (b . 2)) '((a . 3)))
1462 ;; (color-theme-merge-alists '((a . 1) (b . 2)) '((c . 3)))
1463 ;; (color-theme-merge-alists '((a . 1) (b . 2)) '((c . 3) (d . 4)))
1464 ;; (color-theme-merge-alists '((a . 1) (b . 2)) '((c . 3) (d . 4) (b . 5)))
1466 ;;;###autoload
1467 (defun color-theme-compare (theme-a theme-b)
1468 "Compare two color themes.
1469 This will print the differences between installing THEME-A and
1470 installing THEME-B. Note that the order is important: If a face is
1471 defined in THEME-A and not in THEME-B, then this will not show up as a
1472 difference, because there is no reset before installing THEME-B. If a
1473 face is defined in THEME-B and not in THEME-A, then this will show up as
1474 a difference."
1475 (interactive
1476 (list
1477 (intern
1478 (completing-read "Theme A: "
1479 (mapcar (lambda (i) (list (symbol-name (car i))))
1480 color-themes)
1481 (lambda (i) (string-match "color-theme" (car i)))))
1482 (intern
1483 (completing-read "Theme B: "
1484 (mapcar (lambda (i) (list (symbol-name (car i))))
1485 color-themes)
1486 (lambda (i) (string-match "color-theme" (car i)))))))
1487 ;; install the themes in a new frame and get the definitions
1488 (let ((color-theme-is-global nil))
1489 (select-frame (make-frame))
1490 (funcall theme-a)
1491 (setq theme-a (list theme-a
1492 (color-theme-get-params)
1493 (color-theme-get-vars)
1494 (color-theme-get-face-definitions)))
1495 (funcall theme-b)
1496 (setq theme-b (list theme-b
1497 (color-theme-get-params)
1498 (color-theme-get-vars)
1499 (color-theme-get-face-definitions)))
1500 (delete-frame))
1501 (let ((params (set-difference
1502 (color-theme-frame-params theme-b)
1503 (color-theme-frame-params theme-a)
1504 :test 'equal))
1505 (vars (set-difference
1506 (color-theme-variables theme-b)
1507 (color-theme-variables theme-a)
1508 :test 'equal))
1509 (faces (set-difference
1510 (color-theme-faces theme-b)
1511 (color-theme-faces theme-a)
1512 :test 'equal)))
1513 (list 'diff
1514 params
1515 vars
1516 faces)))
1520 ;;; Installing a color theme
1521 ;;;###autoload
1522 (defun color-theme-install (theme)
1523 "Install a color theme defined by frame parameters, variables and faces.
1525 The theme is installed for all present and future frames; any missing
1526 faces are created. See `color-theme-install-faces'.
1528 THEME is a color theme definition. See below for more information.
1530 If you want to install a color theme from your .emacs, use the output
1531 generated by `color-theme-print'. This produces color theme function
1532 which you can copy to your .emacs.
1534 A color theme definition is a list:
1535 \([FUNCTION] FRAME-PARAMETERS VARIABLE-SETTINGS FACE-DEFINITIONS)
1537 FUNCTION is the color theme function which called `color-theme-install'.
1538 This is no longer used. There was a time when this package supported
1539 automatic factoring of color themes. This has been abandoned.
1541 FRAME-PARAMETERS is an alist of frame parameters. These are installed
1542 with `color-theme-install-frame-params'. These are installed last such
1543 that any changes to the default face can be changed by the frame
1544 parameters.
1546 VARIABLE-DEFINITIONS is an alist of variable settings. These are
1547 installed with `color-theme-install-variables'.
1549 FACE-DEFINITIONS is an alist of face definitions. These are installed
1550 with `color-theme-install-faces'.
1552 If `color-theme-is-cumulative' is nil, a color theme will undo face and
1553 frame-parameter settings of previous color themes."
1554 (setq theme (color-theme-canonic theme))
1555 (color-theme-install-variables (color-theme-variables theme))
1556 (color-theme-install-faces (color-theme-faces theme))
1557 ;; frame parameters override faces
1558 (color-theme-install-frame-params (color-theme-frame-params theme))
1559 (when color-theme-history-max-length
1560 (color-theme-add-to-history
1561 (car theme))))
1565 ;; Sharing your stuff
1566 ;;;###autoload
1567 (defun color-theme-submit ()
1568 "Submit your color-theme to the maintainer."
1569 (interactive)
1570 (require 'reporter)
1571 (let ((reporter-eval-buffer (current-buffer))
1572 final-resting-place
1573 after-sep-pos
1574 (reporter-status-message "Formatting buffer...")
1575 (reporter-status-count 0)
1576 (problem "Yet another color-theme")
1577 (agent (reporter-compose-outgoing))
1578 (mailbuf (current-buffer))
1579 hookvar)
1580 ;; do the work
1581 (require 'sendmail)
1582 ;; If mailbuf did not get made visible before, make it visible now.
1583 (let (same-window-buffer-names same-window-regexps)
1584 (pop-to-buffer mailbuf)
1585 ;; Just in case the original buffer is not visible now, bring it
1586 ;; back somewhere
1587 (and pop-up-windows (display-buffer reporter-eval-buffer)))
1588 (goto-char (point-min))
1589 (mail-position-on-field "to")
1590 (insert color-theme-maintainer-address)
1591 (mail-position-on-field "subject")
1592 (insert problem)
1593 ;; move point to the body of the message
1594 (mail-text)
1595 (setq after-sep-pos (point))
1596 (unwind-protect
1597 (progn
1598 (setq final-resting-place (point-marker))
1599 (goto-char final-resting-place))
1600 (color-theme-print (current-buffer))
1601 (goto-char final-resting-place)
1602 (insert "\n\n")
1603 (goto-char final-resting-place)
1604 (insert "Hello there!\n\nHere's my color theme named: ")
1605 (set-marker final-resting-place nil))
1606 ;; compose the minibuf message and display this.
1607 (let* ((sendkey-whereis (where-is-internal
1608 (get agent 'sendfunc) nil t))
1609 (abortkey-whereis (where-is-internal
1610 (get agent 'abortfunc) nil t))
1611 (sendkey (if sendkey-whereis
1612 (key-description sendkey-whereis)
1613 "C-c C-c")); TBD: BOGUS hardcode
1614 (abortkey (if abortkey-whereis
1615 (key-description abortkey-whereis)
1616 "M-x kill-buffer"))); TBD: BOGUS hardcode
1617 (message "Enter a message and type %s to send or %s to abort."
1618 sendkey abortkey))))
1622 ;; Use this to define themes
1623 (defmacro define-color-theme (name author description &rest forms)
1624 (let ((n name))
1625 `(progn
1626 (add-to-list 'color-themes
1627 (list ',n
1628 (upcase-initials
1629 (replace-in-string
1630 (replace-in-string
1631 (symbol-name ',n) "^color-theme-" "") "-" " "))
1632 ,author))
1633 (defun ,n ()
1634 ,description
1635 (interactive)
1636 ,@forms))))
1639 ;;; FIXME: is this useful ??
1640 ;;;###autoload
1641 (defun color-theme-initialize ()
1642 "Initialize the color theme package by loading color-theme-libraries."
1643 (interactive)
1645 (cond ((and (not color-theme-load-all-themes)
1646 color-theme-directory)
1647 (setq color-theme-libraries
1648 (directory-files color-theme-directory t "^color-theme")))
1649 (color-theme-directory
1650 (push (cdr (directory-files color-theme-directory t "^color-theme"))
1651 color-theme-libraries)))
1652 (dolist (library color-theme-libraries)
1653 (load library)))
1655 (when nil
1656 (setq color-theme-directory "themes/"
1657 color-theme-load-all-themes nil)
1658 (color-theme-initialize)
1660 ;; TODO: I don't like all those function names cluttering up my namespace.
1661 ;; Instead, a hashtable for the color-themes should be created. Now that
1662 ;; define-color-theme is around, it should be easy to change in just the
1663 ;; one place.
1666 (provide 'color-theme)
1668 ;;; color-theme.el ends here