Subject: bug#11106: 24.0.94; enhancement request: have autoload treat faces like it does options

From: "Drew Adams" <[email-masked]>
Date: Wed, 28 Mar 2012 06:39:39 -0700

> > 1. Handle faces (deffaces) similarly to how options 
> > (defcustoms) are handled.
> 
> I don't know what that means.

For #1: Make an autoload cookie before a defface do something analogous to what
it does before a defcustom.  I'm no expert on the latter, so yes, this is vague.
IIUC, an autoload cookie handles an option definition by setting the option
value at autoload time, but it does not simply copy the defcustom to the
autoloads file.

> > 2. Have function `autoload' handle both faces and options 
> >    via its TYPE arg.
> 
> Can you provide a sample scenario where that would be useful?

#2 is more important, to me, and is not directly related to #1.

Maybe this scenario will help, maybe not.  (I'm using default "value" of a face
as shorthand for the value of the second arg, SPEC, to defface.)

In the same file, have two deffaces, f1 and f2, in that order.

Suppose that the sexp defining the default value of f2 depends on the value of
f1 and on the availability of function foo.  If foo is not available then f2's
default value uses constants in the SPEC sexp.  If foo is available, then foo is
invoked with f1 as an arg, to come up with f2's default value.

Assume you want to provide autoloading for the faces, to let users get to their
doc.

For that, you add an autoload cookie before each defface.  But that means that
the SPECs get eval'd at autoloads-file generation time, not when the library is
loaded.

What's more, because you want to make foo available if its defining library is
in the user's load-path, you add a soft require: (require 'foolib nil t).  And
since foo would also need to be available at autoloads-generation time, you add
an autoload cookie for that soft require as well.

But one reason for having f2 use f1's (possibly customized) value in its own
SPEC was to let a user customize f1 and have the default value of f2 be based on
that.  At any time, the user should be able to customize f1, restart Emacs and
have f2's value reflect that customization.

(And no, this is not something that can be done in general using face
inheritance.  Assume that in this case function foo does something interesting,
using f1's value as input.)

But if the autoloads file is generated before the user customizes f1 then the
customized f1 value is not used to compute f2.

The dependencies and openness to customization get defeated by the fact that f1
and f2 become fully defined at autoloads generation time (i.e., when the
autoloads file is created).

In addition, foo's library needs to be loaded both when the autoloads file is
generated and when the file with the deffaces is loaded.

Things are a lot more complicated than they should need to be: the logic of
dependencies is carried over (duplicated) from library load time into autoloads
generation time, and some functionality (e.g. customization relationships) is
lost.

The enhancement request (#2) would let you use an autoload cookie with an
explicit `autoload' call for an option or face, on the same line, just as for a
command:

;;;###autoload (autoload 'f2 "file" nil 'face)

At autoload-file generation time, only the `(autoload...)' sexp would be written
to the autoloads file.  And function `autoload' would DTRT, meaning that it
would cause file `file.el[c]' to be loaded whenever face f2 is needed and not
yet defined.

That way, the face itself would not be defined completely at autoload time, but
only when its defining file is loaded.  The autoloads file would only put in
place the autoloading of f2's file; it would not also predefine the face.

Similarly for user options (defcustoms):

;;;###autoload (autoload 'opt1 "optsfile" nil 'option)

That would not set the option value.  It would only set up autoloading for the
option, so that when it is needed and is not yet defined, its defining file,
optsfile.el[c], would be loaded.

This way, the doc for options and faces could be made available to users, and
customization and loading of their definitions would involve only the logic in
their defining files, not also some things happening at autoloads generation
time and possibly getting in the way.

In sum, the idea would be to have function `autoload' become face-aware and
option-aware.  IOW, be able (using function `autoload' with an autoload cookie)
to separate autoloading _per se_ from predefining.

That is essentially what autoloading of functions does.  It does not predefine a
function completely.  It just "defines" it partially using a placeholder, and it
puts in place a mechanism to automatically load its file, which load actually
defines the function fully.  The aim here would be to provide that same feature
(real autoloading) for options and faces.

Autoloading of functions (e.g. commands) does what autoloading was designed to
do: make sure loading takes place automatically if the function is needed but
not yet defined.

IIUC, autoloading of anything other than a function does not do what autoloading
was designed to do.  An autoload cookie simply copies the defining sexp to the
autoloads file, essentially defining it at the time that file is generated.  And
function `autoload' does nothing for a non-function (a keymap being handled as a
function) - it is not option-aware or face-aware.

Dunno whether I'm clear enough.  And again, some lack of clarity is no doubt due
to my insufficient understanding of the autoload code.  Feel free to point out
stuff that I'm missing.  Thx.