aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChong Yidong2006-01-02 22:02:11 +0000
committerChong Yidong2006-01-02 22:02:11 +0000
commitd0f1e2f8e018a86fea56abf75a2dc3435ed88106 (patch)
tree623f191d9ce4046147172ccba4ae1d3bff1f728a
parent01abe918fcabff234ed0cd105bd9e114fbb6a245 (diff)
downloademacs-d0f1e2f8e018a86fea56abf75a2dc3435ed88106.tar.gz
emacs-d0f1e2f8e018a86fea56abf75a2dc3435ed88106.zip
* cus-theme.el: Rewrite the Custom New Theme Mode interface.
(custom-new-theme-mode-map, custom-theme-insert-variable-marker) (custom-theme-insert-face-marker, custom-theme-variable-menu) (custom-theme-face-menu): New variables. (custom-theme-add-variable, custom-theme-variable-action) (custom-variable-reset-theme, custom-theme-delete-variable) (custom-face-reset-theme, custom-theme-face-action) (custom-theme-delete-face, custom-theme-merge-theme) (custom-theme-add-face, custom-theme-visit-theme): New functions.
-rw-r--r--lisp/ChangeLog12
-rw-r--r--lisp/cus-theme.el353
2 files changed, 289 insertions, 76 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 8f01e68d616..53e59f3dca9 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,15 @@
12006-01-02 Chong Yidong <cyd@stupidchicken.com>
2
3 * cus-theme.el: Rewrite the Custom New Theme Mode interface.
4 (custom-new-theme-mode-map, custom-theme-insert-variable-marker)
5 (custom-theme-insert-face-marker, custom-theme-variable-menu)
6 (custom-theme-face-menu): New variables.
7 (custom-theme-add-variable, custom-theme-variable-action)
8 (custom-variable-reset-theme, custom-theme-delete-variable)
9 (custom-face-reset-theme, custom-theme-face-action)
10 (custom-theme-delete-face, custom-theme-merge-theme)
11 (custom-theme-add-face, custom-theme-visit-theme): New functions.
12
12006-01-01 Chong Yidong <cyd@stupidchicken.com> 132006-01-01 Chong Yidong <cyd@stupidchicken.com>
2 14
3 * custom.el: Move Custom Themes commentary to start of theme code. 15 * custom.el: Move Custom Themes commentary to start of theme code.
diff --git a/lisp/cus-theme.el b/lisp/cus-theme.el
index d7102fc11f7..0a421da925c 100644
--- a/lisp/cus-theme.el
+++ b/lisp/cus-theme.el
@@ -58,18 +58,18 @@ use by `customize-create-theme'."
58 (set (make-local-variable 'widget-link-suffix) ""))) 58 (set (make-local-variable 'widget-link-suffix) "")))
59(put 'custom-new-theme-mode 'mode-class 'special) 59(put 'custom-new-theme-mode 'mode-class 'special)
60 60
61(defvar custom-theme-name) 61(defvar custom-theme-name nil)
62(defvar custom-theme-variables) 62(defvar custom-theme-variables nil)
63(defvar custom-theme-faces) 63(defvar custom-theme-faces nil)
64(defvar custom-theme-description) 64(defvar custom-theme-description)
65(defvar custom-theme-insert-variable-marker)
66(defvar custom-theme-insert-face-marker)
65 67
66;;;###autoload 68;;;###autoload
67(defun customize-create-theme () 69(defun customize-create-theme ()
68 "Create a custom theme." 70 "Create a custom theme."
69 (interactive) 71 (interactive)
70 (if (get-buffer "*New Custom Theme*") 72 (switch-to-buffer (generate-new-buffer "*New Custom Theme*"))
71 (kill-buffer "*New Custom Theme*"))
72 (switch-to-buffer "*New Custom Theme*")
73 (let ((inhibit-read-only t)) 73 (let ((inhibit-read-only t))
74 (erase-buffer)) 74 (erase-buffer))
75 (custom-new-theme-mode) 75 (custom-new-theme-mode)
@@ -77,17 +77,39 @@ use by `customize-create-theme'."
77 (make-local-variable 'custom-theme-variables) 77 (make-local-variable 'custom-theme-variables)
78 (make-local-variable 'custom-theme-faces) 78 (make-local-variable 'custom-theme-faces)
79 (make-local-variable 'custom-theme-description) 79 (make-local-variable 'custom-theme-description)
80 (make-local-variable 'custom-theme-insert-variable-marker)
81 (make-local-variable 'custom-theme-insert-face-marker)
80 (widget-insert "This buffer helps you write a custom theme elisp file. 82 (widget-insert "This buffer helps you write a custom theme elisp file.
81This will help you share your customizations with other people. 83This will help you share your customizations with other people.
82 84
83Just insert the names of all variables and faces you want the theme 85Insert the names of all variables and faces you want the theme to include.
84to include. Then clicking mouse-2 or pressing RET on the [Done] button 86Invoke \"Save Theme\" to save the theme. The theme file will be saved to
85will write a theme file that sets all these variables and faces to their 87the directory " custom-theme-directory "\n\n")
86current global values. It will write that file into the directory given 88 (widget-create 'push-button
87by the variable `custom-theme-directory', usually \"~/.emacs.d/\". 89 :tag "Visit Theme"
90 :help-echo "Insert the settings of a pre-defined theme."
91 :action (lambda (widget &optional event)
92 (call-interactively 'custom-theme-visit-theme)))
93 (widget-insert " ")
94 (widget-create 'push-button
95 :tag "Merge Theme"
96 :help-echo "Merge in the settings of a pre-defined theme."
97 :action (lambda (widget &optional event)
98 (call-interactively 'custom-theme-merge-theme)))
99 (widget-insert " ")
100 (widget-create 'push-button
101 :notify (lambda (&rest ignore)
102 (when (y-or-n-p "Discard current changes?")
103 (kill-buffer (current-buffer))
104 (customize-create-theme)))
105 "Reset Buffer")
106 (widget-insert " ")
107 (widget-create 'push-button
108 :notify (function custom-theme-write)
109 "Save Theme")
110 (widget-insert "\n")
88 111
89To undo all your edits to the buffer, use the [Reset] button.\n\n") 112 (widget-insert "\n\nTheme name: ")
90 (widget-insert "Theme name: ")
91 (setq custom-theme-name 113 (setq custom-theme-name
92 (widget-create 'editable-field 114 (widget-create 'editable-field
93 :size 10 115 :size 10
@@ -96,76 +118,254 @@ To undo all your edits to the buffer, use the [Reset] button.\n\n")
96 (setq custom-theme-description 118 (setq custom-theme-description
97 (widget-create 'text 119 (widget-create 'text
98 :value (format-time-string "Created %Y-%m-%d."))) 120 :value (format-time-string "Created %Y-%m-%d.")))
99 (widget-insert "\nVariables:\n\n")
100 (setq custom-theme-variables
101 (widget-create 'editable-list
102 :entry-format "%i %d %v"
103 'variable))
104 (widget-insert "\nFaces:\n\n")
105 (setq custom-theme-faces
106 (widget-create 'editable-list
107 :entry-format "%i %d %v"
108 'face))
109 (widget-insert "\n") 121 (widget-insert "\n")
110 (widget-create 'push-button 122 (widget-create 'push-button
111 :notify (function custom-theme-write) 123 :tag "Insert Variable"
112 "Done") 124 :help-echo "Add another variable to this theme."
113 (widget-insert " ") 125 :action (lambda (widget &optional event)
126 (call-interactively 'custom-theme-add-variable)))
127 (widget-insert "\n")
128 (setq custom-theme-insert-variable-marker (point-marker))
129 (widget-insert "\n")
114 (widget-create 'push-button 130 (widget-create 'push-button
115 :notify (lambda (&rest ignore) 131 :tag "Insert Face"
116 (customize-create-theme)) 132 :help-echo "Add another face to this theme."
117 "Reset") 133 :action (lambda (widget &optional event)
118 (widget-insert " ") 134 (call-interactively 'custom-theme-add-face)))
135 (widget-insert "\n")
136 (setq custom-theme-insert-face-marker (point-marker))
137 (widget-insert "\n")
119 (widget-create 'push-button 138 (widget-create 'push-button
120 :notify (lambda (&rest ignore) 139 :notify (lambda (&rest ignore)
121 (bury-buffer)) 140 (when (y-or-n-p "Discard current changes?")
122 "Bury Buffer") 141 (kill-buffer (current-buffer))
142 (customize-create-theme)))
143 "Reset Buffer")
144 (widget-insert " ")
145 (widget-create 'push-button
146 :notify (function custom-theme-write)
147 "Save Theme")
123 (widget-insert "\n") 148 (widget-insert "\n")
149 (widget-setup)
150 (goto-char (point-min))
151 (message ""))
152
153;;; Theme variables
154
155(defun custom-theme-add-variable (symbol)
156 (interactive "vVariable name: ")
157 (save-excursion
158 (goto-char custom-theme-insert-variable-marker)
159 (if (assq symbol custom-theme-variables)
160 (message "%s is already in the theme" (symbol-name symbol))
161 (widget-insert "\n")
162 (let ((widget (widget-create 'custom-variable
163 :tag (custom-unlispify-tag-name symbol)
164 :custom-level 0
165 :action 'custom-theme-variable-action
166 :custom-state 'unknown
167 :value symbol)))
168 (push (cons symbol widget) custom-theme-variables)
169 (custom-magic-reset widget))
170 (widget-setup))))
171
172(defvar custom-theme-variable-menu
173 `(("Reset to Current" custom-redraw
174 (lambda (widget)
175 (and (boundp (widget-value widget))
176 (memq (widget-get widget :custom-state)
177 '(themed modified changed)))))
178 ("Reset to Theme Value" custom-variable-reset-theme
179 (lambda (widget)
180 (let ((theme (intern (widget-value custom-theme-name)))
181 (symbol (widget-value widget))
182 found)
183 (and (custom-theme-p theme)
184 (dolist (setting (get theme 'theme-settings) found)
185 (if (and (eq (cadr setting) symbol)
186 (eq (car setting) 'theme-value))
187 (setq found t)))))))
188 ("---" ignore ignore)
189 ("Delete" custom-theme-delete-variable nil))
190 "Alist of actions for the `custom-variable' widget in Custom Theme Mode.
191See the documentation for `custom-variable'.")
192
193(defun custom-theme-variable-action (widget &optional event)
194 "Show the Custom Theme Mode menu for a `custom-variable' widget.
195Optional EVENT is the location for the menu."
196 (let ((custom-variable-menu custom-theme-variable-menu))
197 (custom-variable-action widget event)))
198
199(defun custom-variable-reset-theme (widget)
200 "Reset WIDGET to its value for the currently edited theme."
201 (let ((theme (intern (widget-value custom-theme-name)))
202 (symbol (widget-value widget))
203 found)
204 (dolist (setting (get theme 'theme-settings))
205 (if (and (eq (cadr setting) symbol)
206 (eq (car setting) 'theme-value))
207 (setq found setting)))
208 (widget-value-set (car (widget-get widget :children))
209 (nth 3 found)))
210 (widget-put widget :custom-state 'themed)
211 (custom-redraw-magic widget)
212 (widget-setup))
213
214(defun custom-theme-delete-variable (widget)
215 (setq custom-theme-variables
216 (assq-delete-all (widget-value widget) custom-theme-variables))
217 (widget-delete widget))
218
219;;; Theme faces
220
221(defun custom-theme-add-face (symbol)
222 (interactive (list (read-face-name "Face name" nil nil)))
223 (save-excursion
224 (goto-char custom-theme-insert-face-marker)
225 (if (assq symbol custom-theme-faces)
226 (message "%s is already in the theme" (symbol-name symbol))
227 (widget-insert "\n")
228 (let ((widget (widget-create 'custom-face
229 :tag (custom-unlispify-tag-name symbol)
230 :custom-level 0
231 :action 'custom-theme-face-action
232 :custom-state 'unknown
233 :value symbol)))
234 (push (cons symbol widget) custom-theme-faces)
235 (custom-magic-reset widget)
236 (widget-setup)))))
237
238(defvar custom-theme-face-menu
239 `(("Reset to Theme Value" custom-face-reset-theme
240 (lambda (widget)
241 (let ((theme (intern (widget-value custom-theme-name)))
242 (symbol (widget-value widget))
243 found)
244 (and (custom-theme-p theme)
245 (dolist (setting (get theme 'theme-settings) found)
246 (if (and (eq (cadr setting) symbol)
247 (eq (car setting) 'theme-face))
248 (setq found t)))))))
249 ("---" ignore ignore)
250 ("Delete" custom-theme-delete-face nil))
251 "Alist of actions for the `custom-variable' widget in Custom Theme Mode.
252See the documentation for `custom-variable'.")
253
254(defun custom-theme-face-action (widget &optional event)
255 "Show the Custom Theme Mode menu for a `custom-face' widget.
256Optional EVENT is the location for the menu."
257 (let ((custom-face-menu custom-theme-face-menu))
258 (custom-face-action widget event)))
259
260(defun custom-face-reset-theme (widget)
261 "Reset WIDGET to its value for the currently edited theme."
262 (let ((theme (intern (widget-value custom-theme-name)))
263 (symbol (widget-value widget))
264 found)
265 (dolist (setting (get theme 'theme-settings))
266 (if (and (eq (cadr setting) symbol)
267 (eq (car setting) 'theme-face))
268 (setq found setting)))
269 (widget-value-set (car (widget-get widget :children))
270 (nth 3 found)))
271 (widget-put widget :custom-state 'themed)
272 (custom-redraw-magic widget)
124 (widget-setup)) 273 (widget-setup))
125 274
275(defun custom-theme-delete-face (widget)
276 (setq custom-theme-faces
277 (assq-delete-all (widget-value widget) custom-theme-faces))
278 (widget-delete widget))
279
280;;; Reading and writing
281
282(defun custom-theme-visit-theme ()
283 (interactive)
284 (when (or (null custom-theme-variables)
285 (if (y-or-n-p "Discard current changes?")
286 (progn (customize-create-theme) t)))
287 (let ((theme (call-interactively 'custom-theme-merge-theme)))
288 (unless (eq theme 'user)
289 (widget-value-set custom-theme-name (symbol-name theme)))
290 (widget-value-set custom-theme-description
291 (or (get theme 'theme-documentation)
292 (format-time-string "Created %Y-%m-%d.")))
293 (widget-setup))))
294
295(defun custom-theme-merge-theme (theme)
296 (interactive "SCustom theme name: ")
297 (unless (eq theme 'user)
298 (load-theme theme))
299 (let ((settings (get theme 'theme-settings)))
300 (dolist (setting settings)
301 (if (eq (car setting) 'theme-value)
302 (custom-theme-add-variable (cadr setting))
303 (custom-theme-add-face (cadr setting)))))
304 (disable-theme theme)
305 theme)
306
126(defun custom-theme-write (&rest ignore) 307(defun custom-theme-write (&rest ignore)
127 (let ((name (widget-value custom-theme-name)) 308 (let* ((name (widget-value custom-theme-name))
128 (doc (widget-value custom-theme-description)) 309 (filename (expand-file-name (concat name "-theme.el")
129 (variables (widget-value custom-theme-variables)) 310 custom-theme-directory))
130 (faces (widget-value custom-theme-faces))) 311 (doc (widget-value custom-theme-description))
131 (switch-to-buffer (concat name "-theme.el")) 312 (vars custom-theme-variables)
132 (emacs-lisp-mode) 313 (faces custom-theme-faces))
133 (unless (file-exists-p custom-theme-directory) 314 (cond ((or (string-equal name "")
134 (make-directory (file-name-as-directory custom-theme-directory) t)) 315 (string-equal name "user")
135 (setq default-directory custom-theme-directory) 316 (string-equal name "changed"))
136 (setq buffer-file-name (expand-file-name (concat name "-theme.el"))) 317 (error "Custom themes cannot be named `%s'" name))
137 (let ((inhibit-read-only t)) 318 ((string-match " " name)
138 (erase-buffer)) 319 (error "Custom theme names should not contain spaces"))
139 (insert "(deftheme " name) 320 ((if (file-exists-p filename)
140 (when doc 321 (not (y-or-n-p
141 (newline) 322 (format "File %s exists. Overwrite? " filename))))
142 (insert " \"" doc "\"")) 323 (error "Aborted")))
143 (insert ")\n") 324 (with-temp-buffer
144 (custom-theme-write-variables name variables) 325 (emacs-lisp-mode)
145 (custom-theme-write-faces name faces) 326 (unless (file-exists-p custom-theme-directory)
146 (insert "\n(provide-theme '" name ")\n") 327 (make-directory (file-name-as-directory custom-theme-directory) t))
147 (save-buffer))) 328 (setq buffer-file-name filename)
329 (erase-buffer)
330 (insert "(deftheme " name)
331 (if doc (insert "\n \"" doc "\""))
332 (insert ")\n")
333 (custom-theme-write-variables name vars)
334 (custom-theme-write-faces name faces)
335 (insert "\n(provide-theme '" name ")\n")
336 (save-buffer))
337 (dolist (var vars)
338 (widget-put (cdr var) :custom-state 'saved)
339 (custom-redraw-magic (cdr var)))
340 (dolist (face faces)
341 (widget-put (cdr face) :custom-state 'saved)
342 (custom-redraw-magic (cdr face)))))
148 343
149(defun custom-theme-write-variables (theme vars) 344(defun custom-theme-write-variables (theme vars)
150 "Write a `custom-theme-set-variables' command for THEME. 345 "Write a `custom-theme-set-variables' command for THEME.
151It includes all variables in list VARS." 346It includes all variables in list VARS."
152 ;; Most code is stolen from `custom-save-variables'.
153 (when vars 347 (when vars
154 (let ((standard-output (current-buffer))) 348 (let ((standard-output (current-buffer)))
155 (princ "\n(custom-theme-set-variables\n") 349 (princ "\n(custom-theme-set-variables\n")
156 (princ " '") 350 (princ " '")
157 (princ theme) 351 (princ theme)
158 (princ "\n") 352 (princ "\n")
159 (mapc (lambda (symbol) 353 (mapc (lambda (spec)
160 (when (boundp symbol) 354 (let* ((symbol (car spec))
161 (unless (bolp) 355 (child (car-safe (widget-get (cdr spec) :children)))
162 (princ "\n")) 356 (value (if child
163 (princ " '(") 357 (widget-value child)
164 (prin1 symbol) 358 ;; For hidden widgets, use the standard value
165 (princ " ") 359 (get symbol 'standard-value))))
166 (prin1 (custom-quote (symbol-value symbol))) 360 (when (boundp symbol)
167 (princ ")"))) 361 (unless (bolp)
168 vars) 362 (princ "\n"))
363 (princ " '(")
364 (prin1 symbol)
365 (princ " ")
366 (prin1 (custom-quote value))
367 (princ ")"))))
368 vars)
169 (if (bolp) 369 (if (bolp)
170 (princ " ")) 370 (princ " "))
171 (princ ")") 371 (princ ")")
@@ -181,18 +381,19 @@ It includes all faces in list FACES."
181 (princ " '") 381 (princ " '")
182 (princ theme) 382 (princ theme)
183 (princ "\n") 383 (princ "\n")
184 (mapc (lambda (symbol) 384 (mapc (lambda (spec)
185 (when (facep symbol) 385 (let* ((symbol (car spec))
186 (unless (bolp) 386 (child (car-safe (widget-get (cdr spec) :children)))
187 (princ "\n")) 387 (value (if child (widget-value child))))
188 (princ " '(") 388 (when (and (facep symbol) child)
189 (prin1 symbol) 389 (unless (bolp)
190 (princ " ") 390 (princ "\n"))
191 (prin1 (list (append '(t) 391 (princ " '(")
192 (custom-face-attributes-get 392 (prin1 symbol)
193 'font-lock-comment-face nil)))) 393 (princ " ")
194 (princ ")"))) 394 (prin1 value)
195 faces) 395 (princ ")"))))
396 faces)
196 (if (bolp) 397 (if (bolp)
197 (princ " ")) 398 (princ " "))
198 (princ ")") 399 (princ ")")