My ~/.emacs.d/init.el file looks like this:


(require 'init-my-emacs-settings)
(require 'init-my-emacs-performance)
(require 'init-my-emacs-font)
(require 'init-my-emacs-color-theme)
(require 'init-my-emacs-appearance)

(require 'init-my-tool-calendar)
(require 'init-my-tool-dictionary)
(require 'init-my-tool-clock)
(require 'init-my-tool-speak)

(require 'init-my-prog-programming)
(require 'init-my-prog-license)
(require 'init-my-prog-code)
(require 'init-my-prog-comment)

;;; Programming Languages
(require 'init-my-prog-lang-lisp)
(require 'init-my-prog-lang-emacs-lisp)
(require 'init-my-prog-lang-common-lisp)
(require 'init-my-prog-lang-clojure)
(require 'init-my-prog-lang-ruby)
(require 'init-my-prog-lang-python)

I hope to load them only when needed. If for init files like init-my-emacs-settings can’t be lazy load. Then I hope lazy load for programming languages init files like init-my-prog-lang-lisp.

Here is my simple idea to load programming language init files only when load major-mode hook.

;;; TODO: convert code into an macro.

(defvar init-my-prog-lang-lisp-loaded nil)
(add-hook 'lisp-mode-hook
          (lambda ()
            (unless init-my-prog-lang-lisp-loaded
              (require 'init-my-prog-lang-lisp)
              (setq init-my-prog-lang-lisp-loaded t))

(defun symbol-concat (symbol string)
  (intern (concat (symbol-name symbol) string)))

;; (type-of (symbol-concat 'ruby-mode-hook "-p"))

(defmacro my-lazy-load-init-file (init-file mode)
  "Lazy load my `INIT-FILE' only when `MODE' loaded."
  (let ((state (symbol-concat init-file "-loaded")))
    ;; state variable
    (defvar state nil)
    ;; load on major-mode hook
    (add-hook (symbol-concat mode "-hook")
              (lambda ()
                (unless state
                  (require init-file)
                  (setq state t)

My questions: - how to improve this macro? - Do you have better solution? If have, please show me. Thanks

  • 2
    C-h i g (elisp) Autoload and also (elisp) Hooks for Loading. Using mode hooks is sometimes appropriate, too. – phils Oct 18 '16 at 3:06
  • 2
    btw, require is very fast and its entire purpose is to load things only when they are not already loaded. Wrapping a lisp conditional around a call to require is pointless. – phils Oct 18 '16 at 3:17
  • I see, thanks, I will check out those elisp info sections. – stardiviner Oct 18 '16 at 3:19
  • See also emacs.stackexchange.com/questions/2286/… – npostavs Oct 19 '16 at 11:37

Consider using John Wiegley's use-package if you really care about startup time that much. use-package provides built-in support for lazy/deferred loading.

Better yet, don't constantly restart your Emacs. The best way to avoid constantly restarting is to run an Emacs daemon; then you can create as many frames (both GUI and terminal) as you like that will all start instantly and, as an added benefit, share buffers, history, etc. because they're clients.

I use MJ Wall's scripts to easily start/stop the Emacs daemon, launch clients, etc. from the command line. I also set ec (described in the article) as a startup application so I never even notice the Emacs startup time, since it's part of the OS startup.

  • I use use-package, but don't know :defer. I add it now. And I use Emacs daemon before, but it has issue that color-theme not applied. Do you have this issue with your solution? – stardiviner Oct 20 '16 at 2:55
  • My theme is applied just fine. Have you tried starting Emacs with the emacs --debug-init command to see if there are any errors? – Tianxiang Xiong Oct 20 '16 at 3:40

I'd recommend two things to speedup startup:

  • Merge your many init files into a single large file.
  • Look at the content of your init files and try to make sure that they don't require or load but instead, they should just use setq, add-hook, and eval-after-load.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.