2

I maintain an Elisp package that is split over many files, and each of the files has its own group of defcustoms in it, as a subgroup of the main package name.

I am unsure of how to make these defcustoms available before the specific file has been fully loaded. At the moment, the parent Elisp file contains a stack of autoloads for the functions it draws in from the rest of the package's files (for its entry points), but I'm unsure how to achieve the equivalent for the user options.

Specifically, I have an option that I would like to use to determine whether a function should run in the mode's hook, which runs on entering the mode. But it is from a file that would possibly only be loaded much later on.

It would also seem to me to make good sense to make all options visible from the outset, rather than hiding them from users until a particular functionality in the package has been used.

Are my only choices to use defcustom in the main file (breaking the package's distribution into files based on its different aspects) or to require the child file in the main file?

I have also seen defvar used first in the child file then a second time, now without an init value or docstring, in the parent file, but i'm unclear if that is effective or not. (I think it's done to placate flycheck.)

Drew
  • 75,699
  • 9
  • 109
  • 225
user27075
  • 488
  • 3
  • 11

1 Answers1

4

You can just add an autoload cookie before the defcustom:

;;;###autoload
(defcustom diredp-dwim-any-frame-flag pop-up-frames
  "Non-nil means the target directory can be in a window in another frame.
Only visible frames are considered.
This is used by `dired-dwim-target-directory'."
  :type 'boolean :group 'Dired-Plus)

Note, however, that some people advise against autoloading defcustoms.

So think about whether you really want to do that, and why. Will other libraries expect that it's autoloaded, and do they need to expect that?

IMO there are legitimate uses for such autoloading. And I do it myself, in some of my code. But be aware that some people, including Stefan Monnier, generally advise against it.

You say:

It would also seem to me to make good sense to make all options visible from the outset, rather than hiding them from users until a particular functionality in the package has been used.

And yes, that's the use case for autoloading defcustoms: make users aware of them, and provide access to their doc, before the library gets loaded.


You can do the same thing for any Lisp expression, to ensure that it gets autoloaded.

See the Elisp manual, node Autoload. It says this, for example:

The form following the magic comment is copied verbatim, except if it is one of the forms which the autoload facility handles specially (e.g., by conversion into an autoload call). The forms which are not copied verbatim are the following:

(It then lists things like defun and... defcustom as things that don't get copied verbatim.)


Finally, you say this:

I have also seen defvar used first in the child file then a second time, now without an init value or docstring, in the parent file, but i'm unclear if that is effective or not. (I think it's done to placate flycheck.)

Such a "vacuous" defvar, i.e., one that has no init value, proclaims the variable to be dynamically bound, aka "special" -- in particular to the byte-compiler. This prevents byte-compiler warnings that the variable was possibly unbound in some context.

Drew
  • 75,699
  • 9
  • 109
  • 225
  • thanks for the clarification. (i've read your prev posts on autoloads, but still wasn't sure that autoloads were my issue here.) but is there something further i need to do for them to be taken up? my mode hook still complains about a void variable, and my customize groups do not appear. i tried `update-directory-autoloads` and byte-compiling the package to no avail. – user27075 Feb 03 '22 at 08:19
  • You of course need to *load the file that contains the autoloads* (e.g. those produced by `update-directory-autoloads`). – Drew Feb 03 '22 at 16:48
  • thanks drew. my confusion was due to how `package.el` automatically sorts out autoloads. when not dealing with something installed by it, it seems you have to generate and also load the autoloads file manually. – user27075 Feb 05 '22 at 11:44
  • Yes, that's the case. – Drew Feb 05 '22 at 18:25