So you’ve implemented your major mode my-mode in Emacs. Congratulations! You can now do the following three things to start your mode in a buffer:
- M-x my-mode to manually start your major mode.
- Add
(add-to-list 'auto-mode-alist '("\\.suffix" . my-mode))
to the file containing your major mode definition. Emacs opens the file of suffix suffix and automatically loads up your major mode. - M-x my-minor-mode to manually start a minor mode if you have a minor mode.
Everything works locally and you list your major mode in elpa package index. However, you install your package, expect Emacs to autoload it without writing any configuration, but only to find out that Emacs doesn’t load your major mode when you open files with suffix. Emacs doesn’t even see any functions defined by your major mode!
You need to either
- Ask your users to write require to load the whole major mode, or
- Write autoload yourself to properly configure your major mode.
The Problem of require
Why not require? The require evaluates the entire file that defines your major mode. Is it really necessary? No! All your users need is
- A manual way (i.e. M-x) to find your mode and auxiliary functions.
- That your mode starts itself when file name matches some regex.
Emacs just need identifiers to achieve 1, and a proper auto-mode-alist to achieve 2. No Need to evaluate the entire code base.
Autoload
A full-fledged Emacs configuration usually installs tens of hundreds of major modes. Emacs doesn’t load everything at start-up; modern major mode files are configured to load only when users need them.
If they are not loaded, how does Emacs know which functions are available and where to look for them? The feature is called autoload, where function names are generated on the side initially via calling autoload or a magic comment ;;;###autoload. Loading those pre-loaded function names are way faster, and the first time of using the function names will load their actual definitions.
To see the generated names, list your package directory under .emacs.d/elpa-x.x/your-package, you’ll see the package manager automatically generates some files on the side during installation. Take pollen-mode as an example. The following files are auto-generated:
pollen-mode-autoloads.el
pollen-mode-pkg.el
pollen-mode.elc
The interesting one is the -autoloads file, where the code
- inserts the package directory to load-path.
- inserts autoload calls to functions you’ve marked ;;;###autoload.
;;; pollen-mode-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name
(or (file-name-directory #$) (car load-path))))
...
(autoload 'pollen-minor-mode "pollen-mode" ...)
(autoload 'pollen-mode "pollen-mode" ...)
...
Emacs doesn’t load pollen-mode.elc when it starts. Instead it loads pollen-mode-autoloads.el, which is extremely small, contains only a few s-exp. Emacs loads pollen-mode.elc only if pollen-mode or pollen-minor-mode is called.
No require Needed After Autoload
pollen-mode users used to need to explicitly call (require ‘pollen-mode), which evaluates the whole pollen-mode code.
Now with autoload, pollen-mode users don’t need to write require anymore. After Emacs installs the package, it generates pollen-mode-autoloads.el, and only those function names are loaded at start-up, so pollen users don’t lose anything whatsoever with speed gain.
Note that you, the mode writer, have to mark these functions explicitly with ;;;###autoload. See Emacs user manual Autoload.
Don’t Forget Autoload Code for auto-mode-alist
What’s more important is that you should also mark auto-mode-alist for autoload so that the global auto-mode-alist contains the mode mapping as soon as your mode is installed via the package manager. What pollen-mode does is to add ;;;###autoload in front of the add-to-list calls:
;;;; Bind pollen mode with file suffix
;;;###autoload
(progn
(add-to-list 'auto-mode-alist '("\\.pm$" . pollen-mode))
(add-to-list 'auto-mode-alist '("\\.pmd$" . pollen-mode))
(add-to-list 'auto-mode-alist '("\\.pp$" pollen-mode t))
(add-to-list 'auto-mode-alist '("\\.p$" pollen-mode t)))
Mark add-to-list autoload in pollen-mode.el.
The generated pollen-mode-autoloads.el now contains these expressions.
;;; pollen-mode-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name
(or (file-name-directory #$) (car load-path))))
...
(autoload 'pollen-minor-mode "pollen-mode" ...)
(autoload 'pollen-mode "pollen-mode" ...)
(add-to-list 'auto-mode-alist '("\\.pm$" . pollen-mode))
(add-to-list 'auto-mode-alist '("\\.pmd$" . pollen-mode))
(add-to-list 'auto-mode-alist '("\\.pp$" pollen-mode t))
(add-to-list 'auto-mode-alist '("\\.p$" pollen-mode t))
...
Auto generated pollen-mode-autoloads.el contains mode mapping.
After learning how autoload works, autoload has been always my preferred way for configuring my major mode. What about you? Anything I am missing?