├── README.md └── lazy-load.el /README.md: -------------------------------------------------------------------------------- 1 | With the increasing number of plugins for Emacs, Emacs will get more and more slow. 2 | 3 | Emacs startup slow have two main reasons: 4 | 1. The threshold for garbage collection at load time is too small, which causes garbage collection to be triggered when the plugin is loaded, slowing down the startup speed. 5 | 2. By default, Emacs loads too many plugins, which wastes too much time to load the plugin when it starts. 6 | 7 | The solution to the first problem is as follows: 8 | 9 | ```elisp 10 | (let (;; temporarily increase `gc-cons-threshold' when loading to speed up startup. 11 | (gc-cons-threshold most-positive-fixnum) 12 | ;; Empty to avoid analyzing files when loading remote files. 13 | (file-name-handler-alist nil)) 14 | 15 | ;; Emacs configuration file content is written below. 16 | 17 | ) 18 | ``` 19 | 20 | For the purpose of the above code, temporarily set the value of gc-cons-threshold to the maximum before Emacs loads any plugins, to avoid triggering garbage collection when Emacs starts. 21 | After the Emacs configuration file is loaded, the variable gc-cons-threshold is automatically restored to the default value, avoiding Emacs taking up too much memory at runtime. 22 | 23 | As for the solution to the second problem, I will use the lazy-load.el plugin I wrote before. 24 | 25 | During the two years from 2007 to 2008, I almost played all the Emacs plug-ins at the time. When you load hundreds of plug-ins all by default, Emacs startup time can be extended from seconds to minutes. 26 | At that time, I was thinking about how to optimize the startup time of Emacs to the second, without reducing the use of any plug-ins. Finally, I developed the lazy-load.el plug-in. Even if I use the 300+ plug-in, the Emacs startup speed is still in one second. 27 | 28 | ### Principle 29 | 30 | The principle of lazy-load.el is simple: 31 | 1. Let's define our keymap first, and write the function corresponding to each key. 32 | 2. Tell the Emacs function the filename of the plugin so that when the function is called, Emacs knows where to load the plugin. 33 | 3. Emacs only loads very few plugins by default. After the loading is complete, Emacs will dynamically load the plugin and corresponding functions when we first press some key. 34 | 35 | Because 99% of Emacs plugins can be loaded in 1s when loaded separately, so 99% of the plugins are loaded at runtime. 36 | This greatly reduces the number of plug-ins that Emacs needs to load at startup, which ultimately improves Emacs startup time. 37 | 38 | 39 | ### installation method 40 | 1. Download lazy-load.el from [lazy-load](https://github.com/manateelazycat/lazy-load) to the ~/elisp directory 41 | 2. Add the following configuration to ~/.emacs 42 | 43 | ``` 44 | (add-to-list 'load-path (expand-file-name "~/elisp")) 45 | (require 'lazy-load) 46 | ``` 47 | 48 | ### Instructions 49 | The following code means that the first time you press Alt + g, Emacs goes to the load-path directory and finds the goto-line-preview.el file, loads the plugin and executes the goto-line-preview function. 50 | 51 | ```elisp 52 | (lazy-load-global-keys 53 | '(("M-g" . goto-line-preview)) 54 | "goto-line-preview") 55 | ``` 56 | 57 | The following code means that the first time you press Ctrl + c t in ruby ​​mode, Emacs goes to the load-path directory and finds the ruby-extension.el file, loads the plugin and executes ruby-hash-syntax-toggle function. 58 | 59 | ```elisp 60 | (lazy-load-local-keys 61 | '(("C-c t" . ruby-hash-syntax-toggle)) 62 | Ruby-mode-map 63 | "ruby-extension") 64 | ``` 65 | 66 | Many global keystroke are already occupied by Emacs by default. You must unload them before you can re-bind these global keystroke, such as Ctrl + x. The following code is to uninstall the default global keystroke with lazy-load-unset-keys: 67 | 68 | ```elisp 69 | (lazy-load-unset-keys '("C-x C-f" "C-z" "C-q" "s-W" "s-z" "M-h" "C-x C-c" "C-\\" "s-c" "s-x" "s-v")) 70 | ``` 71 | 72 | ### Advanced usage 73 | Sometimes, we will use a prefix keystroke to take different functions in one plugin. For example, the different functions of my sdcv.el plugin can use the Ctrl + z keystroke as the prefix key in the following code. 74 | Press Ctrl + z and press p to trigger the sdcv-search-pointer function. 75 | 76 | ```elisp 77 | (lazy-load-global-keys 78 | '(("p" . sdcv-search-pointer) 79 | ("y" . sdcv-search-pointer+) 80 | ("i" . sdcv-search-input) 81 | (";" . sdcv-search-input+)) 82 | "init-sdcv" 83 | "C-z") 84 | ``` 85 | 86 | The corresponding lazy-load-local-keys also supports the last parameter passing the prefix keystroke, but lazy-load-local-keys use local keymap, not global keymap. 87 | 88 | If Emacs loads a plugin by default, instead of dynamically loading it at runtime, you can also use the lazy-load-set-keys function to do a separate key binding operation, without having to manually write a line of repeated writes (define- Key keymap key) configuration 89 | 90 | ```elisp 91 | (lazy-load-set-keys 92 | '(("M-;" . comment-dwim-with-haskell-style)) 93 | Haskell-mode-map) 94 | ``` 95 | 96 | ### Example 97 | There are a lot of [examples](https://github.com/manateelazycat/lazycat-emacs/blob/master/site-lisp/config/init-key.el) of lazy-load usage 98 | -------------------------------------------------------------------------------- /lazy-load.el: -------------------------------------------------------------------------------- 1 | ;;; lazy-load.el --- Lazy load keys for speed ​​up Emacs startup. 2 | 3 | ;; Filename: lazy-load.el 4 | ;; Description: Lazy set keystroke. 5 | ;; Author: Andy Stewart 6 | ;; Maintainer: Andy Stewart 7 | ;; Copyright (C) 2009, Andy Stewart, all rights reserved. 8 | ;; Created: 2009-02-07 22:32:50 9 | ;; Version: 0.1 10 | ;; Last-Updated: 2009-02-07 22:32:50 11 | ;; By: Andy Stewart 12 | ;; URL: http://www.emacswiki.org/emacs/download/lazy-load.el 13 | ;; Keywords: 14 | ;; Compatibility: GNU Emacs 23.0.60.1 15 | ;; 16 | ;; Features that might be required by this library: 17 | ;; 18 | ;; 19 | ;; 20 | 21 | ;;; This file is NOT part of GNU Emacs 22 | 23 | ;;; License 24 | ;; 25 | ;; This program is free software; you can redistribute it and/or modify 26 | ;; it under the terms of the GNU General Public License as published by 27 | ;; the Free Software Foundation; either version 3, or (at your option) 28 | ;; any later version. 29 | 30 | ;; This program is distributed in the hope that it will be useful, 31 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 32 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 33 | ;; GNU General Public License for more details. 34 | 35 | ;; You should have received a copy of the GNU General Public License 36 | ;; along with this program; see the file COPYING. If not, write to 37 | ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth 38 | ;; Floor, Boston, MA 02110-1301, USA. 39 | 40 | ;;; Commentary: 41 | ;; 42 | ;; Lazy set keystroke. 43 | ;; 44 | 45 | ;;; Installation: 46 | ;; 47 | ;; Put lazy-load.el to your load-path. 48 | ;; The load-path is usually ~/elisp/. 49 | ;; It's set in your ~/.emacs like this: 50 | ;; (add-to-list 'load-path (expand-file-name "~/elisp")) 51 | ;; 52 | ;; And the following to your ~/.emacs startup file. 53 | ;; 54 | ;; (require 'lazy-load) 55 | ;; 56 | ;; No need more. 57 | 58 | ;;; Change log: 59 | ;; 60 | ;; 2019/05/05 61 | ;; * Refactory code. 62 | ;; 63 | ;; 2009/02/07 64 | ;; * First released. 65 | ;; 66 | 67 | ;;; Acknowledgements: 68 | ;; 69 | ;; 70 | ;; 71 | 72 | ;;; TODO 73 | ;; 74 | ;; 75 | ;; 76 | 77 | ;;; Require 78 | 79 | 80 | ;;; Code: 81 | 82 | (defun lazy-load-global-keys (key-alist filename &optional key-prefix) 83 | (lazy-load-set-keys key-alist nil key-prefix) 84 | (dolist (element key-alist) 85 | (setq fun (cdr element)) 86 | (autoload fun filename nil t))) 87 | 88 | (defun lazy-load-local-keys (key-alist keymap filename &optional key-prefix) 89 | (lazy-load-set-keys key-alist keymap key-prefix) 90 | (dolist (element key-alist) 91 | (setq fun (cdr element)) 92 | (autoload fun filename nil t))) 93 | 94 | (defun lazy-load-set-keys (key-alist &optional keymap key-prefix) 95 | "This function is to little type when define key binding. 96 | `KEYMAP' is a add keymap for some binding, default is `current-global-map'. 97 | `KEY-ALIST' is a alist contain main-key and command. 98 | `KEY-PREFIX' is a add prefix for some binding, default is nil." 99 | (let (key def) 100 | (or keymap (setq keymap (current-global-map))) 101 | (if key-prefix 102 | (setq key-prefix (concat key-prefix " ")) 103 | (setq key-prefix "")) 104 | (dolist (element key-alist) 105 | (setq key (car element)) 106 | (setq def (cdr element)) 107 | (cond ((stringp key) (setq key (read-kbd-macro (concat key-prefix key)))) 108 | ((vectorp key) nil) 109 | (t (signal 'wrong-type-argument (list 'array key)))) 110 | (define-key keymap key def)))) 111 | 112 | (defun lazy-load-unset-keys (key-list &optional keymap) 113 | "This function is to little type when unset key binding. 114 | `KEYMAP' is add keymap for some binding, default is `current-global-map' 115 | `KEY-LIST' is list contain key." 116 | (let (key) 117 | (or keymap (setq keymap (current-global-map))) 118 | (dolist (key key-list) 119 | (cond ((stringp key) (setq key (read-kbd-macro (concat key)))) 120 | ((vectorp key) nil) 121 | (t (signal 'wrong-type-argument (list 'array key)))) 122 | (define-key keymap key nil)))) 123 | 124 | (provide 'lazy-load) 125 | 126 | ;;; lazy-load.el ends here 127 | --------------------------------------------------------------------------------