aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/USE-PACKAGE-NEWS26
-rw-r--r--lisp/use-package/use-package-bind-key.el25
-rw-r--r--lisp/use-package/use-package-core.el160
-rw-r--r--test/lisp/use-package/use-package-tests.el79
4 files changed, 181 insertions, 109 deletions
diff --git a/etc/USE-PACKAGE-NEWS b/etc/USE-PACKAGE-NEWS
index 76556be9b2e..c34376d3ffe 100644
--- a/etc/USE-PACKAGE-NEWS
+++ b/etc/USE-PACKAGE-NEWS
@@ -30,10 +30,6 @@
30 parameter, but are now done as an extension to `rest`. Please see 30 parameter, but are now done as an extension to `rest`. Please see
31 `use-package-handler/:bind` for a canonical example. 31 `use-package-handler/:bind` for a canonical example.
32 32
33- For extension authors, if you add a keyword to `use-package-keywords` whose
34 presence should indicate deferred loading, please also add it to
35 `use-package-deferring-keywords`.
36
37### Other changes 33### Other changes
38 34
39- Upgrade license to GPL 3. 35- Upgrade license to GPL 3.
@@ -154,6 +150,28 @@
154 it is loaded, `helm-descbinds` itself is not loaded until the user presses 150 it is loaded, `helm-descbinds` itself is not loaded until the user presses
155 `C-h b`. 151 `C-h b`.
156 152
153- For extension authors, if you add a keyword to `use-package-keywords` whose
154 presence should indicate deferred loading, please also add it to
155 `use-package-deferring-keywords`. Note that this is a bit of a sledgehammer,
156 in that the mere presence of these keywords implies deferred loading. For a
157 more subtle approach, see the new `use-package-autoloads/<KEYWORD>` support
158 mentioned in the next bullet.
159
160- For extension authors, if you wish deferred loading to possibly occur,
161 create functions named `use-package-autoloads/<KEYWORD>` for each keyword
162 that you define, returning an alist of the form `(SYMBOL . TYPE)` of symbols
163 to be autoloaded. `SYMBOL` should be an interactive function, and `TYPE` the
164 smybol `command`, but this functionality may be extended in future. These
165 autoloads are established if deferred loading is to happen.
166
167- If you specify a lambda form rather than a function symbol in any of the
168 constructs that *might* introduce autoloads: `:bind`, `:bind*`,
169 `:interpreter`, `:mode`, `:magic`, `:magic-fallback`, and `:hook`: then
170 deferred loading will no longer be implied, since there's nothing to
171 associate an autoload with that could later load the module. In these cases,
172 it will be as if you'd specified `:demand t`, in order to ensure the lambda
173 form is able to execute in the context of the loaded package.
174
157- For extension authors, there is a new customization variable 175- For extension authors, there is a new customization variable
158 `use-package-merge-key-alist` that specifies how values passed to multiple 176 `use-package-merge-key-alist` that specifies how values passed to multiple
159 occurences of the same key should be merged into a single value, during 177 occurences of the same key should be merged into a single value, during
diff --git a/lisp/use-package/use-package-bind-key.el b/lisp/use-package/use-package-bind-key.el
index 4a3d421522b..6a8e3fbe8eb 100644
--- a/lisp/use-package/use-package-bind-key.el
+++ b/lisp/use-package/use-package-bind-key.el
@@ -114,20 +114,23 @@ deferred until the prefix key sequence is pressed."
114;;;###autoload 114;;;###autoload
115(defalias 'use-package-normalize/:bind* 'use-package-normalize-binder) 115(defalias 'use-package-normalize/:bind* 'use-package-normalize-binder)
116 116
117;; jww (2017-12-07): This is too simplistic. It will fail to determine
118;; autoloads in this situation:
119;; (use-package foo
120;; :bind (:map foo-map (("C-a" . func))))
121;;;###autoload
122(defalias 'use-package-autoloads/:bind 'use-package-autoloads-mode)
123;;;###autoload
124(defalias 'use-package-autoloads/:bind* 'use-package-autoloads-mode)
125
117;;;###autoload 126;;;###autoload
118(defun use-package-handler/:bind 127(defun use-package-handler/:bind
119 (name keyword args rest state &optional bind-macro) 128 (name keyword args rest state &optional bind-macro)
120 (let* ((result (use-package-normalize-commands args)) 129 (use-package-concat
121 (nargs (car result)) 130 (use-package-process-keywords name rest state)
122 (commands (cdr result))) 131 `((ignore
123 (use-package-concat 132 (,(if bind-macro bind-macro 'bind-keys)
124 (use-package-process-keywords name 133 :package ,name ,@(use-package-normalize-commands args))))))
125 (use-package-sort-keywords
126 (use-package-plist-append rest :commands commands))
127 state)
128 `((ignore
129 (,(if bind-macro bind-macro 'bind-keys)
130 :package ,name ,@nargs))))))
131 134
132(defun use-package-handler/:bind* (name keyword arg rest state) 135(defun use-package-handler/:bind* (name keyword arg rest state)
133 (use-package-handler/:bind name keyword arg rest state 'bind-keys*)) 136 (use-package-handler/:bind name keyword arg rest state 'bind-keys*))
diff --git a/lisp/use-package/use-package-core.el b/lisp/use-package/use-package-core.el
index 175e023a5a4..001ffde1534 100644
--- a/lisp/use-package/use-package-core.el
+++ b/lisp/use-package/use-package-core.el
@@ -100,17 +100,15 @@ declaration is incorrect."
100 :group 'use-package) 100 :group 'use-package)
101 101
102(defcustom use-package-deferring-keywords 102(defcustom use-package-deferring-keywords
103 '(:bind 103 '(:bind-keymap
104 :bind*
105 :bind-keymap
106 :bind-keymap* 104 :bind-keymap*
107 :interpreter
108 :mode
109 :magic
110 :magic-fallback
111 :hook
112 :commands) 105 :commands)
113 "Unless `:demand' is used, keywords in this list imply deferred loading." 106 "Unless `:demand' is used, keywords in this list imply deferred loading.
107The reason keywords like `:hook' are not in this list is that
108they only imply deferred loading if they reference actual
109function symbols that can be autoloaded from the module; whereas
110the default keywords provided here always defer loading unless
111otherwise requested."
114 :type '(repeat symbol) 112 :type '(repeat symbol)
115 :group 'use-package) 113 :group 'use-package)
116 114
@@ -160,7 +158,7 @@ See also `use-package-defaults', which uses this value."
160 (and use-package-always-demand 158 (and use-package-always-demand
161 (not (plist-member args :defer)) 159 (not (plist-member args :defer))
162 (not (plist-member args :demand)))))) 160 (not (plist-member args :demand))))))
163 "Alist of default values for `use-package' keywords. 161 "Default values for specified `use-package' keywords.
164Each entry in the alist is a list of three elements. The first 162Each entry in the alist is a list of three elements. The first
165element is the `use-package' keyword and the second is a form 163element is the `use-package' keyword and the second is a form
166that can be evaluated to get the default value. The third element 164that can be evaluated to get the default value. The third element
@@ -497,8 +495,9 @@ extending any keys already present."
497 (xs (use-package-split-list #'keywordp (cdr input))) 495 (xs (use-package-split-list #'keywordp (cdr input)))
498 (args (car xs)) 496 (args (car xs))
499 (tail (cdr xs)) 497 (tail (cdr xs))
500 (normalizer (intern (concat "use-package-normalize/" 498 (normalizer
501 (symbol-name keyword)))) 499 (intern-soft (concat "use-package-normalize/"
500 (symbol-name keyword))))
502 (arg (and (functionp normalizer) 501 (arg (and (functionp normalizer)
503 (funcall normalizer name keyword args)))) 502 (funcall normalizer name keyword args))))
504 (if (memq keyword use-package-keywords) 503 (if (memq keyword use-package-keywords)
@@ -562,6 +561,32 @@ extending any keys already present."
562 (setq args (use-package-plist-maybe-put 561 (setq args (use-package-plist-maybe-put
563 args (nth 0 spec) (eval (nth 1 spec)))))) 562 args (nth 0 spec) (eval (nth 1 spec))))))
564 563
564 ;; Determine any autoloads implied by the keywords used.
565 (let ((iargs args)
566 commands)
567 (while iargs
568 (when (keywordp (car iargs))
569 (let ((autoloads
570 (intern-soft (concat "use-package-autoloads/"
571 (symbol-name (car iargs))))))
572 (when (functionp autoloads)
573 (setq commands
574 ;; jww (2017-12-07): Right now we just ignored the type of
575 ;; the autoload being requested, and assume they are all
576 ;; `command'.
577 (append (mapcar
578 #'car
579 (funcall autoloads name-symbol (car iargs)
580 (cadr iargs)))
581 commands)))))
582 (setq iargs (cddr iargs)))
583 (when commands
584 (setq args
585 ;; Like `use-package-plist-append', but removing duplicates.
586 (plist-put args :commands
587 (delete-dups
588 (append commands (plist-get args :commands)))))))
589
565 ;; If byte-compiling, pre-load the package so all its symbols are in 590 ;; If byte-compiling, pre-load the package so all its symbols are in
566 ;; scope. This is done by prepending statements to the :preface. 591 ;; scope. This is done by prepending statements to the :preface.
567 (when (bound-and-true-p byte-compile-current-file) 592 (when (bound-and-true-p byte-compile-current-file)
@@ -593,10 +618,13 @@ extending any keys already present."
593 use-package-deferring-keywords))) 618 use-package-deferring-keywords)))
594 (setq args (append args '(:defer t)))) 619 (setq args (append args '(:defer t))))
595 620
621 ;; The :load keyword overrides :no-require
596 (when (and (plist-member args :load) 622 (when (and (plist-member args :load)
597 (plist-member args :no-require)) 623 (plist-member args :no-require))
598 (setq args (use-package-plist-delete args :no-require))) 624 (setq args (use-package-plist-delete args :no-require)))
599 625
626 ;; If at this point no :load, :defer or :no-require has been seen, then
627 ;; :load the package itself.
600 (when (and (not (plist-member args :load)) 628 (when (and (not (plist-member args :load))
601 (not (plist-member args :defer)) 629 (not (plist-member args :defer))
602 (not (plist-member args :no-require))) 630 (not (plist-member args :no-require)))
@@ -851,22 +879,12 @@ If RECURSED is non-nil, recurse into sublists."
851 (t v))) 879 (t v)))
852 880
853(defun use-package-normalize-commands (args) 881(defun use-package-normalize-commands (args)
854 "Map over ARGS of the form ((_ . F) ...). 882 "Map over ARGS of the form ((_ . F) ...), normalizing functional F's."
855Normalizing functional F's and returning a list of F's 883 (mapcar #'(lambda (x)
856representing symbols (that may need to be autloaded)." 884 (if (consp x)
857 (let ((nargs (mapcar 885 (cons (car x) (use-package-normalize-function (cdr x)))
858 #'(lambda (x) 886 x))
859 (if (consp x) 887 args))
860 (cons (car x)
861 (use-package-normalize-function (cdr x)))
862 x)) args)))
863 (cons nargs
864 (delete
865 nil (mapcar
866 #'(lambda (x)
867 (and (consp x)
868 (use-package-non-nil-symbolp (cdr x))
869 (cdr x))) nargs)))))
870 888
871(defun use-package-normalize-mode (name keyword args) 889(defun use-package-normalize-mode (name keyword args)
872 "Normalize arguments for keywords which add regexp/mode pairs to an alist." 890 "Normalize arguments for keywords which add regexp/mode pairs to an alist."
@@ -876,6 +894,27 @@ representing symbols (that may need to be autloaded)."
876 #'use-package-recognize-function 894 #'use-package-recognize-function
877 name))) 895 name)))
878 896
897(defun use-package-autoloads-mode (name keyword args)
898 (mapcar
899 #'(lambda (x) (cons (cdr x) 'command))
900 (cl-remove-if-not #'(lambda (x)
901 (and (consp x)
902 (use-package-non-nil-symbolp (cdr x))))
903 args)))
904
905(defun use-package-handle-mode (name alist args rest state)
906 "Handle keywords which add regexp/mode pairs to an alist."
907 (use-package-concat
908 (use-package-process-keywords name rest state)
909 `((ignore
910 ,@(mapcar
911 #'(lambda (thing)
912 `(add-to-list
913 ',alist
914 ',(cons (use-package-normalize-regex (car thing))
915 (cdr thing))))
916 (use-package-normalize-commands args))))))
917
879;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 918;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
880;; 919;;
881;;; Statistics 920;;; Statistics
@@ -1078,26 +1117,8 @@ meaning:
1078 1117
1079;;;; :interpreter 1118;;;; :interpreter
1080 1119
1081(defun use-package-handle-mode (name alist args rest state)
1082 "Handle keywords which add regexp/mode pairs to an alist."
1083 (let* ((result (use-package-normalize-commands args))
1084 (nargs (car result))
1085 (commands (cdr result)))
1086 (use-package-concat
1087 (use-package-process-keywords name
1088 (use-package-sort-keywords
1089 (use-package-plist-append rest :commands commands))
1090 state)
1091 `((ignore
1092 ,@(mapcar
1093 #'(lambda (thing)
1094 `(add-to-list
1095 ',alist
1096 ',(cons (use-package-normalize-regex (car thing))
1097 (cdr thing))))
1098 nargs))))))
1099
1100(defalias 'use-package-normalize/:interpreter 'use-package-normalize-mode) 1120(defalias 'use-package-normalize/:interpreter 'use-package-normalize-mode)
1121(defalias 'use-package-autoloads/:interpreter 'use-package-autoloads-mode)
1101 1122
1102(defun use-package-handler/:interpreter (name keyword arg rest state) 1123(defun use-package-handler/:interpreter (name keyword arg rest state)
1103 (use-package-handle-mode name 'interpreter-mode-alist arg rest state)) 1124 (use-package-handle-mode name 'interpreter-mode-alist arg rest state))
@@ -1105,6 +1126,7 @@ meaning:
1105;;;; :mode 1126;;;; :mode
1106 1127
1107(defalias 'use-package-normalize/:mode 'use-package-normalize-mode) 1128(defalias 'use-package-normalize/:mode 'use-package-normalize-mode)
1129(defalias 'use-package-autoloads/:mode 'use-package-autoloads-mode)
1108 1130
1109(defun use-package-handler/:mode (name keyword arg rest state) 1131(defun use-package-handler/:mode (name keyword arg rest state)
1110 (use-package-handle-mode name 'auto-mode-alist arg rest state)) 1132 (use-package-handle-mode name 'auto-mode-alist arg rest state))
@@ -1112,6 +1134,7 @@ meaning:
1112;;;; :magic 1134;;;; :magic
1113 1135
1114(defalias 'use-package-normalize/:magic 'use-package-normalize-mode) 1136(defalias 'use-package-normalize/:magic 'use-package-normalize-mode)
1137(defalias 'use-package-autoloads/:magic 'use-package-autoloads-mode)
1115 1138
1116(defun use-package-handler/:magic (name keyword arg rest state) 1139(defun use-package-handler/:magic (name keyword arg rest state)
1117 (use-package-handle-mode name 'magic-mode-alist arg rest state)) 1140 (use-package-handle-mode name 'magic-mode-alist arg rest state))
@@ -1119,6 +1142,7 @@ meaning:
1119;;;; :magic-fallback 1142;;;; :magic-fallback
1120 1143
1121(defalias 'use-package-normalize/:magic-fallback 'use-package-normalize-mode) 1144(defalias 'use-package-normalize/:magic-fallback 'use-package-normalize-mode)
1145(defalias 'use-package-autoloads/:magic-fallback 'use-package-autoloads-mode)
1122 1146
1123(defun use-package-handler/:magic-fallback (name keyword arg rest state) 1147(defun use-package-handler/:magic-fallback (name keyword arg rest state)
1124 (use-package-handle-mode name 'magic-fallback-mode-alist arg rest state)) 1148 (use-package-handle-mode name 'magic-fallback-mode-alist arg rest state))
@@ -1145,31 +1169,27 @@ meaning:
1145 #'use-package-recognize-function 1169 #'use-package-recognize-function
1146 name label arg)))) 1170 name label arg))))
1147 1171
1172(defalias 'use-package-autoloads/:hook 'use-package-autoloads-mode)
1173
1148(defun use-package-handler/:hook (name keyword args rest state) 1174(defun use-package-handler/:hook (name keyword args rest state)
1149 "Generate use-package custom keyword code." 1175 "Generate use-package custom keyword code."
1150 (let* ((result (use-package-normalize-commands args)) 1176 (use-package-concat
1151 (nargs (car result)) 1177 (use-package-process-keywords name rest state)
1152 (commands (cdr result))) 1178 `((ignore
1153 (use-package-concat 1179 ,@(cl-mapcan
1154 (use-package-process-keywords name 1180 #'(lambda (def)
1155 (use-package-sort-keywords 1181 (let ((syms (car def))
1156 (use-package-plist-append rest :commands commands)) 1182 (fun (cdr def)))
1157 state) 1183 (when fun
1158 `((ignore 1184 (mapcar
1159 ,@(cl-mapcan 1185 #'(lambda (sym)
1160 #'(lambda (def) 1186 `(add-hook
1161 (let ((syms (car def)) 1187 (quote ,(intern
1162 (fun (cdr def))) 1188 (concat (symbol-name sym)
1163 (when fun 1189 use-package-hook-name-suffix)))
1164 (mapcar 1190 (function ,fun)))
1165 #'(lambda (sym) 1191 (if (use-package-non-nil-symbolp syms) (list syms) syms)))))
1166 `(add-hook 1192 (use-package-normalize-commands args))))))
1167 (quote ,(intern
1168 (concat (symbol-name sym)
1169 use-package-hook-name-suffix)))
1170 (function ,fun)))
1171 (if (use-package-non-nil-symbolp syms) (list syms) syms)))))
1172 nargs))))))
1173 1193
1174;;;; :commands 1194;;;; :commands
1175 1195
diff --git a/test/lisp/use-package/use-package-tests.el b/test/lisp/use-package/use-package-tests.el
index ffff7ced326..08ac5293a99 100644
--- a/test/lisp/use-package/use-package-tests.el
+++ b/test/lisp/use-package/use-package-tests.el
@@ -1001,30 +1001,30 @@
1001 1001
1002(ert-deftest use-package-test/:hook-1 () 1002(ert-deftest use-package-test/:hook-1 ()
1003 (let ((byte-compile-current-file t)) 1003 (let ((byte-compile-current-file t))
1004 (should 1004 (match-expansion
1005 (equal 1005 (use-package foo
1006 (expand-minimally 1006 :bind (("C-a" . key))
1007 (use-package foo 1007 :hook (hook . fun))
1008 :bind (("C-a" . key)) 1008 `(progn
1009 :hook (hook . fun))) 1009 (eval-and-compile
1010 '(progn 1010 (eval-when-compile
1011 (eval-and-compile 1011 (with-demoted-errors
1012 (eval-when-compile 1012 "Cannot load foo: %S" nil
1013 (with-demoted-errors 1013 (load "foo" nil t))))
1014 "Cannot load foo: %S" nil 1014 (unless
1015 (load "foo" nil t)))) 1015 (fboundp 'key)
1016 (unless (fboundp 'fun) 1016 (autoload #'key "foo" nil t))
1017 (autoload #'fun "foo" nil t)) 1017 (eval-when-compile
1018 (eval-when-compile 1018 (declare-function key "foo"))
1019 (declare-function fun "foo")) 1019 (unless
1020 (unless (fboundp 'key) 1020 (fboundp 'fun)
1021 (autoload #'key "foo" nil t)) 1021 (autoload #'fun "foo" nil t))
1022 (eval-when-compile 1022 (eval-when-compile
1023 (declare-function key "foo")) 1023 (declare-function fun "foo"))
1024 (ignore 1024 (ignore
1025 (add-hook 'hook-hook #'fun)) 1025 (add-hook 'hook-hook #'fun))
1026 (ignore 1026 (ignore
1027 (bind-keys :package foo ("C-a" . key)))))))) 1027 (bind-keys :package foo ("C-a" . key)))))))
1028 1028
1029(ert-deftest use-package-test/:hook-2 () 1029(ert-deftest use-package-test/:hook-2 ()
1030 (match-expansion 1030 (match-expansion
@@ -1079,6 +1079,37 @@
1079 #'(lambda nil 1079 #'(lambda nil
1080 (bind-key "" erefactor-map emacs-lisp-mode-map))))))))) 1080 (bind-key "" erefactor-map emacs-lisp-mode-map)))))))))
1081 1081
1082(ert-deftest use-package-test/:hook-6 ()
1083 (match-expansion
1084 (use-package erefactor
1085 :load-path "foo"
1086 :after elisp-mode
1087 :hook (emacs-lisp-mode . function))
1088 `(progn
1089 (eval-and-compile
1090 (add-to-list 'load-path "/Users/johnw/.emacs.d/foo"))
1091 (eval-after-load 'elisp-mode
1092 '(progn
1093 (unless (fboundp 'function)
1094 (autoload #'function "erefactor" nil t))
1095 (ignore
1096 (add-hook 'emacs-lisp-mode-hook #'function)))))))
1097
1098(ert-deftest use-package-test/:hook-7 ()
1099 (match-expansion
1100 (use-package erefactor
1101 :load-path "foo"
1102 :after elisp-mode
1103 :hook (emacs-lisp-mode . (lambda () (function))))
1104 `(progn
1105 (eval-and-compile
1106 (add-to-list 'load-path "/Users/johnw/.emacs.d/foo"))
1107 (eval-after-load 'elisp-mode
1108 '(progn
1109 (require 'erefactor nil nil)
1110 (ignore
1111 (add-hook 'emacs-lisp-mode-hook #'(lambda nil (function)))))))))
1112
1082(ert-deftest use-package-test-normalize/:custom () 1113(ert-deftest use-package-test-normalize/:custom ()
1083 (flet ((norm (&rest args) 1114 (flet ((norm (&rest args)
1084 (apply #'use-package-normalize/:custom 1115 (apply #'use-package-normalize/:custom