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