Subject: RE: bug#15687: 24.3.50; custom themes: disabling does not restore initial configuration

From: Drew Adams <[email-masked]>
Date: Tue, 26 Nov 2013 06:05:21 -0800 (PST)

> > You enable a custom theme.  Then you disable it.  The settings remain
> > those of the "disabled" custom theme.  Your initial state is not
> > restored.
> 
> I tried
> 
>    emacs -Q
>    M-x custom-themes RET
>    RET on the first theme to enable it
>    RET again to disable it
> 
> and the settings were apparently properly reset.  Do you have a recipe
> that triggers the problem?

You skipped the first part:

 You start out with Emacs in your preferred customized state, a
 result perhaps of multiple option settings, frame parameter settings,
 face settings, etc.  For example, you have used `default-frame-alist'
 and customized some particular faces.  No custom theme (except `user')
 has been applied.

A demonstration that disabling a custom-theme can put you back to the
emacs -Q state is not too surprising.  What's missing is the ability
to put you back to anything close to the pre-theme state (i.e., as
much as possible), whatever that customized state might have been.

Of course, that state is not *automatically* recorded anywhere.
What's really missing, AFAICT, is the ability to take a snapshot of
the state, which can then be restored at any time.  As the bug says:

 AFAICT, there is no equivalent of such a snapshot with custom
 themes, and it's not clear how to create one.  But please prove me
 wrong.

 In particular, all of the custom-theme code requires a theme
 argument, which must be defined fully, including actually having been
 written to a theme file.  Hardly something that facilitates dynamic
 state recording and reverting.

See the full description of the bug.  And see the treatment in
color-theme.el (not my library, BTW).  There, you can take such a
snapshot at any time.  And it serves, in effect, more or less as a
theme (a pseudo theme).

As the bug report says:

 However, I do not see, for custom themes, what is an
 important feature of `color-theme.el': the ability to take a snapshot
 of the current settings (independent of how they were set, whether
 via themes or not) as something that can function as a (pseudo)theme.

Compare these commands, which cycle among themes:

1. In doremi-cmd.el: `doremi-custom-themes+' vs `doremi-color-themes+'.
2. In icicles-cmd1.el: `icicle-custom-theme' vs `icicle-color-theme'.

>From the doc string of `icicle-color-theme', this part about undoing:

 If you use `C-g' during this command, the previous color-theme
 snapshot is used to restore that color theme.

 Remember too that you can use the pseudo-theme [Reset] to restore the
 last theme: `M-x color-theme-select [Reset]'.

 By default, each time you invoke this command, a snapshot is first
 made of the current color theme (or current colors, if no theme is
 used).  Thus, by default, if you use `C-g', the colors restored are
 those used before you changed themes using this command.

 However, if you use a prefix arg, then this command takes no new
 snapshot, unless no snapshot has ever been taken during this Emacs
 session.  This can be useful when experimenting, to restore not to
 the state just before this command invocation, but to some previous
 snapshot.

That part about the pseudo-them [Reset] is straight color-theme.el.
It has nothing to do with Icicles.  See color-theme.el for info
about such a snapshot.

>From the doc string of `icicle-custom-theme', by contrast:

 You can use `C-g' to quit and cancel changes by the command.  Note,
 however, that some things might not be restored.  `C-g' can only
 disable any themes that you applied.  It cannot restore other
 customizations that enabling a theme might have overruled.  This is
 a limitation of Emacs custom themes: you can disable them, but you
 cannot restore non-theme settings in effect before enabling a theme.
 Color themes (and command `icicle-color-theme') do not have this
 limitation.

>From the doc string of `doremi-color-themes+':

 You can use `C-g' to quit and cancel changes made so far.
 Alternatively, after using `doremi-color-themes+' you can use
 `color-theme-select' and choose pseudo-theme `[Reset]' - that does
 the same thing.  Note that in either case, some things might not
 be restored.

>From the doc string of `doremi-custom-themes+':

 You can use `C-g' to quit and cancel changes made so far.  Note,
 however, that some things might not be restored.  `C-g' can only
 disable any themes that you applied.  It cannot restore other
 customizations that enabling a theme might have overruled.

----

An additional problem with custom themes, compared with color
themes, is that when multiple frames are present things become
extremely slow (maybe exponentially wrt the number of frames?
dunno).

This alone makes cycling among custom themes almost unusable
when there are multiple frames.

And this is the case even when, as is done for these cycling
commands, accumulation of custom themes is turned off.  If, on
the other hand, accumulation is allowed (the normal case for
custom themes), then things really grind to a halt.

A guess would be that this might be because custom themes record
more information than color themes.  But why this would make such
a difference, and why it might be related to the number of frames
in such a marked way, I have no idea.

If you want to see the difference, just try, say,
`doremi-custom-themes+' compared with `doremi-color-themes+',
with several frames open.  You need only the files doremi.el and
doremi-cmd.el to try that.  Both are on MELPA and on Emacs Wiki
(as are the Icicles files).