From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Luc Teirlinck Newsgroups: gmane.emacs.devel Subject: Re: Custom themes Date: Mon, 27 Jun 2005 20:21:10 -0500 (CDT) Message-ID: <200506280121.j5S1LAT22689@raven.dms.auburn.edu> References: <200506250127.j5P1RWJ11778@raven.dms.auburn.edu> <200506250157.j5P1v5L11801@raven.dms.auburn.edu> <200506260319.j5Q3J5Q14922@raven.dms.auburn.edu> NNTP-Posting-Host: main.gmane.org X-Trace: sea.gmane.org 1119921885 32545 80.91.229.2 (28 Jun 2005 01:24:45 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Tue, 28 Jun 2005 01:24:45 +0000 (UTC) Cc: Seong-Kook Shin , abraham@dina.kvl.dk, emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue Jun 28 03:24:44 2005 Return-path: Original-Received: from lists.gnu.org ([199.232.76.165]) by ciao.gmane.org with esmtp (Exim 4.43) id 1Dn4p1-0001Kc-CG for ged-emacs-devel@m.gmane.org; Tue, 28 Jun 2005 03:23:31 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Dn4ur-0002NA-Fz for ged-emacs-devel@m.gmane.org; Mon, 27 Jun 2005 21:29:33 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Dn4uJ-00027W-Uf for emacs-devel@gnu.org; Mon, 27 Jun 2005 21:29:00 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Dn4uA-000220-Ke for emacs-devel@gnu.org; Mon, 27 Jun 2005 21:28:57 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Dn4u9-0001zv-Gg for emacs-devel@gnu.org; Mon, 27 Jun 2005 21:28:49 -0400 Original-Received: from [131.204.53.104] (helo=manatee.dms.auburn.edu) by monty-python.gnu.org with esmtp (Exim 4.34) id 1Dn4sz-0006g4-Sz; Mon, 27 Jun 2005 21:27:38 -0400 Original-Received: from raven.dms.auburn.edu (raven.dms.auburn.edu [131.204.53.29]) by manatee.dms.auburn.edu (8.12.10/8.12.10) with ESMTP id j5S1MsCK018811; Mon, 27 Jun 2005 20:22:54 -0500 (CDT) Original-Received: (from teirllm@localhost) by raven.dms.auburn.edu (8.11.7p1+Sun/8.11.7) id j5S1LAT22689; Mon, 27 Jun 2005 20:21:10 -0500 (CDT) X-Authentication-Warning: raven.dms.auburn.edu: teirllm set sender to teirllm@dms.auburn.edu using -f Original-To: rms@gnu.org In-reply-to: (rms@gnu.org) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:39706 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:39706 I took a somewhat more detailed look at the Custom Themes code. It definitely is unfinished work that is _not_ currently in progress. >>From looking at past threads, I believe that Alex Schroeder just gave up on it and decided that color-theme.el was the way to go. The problem with color-theme.el is that it bypasses Custom and creates variables which Custom considers rogue. I have the impression that the new etheme.el proposed by Seong-Kook Shin does the same. The patches below correct the five bugs I pointed out, as well as a sixth misfeature, namely the fact that Custom was not able to find the Custom Theme files in subdirectories of the user's home directory, unless the user explicitly added them to load-path. Custom themes without my patches are completely unusable, because there is not only no documentation, but also not a single interactive command to work with them. After my patches, which in addition to the bug fixes make two functions into interactive commands, Custom Themes are "kind of" usable, but not to a degree that they would be ready to be documented in the Emacs manual. Too many problems remain. I did provide all the docs in the buffers created by `M-x custom-create-theme': now it explains how to do create a Theme file in a way that, I believe, can be understood. The resulting Theme file explains how it is supposed to be used, in a way that, I hope, is understandable to somebody who did not create the file himself. You can interactively enable a theme and disable it again. It works. However, first example of a bug: if you then want to re-enable it using `M-x require-theme', it has no effect, although you can re-enable it by manually loading the Theme File. (This type of workaround works for most bugs). I know how to fix this bug, but I do not want to mess with the code _too_ much, because I am unsure about its exact intentions. Second bug. If you load Theme1 setting VAR from a standard value of 0 to 1, then load Theme2 setting it to 2 and then unload Theme2, the new value is 0. I believe that it should be 1. To restore Theme1's values (to obtain the result I believe should be obtained automatically by unloading Theme2), you have to again load the Theme1 theme file manually. There would be a lot less bugs if instead of using `require-theme' as the main interactive Theme enabling command, one would instead use a command that unconditionally loads the Theme file (the workaround to most bugs is to do exactly that). I did not implement that because that _definitely_ does not _seem_ to be the intended use of the code (I do not know _why_ the current code seems to insist on using the buggish `require-theme'). Minibuffer completion for `custom-do-theme-reset' will not work well unless a patch for minibuf.c that I will submit separately is applied. This is a bug in minibuf.c, it has nothing to do with Custom themes. I will discuss this separately. I do not have the time to do any more substantial work on this, but I believe that my patches, if installed, will at least help people to get started. Here are the patches. I can install if desired. ===File ~/custom.el-diff==================================== *** custom.el 13 Apr 2005 13:49:27 -0500 1.83 --- custom.el 27 Jun 2005 17:53:50 -0500 *************** *** 560,566 **** (t (condition-case nil (load load) (error nil)))))))) (defvar custom-known-themes '(user standard) ! "Themes that have been define with `deftheme'. The default value is the list (user standard). The theme `standard' contains the Emacs standard settings from the original Lisp files. The theme `user' contains all the the settings the user customized and saved. --- 560,566 ---- (t (condition-case nil (load load) (error nil)))))))) (defvar custom-known-themes '(user standard) ! "Themes that have been defined with `deftheme'. The default value is the list (user standard). The theme `standard' contains the Emacs standard settings from the original Lisp files. The theme `user' contains all the the settings the user customized and saved. *************** *** 926,931 **** --- 926,944 ---- (defvar custom-loaded-themes nil "Themes in the order they are loaded.") + (defcustom custom-theme-directory + (if (eq system-type 'ms-dos) + ;; MS-DOS cannot have initial dot. + "~/_emacs.d/" + "~/.emacs.d/") + "Directory in which Custom theme files should be written. + `require-theme' searches this directory in addition to load-path. + The command `customize-create-theme' writes the files it produces + into this directory." + :type 'string + :group 'customize + :version "22.1") + (defun custom-theme-loaded-p (theme) "Return non-nil when THEME has been loaded." (memq theme custom-loaded-themes)) *************** *** 949,956 **** by `custom-make-theme-feature'." ;; Note we do no check for validity of the theme here. ;; This allows to pull in themes by a file-name convention ! (require (or (get theme 'theme-feature) ! (custom-make-theme-feature theme)))) (defun custom-remove-theme (spec-alist theme) "Delete all elements from SPEC-ALIST whose car is THEME." --- 962,973 ---- by `custom-make-theme-feature'." ;; Note we do no check for validity of the theme here. ;; This allows to pull in themes by a file-name convention ! (interactive "SAdd theme: ") ! (let ((load-path (if (file-directory-p custom-theme-directory) ! (cons custom-theme-directory load-path) ! load-path))) ! (require (or (get theme 'theme-feature) ! (custom-make-theme-feature theme))))) (defun custom-remove-theme (spec-alist theme) "Delete all elements from SPEC-ALIST whose car is THEME." *************** *** 970,975 **** --- 987,994 ---- face is set to the `user' theme. See `custom-known-themes' for a list of known themes." + (interactive + (list (intern (completing-read "Theme to remove: " custom-known-themes)))) (let (spec-list) (mapatoms (lambda (symbol) ;; This works even if symbol is both a variable and a ============================================================ ===File ~/cus-theme.el-diff================================= *** cus-theme.el 17 Apr 2005 15:28:09 -0500 1.8 --- cus-theme.el 27 Jun 2005 18:56:42 -0500 *************** *** 31,36 **** --- 31,48 ---- (eval-when-compile (require 'wid-edit)) + (define-derived-mode custom-new-theme-mode nil "New-Theme" + "Major mode for the buffer created by `customize-create-theme'. + Do not call this mode function yourself. It is only meant for internal + use by `customize-create-theme'." + (set-keymap-parent custom-new-theme-mode-map widget-keymap)) + (put 'custom-new-theme-mode 'mode-class 'special) + + (defvar custom-theme-name) + (defvar custom-theme-variables) + (defvar custom-theme-faces) + (defvar custom-theme-description) + ;;;###autoload (defun customize-create-theme () "Create a custom theme." *************** *** 38,52 **** (if (get-buffer "*New Custom Theme*") (kill-buffer "*New Custom Theme*")) (switch-to-buffer "*New Custom Theme*") ! (kill-all-local-variables) (make-local-variable 'custom-theme-name) (make-local-variable 'custom-theme-variables) (make-local-variable 'custom-theme-faces) (make-local-variable 'custom-theme-description) - (let ((inhibit-read-only t)) - (erase-buffer)) (widget-insert "This buffer helps you write a custom theme elisp file. ! This will help you share your customizations with other people.\n\n") (widget-insert "Theme name: ") (setq custom-theme-name (widget-create 'editable-field --- 50,72 ---- (if (get-buffer "*New Custom Theme*") (kill-buffer "*New Custom Theme*")) (switch-to-buffer "*New Custom Theme*") ! (let ((inhibit-read-only t)) ! (erase-buffer)) ! (custom-new-theme-mode) (make-local-variable 'custom-theme-name) (make-local-variable 'custom-theme-variables) (make-local-variable 'custom-theme-faces) (make-local-variable 'custom-theme-description) (widget-insert "This buffer helps you write a custom theme elisp file. ! This will help you share your customizations with other people. ! ! Just insert the names of all variables and faces you want the theme ! to include. Then clicking mouse-2 or pressing RET on the [Done] button ! will write a theme file that sets all these variables and faces to their ! current values. It will write that file into the directory given by the ! variable `custom-theme-directory', usually \"~/.emacs.d/\". ! ! To undo all your edits to the buffer, use the [Reset] button.\n\n") (widget-insert "Theme name: ") (setq custom-theme-name (widget-create 'editable-field *************** *** 81,87 **** (bury-buffer)) "Bury Buffer") (widget-insert "\n") - (use-local-map widget-keymap) (widget-setup)) (defun custom-theme-write (&rest ignore) --- 101,106 ---- *************** *** 90,98 **** --- 109,144 ---- (variables (widget-value custom-theme-variables)) (faces (widget-value custom-theme-faces))) (switch-to-buffer (concat name "-theme.el")) + (emacs-lisp-mode) + (unless (file-exists-p custom-theme-directory) + (make-directory (file-name-as-directory custom-theme-directory) t)) + (setq default-directory custom-theme-directory) (setq buffer-file-name (expand-file-name (concat name "-theme.el"))) (let ((inhibit-read-only t)) (erase-buffer)) + (insert (format ";; This file is the Custom theme file for the theme %s. + + ;; If enabled, it sets the variables and faces listed below to the given + ;; values. To enable it, type `M-x require-theme RET %s'. + ;; To reset all variables and faces back to their prior values, type + ;; `M-x custom-do-theme-reset RET %s'. + + ;; You can also write `(require-theme %s)' in your .emacs file. + ;; If you do that before the `custom-set-variables' and `custom-set-faces' + ;; forms, any values explicitly given in these forms take precedence. + ;; If you write it after these forms, the theme takes precedence. + + ;; For the above to work, this file should be in a directory in `load-path', + ;; or in the directory given by `custom-theme-directory' (usually + ;; \"~/.emacs.d/\"), which is the directory in which `custom-theme-create' + ;; writes the theme files it produces. + + ;; *Please note*: this feature is experimental and needs more work. + ;; In Emacs 22, it does not work very well, unless you do only very + ;; basic things. It is expected to work better in future Emacs versions. + ;; In situations where `require-theme' does not seem to work, you can + ;; just directly load this theme file to get the intended results.\n\n" + name name name name name)) (insert "(deftheme " name) (when doc (newline) *************** *** 100,106 **** (insert ")\n") (custom-theme-write-variables name variables) (custom-theme-write-faces name faces) ! (insert "\n(provide-theme '" name ")\n"))) (defun custom-theme-write-variables (theme vars) "Write a `custom-theme-set-variables' command for THEME. --- 146,153 ---- (insert ")\n") (custom-theme-write-variables name variables) (custom-theme-write-faces name faces) ! (insert "\n(provide-theme '" name ")\n") ! (save-buffer))) (defun custom-theme-write-variables (theme vars) "Write a `custom-theme-set-variables' command for THEME. ============================================================