16

I am upgrading to emacs23. I find that my emacs.el loads much more slowly.

It's my own fault really... I have a lot of stuff in there.

So I am also trying to autoload everything possible that is currently "required" by my emacs.el.

I have a module that exposes 12 entry points - interactive functions I can call.

Is the correct approach to have 12 calls to autoload in order to insure that the module is loaded regardless of which function I call? Are there any problems with this approach? Will it present performance issues?

If not that approach, then what?

Cheeso
  • 189,189
  • 101
  • 473
  • 713
  • 1
    Manually adding `autoloads` to your .emacs is icky, you have to constantly update your .emacs, and when packages change interfaces then you're having to *fix* your .emacs for no good reason. – Trey Jackson Nov 15 '10 at 23:14

3 Answers3

22

What you really want is to get the autoloads generated for you automatically, so that your .emacs file remains pristine. Most packages have the ;;;###autoload lines in them already, and if not, you can easily add them.

To manage this, you can put all the packages in a directory, say ~/emacs/lisp, and in there have a file named update-auto-loads.el which contains:

;; put this path into the load-path automatically
;;;###autoload
(progn
  (setq load-path (cons (file-name-directory load-file-name) load-path)))

;;;###autoload
(defun update-autoloads-in-package-area (&optional file)
  "Update autoloads for files in the diretory containing this file."
  (interactive)
  (let ((base (file-truename
       (file-name-directory
        (symbol-file 'update-autoloads-in-package-area 'defun)))))
(require 'autoload)         ;ironic, i know
(let ((generated-autoload-file (concat base "loaddefs.el")))
  (when (not (file-exists-p generated-autoload-file))
    (with-current-buffer (find-file-noselect generated-autoload-file)
      (insert ";;") ;; create the file with non-zero size to appease autoload
      (save-buffer)))
  (cd base)
  (if file
      (update-file-autoloads file)
    (update-autoloads-from-directories base)))))

;;;###autoload
(defun update-autoloads-for-file-in-package-area (file)
  (interactive "f")
  (update-autoloads-in-package-area file))

If you add 'update-autoloads-in-package-area to your kill-emacs-hook, then the loaddefs.el will automatically be updated every time you exit Emacs.

And, to tie it all together, add this to your .emacs:

(load-file "~/emacs/lisp/loaddefs.el")

Now, when you download a new package, just save it in the ~/emacs/lisp directory, update the loaddefs via M-x update-autoloads-in-package-area (or exit emacs), and it'll be available the next time you run Emacs. No more changes to your .emacs to load things.

See this question for other alternatives to speeding up Emacs startup: How can I make Emacs start-up faster?

Community
  • 1
  • 1
Trey Jackson
  • 73,529
  • 11
  • 197
  • 229
  • @SamB What do you mean, this web page (the answer) isn't getting the syntax colors properly? Or the code is getting highlighted in Emacs incorrectly (indicating a possible syntax error)? Or... – Trey Jackson Nov 18 '10 at 22:10
  • @Trey: this page. Unfortunately there [doesn't seem to be](http://meta.stackexchange.com/questions/981/syntax-highlighting-hints) a way to specify what language the code is in, but it could at least be stuck inside of a `
    '
    – SamB Nov 20 '10 at 21:53
  • @SamB Gotcha, yah, the coloring for lisp on SO blows, but I guess I've gotten used to it. – Trey Jackson Nov 21 '10 at 02:21
  • 1
    Hmm, you know, this would be nicer if it could be used with more than one directory. Then I could use it for both my `grail-dist-elisp` and `grail-local-elisp` dirs. (Not that I have anything in the latter in the Emacs profile I'm trying this in at the moment, but if I did I might want to autoload it...) – SamB Jan 05 '11 at 20:09
  • 1
    @SamB You can generalize that routine if you want, just add a loop around the outer `let` statement and set it up so that `base` is set to the various directories. Also, it sounds like you'll want to have it go to a common `loaddefs.el` file, which means pulling that out of the entire loop (and figuring out where you want it). – Trey Jackson Jan 05 '11 at 21:33
4

Well, who cares how slowly it starts?

Fire it up via emacs --daemon & and then connect using either one of

  • emacsclient -c /some/file.ext, or
  • emacsclient -nw

I created aliases for both these as emx and emt, respectively. Continuing once editing session is so much saner...

ocodo
  • 29,401
  • 18
  • 105
  • 117
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • always a good idea to use the `-a` option to start the `emacs --daemon` if it's not already running. – ocodo Dec 11 '10 at 12:36
  • With emacs23 on Linux, `emacs --help` for me does not show a `-a` option. What is it supposed to do? – Dirk Eddelbuettel Dec 11 '10 at 13:40
  • It will automatically start emacs server if its not running. See emacsclient --help. – Matti Pastell Jan 09 '11 at 20:10
  • Ack, thanks. In that Slomojo was of course correct. I tend to start `emacs --daemon` first though so it is a bit of a non-issue for me. Also, should the daemon die, it is nice to know that. With `-a` you silently start a fresh one. – Dirk Eddelbuettel Jan 09 '11 at 20:11
4

Ideally you shouldn't have any load or require in your .emacs file.

You should be using autoload instead...

e.g.

(autoload 'slime-selector "slime" t)

You will need to use eval-after-load to do any library specific config, but the upshot is that you won't need to wait for all this to load up front, or cause errors on versions of Emacs that don't have the same functionality. (e.g. Terminal based, or a different platform etc.)

While this may not affect you right now, chances are, in future you will want to use the same config on all machines / environments where you use Emacs, so it's a very good thing to have your config ready to fly.

Also use (start-server) and open external files into Emacs using emacsclient - So you avoid restarting Emacs.

ocodo
  • 29,401
  • 18
  • 105
  • 117