aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/misc/use-package.texi946
-rw-r--r--etc/USE-PACKAGE-NEWS277
-rw-r--r--lisp/use-package/bind-chord.el113
-rw-r--r--lisp/use-package/bind-key.el544
-rw-r--r--lisp/use-package/use-package-bind-key.el171
-rw-r--r--lisp/use-package/use-package-chords.el54
-rw-r--r--lisp/use-package/use-package-core.el1690
-rw-r--r--lisp/use-package/use-package-delight.el83
-rw-r--r--lisp/use-package/use-package-diminish.el72
-rw-r--r--lisp/use-package/use-package-ensure-system-package.el99
-rw-r--r--lisp/use-package/use-package-ensure.el206
-rw-r--r--lisp/use-package/use-package-jump.el70
-rw-r--r--lisp/use-package/use-package-lint.el76
-rw-r--r--lisp/use-package/use-package.el51
-rw-r--r--test/lisp/use-package/use-package-chords-tests.el153
-rw-r--r--test/lisp/use-package/use-package-tests.el1957
16 files changed, 6562 insertions, 0 deletions
diff --git a/doc/misc/use-package.texi b/doc/misc/use-package.texi
new file mode 100644
index 00000000000..573baac89aa
--- /dev/null
+++ b/doc/misc/use-package.texi
@@ -0,0 +1,946 @@
1\input texinfo @c -*- texinfo -*-
2@c %**start of header
3@setfilename use-package.info
4@settitle use-package User Manual
5@documentencoding UTF-8
6@documentlanguage en
7@c %**end of header
8
9@copying
10@quotation
11Copyright (C) 2012-2022 Free Software Foundation, Inc.
12
13You can redistribute this document and/or modify it under the terms
14of the GNU General Public License as published by the Free Software
15Foundation, either version 3 of the License, or (at your option) any
16later version.
17
18This document is distributed in the hope that it will be useful,
19but WITHOUT ANY WARRANTY; without even the implied warranty of
20MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE@. See the GNU
21General Public License for more details.
22
23@end quotation
24@end copying
25
26@dircategory Emacs
27@direntry
28* use-package: (use-package). Declarative package configuration for Emacs.
29@end direntry
30
31@finalout
32@titlepage
33@title use-package User Manual
34@subtitle for version 2.4.1-119-g0be480e+1
35@author John Wiegley
36@page
37@vskip 0pt plus 1filll
38@insertcopying
39@end titlepage
40
41@contents
42
43@ifnottex
44@node Top
45@top use-package User Manual
46
47The @code{use-package} macro allows you to isolate package configuration in your
48@code{.emacs} file in a way that is both performance-oriented and, well, tidy. I
49created it because I have over 80 packages that I use in Emacs, and things
50were getting difficult to manage. Yet with this utility my total load time is
51around 2 seconds, with no loss of functionality!
52
53@insertcopying
54@end ifnottex
55
56@menu
57* Introduction::
58* Installation::
59* Getting Started::
60* Basic Concepts::
61* Issues/Requests::
62* Keywords::
63* Debugging Tools::
64
65@detailmenu
66--- The Detailed Node Listing ---
67
68Installation
69
70* Installing from GNU ELPA::
71* Installing from the Git Repository::
72* Post-Installation Tasks::
73
74Keywords
75
76* @code{after}:: @code{:after}.
77* @code{bind-keymap} @code{bind-keymap*}:: @code{:bind-keymap}, @code{:bind-keymap*}.
78* @code{bind} @code{bind*}:: @code{:bind}, @code{:bind*}.
79* @code{commands}:: @code{:commands}.
80* @code{preface} @code{init} @code{config}:: @code{:preface}, @code{:init}, @code{:config}.
81* @code{custom}:: @code{:custom}.
82* @code{custom-face}:: @code{:custom-face}.
83* @code{defer} @code{demand}:: @code{:defer}, @code{:demand}.
84* @code{defines} @code{functions}:: @code{:defines}, @code{:functions}.
85* @code{diminish} @code{delight}:: @code{:diminish}, @code{:delight}.
86* @code{disabled}:: @code{:disabled}.
87* @code{ensure} @code{pin}:: @code{:ensure}, @code{:pin}.
88* @code{hook}:: @code{:hook}.
89* @code{if} @code{when} @code{unless}:: @code{:if}, @code{:when}, @code{:unless}.
90* @code{load-path}:: @code{:load-path}.
91* @code{mode} @code{interpreter}:: @code{:mode}, @code{:interpreter}.
92* @code{magic} @code{magic-fallback}:: @code{:magic}, @code{:magic-fallback}.
93* @code{no-require}:: @code{:no-require}.
94* @code{requires}:: @code{:requires}.
95
96@code{bind}, @code{bind*}
97
98* Binding to local keymaps::
99
100
101@end detailmenu
102@end menu
103
104@node Introduction
105@chapter Introduction
106
107The @code{use-package} macro allows you to isolate package configuration in your
108@code{.emacs} file in a way that is both performance-oriented and, well, tidy. I
109created it because I have over 80 packages that I use in Emacs, and things
110were getting difficult to manage. Yet with this utility my total load time is
111around 2 seconds, with no loss of functionality!
112
113More text to come@dots{}
114
115@node Installation
116@chapter Installation
117
118use-package can be installed using Emacs' package manager or manually from
119its development repository.
120
121@menu
122* Installing from GNU ELPA::
123* Installing from the Git Repository::
124* Post-Installation Tasks::
125@end menu
126
127@node Installing from GNU ELPA
128@section Installing from GNU ELPA
129
130use-package is available from GNU ELPA. If you haven't used
131Emacs' package manager before, then it is high time you familiarize yourself
132with it by reading the documentation in the Emacs manual, see
133@ref{Packages,,,emacs,}. Then add one of the archives to @code{package-archives}:
134
135First, you need to update the local package list using:
136
137@example
138M-x package-refresh-contents RET
139@end example
140
141Once you have done that, you can install use-package and its
142dependencies using:
143
144@example
145M-x package-install RET use-package RET
146@end example
147
148Now see @ref{Post-Installation Tasks}.
149
150@node Installing from the Git Repository
151@section Installing from the Git Repository
152
153First, use Git to clone the use-package repository:
154
155@example
156$ git clone https://github.com/jwiegley/use-package.git ~/.emacs.d/site-lisp/use-package
157$ cd ~/.emacs.d/site-lisp/use-package
158@end example
159
160Then compile the libraries and generate the info manuals:
161
162@example
163$ make
164@end example
165
166You may need to create @code{/path/to/use-package/config.mk} with the following
167content before running @code{make}:
168
169@example
170LOAD_PATH = -L /path/to/use-package
171@end example
172
173Finally add this to your init file:
174
175@lisp
176(add-to-list 'load-path "~/.emacs.d/site-lisp/use-package")
177(require 'use-package)
178
179(with-eval-after-load 'info
180 (info-initialize)
181 (add-to-list 'Info-directory-list
182 "~/.emacs.d/site-lisp/use-package/"))
183@end lisp
184
185Note that elements of @code{load-path} should not end with a slash, while those of
186@code{Info-directory-list} should.
187
188Instead of running use-package directly from the repository by adding it to
189the @code{load-path}, you might want to instead install it in some other directory
190using @code{sudo make install} and setting @code{load-path} accordingly.
191
192To update use-package use:
193
194@example
195$ git pull
196$ make
197@end example
198
199At times it might be necessary to run @code{make clean all} instead.
200
201To view all available targets use @code{make help}.
202
203Now see @ref{Post-Installation Tasks}.
204
205@node Post-Installation Tasks
206@section Post-Installation Tasks
207
208After installing use-package you should verify that you are indeed using the
209use-package release you think you are using. It's best to restart Emacs before
210doing so, to make sure you are not using an outdated value for @code{load-path}.
211
212@example
213C-h v use-package-version RET
214@end example
215
216should display something like
217
218@example
219use-package-version’s value is "2.4.3"
220@end example
221
222If you are completely new to use-package then see @ref{Getting Started}.
223
224If you run into problems, then please see the @ref{Debugging Tools}.
225
226@node Getting Started
227@chapter Getting Started
228
229TODO@. For now, see @code{README.md}.
230
231@node Basic Concepts
232@chapter Basic Concepts
233
234@code{use-package} was created for few basic reasons, each of which drove the
235design in various ways. Understanding these reasons may help make some of
236those decisions clearer:
237
238@itemize
239@item
240To gather all configuration details of a package into one place,
241making it easier to copy, disable, or move it elsewhere in the init
242file.
243
244@item
245To reduce duplication and boilerplate, capturing several common
246practices as mere keywords both easy and intuitive to use.
247
248@item
249To make startup time of Emacs as quick as possible, without
250sacrificing the quantity of add-on packages used.
251
252@item
253To make it so errors encountered during startup disable only the
254package raising the error, and as little else as possible, leaving a
255close to a functional Emacs as possible.
256
257@item
258To allow byte-compilation of one's init file so that any warnings or
259errors seen are meaningful. In this way, even if byte-compilation is not
260used for speed (reason 3), it can still be used as a sanity check.
261@end itemize
262
263@node Issues/Requests
264@chapter Issues/Requests
265
266@node Keywords
267@chapter Keywords
268
269@menu
270* @code{after}:: @code{after}.
271* @code{bind-keymap} @code{bind-keymap*}:: @code{:bind-keymap}, @code{:bind-keymap*}.
272* @code{bind} @code{bind*}:: @code{bind} @code{:bind*}.
273* @code{commands}:: @code{:commands}.
274* @code{preface} @code{init} @code{config}:: @code{:preface}, @code{:init}, @code{:config}.
275* @code{custom}:: @code{:custom}.
276* @code{custom-face}:: @code{:custom-face}.
277* @code{defer} @code{demand}:: @code{:defer}, @code{:demand}.
278* @code{defines} @code{functions}:: @code{:defines}, @code{:functions}.
279* @code{diminish} @code{delight}:: @code{:diminish}, @code{:delight}.
280* @code{disabled}:: @code{:disabled}.
281* @code{ensure} @code{pin}:: @code{:ensure}, @code{:pin}.
282* @code{hook}:: @code{:hook}.
283* @code{if} @code{when} @code{unless}:: @code{:if}, @code{:when}, @code{:unless}.
284* @code{load-path}:: @code{:load-path}.
285* @code{mode} @code{interpreter}:: @code{:mode}, @code{:interpreter}.
286* @code{magic} @code{magic-fallback}:: @code{:magic}, @code{:magic-fallback}.
287* @code{no-require}:: @code{:no-require}.
288* @code{requires}:: @code{:requires}.
289@end menu
290
291@node @code{after}
292@section @code{:after}
293
294Sometimes it only makes sense to configure a package after another has been
295loaded, because certain variables or functions are not in scope until that
296time. This can achieved using an @code{:after} keyword that allows a fairly rich
297description of the exact conditions when loading should occur. Here is an
298example:
299
300@lisp
301(use-package hydra
302 :load-path "site-lisp/hydra")
303
304(use-package ivy
305 :load-path "site-lisp/swiper")
306
307(use-package ivy-hydra
308 :after (ivy hydra))
309@end lisp
310
311In this case, because all of these packages are demand-loaded in the order
312they occur, the use of @code{:after} is not strictly necessary. By using it,
313however, the above code becomes order-independent, without an implicit
314depedence on the nature of your init file.
315
316By default, @code{:after (foo bar)} is the same as @code{:after (:all foo bar)}, meaning
317that loading of the given package will not happen until both @code{foo} and @code{bar}
318have been loaded. Here are some of the other possibilities:
319
320@lisp
321:after (foo bar)
322:after (:all foo bar)
323:after (:any foo bar)
324:after (:all (:any foo bar) (:any baz quux))
325:after (:any (:all foo bar) (:all baz quux))
326@end lisp
327
328When you nest selectors, such as @code{(:any (:all foo bar) (:all baz quux))}, it
329means that the package will be loaded when either both @code{foo} and @code{bar} have
330been loaded, or both @code{baz} and @code{quux} have been loaded.
331
332@strong{NOTE}: Pay attention if you set @code{use-package-always-defer} to t, and also use
333the @code{:after} keyword, as you will need to specify how the declared package is
334to be loaded: e.g., by some @code{:bind}. If you're not using one of the mechanisms
335that registers autoloads, such as @code{:bind} or @code{:hook}, and your package manager
336does not provide autoloads, it's possible that without adding @code{:demand t} to
337those declarations, your package will never be loaded.
338
339@node @code{bind-keymap} @code{bind-keymap*}
340@section @code{:bind-keymap}, @code{:bind-keymap*}
341
342Normally @code{:bind} expects that commands are functions that will be autoloaded
343from the given package. However, this does not work if one of those commands
344is actually a keymap, since keymaps are not functions, and cannot be
345autoloaded using Emacs' @code{autoload} mechanism.
346
347To handle this case, @code{use-package} offers a special, limited variant of
348@code{:bind} called @code{:bind-keymap}. The only difference is that the "commands"
349bound to by @code{:bind-keymap} must be keymaps defined in the package, rather than
350command functions. This is handled behind the scenes by generating custom code
351that loads the package containing the keymap, and then re-executes your
352keypress after the first load, to reinterpret that keypress as a prefix key.
353
354For example:
355
356@lisp
357(use-package projectile
358 :bind-keymap
359 ("C-c p" . projectile-command-map)
360@end lisp
361
362@node @code{bind} @code{bind*}
363@section @code{:bind}, @code{:bind*}
364
365Another common thing to do when loading a module is to bind a key to primary
366commands within that module:
367
368@lisp
369(use-package ace-jump-mode
370 :bind ("C-." . ace-jump-mode))
371@end lisp
372
373This does two things: first, it creates an autoload for the @code{ace-jump-mode}
374command and defers loading of @code{ace-jump-mode} until you actually use it.
375Second, it binds the key @code{C-.} to that command. After loading, you can use
376@code{M-x describe-personal-keybindings} to see all such keybindings you've set
377throughout your @code{.emacs} file.
378
379A more literal way to do the exact same thing is:
380
381@lisp
382(use-package ace-jump-mode
383 :commands ace-jump-mode
384 :init
385 (bind-key "C-." 'ace-jump-mode))
386@end lisp
387
388When you use the @code{:commands} keyword, it creates autoloads for those commands
389and defers loading of the module until they are used. Since the @code{:init} form
390is always run---even if @code{ace-jump-mode} might not be on your system---remember
391to restrict @code{:init} code to only what would succeed either way.
392
393The @code{:bind} keyword takes either a cons or a list of conses:
394
395@lisp
396(use-package hi-lock
397 :bind (("M-o l" . highlight-lines-matching-regexp)
398 ("M-o r" . highlight-regexp)
399 ("M-o w" . highlight-phrase)))
400@end lisp
401
402The @code{:commands} keyword likewise takes either a symbol or a list of symbols.
403
404NOTE: Special keys like @code{tab} or @code{F1}-@code{Fn} can be written in square brackets,
405i.e. @code{[tab]} instead of @code{"tab"}. The syntax for the keybindings is similar to
406the "kbd" syntax: see @uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-Rebinding.html, the Emacs Manual} for more information.
407
408Examples:
409
410@lisp
411(use-package helm
412 :bind (("M-x" . helm-M-x)
413 ("M-<f5>" . helm-find-files)
414 ([f10] . helm-buffers-list)
415 ([S-f10] . helm-recentf)))
416@end lisp
417
418@menu
419* Binding to local keymaps::
420@end menu
421
422@node Binding to local keymaps
423@subsection Binding to local keymaps
424
425Slightly different from binding a key to a keymap, is binding a key @strong{within} a
426local keymap that only exists after the package is loaded. @code{use-package}
427supports this with a @code{:map} modifier, taking the local keymap to bind to:
428
429@lisp
430(use-package helm
431 :bind (:map helm-command-map
432 ("C-c h" . helm-execute-persistent-action)))
433@end lisp
434
435The effect of this statement is to wait until @code{helm} has loaded, and then to
436bind the key @code{C-c h} to @code{helm-execute-persistent-action} within Helm's local
437keymap, @code{helm-mode-map}.
438
439Multiple uses of @code{:map} may be specified. Any binding occurring before the
440first use of @code{:map} are applied to the global keymap:
441
442@lisp
443(use-package term
444 :bind (("C-c t" . term)
445 :map term-mode-map
446 ("M-p" . term-send-up)
447 ("M-n" . term-send-down)
448 :map term-raw-map
449 ("M-o" . other-window)
450 ("M-p" . term-send-up)
451 ("M-n" . term-send-down)))
452@end lisp
453
454@node @code{commands}
455@section @code{:commands}
456
457@node @code{preface} @code{init} @code{config}
458@section @code{:preface}, @code{:init}, @code{:config}
459
460Here is the simplest @code{use-package} declaration:
461
462@lisp
463;; This is only needed once, near the top of the file
464(eval-when-compile
465 ;; Following line is not needed if use-package.el is in ~/.emacs.d
466 (add-to-list 'load-path "<path where use-package is installed>")
467 (require 'use-package))
468
469(use-package foo)
470@end lisp
471
472This loads in the package @code{foo}, but only if @code{foo} is available on your
473system. If not, a warning is logged to the @code{*Messages*} buffer. If it
474succeeds, a message about @code{"Loading foo"} is logged, along with the time it
475took to load, if it took over 0.1 seconds.
476
477Use the @code{:init} keyword to execute code before a package is loaded. It
478accepts one or more forms, up until the next keyword:
479
480@lisp
481(use-package foo
482 :init
483 (setq foo-variable t))
484@end lisp
485
486Similarly, @code{:config} can be used to execute code after a package is loaded.
487In cases where loading is done lazily (see more about autoloading below), this
488execution is deferred until after the autoload occurs:
489
490@lisp
491(use-package foo
492 :init
493 (setq foo-variable t)
494 :config
495 (foo-mode 1))
496@end lisp
497
498As you might expect, you can use @code{:init} and @code{:config} together:
499
500@lisp
501(use-package color-moccur
502 :commands (isearch-moccur isearch-all)
503 :bind (("M-s O" . moccur)
504 :map isearch-mode-map
505 ("M-o" . isearch-moccur)
506 ("M-O" . isearch-moccur-all))
507 :init
508 (setq isearch-lazy-highlight t)
509 :config
510 (use-package moccur-edit))
511@end lisp
512
513In this case, I want to autoload the commands @code{isearch-moccur} and
514@code{isearch-all} from @code{color-moccur.el}, and bind keys both at the global level
515and within the @code{isearch-mode-map} (see next section). When the package is
516actually loaded (by using one of these commands), @code{moccur-edit} is also
517loaded, to allow editing of the @code{moccur} buffer.
518
519@node @code{custom}
520@section @code{:custom}
521
522The @code{:custom} keyword allows customization of package custom variables.
523
524@lisp
525(use-package comint
526 :custom
527 (comint-buffer-maximum-size 20000 "Increase comint buffer size.")
528 (comint-prompt-read-only t "Make the prompt read only."))
529@end lisp
530
531The documentation string is not mandatory.
532
533@node @code{custom-face}
534@section @code{:custom-face}
535
536The @code{:custom-face} keyword allows customization of package custom faces.
537
538@lisp
539(use-package eruby-mode
540 :custom-face
541 (eruby-standard-face ((t (:slant italic)))))
542@end lisp
543
544@node @code{defer} @code{demand}
545@section @code{:defer}, @code{:demand}
546
547In almost all cases you don't need to manually specify @code{:defer t}. This is
548implied whenever @code{:bind} or @code{:mode} or @code{:interpreter} is used. Typically, you
549only need to specify @code{:defer} if you know for a fact that some other package
550will do something to cause your package to load at the appropriate time, and
551thus you would like to defer loading even though use-package isn't creating
552any autoloads for you.
553
554You can override package deferral with the @code{:demand} keyword. Thus, even if
555you use @code{:bind}, using @code{:demand} will force loading to occur immediately and
556not establish an autoload for the bound key.
557
558@node @code{defines} @code{functions}
559@section @code{:defines}, @code{:functions}
560
561Another feature of @code{use-package} is that it always loads every file that it
562can when @code{.emacs} is being byte-compiled. This helps to silence spurious
563warnings about unknown variables and functions.
564
565However, there are times when this is just not enough. For those times, use
566the @code{:defines} and @code{:functions} keywords to introduce dummy variable and
567function declarations solely for the sake of the byte-compiler:
568
569@lisp
570(use-package texinfo
571 :defines texinfo-section-list
572 :commands texinfo-mode
573 :init
574 (add-to-list 'auto-mode-alist '("\\.texi$" . texinfo-mode)))
575@end lisp
576
577If you need to silence a missing function warning, you can use @code{:functions}:
578
579@lisp
580(use-package ruby-mode
581 :mode "\\.rb\\'"
582 :interpreter "ruby"
583 :functions inf-ruby-keys
584 :config
585 (defun my-ruby-mode-hook ()
586 (require 'inf-ruby)
587 (inf-ruby-keys))
588
589 (add-hook 'ruby-mode-hook 'my-ruby-mode-hook))
590@end lisp
591
592@node @code{diminish} @code{delight}
593@section @code{:diminish}, @code{:delight}
594
595@code{use-package} also provides built-in support for the diminish and delight
596utilities---if you have them installed. Their purpose is to remove or change
597minor mode strings in your mode-line.
598
599@uref{https://github.com/myrjola/diminish.el, diminish} is invoked with the @code{:diminish} keyword, which is passed either a
600minor mode symbol, a cons of the symbol and its replacement string, or just a
601replacement string, in which case the minor mode symbol is guessed to be the
602package name with "-mode" appended at the end:
603
604@lisp
605(use-package abbrev
606 :diminish abbrev-mode
607 :config
608 (if (file-exists-p abbrev-file-name)
609 (quietly-read-abbrev-file)))
610@end lisp
611
612@uref{https://elpa.gnu.org/packages/delight.html, delight} is invoked with the @code{:delight} keyword, which is passed a minor mode
613symbol, a replacement string or quoted @uref{https://www.gnu.org/software/emacs/manual/html_node/elisp/Mode-Line-Data.html, mode-line data} (in which case the minor
614mode symbol is guessed to be the package name with "-mode" appended at the
615end), both of these, or several lists of both. If no arguments are provided,
616the default mode name is hidden completely.
617
618@lisp
619;; Don't show anything for rainbow-mode.
620(use-package rainbow-mode
621 :delight)
622
623;; Don't show anything for auto-revert-mode, which doesn't match
624;; its package name.
625(use-package autorevert
626 :delight auto-revert-mode)
627
628;; Remove the mode name for projectile-mode, but show the project name.
629(use-package projectile
630 :delight '(:eval (concat " " (projectile-project-name))))
631
632;; Completely hide visual-line-mode and change auto-fill-mode to " AF".
633(use-package emacs
634 :delight
635 (auto-fill-function " AF")
636 (visual-line-mode))
637@end lisp
638
639@node @code{disabled}
640@section @code{:disabled}
641
642The @code{:disabled} keyword can turn off a module you're having difficulties with,
643or stop loading something you're not using at the present time:
644
645@lisp
646(use-package ess-site
647 :disabled
648 :commands R)
649@end lisp
650
651When byte-compiling your @code{.emacs} file, disabled declarations are omitted
652from the output entirely, to accelerate startup times.
653
654@node @code{ensure} @code{pin}
655@section @code{:ensure}, @code{:pin}
656
657You can use @code{use-package} to load packages from ELPA with @code{package.el}. This
658is particularly useful if you share your @code{.emacs} among several machines; the
659relevant packages are downloaded automatically once declared in your @code{.emacs}.
660The @code{:ensure} keyword causes the package(s) to be installed automatically if
661not already present on your system (set @code{(setq use-package-always-ensure t)}
662if you wish this behavior to be global for all packages):
663
664@lisp
665(use-package magit
666 :ensure t)
667@end lisp
668
669If you need to install a different package from the one named by
670@code{use-package}, you can specify it like this:
671
672@lisp
673(use-package tex
674 :ensure auctex)
675@end lisp
676
677Lastly, when running on Emacs 24.4 or later, use-package can pin a package to
678a specific archive, allowing you to mix and match packages from different
679archives. The primary use-case for this is preferring packages from the
680@code{melpa-stable} and @code{gnu} archives, but using specific packages from @code{melpa}
681when you need to track newer versions than what is available in the @code{stable}
682archives is also a valid use-case.
683
684By default @code{package.el} prefers @code{melpa} over @code{melpa-stable} due to the
685versioning @code{(> evil-20141208.623 evil-1.0.9)}, so even if you are tracking
686only a single package from @code{melpa}, you will need to tag all the non-@code{melpa}
687packages with the appropriate archive. If this really annoys you, then you can
688set @code{use-package-always-pin} to set a default.
689
690If you want to manually keep a package updated and ignore upstream updates,
691you can pin it to @code{manual}, which as long as there is no repository by that
692name, will Just Work(tm).
693
694@code{use-package} throws an error if you try to pin a package to an archive that
695has not been configured using @code{package-archives} (apart from the magic
696@code{manual} archive mentioned above):
697
698@example
699Archive 'foo' requested for package 'bar' is not available.
700@end example
701
702Example:
703
704@lisp
705(use-package company
706 :ensure t
707 :pin melpa-stable)
708
709(use-package evil
710 :ensure t)
711 ;; no :pin needed, as package.el will choose the version in melpa
712
713(use-package adaptive-wrap
714 :ensure t
715 ;; as this package is available only in the gnu archive, this is
716 ;; technically not needed, but it helps to highlight where it
717 ;; comes from
718 :pin gnu)
719
720(use-package org
721 :ensure t
722 ;; ignore org-mode from upstream and use a manually installed version
723 :pin manual)
724@end lisp
725
726@strong{NOTE}: the @code{:pin} argument has no effect on emacs versions < 24.4.
727
728@node @code{hook}
729@section @code{:hook}
730
731The @code{:hook} keyword allows adding functions onto hooks, here only the basename
732of the hook is required. Thus, all of the following are equivalent:
733
734@lisp
735(use-package ace-jump-mode
736 :hook prog-mode)
737
738(use-package ace-jump-mode
739 :hook (prog-mode . ace-jump-mode))
740
741(use-package ace-jump-mode
742 :commands ace-jump-mode
743 :init
744 (add-hook 'prog-mode-hook #'ace-jump-mode))
745@end lisp
746
747And likewise, when multiple hooks should be applied, the following are also
748equivalent:
749
750@lisp
751(use-package ace-jump-mode
752 :hook (prog-mode text-mode))
753
754(use-package ace-jump-mode
755 :hook ((prog-mode text-mode) . ace-jump-mode))
756
757(use-package ace-jump-mode
758 :hook ((prog-mode . ace-jump-mode)
759 (text-mode . ace-jump-mode)))
760
761(use-package ace-jump-mode
762 :commands ace-jump-mode
763 :init
764 (add-hook 'prog-mode-hook #'ace-jump-mode)
765 (add-hook 'text-mode-hook #'ace-jump-mode))
766@end lisp
767
768The use of @code{:hook}, as with @code{:bind}, @code{:mode}, @code{:interpreter}, etc., causes the
769functions being hooked to implicitly be read as @code{:commands} (meaning they will
770establish interactive @code{autoload} definitions for that module, if not already
771defined as functions), and so @code{:defer t} is also implied by @code{:hook}.
772
773@node @code{if} @code{when} @code{unless}
774@section @code{:if}, @code{:when}, @code{:unless}
775
776You can use the @code{:if} keyword to predicate the loading and initialization of
777modules.
778
779For example, I only want @code{edit-server} running for my main, graphical Emacs,
780not for other Emacsen I may start at the command line:
781
782@lisp
783(use-package edit-server
784 :if window-system
785 :init
786 (add-hook 'after-init-hook 'server-start t)
787 (add-hook 'after-init-hook 'edit-server-start t))
788@end lisp
789
790In another example, we can load things conditional on the operating system:
791
792@lisp
793(use-package exec-path-from-shell
794 :if (memq window-system '(mac ns))
795 :ensure t
796 :config
797 (exec-path-from-shell-initialize))
798@end lisp
799
800Note that @code{:when} is provided as an alias for @code{:if}, and @code{:unless foo} means
801the same thing as @code{:if (not foo)}.
802
803@node @code{load-path}
804@section @code{:load-path}
805
806If your package needs a directory added to the @code{load-path} in order to load,
807use @code{:load-path}. This takes a symbol, a function, a string or a list of
808strings. If the path is relative, it is expanded within
809@code{user-emacs-directory}:
810
811@lisp
812(use-package ess-site
813 :load-path "site-lisp/ess/lisp/"
814 :commands R)
815@end lisp
816
817Note that when using a symbol or a function to provide a dynamically generated
818list of paths, you must inform the byte-compiler of this definition so the
819value is available at byte-compilation time. This is done by using the special
820form @code{eval-and-compile} (as opposed to @code{eval-when-compile}). Further, this
821value is fixed at whatever was determined during compilation, to avoid looking
822up the same information again on each startup:
823
824@lisp
825(eval-and-compile
826 (defun ess-site-load-path ()
827 (shell-command "find ~ -path ess/lisp")))
828
829(use-package ess-site
830 :load-path (lambda () (list (ess-site-load-path)))
831 :commands R)
832@end lisp
833
834@node @code{mode} @code{interpreter}
835@section @code{:mode}, @code{:interpreter}
836
837Similar to @code{:bind}, you can use @code{:mode} and @code{:interpreter} to establish a
838deferred binding within the @code{auto-mode-alist} and @code{interpreter-mode-alist}
839variables. The specifier to either keyword can be a cons cell, a list of cons
840cells, or a string or regexp:
841
842@lisp
843(use-package ruby-mode
844 :mode "\\.rb\\'"
845 :interpreter "ruby")
846
847;; The package is "python" but the mode is "python-mode":
848(use-package python
849 :mode ("\\.py\\'" . python-mode)
850 :interpreter ("python" . python-mode))
851@end lisp
852
853If you aren't using @code{:commands}, @code{:bind}, @code{:bind*}, @code{:bind-keymap},
854@code{:bind-keymap*}, @code{:mode}, or @code{:interpreter} (all of which imply @code{:defer}; see
855the docstring for @code{use-package} for a brief description of each), you can
856still defer loading with the @code{:defer} keyword:
857
858@lisp
859(use-package ace-jump-mode
860 :defer t
861 :init
862 (autoload 'ace-jump-mode "ace-jump-mode" nil t)
863 (bind-key "C-." 'ace-jump-mode))
864@end lisp
865
866This does exactly the same thing as the following:
867
868@lisp
869(use-package ace-jump-mode
870 :bind ("C-." . ace-jump-mode))
871@end lisp
872
873@node @code{magic} @code{magic-fallback}
874@section @code{:magic}, @code{:magic-fallback}
875
876Similar to @code{:mode} and @code{:interpreter}, you can also use @code{:magic} and
877@code{:magic-fallback} to cause certain function to be run if the beginning of a
878file matches a given regular expression. The difference between the two is
879that @code{:magic-fallback} has a lower priority than @code{:mode}. For example:
880
881@lisp
882(use-package pdf-tools
883 :load-path "site-lisp/pdf-tools/lisp"
884 :magic ("%PDF" . pdf-view-mode)
885 :config
886 (pdf-tools-install))
887@end lisp
888
889This registers an autoloaded command for @code{pdf-view-mode}, defers loading of
890@code{pdf-tools}, and runs @code{pdf-view-mode} if the beginning of a buffer matches the
891string @code{"%PDF"}.
892
893@node @code{no-require}
894@section @code{:no-require}
895
896Normally, @code{use-package} will load each package at compile time before
897compiling the configuration, to ensure that any necessary symbols are in scope
898to satisfy the byte-compiler. At times this can cause problems, since a
899package may have special loading requirements, and all that you want to use
900@code{use-package} for is to add a configuration to the @code{eval-after-load} hook. In
901such cases, use the @code{:no-require} keyword:
902
903@lisp
904(use-package foo
905 :no-require t
906 :config
907 (message "This is evaluated when `foo' is loaded"))
908@end lisp
909
910@node @code{requires}
911@section @code{:requires}
912
913While the @code{:after} keyword delays loading until the dependencies are loaded,
914the somewhat simpler @code{:requires} keyword simply never loads the package if the
915dependencies are not available at the time the @code{use-package} declaration is
916encountered. By "available" in this context it means that @code{foo} is available
917of @code{(featurep 'foo)} evaluates to a non-nil value. For example:
918
919@lisp
920(use-package abbrev
921 :requires foo)
922@end lisp
923
924This is the same as:
925
926@lisp
927(use-package abbrev
928 :if (featurep 'foo))
929@end lisp
930
931As a convenience, a list of such packages may be specified:
932
933@lisp
934(use-package abbrev
935 :requires (foo bar baz))
936@end lisp
937
938For more complex logic, such as that supported by @code{:after}, simply use @code{:if}
939and the appropriate Lisp expression.
940
941@node Debugging Tools
942@chapter Debugging Tools
943
944TODO
945
946@bye
diff --git a/etc/USE-PACKAGE-NEWS b/etc/USE-PACKAGE-NEWS
new file mode 100644
index 00000000000..c499820755f
--- /dev/null
+++ b/etc/USE-PACKAGE-NEWS
@@ -0,0 +1,277 @@
1# Changes
2
3## 2.4.4
4
5This release prepares for inclusion to GNU ELPA and includes no other changes
6
7## 2.4.1
8
9This is mostly a bug-fix release:
10
11- Update the documentation for :custom as per #850
12
13- Fix broken test due to #850
14
15- better tests
16
17- add test for #845
18
19- Support keymap symbol in bind-key. Fix #845
20
21- use-package-core.el: use the Emacs set-default function to avoid saving :custom vars twice
22
23- Fix Travis
24
25- typo, should be a vector, not a bytecode object
26
27 Solves https://github.com/jwiegley/use-package/issues/842
28
29- Add special value back again, in case needed for backwards compat
30
31 I don't know why this special value exists, but perhaps old client code uses it.
32
33 The additional `t' in the macro expansion is accidental but not harmful I guess.
34
35- Even when there's no :config, run any pre/post config hooks
36
37 i.e., following the existing docs for use-package-inject-hooks, these hooks are
38 run:
39
40 use-package--foo--pre-config-hook
41 use-package--foo--post-config-hook
42
43 This should make config customisations more predictable (for example, spacemacs
44 uses these hooks extensively to allow 'layers' to be customised).
45
46 I got rid of the "special" default value for :config, because it doesn't seem to
47 be treated any differently than nil.
48
49 Fixes #785
50
51- Clarify the documentation for :after
52
53- add table of contents to README
54
55- Fix typos
56
57 Typos found with codespell.
58
59- Fix typos
60
61- Attempt to explain omit "-hook" better
62
63- Update tests
64
65- Switch from `require' to `load' + `featurep'
66
67- Use `require', not `load', when byte-compiling
68
69- Make custom-face evaluate elisp.
70
71 Fix #696.
72
73- Add a line of documentation for (use-pacakage ... :hook).
74
75- Fix typo in README
76
77- Fix documentation for defer
78
79- Add no-query option for pdf-tools-install
80
81- Fix typo in README
82
83- Fix all notes in README
84
85- Mention use-package-ensure in README
86
87 Without requiring `use-package-ensure`, setting `use-package-always-ensure`
88 did not actually work for me.
89
90## 2.4
91
92### Breaking changes
93
94- `use-package` no longer requires `diminish` as a dependency, allowing people
95 to decide whether they want to use diminish or delight. This means that if
96 you do use diminish, you'll now need to pull it into your configuration
97 before any use of the `:diminish` kewyord. For example:
98
99 ``` elisp
100 (use-package diminish :ensure t)
101 ```
102
103- Emacs 24.3 or higher is now a requirement.
104
105- The `:defer-install` keyword has been removed. It may reappear as an add-on
106 module for use-package in a future release. See issue #442 for more details.
107
108- There is no longer a `use-package-debug` option, since `use-package-verbose`
109 already has the possible value of `debug`.
110
111- The ordering of several elements of `use-package-keywords` have changed; if
112 you had previously customized this (or were an extension author adding to
113 this list), you may need to rework your changes.
114
115- For extension authors, `:commands` should no longer be propagated down for
116 autoloading. See more below.
117
118### Other changes
119
120- Upgrade license to GPL 3.
121
122- If `use-package-verbose` is set to the symbol `debug`, any evaluation errors
123 during package configuration will cause a complete report to be written to a
124 `*use-package*` buffer, including: the text of the error, the `use-package`
125 declaration that caused the error, the post-normalized form of this
126 declaration, and the macro-expanded version (without verbosity-related
127 code). Note that this still does not help if there are parsing errors, which
128 cause Emacs to register a Lisp error at startup time.
129
130- New customization variable `use-package-deferring-keywords`, mainly intended
131 for use by extension packages, indicates keywords that, if used without
132 `:demand`, cause deferred loading (as if `:defer t` had been specified).
133
134- The `:ensure` keyword now accepts a specific pinning sub-keyword. For
135 example:
136
137 ``` elisp
138 (use-package foo
139 :pin "elpa")
140 ```
141
142 This ensure the package `foo` is installed from `"elpa"`.
143
144 ``` elisp
145 (use-package foo
146 :ensure bar
147 :ensure (quux :pin "melpa"))
148 ```
149
150 This says that `foo` ensures that `bar` is installed, as well as `quux` from
151 `"melpa"`. It does *not* ensure that `foo` is installed, because explicit
152 `:ensure` keywords were given.
153
154- New `:hook` keyword.
155
156- New `:catch` keyword. If `t` or `nil`, it enables (the default, see
157 `use-package-defaults`) or disables catching errors at load time in
158 use-package expansions. It can also be a function taking two arguments: the
159 keyword being processed at the time the error was encountered, and the error
160 object (as generated by `condition-case`).
161
162- New keywords `:custom (foo1 bar1) (foo2 bar2)` etc., and `:custom-face`.
163
164 NOTE: These are only for people who wish to keep customizations with their
165 accompanying use-package declarations. Functionally, the only benefit over
166 using `setq` in a `:config` block is that customizations might execute code
167 when values are assigned. If you currently use `M-x customize-option` and
168 save to a settings file, you do not want to use this option.
169
170- New `:magic` and `:magic-fallback` keywords.
171
172- New `:defer-install` keyword.
173
174- New customization variable `use-package-enable-imenu-support`.
175
176- New customization variable `use-package-hook-name-suffix`. Any symbols named
177 in `:hook`, or in the CAR of cons cells passed to `:hook`, have this text
178 appended to them as a convenience. If you find yourself using this keyword
179 to add to hooks of different names, or just don't want such appending done,
180 you can change the text to an empty string.
181
182- New customization variable `use-package-compute-statistics`, and an
183 accompanying command `M-x use-package-report`. See the README for more
184 details.
185
186- Allow `:diminish` to take no arguments.
187
188- Support multiple symbols passed to `:after`, and a mini-DSL using `:all` and
189 `:any`.
190
191- `:mode` and `:interpreter` can now accept `(rx ...)` forms.
192
193- Using `:load-path` without also using `:ensure` now implies `:ensure nil`.
194
195- `:bind (:map foo-map ...)` now defers binding in the map until the package
196 has been loaded.
197
198- Print key bindings for keymaps in `describe-personal-keybindings`.
199
200- When `use-package-inject-hooks` is non-nil, always fire `:init` and
201 `:config` hooks.
202
203- Documentation added for the `:after`, `:defer-install`, `:delight`,
204 `:requires`, `:when` and `:unless` keywords.
205
206- `:requires SYM` is subtly different from `:if (featurep SYM)`, in that it
207 happens before the `:preface`. This means that using `:requires` will cause
208 definitions in the `:preface` to not be visible to the byte-compiler,
209 leading to possible warnings about unknown functions, or functions that may
210 not be available at run-time (which can generally be ignored, since
211 `:requires` is intended as a check for basic system functionality; `:after`
212 should be used to check for the presence of other modules).
213
214- New undocumented (and currently experimental) keyword `:load` may be used to
215 change the name of the actual package loaded, rather than the package name,
216 and may even add other names. For example: `(use-package auctex :load
217 tex-site)`. This keyword is used internally to generate the `require` for a
218 package, so that deferral is simply a matter of not generating this keyword.
219
220- The source code is now broken into several files, so that certain optional
221 features (diminish, delight, ensure) may be maintained separately from the
222 core functionality.
223
224- When using the `:after` keyword, now even autoloadeds keybinding are
225 deferred until after that other package has loaded, in order to allow
226 convenient `:bind` to maps only present in that other package. Consider the
227 following:
228
229 ``` elisp
230 (use-package helm-descbinds
231 :load-path "site-lisp/helm-descbinds"
232 :after helm
233 :bind ("C-h b" . helm-descbinds)
234 :init
235 (fset 'describe-bindings 'helm-descbinds))
236 ```
237
238 The binding of `C-h b` here will not occur until helm is loaded; and after
239 it is loaded, `helm-descbinds` itself is not loaded until the user presses
240 `C-h b`.
241
242- For extension authors, if you add a keyword to `use-package-keywords` whose
243 presence should indicate deferred loading, please also add it to
244 `use-package-deferring-keywords`. Note that this is a bit of a sledgehammer,
245 in that the mere presence of these keywords implies deferred loading. For a
246 more subtle approach, see the new `use-package-autoloads/<KEYWORD>` support
247 mentioned in the next bullet.
248
249- For extension authors, if you wish deferred loading to possibly occur,
250 create functions named `use-package-autoloads/<KEYWORD>` for each keyword
251 that you define, returning an alist of the form `(SYMBOL . TYPE)` of symbols
252 to be autoloaded. `SYMBOL` should be an interactive function, and `TYPE` the
253 smybol `command`, but this functionality may be extended in future. These
254 autoloads are established if deferred loading is to happen.
255
256- If you specify a lambda form rather than a function symbol in any of the
257 constructs that *might* introduce autoloads: `:bind`, `:bind*`,
258 `:interpreter`, `:mode`, `:magic`, `:magic-fallback`, and `:hook`: then
259 deferred loading will no longer be implied, since there's nothing to
260 associate an autoload with that could later load the module. In these cases,
261 it will be as if you'd specified `:demand t`, in order to ensure the lambda
262 form is able to execute in the context of the loaded package.
263
264- For extension authors, there is a new customization variable
265 `use-package-merge-key-alist` that specifies how values passed to multiple
266 occurrences of the same key should be merged into a single value, during
267 normalization of the `use-package` declaration into a proper plist. The
268 default behavior is to simply append the values together (since they are
269 always normalized to lists).
270
271### Bug fixes
272
273- Repeating a bind no longer causes duplicates in personal-keybindings.
274- When byte-compiling, correctly output declare-function directives.
275- Append to *use-package* when debugging, don't clear it.
276- Don't allow :commands, :bind, etc., to be given an empty list.
277- Explicit :defer t should override use-package-always-demand.
diff --git a/lisp/use-package/bind-chord.el b/lisp/use-package/bind-chord.el
new file mode 100644
index 00000000000..ed736a4b966
--- /dev/null
+++ b/lisp/use-package/bind-chord.el
@@ -0,0 +1,113 @@
1;;; bind-chord.el --- key-chord binding helper for use-package-chords -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
4
5;; Author: Justin Talbott <justin@waymondo.com>
6;; Keywords: convenience, tools, extensions
7;; URL: https://github.com/jwiegley/use-package
8;; Version: 0.2.1
9;; Package-Requires: ((emacs "24.3") (bind-key "1.0") (key-chord "0.6"))
10;; Filename: bind-chord.el
11
12;; This program is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
16
17;; This program is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with this program. If not, see <https://www.gnu.org/licenses/>.
24
25;;; Commentary:
26
27;;; Code:
28
29(require 'bind-key)
30(require 'key-chord nil t)
31
32;;;###autoload
33(defmacro bind-chord (chord command &optional keymap)
34 "Bind CHORD to COMMAND in KEYMAP (`global-map' if not passed)."
35 (let ((key1 (logand 255 (aref chord 0)))
36 (key2 (logand 255 (aref chord 1))))
37 (if (eq key1 key2)
38 `(bind-key (vector 'key-chord ,key1 ,key2) ,command ,keymap)
39 `(progn
40 (bind-key (vector 'key-chord ,key1 ,key2) ,command ,keymap)
41 (bind-key (vector 'key-chord ,key2 ,key1) ,command ,keymap)))))
42
43(defun bind-chords-form (args keymap)
44 "Bind multiple chords at once.
45
46Accepts keyword arguments:
47:map MAP - a keymap into which the keybindings should be
48 added
49
50The rest of the arguments are conses of keybinding string and a
51function symbol (unquoted)."
52 (let (map pkg)
53 (let ((cont t))
54 (while (and cont args)
55 (if (cond ((eq :map (car args))
56 (setq map (cadr args)))
57 ((eq :package (car args))
58 (setq pkg (cadr args))))
59 (setq args (cddr args))
60 (setq cont nil))))
61
62 (unless map (setq map keymap))
63
64 (let (first next)
65 (while args
66 (if (keywordp (car args))
67 (progn
68 (setq next args)
69 (setq args nil))
70 (if first
71 (nconc first (list (car args)))
72 (setq first (list (car args))))
73 (setq args (cdr args))))
74
75 (cl-flet
76 ((wrap (map bindings)
77 (if (and map pkg (not (memq map '(global-map
78 override-global-map))))
79 `((if (boundp ',map)
80 ,(macroexp-progn bindings)
81 (eval-after-load
82 ,(if (symbolp pkg) `',pkg pkg)
83 ',(macroexp-progn bindings))))
84 bindings)))
85
86 (append
87 (wrap map
88 (cl-mapcan
89 (lambda (form)
90 (let ((fun (and (cdr form) (list 'function (cdr form)))))
91 (if (and map (not (eq map 'global-map)))
92 `((bind-chord ,(car form) ,fun ,map))
93 `((bind-chord ,(car form) ,fun nil)))))
94 first))
95 (when next
96 (bind-chords-form (if pkg
97 (cons :package (cons pkg next))
98 next) map)))))))
99
100;;;###autoload
101(defmacro bind-chords (&rest args)
102 "Bind multiple chords at once.
103
104Accepts keyword argument:
105:map - a keymap into which the keybindings should be added
106
107The rest of the arguments are conses of keybinding string and a
108function symbol (unquoted)."
109 (macroexp-progn (bind-chords-form args nil)))
110
111(provide 'bind-chord)
112
113;;; bind-chord.el ends here
diff --git a/lisp/use-package/bind-key.el b/lisp/use-package/bind-key.el
new file mode 100644
index 00000000000..3168f686a09
--- /dev/null
+++ b/lisp/use-package/bind-key.el
@@ -0,0 +1,544 @@
1;;; bind-key.el --- A simple way to manage personal keybindings -*- lexical-binding: t; -*-
2
3;; Copyright (c) 2012-2022 Free Software Foundation, Inc.
4
5;; Author: John Wiegley <johnw@newartisans.com>
6;; Maintainer: John Wiegley <johnw@newartisans.com>
7;; Created: 16 Jun 2012
8;; Version: 2.4.1
9;; Package-Requires: ((emacs "24.3"))
10;; Keywords: keys keybinding config dotemacs extensions
11;; URL: https://github.com/jwiegley/use-package
12
13;; This program is free software; you can redistribute it and/or modify
14;; it under the terms of the GNU General Public License as published by
15;; the Free Software Foundation, either version 3 of the License, or
16;; (at your option) any later version.
17
18;; This program is distributed in the hope that it will be useful,
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
24;; along with this program. If not, see <https://www.gnu.org/licenses/>.
25
26;;; Commentary:
27
28;; If you have lots of keybindings set in your .emacs file, it can be hard to
29;; know which ones you haven't set yet, and which may now be overriding some
30;; new default in a new Emacs version. This module aims to solve that
31;; problem.
32;;
33;; Bind keys as follows in your .emacs:
34;;
35;; (require 'bind-key)
36;;
37;; (bind-key "C-c x" 'my-ctrl-c-x-command)
38;;
39;; If the keybinding argument is a vector, it is passed straight to
40;; `define-key', so remapping a key with `[remap COMMAND]' works as
41;; expected:
42;;
43;; (bind-key [remap original-ctrl-c-x-command] 'my-ctrl-c-x-command)
44;;
45;; If you want the keybinding to override all minor modes that may also bind
46;; the same key, use the `bind-key*' form:
47;;
48;; (bind-key* "<C-return>" 'other-window)
49;;
50;; If you want to rebind a key only in a particular keymap, use:
51;;
52;; (bind-key "C-c x" 'my-ctrl-c-x-command some-other-mode-map)
53;;
54;; To unbind a key within a keymap (for example, to stop your favorite major
55;; mode from changing a binding that you don't want to override everywhere),
56;; use `unbind-key':
57;;
58;; (unbind-key "C-c x" some-other-mode-map)
59;;
60;; To bind multiple keys at once, or set up a prefix map, a `bind-keys' macro
61;; is provided. It accepts keyword arguments, please see its documentation
62;; for a detailed description.
63;;
64;; To add keys into a specific map, use :map argument
65;;
66;; (bind-keys :map dired-mode-map
67;; ("o" . dired-omit-mode)
68;; ("a" . some-custom-dired-function))
69;;
70;; To set up a prefix map, use `:prefix-map' and `:prefix' arguments (both are
71;; required)
72;;
73;; (bind-keys :prefix-map my-customize-prefix-map
74;; :prefix "C-c c"
75;; ("f" . customize-face)
76;; ("v" . customize-variable))
77;;
78;; You can combine all the keywords together. Additionally,
79;; `:prefix-docstring' can be specified to set documentation of created
80;; `:prefix-map' variable.
81;;
82;; To bind multiple keys in a `bind-key*' way (to be sure that your bindings
83;; will not be overridden by other modes), you may use `bind-keys*' macro:
84;;
85;; (bind-keys*
86;; ("C-o" . other-window)
87;; ("C-M-n" . forward-page)
88;; ("C-M-p" . backward-page))
89;;
90;; After Emacs loads, you can see a summary of all your personal keybindings
91;; currently in effect with this command:
92;;
93;; M-x describe-personal-keybindings
94;;
95;; This display will tell you if you've overridden a default keybinding, and
96;; what the default was. Also, it will tell you if the key was rebound after
97;; your binding it with `bind-key', and what it was rebound it to.
98
99;;; Code:
100
101(require 'cl-lib)
102(require 'easy-mmode)
103
104(defgroup bind-key nil
105 "A simple way to manage personal keybindings."
106 :group 'emacs)
107
108(defcustom bind-key-column-widths '(18 . 40)
109 "Width of columns in `describe-personal-keybindings'."
110 :type '(cons integer integer)
111 :group 'bind-key)
112
113(defcustom bind-key-segregation-regexp
114 "\\`\\(\\(C-[chx] \\|M-[gso] \\)\\([CM]-\\)?\\|.+-\\)"
115 "Regular expression used to divide key sets in the output from
116\\[describe-personal-keybindings]."
117 :type 'regexp
118 :group 'bind-key)
119
120(defcustom bind-key-describe-special-forms nil
121 "If non-nil, extract docstrings from lambdas, closures and keymaps if possible."
122 :type 'boolean
123 :group 'bind-key)
124
125;; Create override-global-mode to force key remappings
126
127(defvar override-global-map (make-keymap)
128 "Keymap for `override-global-mode'.")
129
130(define-minor-mode override-global-mode
131 "A minor mode so that keymap settings override other modes."
132 :init-value t
133 :lighter "")
134
135;; the keymaps in `emulation-mode-map-alists' take precedence over
136;; `minor-mode-map-alist'
137(add-to-list 'emulation-mode-map-alists
138 `((override-global-mode . ,override-global-map)))
139
140(defvar personal-keybindings nil
141 "List of bindings performed by `bind-key'.
142
143Elements have the form ((KEY . [MAP]) CMD ORIGINAL-CMD)")
144
145;;;###autoload
146(defmacro bind-key (key-name command &optional keymap predicate)
147 "Bind KEY-NAME to COMMAND in KEYMAP (`global-map' if not passed).
148
149KEY-NAME may be a vector, in which case it is passed straight to
150`define-key'. Or it may be a string to be interpreted as
151spelled-out keystrokes, e.g., `C-c C-z'. See documentation of
152`edmacro-mode' for details.
153
154COMMAND must be an interactive function or lambda form.
155
156KEYMAP, if present, should be a keymap variable or symbol.
157For example:
158
159 (bind-key \"M-h\" #\\='some-interactive-function my-mode-map)
160
161 (bind-key \"M-h\" #\\='some-interactive-function \\='my-mode-map)
162
163If PREDICATE is non-nil, it is a form evaluated to determine when
164a key should be bound. It must return non-nil in such cases.
165Emacs can evaluate this form at any time that it does redisplay
166or operates on menu data structures, so you should write it so it
167can safely be called at any time."
168 (let ((namevar (make-symbol "name"))
169 (keyvar (make-symbol "key"))
170 (kmapvar (make-symbol "kmap"))
171 (kdescvar (make-symbol "kdesc"))
172 (bindingvar (make-symbol "binding")))
173 `(let* ((,namevar ,key-name)
174 (,keyvar ,(if (stringp key-name) (read-kbd-macro key-name)
175 `(if (vectorp ,namevar) ,namevar
176 (read-kbd-macro ,namevar))))
177 (,kmapvar (or (if (and ,keymap (symbolp ,keymap))
178 (symbol-value ,keymap) ,keymap)
179 global-map))
180 (,kdescvar (cons (if (stringp ,namevar) ,namevar
181 (key-description ,namevar))
182 (if (symbolp ,keymap) ,keymap (quote ,keymap))))
183 (,bindingvar (lookup-key ,kmapvar ,keyvar)))
184 (let ((entry (assoc ,kdescvar personal-keybindings))
185 (details (list ,command
186 (unless (numberp ,bindingvar)
187 ,bindingvar))))
188 (if entry
189 (setcdr entry details)
190 (add-to-list 'personal-keybindings (cons ,kdescvar details))))
191 ,(if predicate
192 `(define-key ,kmapvar ,keyvar
193 '(menu-item "" nil :filter (lambda (&optional _)
194 (when ,predicate
195 ,command))))
196 `(define-key ,kmapvar ,keyvar ,command)))))
197
198;;;###autoload
199(defmacro unbind-key (key-name &optional keymap)
200 "Unbind the given KEY-NAME, within the KEYMAP (if specified).
201See `bind-key' for more details."
202 (let ((namevar (make-symbol "name"))
203 (kdescvar (make-symbol "kdesc")))
204 `(let* ((,namevar ,key-name)
205 (,kdescvar (cons (if (stringp ,namevar) ,namevar
206 (key-description ,namevar))
207 (if (symbolp ,keymap) ,keymap (quote ,keymap)))))
208 (bind-key--remove (if (vectorp ,namevar) ,namevar
209 (read-kbd-macro ,namevar))
210 (or (if (and ,keymap (symbolp ,keymap))
211 (symbol-value ,keymap) ,keymap)
212 global-map))
213 (setq personal-keybindings
214 (cl-delete-if (lambda (k) (equal (car k) ,kdescvar))
215 personal-keybindings))
216 nil)))
217
218(defun bind-key--remove (key keymap)
219 "Remove KEY from KEYMAP.
220
221In contrast to `define-key', this function removes the binding from the keymap."
222 (define-key keymap key nil)
223 ;; Split M-key in ESC key
224 (setq key (cl-mapcan (lambda (k)
225 (if (and (integerp k) (/= (logand k ?\M-\0) 0))
226 (list ?\e (logxor k ?\M-\0))
227 (list k)))
228 key))
229 ;; Delete single keys directly
230 (if (= (length key) 1)
231 (delete key keymap)
232 ;; Lookup submap and delete key from there
233 (let* ((prefix (vconcat (butlast key)))
234 (submap (lookup-key keymap prefix)))
235 (unless (keymapp submap)
236 (error "Not a keymap for %s" key))
237 (when (symbolp submap)
238 (setq submap (symbol-function submap)))
239 (delete (last key) submap)
240 ;; Delete submap if it is empty
241 (when (= 1 (length submap))
242 (bind-key--remove prefix keymap)))))
243
244;;;###autoload
245(defmacro bind-key* (key-name command &optional predicate)
246 "Similar to `bind-key', but overrides any mode-specific bindings."
247 `(bind-key ,key-name ,command override-global-map ,predicate))
248
249(defun bind-keys-form (args keymap)
250 "Bind multiple keys at once.
251
252Accepts keyword arguments:
253:map MAP - a keymap into which the keybindings should be
254 added
255:prefix KEY - prefix key for these bindings
256:prefix-map MAP - name of the prefix map that should be created
257 for these bindings
258:prefix-docstring STR - docstring for the prefix-map variable
259:menu-name NAME - optional menu string for prefix map
260:repeat-docstring STR - docstring for the repeat-map variable
261:repeat-map MAP - name of the repeat map that should be created
262 for these bindings. If specified, the
263 `repeat-map' property of each command bound
264 (within the scope of the `:repeat-map' keyword)
265 is set to this map.
266:exit BINDINGS - Within the scope of `:repeat-map' will bind the
267 key in the repeat map, but will not set the
268 `repeat-map' property of the bound command.
269:continue BINDINGS - Within the scope of `:repeat-map' forces the
270 same behaviour as if no special keyword had
271 been used (that is, the command is bound, and
272 it's `repeat-map' property set)
273:filter FORM - optional form to determine when bindings apply
274
275The rest of the arguments are conses of keybinding string and a
276function symbol (unquoted)."
277 (let (map
278 prefix-doc
279 prefix-map
280 prefix
281 repeat-map
282 repeat-doc
283 repeat-type ;; Only used internally
284 filter
285 menu-name
286 pkg)
287
288 ;; Process any initial keyword arguments
289 (let ((cont t)
290 (arg-change-func 'cddr))
291 (while (and cont args)
292 (if (cond ((and (eq :map (car args))
293 (not prefix-map))
294 (setq map (cadr args)))
295 ((eq :prefix-docstring (car args))
296 (setq prefix-doc (cadr args)))
297 ((and (eq :prefix-map (car args))
298 (not (memq map '(global-map
299 override-global-map))))
300 (setq prefix-map (cadr args)))
301 ((eq :repeat-docstring (car args))
302 (setq repeat-doc (cadr args)))
303 ((and (eq :repeat-map (car args))
304 (not (memq map '(global-map
305 override-global-map))))
306 (setq repeat-map (cadr args))
307 (setq map repeat-map))
308 ((eq :continue (car args))
309 (setq repeat-type :continue
310 arg-change-func 'cdr))
311 ((eq :exit (car args))
312 (setq repeat-type :exit
313 arg-change-func 'cdr))
314 ((eq :prefix (car args))
315 (setq prefix (cadr args)))
316 ((eq :filter (car args))
317 (setq filter (cadr args)) t)
318 ((eq :menu-name (car args))
319 (setq menu-name (cadr args)))
320 ((eq :package (car args))
321 (setq pkg (cadr args))))
322 (setq args (funcall arg-change-func args))
323 (setq cont nil))))
324
325 (when (or (and prefix-map (not prefix))
326 (and prefix (not prefix-map)))
327 (error "Both :prefix-map and :prefix must be supplied"))
328
329 (when repeat-type
330 (unless repeat-map
331 (error ":continue and :exit require specifying :repeat-map")))
332
333 (when (and menu-name (not prefix))
334 (error "If :menu-name is supplied, :prefix must be too"))
335
336 (unless map (setq map keymap))
337
338 ;; Process key binding arguments
339 (let (first next)
340 (while args
341 (if (keywordp (car args))
342 (progn
343 (setq next args)
344 (setq args nil))
345 (if first
346 (nconc first (list (car args)))
347 (setq first (list (car args))))
348 (setq args (cdr args))))
349
350 (cl-flet
351 ((wrap (map bindings)
352 (if (and map pkg (not (memq map '(global-map
353 override-global-map))))
354 `((if (boundp ',map)
355 ,(macroexp-progn bindings)
356 (eval-after-load
357 ,(if (symbolp pkg) `',pkg pkg)
358 ',(macroexp-progn bindings))))
359 bindings)))
360
361 (append
362 (when prefix-map
363 `((defvar ,prefix-map)
364 ,@(when prefix-doc `((put ',prefix-map 'variable-documentation ,prefix-doc)))
365 ,@(if menu-name
366 `((define-prefix-command ',prefix-map nil ,menu-name))
367 `((define-prefix-command ',prefix-map)))
368 ,@(if (and map (not (eq map 'global-map)))
369 (wrap map `((bind-key ,prefix ',prefix-map ,map ,filter)))
370 `((bind-key ,prefix ',prefix-map nil ,filter)))))
371 (when repeat-map
372 `((defvar ,repeat-map (make-sparse-keymap)
373 ,@(when repeat-doc `(,repeat-doc)))))
374 (wrap map
375 (cl-mapcan
376 (lambda (form)
377 (let ((fun (and (cdr form) (list 'function (cdr form)))))
378 (if prefix-map
379 `((bind-key ,(car form) ,fun ,prefix-map ,filter))
380 (if (and map (not (eq map 'global-map)))
381 ;; Only needed in this branch, since when
382 ;; repeat-map is non-nil, map is always
383 ;; non-nil
384 `(,@(when (and repeat-map (not (eq repeat-type :exit)))
385 `((put ,fun 'repeat-map ',repeat-map)))
386 (bind-key ,(car form) ,fun ,map ,filter))
387 `((bind-key ,(car form) ,fun nil ,filter))))))
388 first))
389 (when next
390 (bind-keys-form `(,@(when repeat-map `(:repeat-map ,repeat-map))
391 ,@(if pkg
392 (cons :package (cons pkg next))
393 next)) map)))))))
394
395;;;###autoload
396(defmacro bind-keys (&rest args)
397 "Bind multiple keys at once.
398
399Accepts keyword arguments:
400:map MAP - a keymap into which the keybindings should be
401 added
402:prefix KEY - prefix key for these bindings
403:prefix-map MAP - name of the prefix map that should be created
404 for these bindings
405:prefix-docstring STR - docstring for the prefix-map variable
406:menu-name NAME - optional menu string for prefix map
407:repeat-docstring STR - docstring for the repeat-map variable
408:repeat-map MAP - name of the repeat map that should be created
409 for these bindings. If specified, the
410 `repeat-map' property of each command bound
411 (within the scope of the `:repeat-map' keyword)
412 is set to this map.
413:exit BINDINGS - Within the scope of `:repeat-map' will bind the
414 key in the repeat map, but will not set the
415 `repeat-map' property of the bound command.
416:continue BINDINGS - Within the scope of `:repeat-map' forces the
417 same behaviour as if no special keyword had
418 been used (that is, the command is bound, and
419 it's `repeat-map' property set)
420:filter FORM - optional form to determine when bindings apply
421
422The rest of the arguments are conses of keybinding string and a
423function symbol (unquoted)."
424 (macroexp-progn (bind-keys-form args nil)))
425
426;;;###autoload
427(defmacro bind-keys* (&rest args)
428 (macroexp-progn (bind-keys-form args 'override-global-map)))
429
430(defun get-binding-description (elem)
431 (cond
432 ((listp elem)
433 (cond
434 ((memq (car elem) '(lambda function))
435 (if (and bind-key-describe-special-forms
436 (stringp (nth 2 elem)))
437 (nth 2 elem)
438 "#<lambda>"))
439 ((eq 'closure (car elem))
440 (if (and bind-key-describe-special-forms
441 (stringp (nth 3 elem)))
442 (nth 3 elem)
443 "#<closure>"))
444 ((eq 'keymap (car elem))
445 "#<keymap>")
446 (t
447 elem)))
448 ;; must be a symbol, non-symbol keymap case covered above
449 ((and bind-key-describe-special-forms (keymapp elem))
450 (let ((doc (get elem 'variable-documentation)))
451 (if (stringp doc) doc elem)))
452 ((symbolp elem)
453 elem)
454 (t
455 "#<byte-compiled lambda>")))
456
457(defun compare-keybindings (l r)
458 (let* ((regex bind-key-segregation-regexp)
459 (lgroup (and (string-match regex (caar l))
460 (match-string 0 (caar l))))
461 (rgroup (and (string-match regex (caar r))
462 (match-string 0 (caar r))))
463 (lkeymap (cdar l))
464 (rkeymap (cdar r)))
465 (cond
466 ((and (null lkeymap) rkeymap)
467 (cons t t))
468 ((and lkeymap (null rkeymap))
469 (cons nil t))
470 ((and lkeymap rkeymap
471 (not (string= (symbol-name lkeymap) (symbol-name rkeymap))))
472 (cons (string< (symbol-name lkeymap) (symbol-name rkeymap)) t))
473 ((and (null lgroup) rgroup)
474 (cons t t))
475 ((and lgroup (null rgroup))
476 (cons nil t))
477 ((and lgroup rgroup)
478 (if (string= lgroup rgroup)
479 (cons (string< (caar l) (caar r)) nil)
480 (cons (string< lgroup rgroup) t)))
481 (t
482 (cons (string< (caar l) (caar r)) nil)))))
483
484;;;###autoload
485(defun describe-personal-keybindings ()
486 "Display all the personal keybindings defined by `bind-key'."
487 (interactive)
488 (with-output-to-temp-buffer "*Personal Keybindings*"
489 (princ (format (concat "Key name%s Command%s Comments\n%s %s "
490 "---------------------\n")
491 (make-string (- (car bind-key-column-widths) 9) ? )
492 (make-string (- (cdr bind-key-column-widths) 8) ? )
493 (make-string (1- (car bind-key-column-widths)) ?-)
494 (make-string (1- (cdr bind-key-column-widths)) ?-)))
495 (let (last-binding)
496 (dolist (binding
497 (setq personal-keybindings
498 (sort personal-keybindings
499 (lambda (l r)
500 (car (compare-keybindings l r))))))
501
502 (if (not (eq (cdar last-binding) (cdar binding)))
503 (princ (format "\n\n%s: %s\n%s\n\n"
504 (cdar binding) (caar binding)
505 (make-string (+ 21 (car bind-key-column-widths)
506 (cdr bind-key-column-widths)) ?-)))
507 (if (and last-binding
508 (cdr (compare-keybindings last-binding binding)))
509 (princ "\n")))
510
511 (let* ((key-name (caar binding))
512 (at-present (lookup-key (or (symbol-value (cdar binding))
513 (current-global-map))
514 (read-kbd-macro key-name)))
515 (command (nth 1 binding))
516 (was-command (nth 2 binding))
517 (command-desc (get-binding-description command))
518 (was-command-desc (and was-command
519 (get-binding-description was-command)))
520 (at-present-desc (get-binding-description at-present)))
521 (let ((line
522 (format
523 (format "%%-%ds%%-%ds%%s\n" (car bind-key-column-widths)
524 (cdr bind-key-column-widths))
525 key-name (format "`%s\'" command-desc)
526 (if (string= command-desc at-present-desc)
527 (if (or (null was-command)
528 (string= command-desc was-command-desc))
529 ""
530 (format "was `%s\'" was-command-desc))
531 (format "[now: `%s\']" at-present)))))
532 (princ (if (string-match "[ \t]+\n" line)
533 (replace-match "\n" t t line)
534 line))))
535
536 (setq last-binding binding)))))
537
538(provide 'bind-key)
539
540;; Local Variables:
541;; outline-regexp: ";;;\\(;* [^\s\t\n]\\|###autoload\\)\\|("
542;; End:
543
544;;; bind-key.el ends here
diff --git a/lisp/use-package/use-package-bind-key.el b/lisp/use-package/use-package-bind-key.el
new file mode 100644
index 00000000000..75def7febdf
--- /dev/null
+++ b/lisp/use-package/use-package-bind-key.el
@@ -0,0 +1,171 @@
1;;; use-package-bind-key.el --- Support for the :bind/:bind-keymap keywords -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
4
5;; Author: John Wiegley <johnw@newartisans.com>
6;; Maintainer: John Wiegley <johnw@newartisans.com>
7
8;; This program is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation, either version 3 of the License, or
11;; (at your option) any later version.
12
13;; This program is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with this program. If not, see <https://www.gnu.org/licenses/>.
20
21;;; Commentary:
22
23;; Provides support for the :bind, :bind*, :bind-keymap and :bind-keymap*
24;; keywords. Note that these are currently still baked into
25;; `use-package-keywords' and `use-package-deferring-keywords', although this
26;; is harmless if they are never used.
27
28;;; Code:
29
30(require 'use-package-core)
31(require 'bind-key)
32
33;;;###autoload
34(defun use-package-autoload-keymap (keymap-symbol package override)
35 "Loads PACKAGE and then binds the key sequence used to invoke
36this function to KEYMAP-SYMBOL. It then simulates pressing the
37same key sequence a again, so that the next key pressed is routed
38to the newly loaded keymap.
39
40This function supports use-package's :bind-keymap keyword. It
41works by binding the given key sequence to an invocation of this
42function for a particular keymap. The keymap is expected to be
43defined by the package. In this way, loading the package is
44deferred until the prefix key sequence is pressed."
45 (if (not (require package nil t))
46 (use-package-error (format "Cannot load package.el: %s" package))
47 (if (and (boundp keymap-symbol)
48 (keymapp (symbol-value keymap-symbol)))
49 (let* ((kv (this-command-keys-vector))
50 (key (key-description kv))
51 (keymap (symbol-value keymap-symbol)))
52 (if override
53 (bind-key* key keymap)
54 (bind-key key keymap))
55 (setq unread-command-events
56 (mapcar (lambda (ev) (cons t ev))
57 (listify-key-sequence kv))))
58 (use-package-error
59 (format "package.el %s failed to define keymap %s"
60 package keymap-symbol)))))
61
62;;;###autoload
63(defun use-package-normalize-binder (name keyword args)
64 (let ((arg args)
65 args*)
66 (while arg
67 (let ((x (car arg)))
68 (cond
69 ;; (KEY . COMMAND)
70 ((and (consp x)
71 (or (stringp (car x))
72 (vectorp (car x)))
73 (or (use-package-recognize-function (cdr x) t #'stringp)))
74 (setq args* (nconc args* (list x)))
75 (setq arg (cdr arg)))
76 ;; KEYWORD
77 ;; :map KEYMAP
78 ;; :prefix-docstring STRING
79 ;; :prefix-map SYMBOL
80 ;; :prefix STRING
81 ;; :repeat-docstring STRING
82 ;; :repeat-map SYMBOL
83 ;; :filter SEXP
84 ;; :menu-name STRING
85 ;; :package SYMBOL
86 ;; :continue and :exit are used within :repeat-map
87 ((or (and (eq x :map) (symbolp (cadr arg)))
88 (and (eq x :prefix) (stringp (cadr arg)))
89 (and (eq x :prefix-map) (symbolp (cadr arg)))
90 (and (eq x :prefix-docstring) (stringp (cadr arg)))
91 (and (eq x :repeat-map) (symbolp (cadr arg)))
92 (eq x :continue)
93 (eq x :exit)
94 (and (eq x :repeat-docstring) (stringp (cadr arg)))
95 (eq x :filter)
96 (and (eq x :menu-name) (stringp (cadr arg)))
97 (and (eq x :package) (symbolp (cadr arg))))
98 (setq args* (nconc args* (list x (cadr arg))))
99 (setq arg (cddr arg)))
100 ((listp x)
101 (setq args*
102 (nconc args* (use-package-normalize-binder name keyword x)))
103 (setq arg (cdr arg)))
104 (t
105 ;; Error!
106 (use-package-error
107 (concat (symbol-name name)
108 " wants arguments acceptable to the `bind-keys' macro,"
109 " or a list of such values"))))))
110 args*))
111
112;;;; :bind, :bind*
113
114;;;###autoload
115(defalias 'use-package-normalize/:bind 'use-package-normalize-binder)
116;;;###autoload
117(defalias 'use-package-normalize/:bind* 'use-package-normalize-binder)
118
119;; jww (2017-12-07): This is too simplistic. It will fail to determine
120;; autoloads in this situation:
121;; (use-package foo
122;; :bind (:map foo-map (("C-a" . func))))
123;;;###autoload
124(defalias 'use-package-autoloads/:bind 'use-package-autoloads-mode)
125;;;###autoload
126(defalias 'use-package-autoloads/:bind* 'use-package-autoloads-mode)
127
128;;;###autoload
129(defun use-package-handler/:bind
130 (name _keyword args rest state &optional bind-macro)
131 (use-package-concat
132 (use-package-process-keywords name rest state)
133 `(,@(mapcar
134 #'(lambda (xs)
135 `(,(if bind-macro bind-macro 'bind-keys)
136 :package ,name ,@(use-package-normalize-commands xs)))
137 (use-package-split-list-at-keys :break args)))))
138
139(defun use-package-handler/:bind* (name keyword arg rest state)
140 (use-package-handler/:bind name keyword arg rest state 'bind-keys*))
141
142;;;; :bind-keymap, :bind-keymap*
143
144;;;###autoload
145(defalias 'use-package-normalize/:bind-keymap 'use-package-normalize-binder)
146;;;###autoload
147(defalias 'use-package-normalize/:bind-keymap* 'use-package-normalize-binder)
148
149;;;###autoload
150(defun use-package-handler/:bind-keymap
151 (name _keyword args rest state &optional override)
152 (use-package-concat
153 (use-package-process-keywords name rest state)
154 (mapcar
155 #'(lambda (binding)
156 `(,(if override 'bind-key* 'bind-key)
157 ,(car binding)
158 #'(lambda ()
159 (interactive)
160 (use-package-autoload-keymap
161 ',(cdr binding) ',(use-package-as-symbol name)
162 ,override))))
163 args)))
164
165;;;###autoload
166(defun use-package-handler/:bind-keymap* (name keyword arg rest state)
167 (use-package-handler/:bind-keymap name keyword arg rest state t))
168
169(provide 'use-package-bind-key)
170
171;;; use-package-bind-key.el ends here
diff --git a/lisp/use-package/use-package-chords.el b/lisp/use-package/use-package-chords.el
new file mode 100644
index 00000000000..479083b9296
--- /dev/null
+++ b/lisp/use-package/use-package-chords.el
@@ -0,0 +1,54 @@
1;;; use-package-chords.el --- key-chord keyword for use-package -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
4
5;; Author: Justin Talbott <justin@waymondo.com>
6;; Keywords: convenience, tools, extensions
7;; URL: https://github.com/jwiegley/use-package
8;; Version: 0.2.1
9;; Package-Requires: ((use-package "2.1") (bind-key "1.0") (bind-chord "0.2") (key-chord "0.6"))
10;; Filename: use-package-chords.el
11
12;; This program is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
16
17;; This program is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with this program. If not, see <https://www.gnu.org/licenses/>.
24
25;;; Commentary:
26
27;; The `:chords' keyword allows you to define `key-chord' bindings for
28;; `use-package' declarations in the same manner as the `:bind'
29;; keyword.
30
31;;; Code:
32
33(require 'use-package)
34(require 'bind-chord)
35
36;;;###autoload
37(defalias 'use-package-autoloads/:chords 'use-package-autoloads-mode)
38
39;;;###autoload
40(defalias 'use-package-normalize/:chords 'use-package-normalize-binder)
41
42;;;###autoload
43(defun use-package-handler/:chords (name _keyword arg rest state)
44 "Handler for `:chords' keyword in `use-package'."
45 (use-package-concat
46 (use-package-process-keywords name rest state)
47 `(,(macroexpand
48 `(bind-chords :package ,name ,@arg)))))
49
50(add-to-list 'use-package-keywords :chords)
51
52(provide 'use-package-chords)
53
54;;; use-package-chords.el ends here
diff --git a/lisp/use-package/use-package-core.el b/lisp/use-package/use-package-core.el
new file mode 100644
index 00000000000..6606681f2ea
--- /dev/null
+++ b/lisp/use-package/use-package-core.el
@@ -0,0 +1,1690 @@
1;;; use-package-core.el --- A configuration macro for simplifying your .emacs -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
4
5;; Author: John Wiegley <johnw@newartisans.com>
6;; Maintainer: John Wiegley <johnw@newartisans.com>
7
8;; This program is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation, either version 3 of the License, or
11;; (at your option) any later version.
12
13;; This program is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with this program. If not, see <https://www.gnu.org/licenses/>.
20
21;;; Commentary:
22
23;; The `use-package' declaration macro allows you to isolate package
24;; configuration in your ".emacs" in a way that is performance-oriented and,
25;; well, just tidy. I created it because I have over 80 packages that I use
26;; in Emacs, and things were getting difficult to manage. Yet with this
27;; utility my total load time is just under 1 second, with no loss of
28;; functionality!
29;;
30;; Please see README.md from the same repository for documentation.
31
32;;; Code:
33
34(require 'bytecomp)
35(require 'cl-lib)
36(require 'tabulated-list)
37
38(eval-and-compile
39 ;; Declare a synthetic theme for :custom variables.
40 ;; Necessary in order to avoid having those variables saved by custom.el.
41 (deftheme use-package))
42
43(enable-theme 'use-package)
44;; Remove the synthetic use-package theme from the enabled themes, so
45;; iterating over them to "disable all themes" won't disable it.
46(setq custom-enabled-themes (remq 'use-package custom-enabled-themes))
47
48(eval-when-compile
49 (if (and (eq emacs-major-version 24) (eq emacs-minor-version 3))
50 (progn
51 (defsubst hash-table-keys (hash-table)
52 "Return a list of keys in HASH-TABLE."
53 (cl-loop for k being the hash-keys of hash-table collect k))
54 (defsubst string-suffix-p (suffix string &optional ignore-case)
55 (let ((start-pos (- (length string) (length suffix))))
56 (and (>= start-pos 0)
57 (eq t (compare-strings suffix nil nil
58 string start-pos nil ignore-case))))))
59 (require 'subr-x)))
60
61(eval-when-compile
62 (require 'regexp-opt))
63
64(defgroup use-package nil
65 "A `use-package' declaration for simplifying your `.emacs'."
66 :group 'startup)
67
68(defconst use-package-version "2.4.4"
69 "This version of `use-package'.")
70
71(defcustom use-package-keywords
72 '(:disabled
73 :load-path
74 :requires
75 :defines
76 :functions
77 :preface
78 :if :when :unless
79 :no-require
80 :catch
81 :after
82 :custom
83 :custom-face
84 :bind
85 :bind*
86 :bind-keymap
87 :bind-keymap*
88 :interpreter
89 :mode
90 :magic
91 :magic-fallback
92 :hook
93 ;; Any other keyword that also declares commands to be autoloaded (such as
94 ;; :bind) must appear before this keyword.
95 :commands
96 :autoload
97 :init
98 :defer
99 :demand
100 :load
101 ;; This must occur almost last; the only forms which should appear after
102 ;; are those that must happen directly after the config forms.
103 :config)
104 "The set of valid keywords, in the order they are processed in.
105The order of this list is *very important*, so it is only
106advisable to insert new keywords, never to delete or reorder
107them. Further, attention should be paid to the NEWS.md if the
108default order ever changes, as they may have subtle effects on
109the semantics of `use-package' declarations and may necessitate
110changing where you had inserted a new keyword earlier.
111
112Note that `:disabled' is special in this list, as it causes
113nothing at all to happen, even if the rest of the `use-package'
114declaration is incorrect."
115 :type '(repeat symbol)
116 :group 'use-package)
117
118(defcustom use-package-deferring-keywords
119 '(:bind-keymap
120 :bind-keymap*
121 :commands
122 :autoload)
123 "Unless `:demand' is used, keywords in this list imply deferred loading.
124The reason keywords like `:hook' are not in this list is that
125they only imply deferred loading if they reference actual
126function symbols that can be autoloaded from the module; whereas
127the default keywords provided here always defer loading unless
128otherwise requested."
129 :type '(repeat symbol)
130 :group 'use-package)
131
132(defcustom use-package-ignore-unknown-keywords nil
133 "If non-nil, warn instead of signaling error for unknown keywords.
134The unknown keyword and its associated arguments will be ignored
135in the `use-package' expansion."
136 :type 'boolean
137 :group 'use-package)
138
139(defcustom use-package-use-theme t
140 "If non-nil, use a custom theme to avoid saving :custom
141variables twice (once in the Custom file, once in the use-package
142call)."
143 :type 'boolean
144 :group 'use-package)
145
146(defcustom use-package-verbose nil
147 "Whether to report about loading and configuration details.
148If you customize this, then you should require the `use-package'
149feature in files that use `use-package', even if these files only
150contain compiled expansions of the macros. If you don't do so,
151then the expanded macros do their job silently."
152 :type '(choice (const :tag "Quiet, without catching errors" errors)
153 (const :tag "Quiet" nil)
154 (const :tag "Verbose" t)
155 (const :tag "Debug" debug))
156 :group 'use-package)
157
158(defcustom use-package-check-before-init nil
159 "If non-nil, check that package exists before executing its `:init' block.
160This check is performed by calling `locate-library'."
161 :type 'boolean
162 :group 'use-package)
163
164(defcustom use-package-always-defer nil
165 "If non-nil, assume `:defer t' unless `:demand' is used.
166See also `use-package-defaults', which uses this value."
167 :type 'boolean
168 :group 'use-package)
169
170(defcustom use-package-always-demand nil
171 "If non-nil, assume `:demand t' unless `:defer' is used.
172See also `use-package-defaults', which uses this value."
173 :type 'boolean
174 :group 'use-package)
175
176(defcustom use-package-defaults
177 '(;; this '(t) has special meaning; see `use-package-handler/:config'
178 (:config '(t) t)
179 (:init nil t)
180 (:catch t (lambda (name args)
181 (not use-package-expand-minimally)))
182 (:defer use-package-always-defer
183 (lambda (name args)
184 (and use-package-always-defer
185 (not (plist-member args :defer))
186 (not (plist-member args :demand)))))
187 (:demand use-package-always-demand
188 (lambda (name args)
189 (and use-package-always-demand
190 (not (plist-member args :defer))
191 (not (plist-member args :demand))))))
192 "Default values for specified `use-package' keywords.
193Each entry in the alist is a list of three elements:
194The first element is the `use-package' keyword.
195
196The second is a form that can be evaluated to get the default
197value. It can also be a function that will receive the name of
198the `use-package' declaration and the keyword plist given to
199`use-package', in normalized form. The value it returns should
200also be in normalized form (which is sometimes *not* what one
201would normally write in a `use-package' declaration, so use
202caution).
203
204The third element is a form that can be evaluated to determine
205whether or not to assign a default value; if it evaluates to nil,
206then the default value is not assigned even if the keyword is not
207present in the `use-package' form. This third element may also be
208a function, in which case it receives the name of the package (as
209a symbol) and a list of keywords (in normalized form). It should
210return nil or non-nil depending on whether defaulting should be
211attempted."
212 :type `(repeat
213 (list (choice :tag "Keyword"
214 ,@(mapcar #'(lambda (k) (list 'const k))
215 use-package-keywords))
216 (choice :tag "Default value" sexp function)
217 (choice :tag "Enable if non-nil" sexp function)))
218 :group 'use-package)
219
220(defcustom use-package-merge-key-alist
221 '((:if . (lambda (new old) `(and ,new ,old)))
222 (:after . (lambda (new old) `(:all ,new ,old)))
223 (:defer . (lambda (new old) old))
224 (:bind . (lambda (new old) (append new (list :break) old))))
225 "Alist of keys and the functions used to merge multiple values.
226For example, if the following form is provided:
227
228 (use-package foo :if pred1 :if pred2)
229
230Then based on the above defaults, the merged result will be:
231
232 (use-package foo :if (and pred1 pred2))
233
234This is done so that, at the stage of invoking handlers, each
235handler is called only once."
236 :type `(repeat
237 (cons (choice :tag "Keyword"
238 ,@(mapcar #'(lambda (k) (list 'const k))
239 use-package-keywords)
240 (const :tag "Any" t))
241 function))
242 :group 'use-package)
243
244(defcustom use-package-hook-name-suffix "-hook"
245 "Text append to the name of hooks mentioned by :hook.
246Set to nil if you don't want this to happen; it's only a
247convenience."
248 :type '(choice string (const :tag "No suffix" nil))
249 :group 'use-package)
250
251(defcustom use-package-minimum-reported-time 0.1
252 "Minimal load time that will be reported.
253Note that `use-package-verbose' has to be set to a non-nil value
254for anything to be reported at all."
255 :type 'number
256 :group 'use-package)
257
258(defcustom use-package-inject-hooks nil
259 "If non-nil, add hooks to the `:init' and `:config' sections.
260In particular, for a given package `foo', the following hooks
261become available:
262
263 `use-package--foo--pre-init-hook'
264 `use-package--foo--post-init-hook'
265 `use-package--foo--pre-config-hook'
266 `use-package--foo--post-config-hook'
267
268This way, you can add to these hooks before evaluation of a
269`use-package` declaration, and exercise some control over what
270happens.
271
272NOTE: These hooks are run even if the user does not specify an
273`:init' or `:config' block, and they will happen at the regular
274time when initialization and configuration would have been
275performed.
276
277NOTE: If the `pre-init' hook return a nil value, that block's
278user-supplied configuration is not evaluated, so be certain to
279return t if you only wish to add behavior to what the user had
280specified."
281 :type 'boolean
282 :group 'use-package)
283
284(defcustom use-package-expand-minimally nil
285 "If non-nil, make the expanded code as minimal as possible.
286This disables:
287
288 - Printing to the *Messages* buffer of slowly-evaluating forms
289 - Capturing of load errors (normally redisplayed as warnings)
290 - Conditional loading of packages (load failures become errors)
291
292The main advantage to this variable is that, if you know your
293configuration works, it will make the byte-compiled file as
294minimal as possible. It can also help with reading macro-expanded
295definitions, to understand the main intent of what's happening."
296 :type 'boolean
297 :group 'use-package)
298
299(defcustom use-package-form-regexp-eval
300 `(concat ,(eval-when-compile
301 (concat "^\\s-*("
302 (regexp-opt '("use-package" "require") t)
303 "\\s-+\\("))
304 (or (bound-and-true-p lisp-mode-symbol-regexp)
305 "\\(?:\\sw\\|\\s_\\|\\\\.\\)+") "\\)")
306 "Sexp providing regexp for finding `use-package' forms in user files.
307This is used by `use-package-jump-to-package-form' and
308`use-package-enable-imenu-support'."
309 :type 'sexp
310 :group 'use-package)
311
312(defcustom use-package-enable-imenu-support nil
313 "If non-nil, cause imenu to see `use-package' declarations.
314This is done by adjusting `lisp-imenu-generic-expression' to
315include support for finding `use-package' and `require' forms.
316
317Must be set before loading `use-package'."
318 :type 'boolean
319 :set
320 #'(lambda (sym value)
321 (eval-after-load 'lisp-mode
322 (if value
323 `(add-to-list 'lisp-imenu-generic-expression
324 (list "Packages" ,use-package-form-regexp-eval 2))
325 `(setq lisp-imenu-generic-expression
326 (remove (list "Packages" ,use-package-form-regexp-eval 2)
327 lisp-imenu-generic-expression))))
328 (set-default sym value))
329 :group 'use-package)
330
331(defconst use-package-font-lock-keywords
332 '(("(\\(use-package\\)\\_>[ \t']*\\(\\(?:\\sw\\|\\s_\\)+\\)?"
333 (1 font-lock-keyword-face)
334 (2 font-lock-constant-face nil t))))
335
336(font-lock-add-keywords 'emacs-lisp-mode use-package-font-lock-keywords)
337
338(defcustom use-package-compute-statistics nil
339 "If non-nil, compute statistics concerned `use-package' declarations.
340View the statistical report using `use-package-report'. Note that
341if this option is enabled, you must require `use-package' in your
342user init file at loadup time, or you will see errors concerning
343undefined variables."
344 :type 'boolean
345 :group 'use-package)
346
347(defvar use-package-statistics (make-hash-table))
348
349;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
350;;
351;;; Utility functions
352;;
353
354(defsubst use-package-error (msg)
355 "Report MSG as an error, so the user knows it came from this package."
356 (error "use-package: %s" msg))
357
358(defsubst use-package-concat (&rest elems)
359 "Delete all empty lists from ELEMS (nil or (list nil)), and append them."
360 (apply #'append (delete nil (delete (list nil) elems))))
361
362(defsubst use-package-non-nil-symbolp (sym)
363 (and sym (symbolp sym)))
364
365(defsubst use-package-as-symbol (string-or-symbol)
366 "If STRING-OR-SYMBOL is already a symbol, return it.
367Otherwise convert it to a symbol and return that."
368 (if (symbolp string-or-symbol) string-or-symbol
369 (intern string-or-symbol)))
370
371(defsubst use-package-as-string (string-or-symbol)
372 "If STRING-OR-SYMBOL is already a string, return it.
373Otherwise convert it to a string and return that."
374 (if (stringp string-or-symbol) string-or-symbol
375 (symbol-name string-or-symbol)))
376
377(defsubst use-package-regex-p (re)
378 "Return t if RE is some regexp-like thing."
379 (or (and (listp re) (eq (car re) 'rx))
380 (stringp re)))
381
382(defun use-package-normalize-regex (re)
383 "Given some regexp-like thing in RE, resolve to a regular expression."
384 (cond
385 ((and (listp re) (eq (car re) 'rx)) (eval re))
386 ((stringp re) re)
387 (t (error "Not recognized as regular expression: %s" re))))
388
389(defsubst use-package-is-pair (x car-pred cdr-pred)
390 "Return non-nil if X is a cons satisfying the given predicates.
391CAR-PRED and CDR-PRED are applied to X's `car' and `cdr',
392respectively."
393 (and (consp x)
394 (funcall car-pred (car x))
395 (funcall cdr-pred (cdr x))))
396
397(defun use-package-as-mode (string-or-symbol)
398 "If STRING-OR-SYMBOL ends in `-mode' (or its name does), return
399it as a symbol. Otherwise, return it as a symbol with `-mode'
400appended."
401 (let ((string (use-package-as-string string-or-symbol)))
402 (intern (if (string-match "-mode\\'" string)
403 string
404 (concat string "-mode")))))
405
406(defsubst use-package-load-name (name &optional noerror)
407 "Return a form which will load or require NAME.
408It does the right thing no matter if NAME is a string or symbol.
409Argument NOERROR means to indicate load failures as a warning."
410 (if (stringp name)
411 `(load ,name ,noerror)
412 `(require ',name nil ,noerror)))
413
414(defun use-package-hook-injector (name-string keyword body)
415 "Wrap pre/post hook injections around the given BODY for KEYWORD.
416The BODY is a list of forms, so `((foo))' if only `foo' is being called."
417 (if (not use-package-inject-hooks)
418 body
419 (let ((keyword-name (substring (format "%s" keyword) 1)))
420 `((when (run-hook-with-args-until-failure
421 ',(intern (concat "use-package--" name-string
422 "--pre-" keyword-name "-hook")))
423 ,@body
424 (run-hooks
425 ',(intern (concat "use-package--" name-string
426 "--post-" keyword-name "-hook"))))))))
427
428(defun use-package-with-elapsed-timer (text body)
429 "BODY is a list of forms, so `((foo))' if only `foo' is being called."
430 (declare (indent 1))
431 (if use-package-expand-minimally
432 body
433 (let ((nowvar (make-symbol "now")))
434 (if (bound-and-true-p use-package-verbose)
435 `((let ((,nowvar (current-time)))
436 (message "%s..." ,text)
437 (prog1
438 ,(macroexp-progn body)
439 (let ((elapsed
440 (float-time (time-subtract (current-time) ,nowvar))))
441 (if (> elapsed ,use-package-minimum-reported-time)
442 (message "%s...done (%.3fs)" ,text elapsed)
443 (message "%s...done" ,text))))))
444 body))))
445
446(put 'use-package-with-elapsed-timer 'lisp-indent-function 1)
447
448(defun use-package-require (name &optional no-require body)
449 (if use-package-expand-minimally
450 (use-package-concat
451 (unless no-require
452 (list (use-package-load-name name)))
453 body)
454 (if no-require
455 body
456 (use-package-with-elapsed-timer
457 (format "Loading package %s" name)
458 `((if (not ,(use-package-load-name name t))
459 (display-warning 'use-package
460 (format "Cannot load %s" ',name)
461 :error)
462 ,@body))))))
463
464;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
465;;
466;;; Property lists
467;;
468
469(defun use-package-plist-delete (plist property)
470 "Delete PROPERTY from PLIST.
471This is in contrast to merely setting it to 0."
472 (let (p)
473 (while plist
474 (if (not (eq property (car plist)))
475 (setq p (plist-put p (car plist) (nth 1 plist))))
476 (setq plist (cddr plist)))
477 p))
478
479(defun use-package-plist-delete-first (plist property)
480 "Delete PROPERTY from PLIST.
481This is in contrast to merely setting it to 0."
482 (let (p)
483 (while plist
484 (if (eq property (car plist))
485 (setq p (nconc p (cddr plist))
486 plist nil)
487 (setq p (nconc p (list (car plist) (cadr plist)))
488 plist (cddr plist))))
489 p))
490
491(defsubst use-package-plist-maybe-put (plist property value)
492 "Add a VALUE for PROPERTY to PLIST, if it does not already exist."
493 (if (plist-member plist property)
494 plist
495 (plist-put plist property value)))
496
497(defsubst use-package-plist-cons (plist property value)
498 "Cons VALUE onto the head of the list at PROPERTY in PLIST."
499 (plist-put plist property (cons value (plist-get plist property))))
500
501(defsubst use-package-plist-append (plist property value)
502 "Append VALUE onto the front of the list at PROPERTY in PLIST."
503 (plist-put plist property (append value (plist-get plist property))))
504
505(defun use-package-split-list (pred xs)
506 (let ((ys (list nil)) (zs (list nil)) flip)
507 (cl-dolist (x xs)
508 (if flip
509 (nconc zs (list x))
510 (if (funcall pred x)
511 (progn
512 (setq flip t)
513 (nconc zs (list x)))
514 (nconc ys (list x)))))
515 (cons (cdr ys) (cdr zs))))
516
517(defun use-package-split-list-at-keys (key lst)
518 (and lst
519 (let ((xs (use-package-split-list (apply-partially #'eq key) lst)))
520 (cons (car xs) (use-package-split-list-at-keys key (cddr xs))))))
521
522;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
523;;
524;;; Keywords
525;;
526
527(defun use-package-keyword-index (keyword)
528 (cl-loop named outer
529 with index = 0
530 for k in use-package-keywords do
531 (if (eq k keyword)
532 (cl-return-from outer index))
533 (cl-incf index)))
534
535(defun use-package-normalize-plist (name input &optional plist merge-function)
536 "Given a pseudo-plist, normalize it to a regular plist.
537The normalized key/value pairs from input are added to PLIST,
538extending any keys already present."
539 (if (null input)
540 plist
541 (let* ((keyword (car input))
542 (xs (use-package-split-list #'keywordp (cdr input)))
543 (args (car xs))
544 (tail (cdr xs))
545 (normalizer
546 (intern-soft (concat "use-package-normalize/"
547 (symbol-name keyword))))
548 (arg (and (functionp normalizer)
549 (funcall normalizer name keyword args)))
550 (error-string (format "Unrecognized keyword: %s" keyword)))
551 (if (memq keyword use-package-keywords)
552 (progn
553 (setq plist (use-package-normalize-plist
554 name tail plist merge-function))
555 (plist-put plist keyword
556 (if (plist-member plist keyword)
557 (funcall merge-function keyword arg
558 (plist-get plist keyword))
559 arg)))
560 (if use-package-ignore-unknown-keywords
561 (progn
562 (display-warning 'use-package error-string)
563 (use-package-normalize-plist
564 name tail plist merge-function))
565 (use-package-error error-string))))))
566
567(defun use-package-unalias-keywords (_name args)
568 (setq args (cl-nsubstitute :if :when args))
569 (let (temp)
570 (while (setq temp (plist-get args :unless))
571 (setq args (use-package-plist-delete-first args :unless)
572 args (append args `(:if (not ,temp))))))
573 args)
574
575(defun use-package-merge-keys (key new old)
576 (let ((merger (assq key use-package-merge-key-alist)))
577 (if merger
578 (funcall (cdr merger) new old)
579 (append new old))))
580
581(defun use-package-sort-keywords (plist)
582 (let (plist-grouped)
583 (while plist
584 (push (cons (car plist) (cadr plist))
585 plist-grouped)
586 (setq plist (cddr plist)))
587 (let (result)
588 (cl-dolist
589 (x
590 (nreverse
591 (sort plist-grouped
592 #'(lambda (l r) (< (use-package-keyword-index (car l))
593 (use-package-keyword-index (car r)))))))
594 (setq result (cons (car x) (cons (cdr x) result))))
595 result)))
596
597(defun use-package-normalize-keywords (name args)
598 (let* ((name-symbol (if (stringp name) (intern name) name))
599 (name-string (symbol-name name-symbol)))
600
601 ;; The function `elisp--local-variables' inserts this unbound variable into
602 ;; macro forms to determine the locally bound variables for
603 ;; `elisp-completion-at-point'. It ends up throwing a lot of errors since it
604 ;; can occupy the position of a keyword (or look like a second argument to a
605 ;; keyword that takes one). Deleting it when it's at the top level should be
606 ;; harmless since there should be no locally bound variables to discover
607 ;; here anyway.
608 (setq args (delq 'elisp--witness--lisp args))
609
610 ;; Reduce the set of keywords down to its most fundamental expression.
611 (setq args (use-package-unalias-keywords name-symbol args))
612
613 ;; Normalize keyword values, coalescing multiple occurrences.
614 (setq args (use-package-normalize-plist name-symbol args nil
615 #'use-package-merge-keys))
616
617 ;; Add default values for keywords not specified, when applicable.
618 (cl-dolist (spec use-package-defaults)
619 (when (let ((func (nth 2 spec)))
620 (if (and func (functionp func))
621 (funcall func name args)
622 (eval func)))
623 (setq args (use-package-plist-maybe-put
624 args (nth 0 spec)
625 (let ((func (nth 1 spec)))
626 (if (and func (functionp func))
627 (funcall func name args)
628 (eval func)))))))
629
630 ;; Determine any autoloads implied by the keywords used.
631 (let ((iargs args)
632 commands)
633 (while iargs
634 (when (keywordp (car iargs))
635 (let ((autoloads
636 (intern-soft (concat "use-package-autoloads/"
637 (symbol-name (car iargs))))))
638 (when (functionp autoloads)
639 (setq commands
640 ;; jww (2017-12-07): Right now we just ignored the type of
641 ;; the autoload being requested, and assume they are all
642 ;; `command'.
643 (append (mapcar
644 #'car
645 (funcall autoloads name-symbol (car iargs)
646 (cadr iargs)))
647 commands)))))
648 (setq iargs (cddr iargs)))
649 (when commands
650 (setq args
651 ;; Like `use-package-plist-append', but removing duplicates.
652 (plist-put args :commands
653 (delete-dups
654 (append commands (plist-get args :commands)))))))
655
656 ;; If byte-compiling, pre-load the package so all its symbols are in
657 ;; scope. This is done by prepending statements to the :preface.
658 (when (bound-and-true-p byte-compile-current-file)
659 (setq args
660 (use-package-plist-append
661 args :preface
662 (use-package-concat
663 (mapcar #'(lambda (var) `(defvar ,var))
664 (plist-get args :defines))
665 (mapcar #'(lambda (fn) `(declare-function ,fn ,name-string))
666 (plist-get args :functions))
667 `((eval-when-compile
668 (with-demoted-errors
669 ,(format "Cannot load %s: %%S" name-string)
670 ,(when (eq use-package-verbose 'debug)
671 `(message ,(format "Compiling package %s" name-string)))
672 ,(unless (plist-get args :no-require)
673 `(unless (featurep ',name-symbol)
674 (load ,name-string nil t))))))))))
675
676 ;; Certain keywords imply :defer, if :demand was not specified.
677 (when (and (not (plist-member args :demand))
678 (not (plist-member args :defer))
679 (not (or (equal '(t) (plist-get args :load))
680 (equal (list (use-package-as-string name))
681 (mapcar #'use-package-as-string
682 (plist-get args :load)))))
683 (cl-some #'identity
684 (mapcar (apply-partially #'plist-member args)
685 use-package-deferring-keywords)))
686 (setq args (append args '(:defer t))))
687
688 ;; The :load keyword overrides :no-require
689 (when (and (plist-member args :load)
690 (plist-member args :no-require))
691 (setq args (use-package-plist-delete args :no-require)))
692
693 ;; If at this point no :load, :defer or :no-require has been seen, then
694 ;; :load the package itself.
695 (when (and (not (plist-member args :load))
696 (not (plist-member args :defer))
697 (not (plist-member args :no-require)))
698 (setq args (append args `(:load (,name)))))
699
700 ;; Sort the list of keywords based on the order of `use-package-keywords'.
701 (use-package-sort-keywords args)))
702
703(defun use-package-process-keywords (name plist &optional state)
704 "Process the next keyword in the free-form property list PLIST.
705The values in the PLIST have each been normalized by the function
706use-package-normalize/KEYWORD (minus the colon).
707
708STATE is a property list that the function may modify and/or
709query. This is useful if a package defines multiple keywords and
710wishes them to have some kind of stateful interaction.
711
712Unless the KEYWORD being processed intends to ignore remaining
713keywords, it must call this function recursively, passing in the
714plist with its keyword and argument removed, and passing in the
715next value for the STATE."
716 (declare (indent 1))
717 (unless (null plist)
718 (let* ((keyword (car plist))
719 (arg (cadr plist))
720 (rest (cddr plist)))
721 (unless (keywordp keyword)
722 (use-package-error (format "%s is not a keyword" keyword)))
723 (let* ((handler (concat "use-package-handler/" (symbol-name keyword)))
724 (handler-sym (intern handler)))
725 (if (functionp handler-sym)
726 (funcall handler-sym name keyword arg rest state)
727 (use-package-error
728 (format "Keyword handler not defined: %s" handler)))))))
729
730(put 'use-package-process-keywords 'lisp-indent-function 'defun)
731
732(defun use-package-list-insert (elem xs &optional anchor after test)
733 "Insert ELEM into the list XS.
734If ANCHOR is also a keyword, place the new KEYWORD before that
735one.
736If AFTER is non-nil, insert KEYWORD either at the end of the
737keywords list, or after the ANCHOR if one has been provided.
738If TEST is non-nil, it is the test used to compare ELEM to list
739elements. The default is `eq'.
740The modified list is returned. The original list is not modified."
741 (let (result)
742 (dolist (k xs)
743 (if (funcall (or test #'eq) k anchor)
744 (if after
745 (setq result (cons k result)
746 result (cons elem result))
747 (setq result (cons elem result)
748 result (cons k result)))
749 (setq result (cons k result))))
750 (if anchor
751 (nreverse result)
752 (if after
753 (nreverse (cons elem result))
754 (cons elem (nreverse result))))))
755
756;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
757;;
758;;; Argument Processing
759;;
760
761(defun use-package-only-one (label args f)
762 "Call F on the first member of ARGS if it has exactly one element."
763 (declare (indent 1))
764 (cond
765 ((and (listp args) (listp (cdr args))
766 (= (length args) 1))
767 (funcall f label (car args)))
768 (t
769 (use-package-error
770 (concat label " wants exactly one argument")))))
771
772(put 'use-package-only-one 'lisp-indent-function 'defun)
773
774(defun use-package-as-one (label args f &optional allow-empty)
775 "Call F on the first element of ARGS if it has one element, or all of ARGS.
776If ALLOW-EMPTY is non-nil, it's OK for ARGS to be an empty list."
777 (declare (indent 1))
778 (if (if args
779 (and (listp args) (listp (cdr args)))
780 allow-empty)
781 (if (= (length args) 1)
782 (funcall f label (car args))
783 (funcall f label args))
784 (use-package-error
785 (concat label " wants a non-empty list"))))
786
787(put 'use-package-as-one 'lisp-indent-function 'defun)
788
789(defun use-package-memoize (f arg)
790 "Ensure the macro-expansion of F applied to ARG evaluates ARG
791no more than once."
792 (let ((loaded (cl-gentemp "use-package--loaded"))
793 (result (cl-gentemp "use-package--result"))
794 (next (cl-gentemp "use-package--next")))
795 `((defvar ,loaded nil)
796 (defvar ,result nil)
797 (defvar ,next #'(lambda () (if ,loaded ,result
798 (setq ,loaded t ,result ,arg))))
799 ,@(funcall f `((funcall ,next))))))
800
801(defsubst use-package-normalize-value (_label arg)
802 "Normalize the Lisp value given by ARG.
803The argument LABEL is ignored."
804 (cond ((null arg) nil)
805 ((eq t arg) t)
806 ((use-package-non-nil-symbolp arg)
807 `(symbol-value ',arg))
808 ((functionp arg)
809 `(funcall #',arg))
810 (t arg)))
811
812(defun use-package-normalize-symbols (label arg &optional recursed)
813 "Normalize a list of symbols."
814 (cond
815 ((use-package-non-nil-symbolp arg)
816 (list arg))
817 ((and (not recursed) (listp arg) (listp (cdr arg)))
818 (mapcar #'(lambda (x) (car (use-package-normalize-symbols label x t))) arg))
819 (t
820 (use-package-error
821 (concat label " wants a symbol, or list of symbols")))))
822
823(defun use-package-normalize-symlist (_name keyword args)
824 (use-package-as-one (symbol-name keyword) args
825 #'use-package-normalize-symbols))
826
827(defun use-package-normalize-recursive-symbols (label arg)
828 "Normalize a list of symbols."
829 (cond
830 ((use-package-non-nil-symbolp arg)
831 arg)
832 ((and (listp arg) (listp (cdr arg)))
833 (mapcar #'(lambda (x) (use-package-normalize-recursive-symbols label x))
834 arg))
835 (t
836 (use-package-error
837 (concat label " wants a symbol, or nested list of symbols")))))
838
839(defun use-package-normalize-recursive-symlist (_name keyword args)
840 (use-package-as-one (symbol-name keyword) args
841 #'use-package-normalize-recursive-symbols))
842
843(defun use-package-normalize-paths (label arg &optional recursed)
844 "Normalize a list of filesystem paths."
845 (cond
846 ((and arg (or (use-package-non-nil-symbolp arg) (functionp arg)))
847 (let ((value (use-package-normalize-value label arg)))
848 (use-package-normalize-paths label (eval value))))
849 ((stringp arg)
850 (let ((path (if (file-name-absolute-p arg)
851 arg
852 (expand-file-name arg user-emacs-directory))))
853 (list path)))
854 ((and (not recursed) (listp arg) (listp (cdr arg)))
855 (mapcar #'(lambda (x)
856 (car (use-package-normalize-paths label x t))) arg))
857 (t
858 (use-package-error
859 (concat label " wants a directory path, or list of paths")))))
860
861(defun use-package-normalize-predicate (_name keyword args)
862 (if (null args)
863 t
864 (use-package-only-one (symbol-name keyword) args
865 #'use-package-normalize-value)))
866
867(defun use-package-normalize-form (label args)
868 "Given a list of forms, return it wrapped in `progn'."
869 (unless (listp (car args))
870 (use-package-error (concat label " wants a sexp or list of sexps")))
871 (mapcar #'(lambda (form)
872 (if (and (consp form)
873 (memq (car form)
874 '(use-package bind-key bind-key*
875 unbind-key bind-keys bind-keys*)))
876 (macroexpand form)
877 form)) args))
878
879(defun use-package-normalize-forms (_name keyword args)
880 (use-package-normalize-form (symbol-name keyword) args))
881
882(defun use-package-normalize-pairs
883 (key-pred val-pred name label arg &optional recursed)
884 "Normalize a list of pairs.
885KEY-PRED and VAL-PRED are predicates recognizing valid keys and
886values, respectively.
887If RECURSED is non-nil, recurse into sublists."
888 (cond
889 ((funcall key-pred arg)
890 (list (cons arg (use-package-as-symbol name))))
891 ((use-package-is-pair arg key-pred val-pred)
892 (list arg))
893 ((and (not recursed) (listp arg) (listp (cdr arg)))
894 (let (last-item)
895 (mapcar
896 #'(lambda (x)
897 (prog1
898 (let ((ret (use-package-normalize-pairs
899 key-pred val-pred name label x t)))
900 (if (and (listp ret)
901 (not (keywordp last-item)))
902 (car ret)
903 ret))
904 (setq last-item x))) arg)))
905 (t arg)))
906
907(defun use-package-recognize-function (v &optional binding additional-pred)
908 "A predicate that recognizes functional constructions:
909 nil
910 sym
911 \\='sym
912 (quote sym)
913 #\\='sym
914 (function sym)
915 (lambda () ...)
916 \\='(lambda () ...)
917 (quote (lambda () ...))
918 #\\='(lambda () ...)
919 (function (lambda () ...))"
920 (or (if binding
921 (symbolp v)
922 (use-package-non-nil-symbolp v))
923 (and (listp v)
924 (memq (car v) '(quote function))
925 (use-package-non-nil-symbolp (cadr v)))
926 (if binding (commandp v) (functionp v))
927 (and additional-pred
928 (funcall additional-pred v))))
929
930(defun use-package-normalize-function (v)
931 "Reduce functional constructions to one of two normal forms:
932 sym
933 #\\='(lambda () ...)"
934 (cond ((symbolp v) v)
935 ((and (listp v)
936 (memq (car v) '(quote function))
937 (use-package-non-nil-symbolp (cadr v)))
938 (cadr v))
939 ((and (consp v)
940 (eq 'lambda (car v)))
941 v)
942 ((and (listp v)
943 (memq (car v) '(quote function))
944 (eq 'lambda (car (cadr v))))
945 (cadr v))
946 (t v)))
947
948(defun use-package-normalize-commands (args)
949 "Map over ARGS of the form ((_ . F) ...), normalizing functional F's."
950 (mapcar #'(lambda (x)
951 (if (consp x)
952 (cons (car x) (use-package-normalize-function (cdr x)))
953 x))
954 args))
955
956(defun use-package-normalize-mode (name keyword args)
957 "Normalize arguments for keywords which add regexp/mode pairs to an alist."
958 (use-package-as-one (symbol-name keyword) args
959 (apply-partially #'use-package-normalize-pairs
960 #'use-package-regex-p
961 #'use-package-recognize-function
962 name)))
963
964(defun use-package-autoloads-mode (_name _keyword args)
965 (mapcar
966 #'(lambda (x) (cons (cdr x) 'command))
967 (cl-remove-if-not #'(lambda (x)
968 (and (consp x)
969 (use-package-non-nil-symbolp (cdr x))))
970 args)))
971
972(defun use-package-handle-mode (name alist args rest state)
973 "Handle keywords which add regexp/mode pairs to an alist."
974 (use-package-concat
975 (use-package-process-keywords name rest state)
976 (mapcar
977 #'(lambda (thing)
978 `(add-to-list
979 ',alist
980 ',(cons (use-package-normalize-regex (car thing))
981 (cdr thing))))
982 (use-package-normalize-commands args))))
983
984;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
985;;
986;;; Statistics
987;;
988
989(defun use-package-reset-statistics ()
990 "Reset statistics for `use-package'.
991See also `use-package-statistics'."
992 (interactive)
993 (setq use-package-statistics (make-hash-table)))
994
995(defun use-package-statistics-status (package)
996 "Return loading configuration status of PACKAGE statistics."
997 (cond ((gethash :config package) "Configured")
998 ((gethash :init package) "Initialized")
999 ((gethash :preface package) "Prefaced")
1000 ((gethash :use-package package) "Declared")))
1001
1002(defun use-package-statistics-last-event (package)
1003 "Return the date when PACKAGE's status last changed.
1004The date is returned as a string."
1005 (or (gethash :config package)
1006 (gethash :init package)
1007 (gethash :preface package)
1008 (gethash :use-package package)))
1009
1010(defun use-package-statistics-time (package)
1011 "Return the time is took for PACKAGE to load."
1012 (+ (float-time (gethash :config-secs package '(0 0 0 0)))
1013 (float-time (gethash :init-secs package '(0 0 0 0)))
1014 (float-time (gethash :preface-secs package '(0 0 0 0)))
1015 (float-time (gethash :use-package-secs package '(0 0 0 0)))))
1016
1017(defun use-package-statistics-convert (package)
1018 "Return information about PACKAGE.
1019
1020The information is formatted in a way suitable for
1021`use-package-statistics-mode'."
1022 (let ((statistics (gethash package use-package-statistics)))
1023 (list
1024 package
1025 (vector
1026 (symbol-name package)
1027 (use-package-statistics-status statistics)
1028 (format-time-string
1029 "%H:%M:%S.%6N"
1030 (use-package-statistics-last-event statistics))
1031 (format "%.2f" (use-package-statistics-time statistics))))))
1032
1033(defun use-package-report ()
1034 "Show current statistics gathered about `use-package' declarations.
1035In the table that's generated, the status field has the following
1036meaning:
1037 Configured :config has been processed (the package is loaded!)
1038 Initialized :init has been processed (load status unknown)
1039 Prefaced :preface has been processed
1040 Declared the use-package declaration was seen"
1041 (interactive)
1042 (with-current-buffer (get-buffer-create "*use-package statistics*")
1043 (setq tabulated-list-entries
1044 (mapcar #'use-package-statistics-convert
1045 (hash-table-keys use-package-statistics)))
1046 (use-package-statistics-mode)
1047 (tabulated-list-print)
1048 (display-buffer (current-buffer))))
1049
1050(defvar use-package-statistics-status-order
1051 '(("Declared" . 0)
1052 ("Prefaced" . 1)
1053 ("Initialized" . 2)
1054 ("Configured" . 3)))
1055
1056(define-derived-mode use-package-statistics-mode tabulated-list-mode
1057 "use-package statistics"
1058 "Show current statistics gathered about `use-package' declarations."
1059 (setq tabulated-list-format
1060 ;; The sum of column width is 80 characters:
1061 [("Package" 25 t)
1062 ("Status" 13
1063 (lambda (a b)
1064 (< (assoc-default
1065 (use-package-statistics-status
1066 (gethash (car a) use-package-statistics))
1067 use-package-statistics-status-order)
1068 (assoc-default
1069 (use-package-statistics-status
1070 (gethash (car b) use-package-statistics))
1071 use-package-statistics-status-order))))
1072 ("Last Event" 23
1073 (lambda (a b)
1074 (< (float-time
1075 (use-package-statistics-last-event
1076 (gethash (car a) use-package-statistics)))
1077 (float-time
1078 (use-package-statistics-last-event
1079 (gethash (car b) use-package-statistics))))))
1080 ("Time" 10
1081 (lambda (a b)
1082 (< (use-package-statistics-time
1083 (gethash (car a) use-package-statistics))
1084 (use-package-statistics-time
1085 (gethash (car b) use-package-statistics)))))])
1086 (setq tabulated-list-sort-key '("Time" . t))
1087 (tabulated-list-init-header))
1088
1089(defun use-package-statistics-gather (keyword name after)
1090 (let* ((hash (gethash name use-package-statistics
1091 (make-hash-table)))
1092 (before (and after (gethash keyword hash (current-time)))))
1093 (puthash keyword (current-time) hash)
1094 (when after
1095 (puthash (intern (concat (symbol-name keyword) "-secs"))
1096 (time-subtract (current-time) before) hash))
1097 (puthash name hash use-package-statistics)))
1098
1099;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1100;;
1101;;; Handlers
1102;;
1103
1104;;;; :disabled
1105
1106;; Don't alias this to `ignore', as that will cause the resulting
1107;; function to be interactive.
1108(defun use-package-normalize/:disabled (_name _keyword _arg)
1109 "Do nothing, return nil.")
1110
1111(defun use-package-handler/:disabled (name _keyword _arg rest state)
1112 (use-package-process-keywords name rest state))
1113
1114;;;; :if, :when and :unless
1115
1116(defun use-package-normalize-test (_name keyword args)
1117 (use-package-only-one (symbol-name keyword) args
1118 #'use-package-normalize-value))
1119
1120(defalias 'use-package-normalize/:if 'use-package-normalize-test)
1121
1122(defun use-package-handler/:if (name _keyword pred rest state)
1123 (let ((body (use-package-process-keywords name rest state)))
1124 `((when ,pred ,@body))))
1125
1126(defalias 'use-package-normalize/:when 'use-package-normalize-test)
1127
1128(defalias 'use-package-handler/:when 'use-package-handler/:if)
1129
1130(defalias 'use-package-normalize/:unless 'use-package-normalize-test)
1131
1132(defun use-package-handler/:unless (name _keyword pred rest state)
1133 (let ((body (use-package-process-keywords name rest state)))
1134 `((unless ,pred ,@body))))
1135
1136;;;; :requires
1137
1138(defalias 'use-package-normalize/:requires 'use-package-normalize-symlist)
1139
1140(defun use-package-handler/:requires (name _keyword requires rest state)
1141 (let ((body (use-package-process-keywords name rest state)))
1142 (if (null requires)
1143 body
1144 `((when ,(if (> (length requires) 1)
1145 `(not (member nil (mapcar #'featurep ',requires)))
1146 `(featurep ',(car requires)))
1147 ,@body)))))
1148
1149;;;; :load-path
1150
1151(defun use-package-normalize/:load-path (_name keyword args)
1152 (use-package-as-one (symbol-name keyword) args
1153 #'use-package-normalize-paths))
1154
1155(defun use-package-handler/:load-path (name _keyword arg rest state)
1156 (let ((body (use-package-process-keywords name rest state)))
1157 (use-package-concat
1158 (mapcar #'(lambda (path)
1159 `(eval-and-compile (add-to-list 'load-path ,path)))
1160 arg)
1161 body)))
1162
1163;;;; :no-require
1164
1165(defalias 'use-package-normalize/:no-require 'use-package-normalize-predicate)
1166
1167(defun use-package-handler/:no-require (name _keyword _arg rest state)
1168 (use-package-process-keywords name rest state))
1169
1170;;;; :defines
1171
1172(defalias 'use-package-normalize/:defines 'use-package-normalize-symlist)
1173
1174(defun use-package-handler/:defines (name _keyword _arg rest state)
1175 (use-package-process-keywords name rest state))
1176
1177;;;; :functions
1178
1179(defalias 'use-package-normalize/:functions 'use-package-normalize-symlist)
1180
1181(defun use-package-handler/:functions (name _keyword _arg rest state)
1182 (use-package-process-keywords name rest state))
1183
1184;;;; :preface
1185
1186(defalias 'use-package-normalize/:preface 'use-package-normalize-forms)
1187
1188(defun use-package-handler/:preface (name _keyword arg rest state)
1189 (let ((body (use-package-process-keywords name rest state)))
1190 (use-package-concat
1191 (when use-package-compute-statistics
1192 `((use-package-statistics-gather :preface ',name nil)))
1193 (when arg
1194 `((eval-and-compile ,@arg)))
1195 body
1196 (when use-package-compute-statistics
1197 `((use-package-statistics-gather :preface ',name t))))))
1198
1199;;;; :catch
1200
1201(defvar use-package--form)
1202(defvar use-package--hush-function #'(lambda (_keyword body) body))
1203
1204(defsubst use-package-hush (context keyword body)
1205 `((condition-case-unless-debug err
1206 ,(macroexp-progn body)
1207 (error (funcall ,context ,keyword err)))))
1208
1209(defun use-package-normalize/:catch (_name keyword args)
1210 (if (null args)
1211 t
1212 (use-package-only-one (symbol-name keyword) args
1213 use-package--hush-function)))
1214
1215(defun use-package-handler/:catch (name keyword arg rest state)
1216 (let* ((context (cl-gentemp "use-package--warning")))
1217 (cond
1218 ((not arg)
1219 (use-package-process-keywords name rest state))
1220 ((eq arg t)
1221 `((defvar ,context
1222 #'(lambda (keyword err)
1223 (let ((msg (format "%s/%s: %s" ',name keyword
1224 (error-message-string err))))
1225 ,@(when (eq use-package-verbose 'debug)
1226 `((with-current-buffer
1227 (get-buffer-create "*use-package*")
1228 (goto-char (point-max))
1229 (insert "-----\n" msg ,use-package--form)
1230 (emacs-lisp-mode))
1231 (setq msg
1232 (concat msg
1233 " (see the *use-package* buffer)"))))
1234 (display-warning 'use-package msg :error))))
1235 ,@(let ((use-package--hush-function
1236 (apply-partially #'use-package-hush context)))
1237 (funcall use-package--hush-function keyword
1238 (use-package-process-keywords name rest state)))))
1239 ((functionp arg)
1240 `((defvar ,context ,arg)
1241 ,@(let ((use-package--hush-function
1242 (apply-partially #'use-package-hush context)))
1243 (funcall use-package--hush-function keyword
1244 (use-package-process-keywords name rest state)))))
1245 (t
1246 (use-package-error "The :catch keyword expects 't' or a function")))))
1247
1248;;;; :interpreter
1249
1250(defalias 'use-package-normalize/:interpreter 'use-package-normalize-mode)
1251(defalias 'use-package-autoloads/:interpreter 'use-package-autoloads-mode)
1252
1253(defun use-package-handler/:interpreter (name _keyword arg rest state)
1254 (use-package-handle-mode name 'interpreter-mode-alist arg rest state))
1255
1256;;;; :mode
1257
1258(defalias 'use-package-normalize/:mode 'use-package-normalize-mode)
1259(defalias 'use-package-autoloads/:mode 'use-package-autoloads-mode)
1260
1261(defun use-package-handler/:mode (name _keyword arg rest state)
1262 (use-package-handle-mode name 'auto-mode-alist arg rest state))
1263
1264;;;; :magic
1265
1266(defalias 'use-package-normalize/:magic 'use-package-normalize-mode)
1267(defalias 'use-package-autoloads/:magic 'use-package-autoloads-mode)
1268
1269(defun use-package-handler/:magic (name _keyword arg rest state)
1270 (use-package-handle-mode name 'magic-mode-alist arg rest state))
1271
1272;;;; :magic-fallback
1273
1274(defalias 'use-package-normalize/:magic-fallback 'use-package-normalize-mode)
1275(defalias 'use-package-autoloads/:magic-fallback 'use-package-autoloads-mode)
1276
1277(defun use-package-handler/:magic-fallback (name _keyword arg rest state)
1278 (use-package-handle-mode name 'magic-fallback-mode-alist arg rest state))
1279
1280;;;; :hook
1281
1282(defun use-package-normalize/:hook (name keyword args)
1283 (use-package-as-one (symbol-name keyword) args
1284 #'(lambda (label arg)
1285 (unless (or (use-package-non-nil-symbolp arg) (consp arg))
1286 (use-package-error
1287 (concat label " a <symbol> or (<symbol or list of symbols> . <symbol or function>)"
1288 " or list of these")))
1289 (use-package-normalize-pairs
1290 #'(lambda (k)
1291 (or (use-package-non-nil-symbolp k)
1292 (and k (let ((every t))
1293 (while (and every k)
1294 (if (and (consp k)
1295 (use-package-non-nil-symbolp (car k)))
1296 (setq k (cdr k))
1297 (setq every nil)))
1298 every))))
1299 #'use-package-recognize-function
1300 (if (string-suffix-p "-mode" (symbol-name name))
1301 name
1302 (intern (concat (symbol-name name) "-mode")))
1303 label arg))))
1304
1305(defalias 'use-package-autoloads/:hook 'use-package-autoloads-mode)
1306
1307(defun use-package-handler/:hook (name _keyword args rest state)
1308 "Generate use-package custom keyword code."
1309 (use-package-concat
1310 (use-package-process-keywords name rest state)
1311 (cl-mapcan
1312 #'(lambda (def)
1313 (let ((syms (car def))
1314 (fun (cdr def)))
1315 (when fun
1316 (mapcar
1317 #'(lambda (sym)
1318 `(add-hook
1319 (quote ,(intern
1320 (concat (symbol-name sym)
1321 use-package-hook-name-suffix)))
1322 (function ,fun)))
1323 (use-package-hook-handler-normalize-mode-symbols syms)))))
1324 (use-package-normalize-commands args))))
1325
1326(defun use-package-hook-handler-normalize-mode-symbols (syms)
1327 "Ensure that `SYMS' turns into a list of modes."
1328 (if (use-package-non-nil-symbolp syms) (list syms) syms))
1329
1330;;;; :commands
1331
1332(defalias 'use-package-normalize/:commands 'use-package-normalize-symlist)
1333
1334(defun use-package-handler/:commands (name _keyword arg rest state)
1335 (use-package-concat
1336 ;; Since we deferring load, establish any necessary autoloads, and also
1337 ;; keep the byte-compiler happy.
1338 (let ((name-string (use-package-as-string name)))
1339 (cl-mapcan
1340 #'(lambda (command)
1341 (when (symbolp command)
1342 (append
1343 (unless (plist-get state :demand)
1344 `((unless (fboundp ',command)
1345 (autoload #',command ,name-string nil t))))
1346 (when (bound-and-true-p byte-compile-current-file)
1347 `((eval-when-compile
1348 (declare-function ,command ,name-string)))))))
1349 (delete-dups arg)))
1350 (use-package-process-keywords name rest state)))
1351
1352;;;; :autoload
1353
1354(defalias 'use-package-normalize/:autoload 'use-package-normalize/:commands)
1355
1356(defun use-package-handler/:autoload (name _keyword arg rest state)
1357 (use-package-concat
1358 ;; Since we deferring load, establish any necessary autoloads, and also
1359 ;; keep the byte-compiler happy.
1360 (let ((name-string (use-package-as-string name)))
1361 (cl-mapcan
1362 #'(lambda (command)
1363 (when (symbolp command)
1364 (append
1365 (unless (plist-get state :demand)
1366 `((unless (fboundp ',command)
1367 (autoload #',command ,name-string))))
1368 (when (bound-and-true-p byte-compile-current-file)
1369 `((eval-when-compile
1370 (declare-function ,command ,name-string)))))))
1371 (delete-dups arg)))
1372 (use-package-process-keywords name rest state)))
1373
1374;;;; :defer
1375
1376(defalias 'use-package-normalize/:defer 'use-package-normalize-predicate)
1377
1378(defun use-package-handler/:defer (name _keyword arg rest state)
1379 (let ((body (use-package-process-keywords name rest state)))
1380 (use-package-concat
1381 ;; Load the package after a set amount of idle time, if the argument to
1382 ;; `:defer' was a number.
1383 (when (numberp arg)
1384 `((run-with-idle-timer ,arg nil #'require
1385 ',(use-package-as-symbol name) nil t)))
1386 (if (or (not arg) (null body))
1387 body
1388 `((eval-after-load ',name ',(macroexp-progn body)))))))
1389
1390;;;; :after
1391
1392(defun use-package-normalize/:after (name keyword args)
1393 (setq args (use-package-normalize-recursive-symlist name keyword args))
1394 (if (consp args)
1395 args
1396 (list args)))
1397
1398(defun use-package-after-count-uses (features*)
1399 "Count the number of time the body would appear in the result."
1400 (cond ((use-package-non-nil-symbolp features*)
1401 1)
1402 ((and (consp features*)
1403 (memq (car features*) '(:or :any)))
1404 (let ((num 0))
1405 (cl-dolist (next (cdr features*))
1406 (setq num (+ num (use-package-after-count-uses next))))
1407 num))
1408 ((and (consp features*)
1409 (memq (car features*) '(:and :all)))
1410 (apply #'max (mapcar #'use-package-after-count-uses
1411 (cdr features*))))
1412 ((listp features*)
1413 (use-package-after-count-uses (cons :all features*)))))
1414
1415(defun use-package-require-after-load (features* body)
1416 "Generate `eval-after-load' statements to represents FEATURES*.
1417FEATURES* is a list containing keywords `:and' and `:all', where
1418no keyword implies `:all'."
1419 (cond
1420 ((use-package-non-nil-symbolp features*)
1421 `((eval-after-load ',features* ',(macroexp-progn body))))
1422 ((and (consp features*)
1423 (memq (car features*) '(:or :any)))
1424 (cl-mapcan #'(lambda (x) (use-package-require-after-load x body))
1425 (cdr features*)))
1426 ((and (consp features*)
1427 (memq (car features*) '(:and :all)))
1428 (cl-dolist (next (cdr features*))
1429 (setq body (use-package-require-after-load next body)))
1430 body)
1431 ((listp features*)
1432 (use-package-require-after-load (cons :all features*) body))))
1433
1434(defun use-package-handler/:after (name _keyword arg rest state)
1435 (let ((body (use-package-process-keywords name rest state))
1436 (uses (use-package-after-count-uses arg)))
1437 (if (or (null uses) (null body))
1438 body
1439 (if (<= uses 1)
1440 (use-package-require-after-load arg body)
1441 (use-package-memoize
1442 (apply-partially #'use-package-require-after-load arg)
1443 (macroexp-progn body))))))
1444
1445;;;; :demand
1446
1447(defalias 'use-package-normalize/:demand 'use-package-normalize-predicate)
1448
1449(defun use-package-handler/:demand (name _keyword _arg rest state)
1450 (use-package-process-keywords name rest state))
1451
1452;;;; :custom
1453
1454(defun use-package-normalize/:custom (_name keyword args)
1455 "Normalize use-package custom keyword."
1456 (use-package-as-one (symbol-name keyword) args
1457 #'(lambda (label arg)
1458 (unless (listp arg)
1459 (use-package-error
1460 (concat label " a (<symbol> <value> [comment])"
1461 " or list of these")))
1462 (if (use-package-non-nil-symbolp (car arg))
1463 (list arg)
1464 arg))))
1465
1466(defun use-package-handler/:custom (name _keyword args rest state)
1467 "Generate use-package custom keyword code."
1468 (use-package-concat
1469 (if (bound-and-true-p use-package-use-theme)
1470 `((let ((custom--inhibit-theme-enable nil))
1471 ;; Declare the theme here so use-package can be required inside
1472 ;; eval-and-compile without warnings about unknown theme.
1473 (unless (memq 'use-package custom-known-themes)
1474 (deftheme use-package)
1475 (enable-theme 'use-package)
1476 (setq custom-enabled-themes (remq 'use-package custom-enabled-themes)))
1477 (custom-theme-set-variables
1478 'use-package
1479 ,@(mapcar
1480 #'(lambda (def)
1481 (let ((variable (nth 0 def))
1482 (value (nth 1 def))
1483 (comment (nth 2 def)))
1484 (unless (and comment (stringp comment))
1485 (setq comment (format "Customized with use-package %s" name)))
1486 `'(,variable ,value nil () ,comment)))
1487 args))))
1488 (mapcar
1489 #'(lambda (def)
1490 (let ((variable (nth 0 def))
1491 (value (nth 1 def))
1492 (comment (nth 2 def)))
1493 (unless (and comment (stringp comment))
1494 (setq comment (format "Customized with use-package %s" name)))
1495 `(customize-set-variable (quote ,variable) ,value ,comment)))
1496 args))
1497 (use-package-process-keywords name rest state)))
1498
1499;;;; :custom-face
1500
1501(defun use-package-normalize/:custom-face (name-symbol _keyword arg)
1502 "Normalize use-package custom-face keyword."
1503 (let ((error-msg
1504 (format "%s wants a (<symbol> <face-spec> [spec-type]) or list of these"
1505 name-symbol)))
1506 (unless (listp arg)
1507 (use-package-error error-msg))
1508 (cl-dolist (def arg arg)
1509 (unless (listp def)
1510 (use-package-error error-msg))
1511 (let ((face (nth 0 def))
1512 (spec (nth 1 def)))
1513 (when (or (not face)
1514 (not spec)
1515 (> (length def) 3))
1516 (use-package-error error-msg))))))
1517
1518(defun use-package-handler/:custom-face (name _keyword args rest state)
1519 "Generate use-package custom-face keyword code."
1520 (use-package-concat
1521 (mapcar #'(lambda (def) `(apply #'face-spec-set (backquote ,def))) args)
1522 (use-package-process-keywords name rest state)))
1523
1524;;;; :init
1525
1526(defalias 'use-package-normalize/:init 'use-package-normalize-forms)
1527
1528(defun use-package-handler/:init (name _keyword arg rest state)
1529 (use-package-concat
1530 (when use-package-compute-statistics
1531 `((use-package-statistics-gather :init ',name nil)))
1532 (let ((init-body
1533 (use-package-hook-injector (use-package-as-string name)
1534 :init arg)))
1535 (when init-body
1536 (funcall use-package--hush-function :init
1537 (if use-package-check-before-init
1538 `((when (locate-library ,(use-package-as-string name))
1539 ,@init-body))
1540 init-body))))
1541 (use-package-process-keywords name rest state)
1542 (when use-package-compute-statistics
1543 `((use-package-statistics-gather :init ',name t)))))
1544
1545;;;; :load
1546
1547(defun use-package-normalize/:load (name keyword args)
1548 (setq args (use-package-normalize-recursive-symlist name keyword args))
1549 (if (consp args)
1550 args
1551 (list args)))
1552
1553(defun use-package-handler/:load (name _keyword arg rest state)
1554 (let ((body (use-package-process-keywords name rest state)))
1555 (cl-dolist (pkg arg)
1556 (setq body (use-package-require (if (eq t pkg) name pkg) nil body)))
1557 body))
1558
1559;;;; :config
1560
1561(defalias 'use-package-normalize/:config 'use-package-normalize-forms)
1562
1563(defun use-package-handler/:config (name _keyword arg rest state)
1564 (let* ((body (use-package-process-keywords name rest state))
1565 (name-symbol (use-package-as-symbol name)))
1566 (use-package-concat
1567 (when use-package-compute-statistics
1568 `((use-package-statistics-gather :config ',name nil)))
1569 (if (and (or (null arg) (equal arg '(t))) (not use-package-inject-hooks))
1570 body
1571 (use-package-with-elapsed-timer
1572 (format "Configuring package %s" name-symbol)
1573 (funcall use-package--hush-function :config
1574 (use-package-concat
1575 (use-package-hook-injector
1576 (symbol-name name-symbol) :config arg)
1577 body
1578 (list t)))))
1579 (when use-package-compute-statistics
1580 `((use-package-statistics-gather :config ',name t))))))
1581
1582;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1583;;
1584;;; The main macro
1585;;
1586
1587(defmacro use-package-core (name args)
1588 `(let* ((args* (use-package-normalize-keywords ,name ,args))
1589 (use-package--form
1590 (if (eq use-package-verbose 'debug)
1591 (concat "\n\n"
1592 (pp-to-string `(use-package ,name ,@,args))
1593 "\n -->\n\n"
1594 (pp-to-string `(use-package ,name ,@args*))
1595 "\n ==>\n\n"
1596 (pp-to-string
1597 (macroexp-progn
1598 (let ((use-package-verbose 'errors)
1599 (use-package-expand-minimally t))
1600 (use-package-process-keywords name args*
1601 (and (plist-get args* :demand)
1602 (list :demand t)))))))
1603 "")))
1604 (use-package-process-keywords name args*
1605 (and (plist-get args* :demand)
1606 (list :demand t)))))
1607
1608;;;###autoload
1609(defmacro use-package (name &rest args)
1610 "Declare an Emacs package by specifying a group of configuration options.
1611
1612For full documentation, please see the README file that came with
1613this file. Usage:
1614
1615 (use-package package-name
1616 [:keyword [option]]...)
1617
1618:init Code to run before PACKAGE-NAME has been loaded.
1619:config Code to run after PACKAGE-NAME has been loaded. Note that
1620 if loading is deferred for any reason, this code does not
1621 execute until the lazy load has occurred.
1622:preface Code to be run before everything except `:disabled'; this
1623 can be used to define functions for use in `:if', or that
1624 should be seen by the byte-compiler.
1625
1626:mode Form to be added to `auto-mode-alist'.
1627:magic Form to be added to `magic-mode-alist'.
1628:magic-fallback Form to be added to `magic-fallback-mode-alist'.
1629:interpreter Form to be added to `interpreter-mode-alist'.
1630
1631:commands Define autoloads for commands that will be defined by the
1632 package. This is useful if the package is being lazily
1633 loaded, and you wish to conditionally call functions in your
1634 `:init' block that are defined in the package.
1635:autoload Similar to :commands, but it for no-interactive one.
1636:hook Specify hook(s) to attach this package to.
1637
1638:bind Bind keys, and define autoloads for the bound commands.
1639:bind* Bind keys, and define autoloads for the bound commands,
1640 *overriding all minor mode bindings*.
1641:bind-keymap Bind a key prefix to an auto-loaded keymap defined in the
1642 package. This is like `:bind', but for keymaps.
1643:bind-keymap* Like `:bind-keymap', but overrides all minor mode bindings
1644
1645:defer Defer loading of a package -- this is implied when using
1646 `:commands', `:bind', `:bind*', `:mode', `:magic', `:hook',
1647 `:magic-fallback', or `:interpreter'. This can be an integer,
1648 to force loading after N seconds of idle time, if the package
1649 has not already been loaded.
1650:after Delay the use-package declaration until after the named modules
1651 have loaded. Once load, it will be as though the use-package
1652 declaration (without `:after') had been seen at that moment.
1653:demand Prevent the automatic deferred loading introduced by constructs
1654 such as `:bind' (see `:defer' for the complete list).
1655
1656:if EXPR Initialize and load only if EXPR evaluates to a non-nil value.
1657:disabled The package is ignored completely if this keyword is present.
1658:defines Declare certain variables to silence the byte-compiler.
1659:functions Declare certain functions to silence the byte-compiler.
1660:load-path Add to the `load-path' before attempting to load the package.
1661:diminish Support for diminish.el (if installed).
1662:delight Support for delight.el (if installed).
1663:custom Call `Custom-set' or `set-default' with each variable
1664 definition without modifying the Emacs `custom-file'.
1665 (compare with `custom-set-variables').
1666:custom-face Call `custom-set-faces' with each face definition.
1667:ensure Loads the package using package.el if necessary.
1668:pin Pin the package to an archive."
1669 (declare (indent defun))
1670 (unless (memq :disabled args)
1671 (macroexp-progn
1672 (use-package-concat
1673 (when use-package-compute-statistics
1674 `((use-package-statistics-gather :use-package ',name nil)))
1675 (if (eq use-package-verbose 'errors)
1676 (use-package-core name args)
1677 (condition-case-unless-debug err
1678 (use-package-core name args)
1679 (error
1680 (ignore
1681 (display-warning
1682 'use-package
1683 (format "Failed to parse package %s: %s"
1684 name (error-message-string err)) :error)))))
1685 (when use-package-compute-statistics
1686 `((use-package-statistics-gather :use-package ',name t)))))))
1687
1688(provide 'use-package-core)
1689
1690;;; use-package-core.el ends here
diff --git a/lisp/use-package/use-package-delight.el b/lisp/use-package/use-package-delight.el
new file mode 100644
index 00000000000..c6abac9a643
--- /dev/null
+++ b/lisp/use-package/use-package-delight.el
@@ -0,0 +1,83 @@
1;;; use-package-delight.el --- Support for the :delight keyword -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
4
5;; Author: John Wiegley <johnw@newartisans.com>
6;; Maintainer: John Wiegley <johnw@newartisans.com>
7
8;; This program is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation, either version 3 of the License, or
11;; (at your option) any later version.
12
13;; This program is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with this program. If not, see <https://www.gnu.org/licenses/>.
20
21;;; Commentary:
22
23;; Provides support for the :delight keyword, which is made available by
24;; default by requiring `use-package'.
25
26;;; Code:
27
28(require 'use-package-core)
29
30(defun use-package-normalize-delight (name args)
31 "Normalize ARGS for a single call to `delight'."
32 (when (eq :eval (car args))
33 ;; Handle likely common mistake.
34 (use-package-error ":delight mode line constructs must be quoted"))
35 (cond ((and (= (length args) 1)
36 (use-package-non-nil-symbolp (car args)))
37 `(,(nth 0 args) nil ,name))
38 ((= (length args) 2)
39 `(,(nth 0 args) ,(nth 1 args) ,name))
40 ((= (length args) 3)
41 args)
42 (t
43 (use-package-error
44 ":delight expects `delight' arguments or a list of them"))))
45
46;;;###autoload
47(defun use-package-normalize/:delight (name _keyword args)
48 "Normalize arguments to delight."
49 (cond ((null args)
50 `((,(use-package-as-mode name) nil ,name)))
51 ((and (= (length args) 1)
52 (use-package-non-nil-symbolp (car args)))
53 `((,(car args) nil ,name)))
54 ((and (= (length args) 1)
55 (stringp (car args)))
56 `((,(use-package-as-mode name) ,(car args) ,name)))
57 ((and (= (length args) 1)
58 (listp (car args))
59 (eq 'quote (caar args)))
60 `((,(use-package-as-mode name) ,@(cdar args) ,name)))
61 ((and (= (length args) 2)
62 (listp (nth 1 args))
63 (eq 'quote (car (nth 1 args))))
64 `((,(car args) ,@(cdr (nth 1 args)) ,name)))
65 (t (mapcar
66 (apply-partially #'use-package-normalize-delight name)
67 (if (use-package-non-nil-symbolp (car args))
68 (list args)
69 args)))))
70
71;;;###autoload
72(defun use-package-handler/:delight (name _keyword args rest state)
73 (let ((body (use-package-process-keywords name rest state)))
74 (use-package-concat
75 body
76 `((if (fboundp 'delight)
77 (delight '(,@args)))))))
78
79(add-to-list 'use-package-keywords :delight t)
80
81(provide 'use-package-delight)
82
83;;; use-package-delight.el ends here
diff --git a/lisp/use-package/use-package-diminish.el b/lisp/use-package/use-package-diminish.el
new file mode 100644
index 00000000000..9b8a09a2973
--- /dev/null
+++ b/lisp/use-package/use-package-diminish.el
@@ -0,0 +1,72 @@
1;;; use-package-diminish.el --- Support for the :diminish keyword -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
4
5;; Author: John Wiegley <johnw@newartisans.com>
6;; Maintainer: John Wiegley <johnw@newartisans.com>
7
8;; This program is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation, either version 3 of the License, or
11;; (at your option) any later version.
12
13;; This program is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with this program. If not, see <https://www.gnu.org/licenses/>.
20
21;;; Commentary:
22
23;; Provides support for the :diminish keyword, which is made available by
24;; default by requiring `use-package'.
25
26;;; Code:
27
28(require 'use-package-core)
29
30(defun use-package-normalize-diminish (name label arg &optional recursed)
31 "Normalize the arguments to diminish down to a list of one of two forms:
32 SYMBOL
33 (SYMBOL . STRING)"
34 (cond
35 ((not arg)
36 (list (use-package-as-mode name)))
37 ((use-package-non-nil-symbolp arg)
38 (list arg))
39 ((stringp arg)
40 (list (cons (use-package-as-mode name) arg)))
41 ((and (consp arg) (stringp (cdr arg)))
42 (list arg))
43 ((and (not recursed) (listp arg) (listp (cdr arg)))
44 (mapcar #'(lambda (x) (car (use-package-normalize-diminish
45 name label x t))) arg))
46 (t
47 (use-package-error
48 (concat label " wants a string, symbol, "
49 "(symbol . string) or list of these")))))
50
51;;;###autoload
52(defun use-package-normalize/:diminish (name keyword args)
53 (use-package-as-one (symbol-name keyword) args
54 (apply-partially #'use-package-normalize-diminish name) t))
55
56;;;###autoload
57(defun use-package-handler/:diminish (name _keyword arg rest state)
58 (let ((body (use-package-process-keywords name rest state)))
59 (use-package-concat
60 (mapcar #'(lambda (var)
61 `(if (fboundp 'diminish)
62 ,(if (consp var)
63 `(diminish ',(car var) ,(cdr var))
64 `(diminish ',var))))
65 arg)
66 body)))
67
68(add-to-list 'use-package-keywords :diminish t)
69
70(provide 'use-package-diminish)
71
72;;; use-package-diminish.el ends here
diff --git a/lisp/use-package/use-package-ensure-system-package.el b/lisp/use-package/use-package-ensure-system-package.el
new file mode 100644
index 00000000000..9c9f0797a05
--- /dev/null
+++ b/lisp/use-package/use-package-ensure-system-package.el
@@ -0,0 +1,99 @@
1;;; use-package-ensure-system-package.el --- auto install system packages -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2022 Free Software Foundation, Inc.
4
5;; Author: Justin Talbott <justin@waymondo.com>
6;; Keywords: convenience, tools, extensions
7;; URL: https://github.com/waymondo/use-package-ensure-system-package
8;; Version: 0.2
9;; Package-Requires: ((use-package "2.1") (system-packages "1.0.4"))
10;; Filename: use-package-ensure-system-package.el
11
12;; This program is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
16
17;; This program is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with this program. If not, see <https://www.gnu.org/licenses/>.
24
25;;; Commentary:
26;;
27;; The `:ensure-system-package` keyword allows you to ensure system
28;; binaries exist alongside your `use-package` declarations.
29;;
30
31;;; Code:
32
33(require 'use-package)
34(require 'system-packages nil t)
35
36(eval-when-compile
37 (declare-function system-packages-get-command "system-packages"))
38
39(defvar use-package-ensure-system-package--custom-packages '()
40 "List of custom packages installed.")
41
42(defun use-package-ensure-system-package-consify (arg)
43 "Turn ARG into a cons of (`package-name' . `install-command')."
44 (cond
45 ((stringp arg)
46 (cons arg `(system-packages-install ,arg)))
47 ((symbolp arg)
48 (cons arg `(system-packages-install ,(symbol-name arg))))
49 ((consp arg)
50 (cond
51 ((not (cdr arg))
52 (use-package-ensure-system-package-consify (car arg)))
53 ((stringp (cdr arg))
54 (progn
55 (push (cdr arg) use-package-ensure-system-package--custom-packages)
56 (cons (car arg) `(async-shell-command ,(cdr arg)))))
57 (t
58 (cons (car arg)
59 `(system-packages-install ,(symbol-name (cdr arg)))))))))
60
61(defun use-package-ensure-system-package-update-custom-packages ()
62 (interactive)
63 (dolist (cmd use-package-ensure-system-package--custom-packages)
64 (async-shell-command cmd)))
65
66;;;###autoload
67(defun use-package-normalize/:ensure-system-package (_name-symbol keyword args)
68 "Turn ARGS into a list of conses of (`package-name' . `install-command')."
69 (use-package-as-one (symbol-name keyword) args
70 (lambda (_label arg)
71 (cond
72 ((and (listp arg) (listp (cdr arg)))
73 (mapcar #'use-package-ensure-system-package-consify arg))
74 (t
75 (list (use-package-ensure-system-package-consify arg)))))))
76
77(defun use-package-ensure-system-package-exists? (file-or-exe)
78 "If variable is a string, ensure the file path exists.
79If it is a symbol, ensure the binary exist."
80 (if (stringp file-or-exe)
81 (file-exists-p file-or-exe)
82 (executable-find (symbol-name file-or-exe))))
83
84
85;;;###autoload
86(defun use-package-handler/:ensure-system-package (name _keyword arg rest state)
87 "Execute the handler for `:ensure-system-package' keyword in `use-package'."
88 (let ((body (use-package-process-keywords name rest state)))
89 (use-package-concat
90 (mapcar #'(lambda (cons)
91 `(unless (use-package-ensure-system-package-exists? ',(car cons))
92 ,(cdr cons))) arg)
93 body)))
94
95(add-to-list 'use-package-keywords :ensure-system-package t)
96
97(provide 'use-package-ensure-system-package)
98
99;;; use-package-ensure-system-package.el ends here
diff --git a/lisp/use-package/use-package-ensure.el b/lisp/use-package/use-package-ensure.el
new file mode 100644
index 00000000000..c9cc6e70c51
--- /dev/null
+++ b/lisp/use-package/use-package-ensure.el
@@ -0,0 +1,206 @@
1;;; use-package-ensure.el --- Support for the :ensure and :pin keywords -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
4
5;; Author: John Wiegley <johnw@newartisans.com>
6;; Maintainer: John Wiegley <johnw@newartisans.com>
7
8;; This program is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation, either version 3 of the License, or
11;; (at your option) any later version.
12
13;; This program is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with this program. If not, see <https://www.gnu.org/licenses/>.
20
21;;; Commentary:
22
23;; Provides support for the :ensure and :pin keywords, which is made available
24;; by default by requiring `use-package'.
25
26;;; Code:
27
28(require 'cl-lib)
29(require 'use-package-core)
30
31(defgroup use-package-ensure nil
32 "Support for :ensure and :pin keywords in `use-package' declarations."
33 :group 'use-package)
34
35(eval-when-compile
36 (declare-function package-installed-p "package")
37 (declare-function package-read-all-archive-contents "package" ()))
38
39(defcustom use-package-always-ensure nil
40 "Treat every package as though it had specified using `:ensure SEXP'.
41See also `use-package-defaults', which uses this value."
42 :type 'sexp
43 :group 'use-package-ensure)
44
45(defcustom use-package-always-pin nil
46 "Treat every package as though it had specified using `:pin SYM'.
47See also `use-package-defaults', which uses this value."
48 :type 'symbol
49 :group 'use-package-ensure)
50
51(defcustom use-package-ensure-function 'use-package-ensure-elpa
52 "Function that ensures a package is installed.
53This function is called with three arguments: the name of the
54package declared in the `use-package' form; the arguments passed
55to all `:ensure' keywords (always a list, even if only one); and
56the current `state' plist created by previous handlers.
57
58Note that this function is called whenever `:ensure' is provided,
59even if it is nil. It is up to the function to decide on the
60semantics of the various values for `:ensure'.
61
62This function should return non-nil if the package is installed.
63
64The default value uses package.el to install the package."
65 :type '(choice (const :tag "package.el" use-package-ensure-elpa)
66 (function :tag "Custom"))
67 :group 'use-package-ensure)
68
69;;;; :pin
70
71(defun use-package-normalize/:pin (_name keyword args)
72 (use-package-only-one (symbol-name keyword) args
73 #'(lambda (_label arg)
74 (cond
75 ((stringp arg) arg)
76 ((use-package-non-nil-symbolp arg) (symbol-name arg))
77 (t
78 (use-package-error
79 ":pin wants an archive name (a string)"))))))
80
81(eval-when-compile
82 (defvar package-pinned-packages)
83 (defvar package-archives))
84
85(defun use-package-archive-exists-p (archive)
86 "Check if a given ARCHIVE is enabled.
87
88ARCHIVE can be a string or a symbol or `manual' to indicate a
89manually updated package."
90 (if (member archive '(manual "manual"))
91 't
92 (let ((valid nil))
93 (dolist (pa package-archives)
94 (when (member archive (list (car pa) (intern (car pa))))
95 (setq valid 't)))
96 valid)))
97
98(defun use-package-pin-package (package archive)
99 "Pin PACKAGE to ARCHIVE."
100 (unless (boundp 'package-pinned-packages)
101 (setq package-pinned-packages ()))
102 (let ((archive-symbol (if (symbolp archive) archive (intern archive)))
103 (archive-name (if (stringp archive) archive (symbol-name archive))))
104 (if (use-package-archive-exists-p archive-symbol)
105 (add-to-list 'package-pinned-packages (cons package archive-name))
106 (error "Archive '%s' requested for package '%s' is not available"
107 archive-name package))
108 (unless (bound-and-true-p package--initialized)
109 (package-initialize t))))
110
111(defun use-package-handler/:pin (name _keyword archive-name rest state)
112 (let ((body (use-package-process-keywords name rest state))
113 (pin-form (if archive-name
114 `(use-package-pin-package ',(use-package-as-symbol name)
115 ,archive-name))))
116 ;; Pinning should occur just before ensuring
117 ;; See `use-package-handler/:ensure'.
118 (if (bound-and-true-p byte-compile-current-file)
119 (eval pin-form) ; Eval when byte-compiling,
120 (push pin-form body)) ; or else wait until runtime.
121 body))
122
123;;;; :ensure
124
125(defvar package-archive-contents)
126
127;;;###autoload
128(defun use-package-normalize/:ensure (_name keyword args)
129 (if (null args)
130 (list t)
131 (use-package-only-one (symbol-name keyword) args
132 #'(lambda (_label arg)
133 (cond
134 ((symbolp arg)
135 (list arg))
136 ((and (listp arg) (= 3 (length arg))
137 (symbolp (nth 0 arg))
138 (eq :pin (nth 1 arg))
139 (or (stringp (nth 2 arg))
140 (symbolp (nth 2 arg))))
141 (list (cons (nth 0 arg) (nth 2 arg))))
142 (t
143 (use-package-error
144 (concat ":ensure wants an optional package name "
145 "(an unquoted symbol name), or (<symbol> :pin <string>)"))))))))
146
147(defun use-package-ensure-elpa (name args _state &optional _no-refresh)
148 (dolist (ensure args)
149 (let ((package
150 (or (and (eq ensure t) (use-package-as-symbol name))
151 ensure)))
152 (when package
153 (require 'package)
154 (when (consp package)
155 (use-package-pin-package (car package) (cdr package))
156 (setq package (car package)))
157 (unless (package-installed-p package)
158 (condition-case-unless-debug err
159 (progn
160 (when (assoc package (bound-and-true-p
161 package-pinned-packages))
162 (package-read-all-archive-contents))
163 (if (assoc package package-archive-contents)
164 (package-install package)
165 (package-refresh-contents)
166 (when (assoc package (bound-and-true-p
167 package-pinned-packages))
168 (package-read-all-archive-contents))
169 (package-install package))
170 t)
171 (error
172 (display-warning 'use-package
173 (format "Failed to install %s: %s"
174 name (error-message-string err))
175 :error))))))))
176
177;;;###autoload
178(defun use-package-handler/:ensure (name _keyword ensure rest state)
179 (let* ((body (use-package-process-keywords name rest state)))
180 ;; We want to avoid installing packages when the `use-package' macro is
181 ;; being macro-expanded by elisp completion (see `lisp--local-variables'),
182 ;; but still install packages when byte-compiling, to avoid requiring
183 ;; `package' at runtime.
184 (if (bound-and-true-p byte-compile-current-file)
185 ;; Eval when byte-compiling,
186 (funcall use-package-ensure-function name ensure state)
187 ;; or else wait until runtime.
188 (push `(,use-package-ensure-function ',name ',ensure ',state)
189 body))
190 body))
191
192(add-to-list 'use-package-defaults
193 '(:ensure (list use-package-always-ensure)
194 (lambda (name args)
195 (and use-package-always-ensure
196 (not (plist-member args :load-path))))) t)
197
198(add-to-list 'use-package-defaults
199 '(:pin use-package-always-pin use-package-always-pin) t)
200
201(add-to-list 'use-package-keywords :ensure)
202(add-to-list 'use-package-keywords :pin)
203
204(provide 'use-package-ensure)
205
206;;; use-package-ensure.el ends here
diff --git a/lisp/use-package/use-package-jump.el b/lisp/use-package/use-package-jump.el
new file mode 100644
index 00000000000..0c4cd20d052
--- /dev/null
+++ b/lisp/use-package/use-package-jump.el
@@ -0,0 +1,70 @@
1;;; use-package-jump.el --- Attempt to jump to a use-package declaration -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
4
5;; Author: John Wiegley <johnw@newartisans.com>
6;; Maintainer: John Wiegley <johnw@newartisans.com>
7
8;; This program is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation, either version 3 of the License, or
11;; (at your option) any later version.
12
13;; This program is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with this program. If not, see <https://www.gnu.org/licenses/>.
20
21;;; Commentary:
22
23;; Provides the command `M-x use-package-jump-to-package-form', however it
24;; only works if the package being jumped to was required during
25;; initialization. If it was delay-loaded, it will not work.
26;; Improvements are needed.
27
28;;; Code:
29
30(require 'use-package-core)
31
32(defun use-package-find-require (package)
33 "Find file that required PACKAGE by searching `load-history'.
34Returns an absolute file path or nil if none is found."
35 (catch 'suspect
36 (dolist (filespec load-history)
37 (dolist (entry (cdr filespec))
38 (when (equal entry (cons 'require package))
39 (throw 'suspect (car filespec)))))))
40
41;;;###autoload
42(defun use-package-jump-to-package-form (package)
43 "Attempt to find and jump to the `use-package' form that loaded PACKAGE.
44This will only find the form if that form actually required
45PACKAGE. If PACKAGE was previously required then this function
46will jump to the file that originally required PACKAGE instead."
47 (interactive (list (completing-read "Package: " features)))
48 (let* ((package (if (stringp package) (intern package) package))
49 (requiring-file (use-package-find-require package))
50 file location)
51 (if (null requiring-file)
52 (user-error "Can't find file requiring file; may have been autoloaded")
53 (setq file (if (string= (file-name-extension requiring-file) "elc")
54 (concat (file-name-sans-extension requiring-file) ".el")
55 requiring-file))
56 (when (file-exists-p file)
57 (find-file-other-window file)
58 (save-excursion
59 (goto-char (point-min))
60 (setq location
61 (re-search-forward
62 (format (eval use-package-form-regexp-eval) package) nil t)))
63 (if (null location)
64 (message "No use-package form found.")
65 (goto-char location)
66 (beginning-of-line))))))
67
68(provide 'use-package-jump)
69
70;;; use-package-jump.el ends here
diff --git a/lisp/use-package/use-package-lint.el b/lisp/use-package/use-package-lint.el
new file mode 100644
index 00000000000..2092c0d269c
--- /dev/null
+++ b/lisp/use-package/use-package-lint.el
@@ -0,0 +1,76 @@
1;;; use-package-lint.el --- Attempt to find errors in use-package declarations -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
4
5;; Author: John Wiegley <johnw@newartisans.com>
6;; Maintainer: John Wiegley <johnw@newartisans.com>
7
8;; This program is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation, either version 3 of the License, or
11;; (at your option) any later version.
12
13;; This program is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with this program. If not, see <https://www.gnu.org/licenses/>.
20
21;;; Commentary:
22
23;; Provides the command `M-x use-package-lint'.
24
25;;; Code:
26
27(require 'cl-lib)
28(require 'use-package-core)
29
30(defun use-package-lint-declaration (name plist)
31 (dolist (path (plist-get plist :load-path))
32 (unless (file-exists-p path)
33 (display-warning
34 'use-package
35 (format "%s :load-path does not exist: %s"
36 name path) :error)))
37
38 (unless (or (plist-member plist :disabled)
39 (plist-get plist :no-require)
40 (locate-library (use-package-as-string name) nil
41 (plist-get plist :load-path)))
42 (display-warning
43 'use-package
44 (format "%s module cannot be located" name) :error))
45
46 ;; (dolist (command (plist-get plist :commands))
47 ;; (unless (string= (find-lisp-object-file-name command nil)
48 ;; (locate-library (use-package-as-string name) nil
49 ;; (plist-get plist :load-path)))
50 ;; (display-warning
51 ;; 'use-package
52 ;; (format "%s :command is from different path: %s"
53 ;; name (symbol-name command)) :error)))
54 )
55
56;;;###autoload
57(defun use-package-lint ()
58 "Check for errors in `use-package' declarations.
59For example, if the module's `:if' condition is met, but even
60with the specified `:load-path' the module cannot be found."
61 (interactive)
62 (save-excursion
63 (goto-char (point-min))
64 (let ((re (eval use-package-form-regexp-eval)))
65 (while (re-search-forward re nil t)
66 (goto-char (match-beginning 0))
67 (let ((decl (read (current-buffer))))
68 (when (eq (car decl) 'use-package)
69 (use-package-lint-declaration
70 (use-package-as-string (cadr decl))
71 (use-package-normalize-keywords
72 (cadr decl) (cddr decl)))))))))
73
74(provide 'use-package-lint)
75
76;;; use-package-lint.el ends here
diff --git a/lisp/use-package/use-package.el b/lisp/use-package/use-package.el
new file mode 100644
index 00000000000..bafa0934a6d
--- /dev/null
+++ b/lisp/use-package/use-package.el
@@ -0,0 +1,51 @@
1;;; use-package.el --- A configuration macro for simplifying your .emacs -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
4
5;; Author: John Wiegley <johnw@newartisans.com>
6;; Maintainer: John Wiegley <johnw@newartisans.com>
7;; Created: 17 Jun 2012
8;; Version: 2.4.4
9;; Package-Requires: ((emacs "24.3") (bind-key "2.4"))
10;; Keywords: dotemacs startup speed config package extensions
11;; URL: https://github.com/jwiegley/use-package
12
13;; This program is free software; you can redistribute it and/or modify
14;; it under the terms of the GNU General Public License as published by
15;; the Free Software Foundation, either version 3 of the License, or
16;; (at your option) any later version.
17
18;; This program is distributed in the hope that it will be useful,
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
24;; along with this program. If not, see <https://www.gnu.org/licenses/>.
25
26;;; Commentary:
27
28;; The `use-package' declaration macro allows you to isolate package
29;; configuration in your ".emacs" in a way that is performance-oriented and,
30;; well, just tidy. I created it because I have over 80 packages that I use
31;; in Emacs, and things were getting difficult to manage. Yet with this
32;; utility my total load time is just under 1 second, with no loss of
33;; functionality!
34;;
35;; Please see README.md from the same repository for documentation.
36
37;;; Code:
38
39(require 'use-package-core)
40
41(require 'use-package-bind-key)
42(require 'use-package-diminish)
43(require 'use-package-delight)
44(require 'use-package-ensure)
45
46(declare-function use-package-jump-to-package-form "use-package-jump")
47(autoload #'use-package-jump-to-package-form "use-package-jump" nil t)
48
49(provide 'use-package)
50
51;;; use-package.el ends here
diff --git a/test/lisp/use-package/use-package-chords-tests.el b/test/lisp/use-package/use-package-chords-tests.el
new file mode 100644
index 00000000000..d78f6883c7d
--- /dev/null
+++ b/test/lisp/use-package/use-package-chords-tests.el
@@ -0,0 +1,153 @@
1;;; use-package-chords-tests.el --- Tests for use-package-chords.el -*- lexical-binding: t; -*-
2
3;; This program is free software; you can redistribute it and/or modify
4;; it under the terms of the GNU General Public License as published by
5;; the Free Software Foundation, either version 3 of the License, or
6;; (at your option) any later version.
7
8;; This program is distributed in the hope that it will be useful,
9;; but WITHOUT ANY WARRANTY; without even the implied warranty of
10;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11;; GNU General Public License for more details.
12
13;; You should have received a copy of the GNU General Public License
14;; along with this program. If not, see <https://www.gnu.org/licenses/>.
15
16;;; Code:
17
18(require 'use-package)
19(require 'use-package-tests)
20(require 'use-package-chords)
21
22(defmacro match-expansion (form &rest value)
23 `(should (pcase (expand-minimally ,form)
24 ,@(mapcar #'(lambda (x) (list x t)) value))))
25
26(defun use-package-test-normalize-chord (&rest args)
27 (apply #'use-package-normalize-binder 'foo :chords args))
28
29(ert-deftest use-package-test-normalize/:chords-1 ()
30 (should (equal (use-package-test-normalize-chord
31 '(("C-a" . alpha)))
32 '(("C-a" . alpha)))))
33
34(ert-deftest use-package-test-normalize/:chords-2 ()
35 (should (equal (use-package-test-normalize-chord
36 '(("C-a" . alpha)
37 :map foo-map
38 ("C-b" . beta)))
39 '(("C-a" . alpha)
40 :map foo-map
41 ("C-b" . beta)))))
42
43(ert-deftest use-package-test-normalize/:chords-3 ()
44 (should (equal (use-package-test-normalize-chord
45 '(:map foo-map
46 ("C-a" . alpha)
47 ("C-b" . beta)))
48 '(:map foo-map
49 ("C-a" . alpha)
50 ("C-b" . beta)))))
51
52(ert-deftest use-package-test/:chords-1 ()
53 (match-expansion
54 (use-package foo :chords ("C-k" . key1) ("C-u" . key2))
55 `(progn
56 (unless
57 (fboundp 'key1)
58 (autoload #'key1 "foo" nil t))
59 (unless
60 (fboundp 'key2)
61 (autoload #'key2 "foo" nil t))
62 (bind-chord "C-k" #'key1 nil)
63 (bind-chord "C-u" #'key2 nil))))
64
65(ert-deftest use-package-test/:chords-2 ()
66 (match-expansion
67 (use-package foo :chords (("C-k" . key1) ("C-u" . key2)))
68 `(progn
69 (unless (fboundp 'key1)
70 (autoload #'key1 "foo" nil t))
71 (unless (fboundp 'key2)
72 (autoload #'key2 "foo" nil t))
73 (bind-chord "C-k" #'key1 nil)
74 (bind-chord "C-u" #'key2 nil))))
75
76(ert-deftest use-package-test/:chords-3 ()
77 (match-expansion
78 (use-package foo :chords (:map my-map ("C-k" . key1) ("C-u" . key2)))
79 `(progn
80 (unless
81 (fboundp 'key1)
82 (autoload #'key1 "foo" nil t))
83 (unless
84 (fboundp 'key2)
85 (autoload #'key2 "foo" nil t))
86 (if
87 (boundp 'my-map)
88 (progn
89 (bind-chord "C-k" #'key1 my-map)
90 (bind-chord "C-u" #'key2 my-map))
91 (eval-after-load 'foo
92 '(progn
93 (bind-chord "C-k" #'key1 my-map)
94 (bind-chord "C-u" #'key2 my-map)))))))
95
96(ert-deftest use-package-test/:chords-4 ()
97 (should-error
98 (match-expansion
99 (use-package foo :chords :map my-map ("C-k" . key1) ("C-u" . key2))
100 `(bind-chords :package foo))))
101
102(ert-deftest use-package-test/:chords-5 ()
103 (match-expansion
104 (use-package foo :chords ("C-k" . key1) (:map my-map ("C-u" . key2)))
105 `(progn
106 (unless (fboundp 'key1)
107 (autoload #'key1 "foo" nil t))
108 (unless (fboundp 'key2)
109 (autoload #'key2 "foo" nil t))
110 (progn
111 (bind-chord "C-k" #'key1 nil)
112 (if
113 (boundp 'my-map)
114 (bind-chord "C-u" #'key2 my-map)
115 (eval-after-load 'foo
116 '(bind-chord "C-u" #'key2 my-map)))))))
117
118(ert-deftest use-package-test/:chords-6 ()
119 (match-expansion
120 (use-package foo
121 :chords
122 ("C-k" . key1)
123 (:map my-map ("C-u" . key2))
124 (:map my-map2 ("C-u" . key3)))
125 `(progn
126 (unless
127 (fboundp 'key1)
128 (autoload #'key1 "foo" nil t))
129 (unless
130 (fboundp 'key2)
131 (autoload #'key2 "foo" nil t))
132 (unless
133 (fboundp 'key3)
134 (autoload #'key3 "foo" nil t))
135 (progn
136 (bind-chord "C-k" #'key1 nil)
137 (if
138 (boundp 'my-map)
139 (bind-chord "C-u" #'key2 my-map)
140 (eval-after-load 'foo
141 '(bind-chord "C-u" #'key2 my-map)))
142 (if
143 (boundp 'my-map2)
144 (bind-chord "C-u" #'key3 my-map2)
145 (eval-after-load 'foo
146 '(bind-chord "C-u" #'key3 my-map2)))))))
147
148;; Local Variables:
149;; no-byte-compile: t
150;; no-update-autoloads: t
151;; End:
152
153;;; use-package-chords-tests.el ends here
diff --git a/test/lisp/use-package/use-package-tests.el b/test/lisp/use-package/use-package-tests.el
new file mode 100644
index 00000000000..b66b08ec117
--- /dev/null
+++ b/test/lisp/use-package/use-package-tests.el
@@ -0,0 +1,1957 @@
1;;; use-package-tests.el --- Tests for use-package.el -*- lexical-binding: t; -*-
2
3;; This program is free software; you can redistribute it and/or modify
4;; it under the terms of the GNU General Public License as published by
5;; the Free Software Foundation, either version 3 of the License, or
6;; (at your option) any later version.
7
8;; This program is distributed in the hope that it will be useful,
9;; but WITHOUT ANY WARRANTY; without even the implied warranty of
10;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11;; GNU General Public License for more details.
12
13;; You should have received a copy of the GNU General Public License
14;; along with this program. If not, see <https://www.gnu.org/licenses/>.
15
16;;; Commentary:
17
18;;; Code:
19
20(require 'cl-lib)
21(require 'ert)
22(require 'use-package)
23
24(setq use-package-always-ensure nil
25 use-package-verbose 'errors
26 use-package-expand-minimally t
27 ;; These are needed for certain tests below where the `pcase' match
28 ;; expression is large and contains holes, such as the :after tests.
29 max-lisp-eval-depth 8000
30 max-specpdl-size 8000)
31
32(unless (fboundp 'macroexpand-1)
33 (defun macroexpand-1 (form &optional environment)
34 "Perform (at most) one step of macroexpansion."
35 (cond
36 ((consp form)
37 (let* ((head (car form))
38 (env-expander (assq head environment)))
39 (if env-expander
40 (if (cdr env-expander)
41 (apply (cdr env-expander) (cdr form))
42 form)
43 (if (not (and (symbolp head) (fboundp head)))
44 form
45 (let ((def (autoload-do-load (symbol-function head) head 'macro)))
46 (cond
47 ;; Follow alias, but only for macros, otherwise we may end up
48 ;; skipping an important compiler-macro (e.g. cl--block-wrapper).
49 ((and (symbolp def) (macrop def)) (cons def (cdr form)))
50 ((not (consp def)) form)
51 (t
52 (if (eq 'macro (car def))
53 (apply (cdr def) (cdr form))
54 form))))))))
55 (t form))))
56
57(defmacro expand-minimally (form)
58 `(let ((use-package-verbose 'errors)
59 (use-package-expand-minimally t))
60 (macroexpand-1 ',form)))
61
62(defmacro expand-maximally (form)
63 `(let ((use-package-verbose 'debug)
64 (use-package-expand-minimally nil))
65 (macroexpand-1 ',form)))
66
67(defmacro match-expansion (form &rest value)
68 `(should (pcase (expand-minimally ,form)
69 ,@(mapcar #'(lambda (x) (list x t)) value))))
70
71(defun fix-expansion ()
72 (interactive)
73 (save-excursion
74 (unless (looking-at "(match-expansion")
75 (backward-up-list))
76 (when (looking-at "(match-expansion")
77 (re-search-forward "(\\(use-package\\|bind-key\\)")
78 (goto-char (match-beginning 0))
79 (let ((decl (read (current-buffer))))
80 (kill-sexp)
81 (let (vars)
82 (catch 'exit
83 (save-excursion
84 (while (ignore-errors (backward-up-list) t)
85 (when (looking-at "(let\\s-+")
86 (goto-char (match-end 0))
87 (setq vars (read (current-buffer)))
88 (throw 'exit t)))))
89 (eval
90 `(let (,@ (append vars
91 '((use-package-verbose 'errors)
92 (use-package-expand-minimally t))))
93 (insert ?\n ?\` (pp-to-string (macroexpand-1 decl))))))))))
94
95(bind-key "C-c C-u" #'fix-expansion emacs-lisp-mode-map)
96
97(ert-deftest use-package-test-recognize-function ()
98 (should (use-package-recognize-function nil t))
99 (should-not (use-package-recognize-function nil))
100 (should (use-package-recognize-function t))
101 (should (use-package-recognize-function 'sym))
102 (should (use-package-recognize-function #'sym))
103 (should (use-package-recognize-function (lambda () ...)))
104 (should (use-package-recognize-function '(lambda () ...)))
105 (should (use-package-recognize-function #'(lambda () ...)))
106
107 (should-not (use-package-recognize-function 1))
108 (should-not (use-package-recognize-function "Hello"))
109 (should-not (use-package-recognize-function '(nil . nil))))
110
111(ert-deftest use-package-test-normalize-function ()
112 (should (equal (use-package-normalize-function nil) nil))
113 (should (equal (use-package-normalize-function t) t))
114 (should (equal (use-package-normalize-function 'sym) 'sym))
115 (should (equal (use-package-normalize-function #'sym) 'sym))
116 (should (equal (use-package-normalize-function '(lambda () ...)) '(lambda () ...)))
117 (should (equal (use-package-normalize-function ''(lambda () ...)) '(lambda () ...)))
118 (should (equal (use-package-normalize-function '#'(lambda () ...)) '(lambda () ...)))
119
120 (should (equal (use-package-normalize-function 1) 1))
121 (should (equal (use-package-normalize-function "Hello") "Hello"))
122 (should (equal (use-package-normalize-function '(nil . nil)) '(nil . nil))))
123
124(ert-deftest use-package-test/:disabled-1 ()
125 (match-expansion
126 (use-package foo :disabled t)
127 `()))
128
129(ert-deftest use-package-test/:preface-1 ()
130 (match-expansion
131 (use-package foo :preface (t))
132 `(progn
133 (eval-and-compile
134 (t))
135 (require 'foo nil nil))))
136
137(ert-deftest use-package-test/:preface-2 ()
138 (let ((byte-compile-current-file t))
139 (match-expansion
140 (use-package foo :preface (t))
141 `(progn
142 (eval-and-compile
143 (eval-when-compile
144 (with-demoted-errors
145 "Cannot load foo: %S" nil
146 (unless (featurep 'foo)
147 (load "foo" nil t))))
148 (t))
149 (require 'foo nil nil)))))
150
151(ert-deftest use-package-test/:preface-3 ()
152 (let ((byte-compile-current-file t))
153 (match-expansion
154 (use-package foo
155 :preface (preface)
156 :init (init)
157 :config (config)
158 :functions func
159 :defines def)
160 `(progn
161 (eval-and-compile
162 (defvar def)
163 (declare-function func "foo")
164 (eval-when-compile
165 (with-demoted-errors
166 "Cannot load foo: %S" nil
167 (unless (featurep 'foo)
168 (load "foo" nil t))))
169 (preface))
170 (init)
171 (require 'foo nil nil)
172 (config)
173 t))))
174
175(ert-deftest use-package-test/:preface-4 ()
176 (let ((byte-compile-current-file t))
177 (match-expansion
178 (use-package foo
179 :preface (preface)
180 :init (init)
181 :config (config)
182 :functions func
183 :defines def
184 :defer t)
185 `(progn
186 (eval-and-compile
187 (defvar def)
188 (declare-function func "foo")
189 (eval-when-compile
190 (with-demoted-errors
191 "Cannot load foo: %S" nil
192 (unless (featurep 'foo)
193 (load "foo" nil t))))
194 (preface))
195 (init)
196 (eval-after-load 'foo
197 '(progn
198 (config)
199 t))))))
200
201(ert-deftest use-package-test/:pin-1 ()
202 (match-expansion
203 (use-package foo :pin foo)
204 `(progn
205 (use-package-pin-package 'foo "foo")
206 (require 'foo nil nil))))
207
208(ert-deftest use-package-test/:pin-2 ()
209 (match-expansion
210 (use-package foo :pin "foo")
211 `(progn
212 (use-package-pin-package 'foo "foo")
213 (require 'foo nil nil))))
214
215(ert-deftest use-package-test-normalize/:ensure ()
216 (cl-flet ((norm (&rest args)
217 (apply #'use-package-normalize/:ensure
218 'foopkg :ensure args)))
219 (should (equal (norm '(t)) '(t)))
220 (should (equal (norm '(nil)) '(nil)))
221 (should (equal (norm '(sym)) '(sym)))
222 (should-error (norm '(1)))
223 (should-error (norm '("Hello")))))
224
225(ert-deftest use-package-test/:ensure-1 ()
226 (let ((use-package-always-ensure nil))
227 (match-expansion
228 (use-package foo :ensure t)
229 `(progn
230 (use-package-ensure-elpa 'foo '(t) 'nil)
231 (require 'foo nil nil)))))
232
233(ert-deftest use-package-test/:ensure-2 ()
234 (let ((use-package-always-ensure t))
235 (match-expansion
236 (use-package foo :ensure t)
237 `(progn
238 (use-package-ensure-elpa 'foo '(t) 'nil)
239 (require 'foo nil nil)))))
240
241(ert-deftest use-package-test/:ensure-3 ()
242 (let ((use-package-always-ensure nil))
243 (match-expansion
244 (use-package foo :ensure nil)
245 `(progn
246 (use-package-ensure-elpa 'foo '(nil) 'nil)
247 (require 'foo nil nil)))))
248
249(ert-deftest use-package-test/:ensure-4 ()
250 (let ((use-package-always-ensure t))
251 (match-expansion
252 (use-package foo :ensure nil)
253 `(progn
254 (use-package-ensure-elpa 'foo '(nil) 'nil)
255 (require 'foo nil nil)))))
256
257(ert-deftest use-package-test/:ensure-5 ()
258 (let ((use-package-always-ensure nil))
259 (match-expansion
260 (use-package foo :load-path "foo")
261 `(progn
262 (eval-and-compile
263 (add-to-list 'load-path ,(pred stringp)))
264 (require 'foo nil nil)))))
265
266(ert-deftest use-package-test/:ensure-6 ()
267 (let ((use-package-always-ensure t))
268 (match-expansion
269 (use-package foo :load-path "foo")
270 `(progn
271 (eval-and-compile
272 (add-to-list 'load-path ,(pred stringp)))
273 (require 'foo nil nil)))))
274
275(ert-deftest use-package-test/:ensure-7 ()
276 (let ((use-package-always-ensure nil))
277 (match-expansion
278 (use-package foo :ensure nil :load-path "foo")
279 `(progn
280 (use-package-ensure-elpa 'foo '(nil) 'nil)
281 (eval-and-compile
282 (add-to-list 'load-path ,(pred stringp)))
283 (require 'foo nil nil)))))
284
285(ert-deftest use-package-test/:ensure-8 ()
286 (let ((use-package-always-ensure t))
287 (match-expansion
288 (use-package foo :ensure nil :load-path "foo")
289 `(progn
290 (use-package-ensure-elpa 'foo '(nil) 'nil)
291 (eval-and-compile
292 (add-to-list 'load-path ,(pred stringp)))
293 (require 'foo nil nil)))))
294
295(ert-deftest use-package-test/:ensure-9 ()
296 (let ((use-package-always-ensure nil))
297 (match-expansion
298 (use-package foo :ensure t :load-path "foo")
299 `(progn
300 (use-package-ensure-elpa 'foo '(t) 'nil)
301 (eval-and-compile
302 (add-to-list 'load-path ,(pred stringp)))
303 (require 'foo nil nil)))))
304
305(ert-deftest use-package-test/:ensure-10 ()
306 (let ((use-package-always-ensure t))
307 (match-expansion
308 (use-package foo :ensure t :load-path "foo")
309 `(progn
310 (use-package-ensure-elpa 'foo '(t) 'nil)
311 (eval-and-compile
312 (add-to-list 'load-path ,(pred stringp)))
313 (require 'foo nil nil)))))
314
315(ert-deftest use-package-test/:ensure-11 ()
316 (let (tried-to-install)
317 (cl-letf (((symbol-function #'use-package-ensure-elpa)
318 (lambda (name ensure state &optional no-refresh)
319 (when ensure
320 (setq tried-to-install name))))
321 ((symbol-function #'require) #'ignore))
322 (use-package foo :ensure t)
323 (should (eq tried-to-install 'foo)))))
324
325(ert-deftest use-package-test/:ensure-12 ()
326 (let ((use-package-always-ensure t))
327 (match-expansion
328 (use-package foo :ensure bar)
329 `(progn
330 (use-package-ensure-elpa 'foo '(bar) 'nil)
331 (require 'foo nil nil)))))
332
333(ert-deftest use-package-test/:ensure-13 ()
334 (let ((use-package-always-ensure t))
335 (match-expansion
336 (use-package foo :ensure bar :ensure quux)
337 `(progn
338 (use-package-ensure-elpa 'foo '(bar quux) 'nil)
339 (require 'foo nil nil)))))
340
341(ert-deftest use-package-test/:ensure-14 ()
342 (match-expansion
343 (use-package ess-site
344 :ensure ess1
345 :ensure ess2
346 :ensure (ess3 :pin "melpa-unstable")
347 :pin melpa-stable)
348 `(progn
349 (use-package-pin-package 'ess-site "melpa-stable")
350 (use-package-ensure-elpa 'ess-site
351 '(ess1 ess2
352 (ess3 . "melpa-unstable"))
353 'nil)
354 (require 'ess-site nil nil))))
355
356(ert-deftest use-package-test/:ensure-15 ()
357 (let ((use-package-always-ensure t))
358 (match-expansion
359 (use-package foo
360 :pin "elpa"
361 :ensure bar
362 :ensure (quux :pin "melpa"))
363 `(progn
364 (use-package-pin-package 'foo "elpa")
365 (use-package-ensure-elpa 'foo
366 '(bar
367 (quux . "melpa"))
368 'nil)
369 (require 'foo nil nil)))))
370
371(ert-deftest use-package-test/:if-1 ()
372 (match-expansion
373 (use-package foo :if t)
374 `(when t
375 (require 'foo nil nil))))
376
377(ert-deftest use-package-test/:if-2 ()
378 (match-expansion
379 (use-package foo :if (and t t))
380 `(when (and t t)
381 (require 'foo nil nil))))
382
383(ert-deftest use-package-test/:if-3 ()
384 (match-expansion
385 (use-package foo :if nil)
386 `(when nil
387 (require 'foo nil nil))))
388
389(ert-deftest use-package-test/:when-1 ()
390 (match-expansion
391 (use-package foo :when t)
392 `(when t
393 (require 'foo nil nil))))
394
395(ert-deftest use-package-test/:when-2 ()
396 (match-expansion
397 (use-package foo :when (and t t))
398 `(when (and t t)
399 (require 'foo nil nil))))
400
401(ert-deftest use-package-test/:when-3 ()
402 (match-expansion
403 (use-package foo :when nil)
404 `(when nil
405 (require 'foo nil nil))))
406
407(ert-deftest use-package-test/:unless-1 ()
408 (match-expansion
409 (use-package foo :unless t)
410 `(when (not t)
411 (require 'foo nil nil))))
412
413(ert-deftest use-package-test/:unless-2 ()
414 (match-expansion
415 (use-package foo :unless (and t t))
416 `(when (not (and t t))
417 (require 'foo nil nil))))
418
419(ert-deftest use-package-test/:unless-3 ()
420 (match-expansion
421 (use-package foo :unless nil)
422 `(unless nil
423 (require 'foo nil nil))))
424
425(ert-deftest use-package-test/:requires-1 ()
426 (match-expansion
427 (use-package foo :requires bar)
428 `(when (featurep 'bar)
429 (require 'foo nil nil))))
430
431(ert-deftest use-package-test/:requires-2 ()
432 (let ((byte-compile-current-file t))
433 (match-expansion
434 (use-package foo :requires bar)
435 `(when (featurep 'bar)
436 (eval-and-compile
437 (eval-when-compile
438 (with-demoted-errors
439 "Cannot load foo: %S" nil
440 (unless (featurep 'foo)
441 (load "foo" nil t)))))
442 (require 'foo nil nil)))))
443
444(ert-deftest use-package-test/:requires-3 ()
445 (match-expansion
446 (use-package foo :requires (bar quux))
447 `(when (not (member nil (mapcar #'featurep '(bar quux))))
448 (require 'foo nil nil))))
449
450(ert-deftest use-package-test/:requires-4 ()
451 (let ((byte-compile-current-file t))
452 (match-expansion
453 (use-package foo :requires bar)
454 `(when (featurep 'bar)
455 (eval-and-compile
456 (eval-when-compile
457 (with-demoted-errors "Cannot load foo: %S" nil
458 (unless (featurep 'foo)
459 (load "foo" nil t)))))
460 (require 'foo nil nil)))))
461
462(ert-deftest use-package-test/:load-path-1 ()
463 (match-expansion
464 (use-package foo :load-path "bar")
465 `(progn
466 (eval-and-compile
467 (add-to-list 'load-path
468 ,(pred (apply-partially
469 #'string=
470 (expand-file-name
471 "bar" user-emacs-directory)))))
472 (require 'foo nil nil))))
473
474(ert-deftest use-package-test/:load-path-2 ()
475 (let ((byte-compile-current-file t))
476 (match-expansion
477 (use-package foo :load-path "bar")
478 `(progn
479 (eval-and-compile
480 (add-to-list 'load-path
481 ,(pred (apply-partially
482 #'string=
483 (expand-file-name
484 "bar" user-emacs-directory)))))
485 (eval-and-compile
486 (eval-when-compile
487 (with-demoted-errors "Cannot load foo: %S" nil
488 (unless (featurep 'foo)
489 (load "foo" nil t)))))
490 (require 'foo nil nil)))))
491
492(ert-deftest use-package-test/:load-path-3 ()
493 (match-expansion
494 (use-package foo :load-path ("bar" "quux"))
495 `(progn
496 (eval-and-compile
497 (add-to-list 'load-path
498 ,(pred (apply-partially
499 #'string=
500 (expand-file-name
501 "bar" user-emacs-directory)))))
502 (eval-and-compile
503 (add-to-list 'load-path
504 ,(pred (apply-partially
505 #'string=
506 (expand-file-name
507 "quux" user-emacs-directory)))))
508 (require 'foo nil nil))))
509
510(ert-deftest use-package-test/:load-path-4 ()
511 (match-expansion
512 (use-package foo :load-path (lambda () (list "bar" "quux")))
513 `(progn
514 (eval-and-compile
515 (add-to-list 'load-path
516 ,(pred (apply-partially
517 #'string=
518 (expand-file-name
519 "bar" user-emacs-directory)))))
520 (eval-and-compile
521 (add-to-list 'load-path
522 ,(pred (apply-partially
523 #'string=
524 (expand-file-name
525 "quux" user-emacs-directory)))))
526 (require 'foo nil nil))))
527
528(ert-deftest use-package-test/:no-require-1 ()
529 (match-expansion
530 (use-package foo :no-require t)
531 `nil))
532
533(ert-deftest use-package-test/:no-require-2 ()
534 (match-expansion
535 (use-package foo :no-require t :config (config))
536 `(progn
537 (config)
538 t)))
539
540(ert-deftest use-package-test/:no-require-3 ()
541 (let ((byte-compile-current-file t))
542 (match-expansion
543 (use-package foo :no-require t)
544 `(eval-and-compile
545 (eval-when-compile
546 (with-demoted-errors "Cannot load foo: %S" nil nil))))))
547
548(defun use-package-test-normalize-bind (&rest args)
549 (apply #'use-package-normalize-binder 'foo :bind args))
550
551(ert-deftest use-package-test-normalize/:bind-1 ()
552 (should (equal (use-package-test-normalize-bind
553 '(("C-a" . alpha)))
554 '(("C-a" . alpha)))))
555
556(ert-deftest use-package-test-normalize/:bind-2 ()
557 (should (equal (use-package-test-normalize-bind
558 '(("C-a" . alpha)
559 :map foo-map
560 ("C-b" . beta)))
561 '(("C-a" . alpha)
562 :map foo-map
563 ("C-b" . beta)))))
564
565(ert-deftest use-package-test-normalize/:bind-3 ()
566 (should (equal (use-package-test-normalize-bind
567 '(:map foo-map
568 ("C-a" . alpha)
569 ("C-b" . beta)))
570 '(:map foo-map
571 ("C-a" . alpha)
572 ("C-b" . beta)))))
573
574(ert-deftest use-package-test/:bind-1 ()
575 (match-expansion
576 (use-package foo :bind ("C-k" . key1) ("C-u" . key2))
577 `(progn
578 (unless
579 (fboundp 'key1)
580 (autoload #'key1 "foo" nil t))
581 (unless
582 (fboundp 'key2)
583 (autoload #'key2 "foo" nil t))
584 (bind-keys :package foo
585 ("C-k" . key1)
586 ("C-u" . key2)))))
587
588(ert-deftest use-package-test/:bind-2 ()
589 (match-expansion
590 (use-package foo :bind (("C-k" . key1) ("C-u" . key2)))
591 `(progn
592 (unless (fboundp 'key1)
593 (autoload #'key1 "foo" nil t))
594 (unless (fboundp 'key2)
595 (autoload #'key2 "foo" nil t))
596 (bind-keys :package foo
597 ("C-k" . key1)
598 ("C-u" . key2)))))
599
600(ert-deftest use-package-test/:bind-3 ()
601 (match-expansion
602 (use-package foo :bind (:map my-map ("C-k" . key1) ("C-u" . key2)))
603 `(progn
604 (unless
605 (fboundp 'key1)
606 (autoload #'key1 "foo" nil t))
607 (unless
608 (fboundp 'key2)
609 (autoload #'key2 "foo" nil t))
610 (bind-keys :package foo :map my-map
611 ("C-k" . key1)
612 ("C-u" . key2)))))
613
614(ert-deftest use-package-test/:bind-4 ()
615 (should-error
616 (match-expansion
617 (use-package foo :bind :map my-map ("C-k" . key1) ("C-u" . key2))
618 `(bind-keys :package foo))))
619
620(ert-deftest use-package-test/:bind-5 ()
621 (match-expansion
622 (use-package foo :bind ("C-k" . key1) (:map my-map ("C-u" . key2)))
623 `(progn
624 (unless (fboundp 'key1)
625 (autoload #'key1 "foo" nil t))
626 (unless (fboundp 'key2)
627 (autoload #'key2 "foo" nil t))
628 (bind-keys :package foo
629 ("C-k" . key1)
630 :map my-map
631 ("C-u" . key2)))))
632
633(ert-deftest use-package-test/:bind-6 ()
634 (match-expansion
635 (use-package foo
636 :bind
637 ("C-k" . key1)
638 (:map my-map ("C-u" . key2))
639 (:map my-map2 ("C-u" . key3)))
640 `(progn
641 (unless (fboundp 'key1)
642 (autoload #'key1 "foo" nil t))
643 (unless (fboundp 'key2)
644 (autoload #'key2 "foo" nil t))
645 (unless (fboundp 'key3)
646 (autoload #'key3 "foo" nil t))
647 (bind-keys :package foo
648 ("C-k" . key1)
649 :map my-map ("C-u" . key2)
650 :map my-map2 ("C-u" . key3)))))
651
652(ert-deftest use-package-test/:bind-7 ()
653 (match-expansion
654 (use-package foo
655 :ensure
656 :bind ("C-c r" . browse-at-remote))
657 `(progn
658 (use-package-ensure-elpa 'foo '(t) 'nil)
659 (unless (fboundp 'browse-at-remote)
660 (autoload #'browse-at-remote "foo" nil t))
661 (bind-keys :package foo ("C-c r" . browse-at-remote)))))
662
663(ert-deftest use-package-test/:bind-8 ()
664 (match-expansion
665 (use-package foo
666 :ensure
667 :bind (:map foo-map
668 (("C-c r" . foo)
669 ("C-c r" . bar))))
670 `(progn
671 (use-package-ensure-elpa 'foo '(t) 'nil)
672 (unless (fboundp 'foo)
673 (autoload #'foo "foo" nil t))
674 (unless (fboundp 'bar)
675 (autoload #'bar "foo" nil t))
676 (bind-keys :package foo :map foo-map
677 ("C-c r" . foo)
678 ("C-c r" . bar)))))
679
680(ert-deftest use-package-test/:bind*-1 ()
681 (match-expansion
682 (use-package foo :bind* ("C-k" . key))
683 `(progn
684 (unless (fboundp 'key)
685 (autoload #'key "foo" nil t))
686 (bind-keys* :package foo ("C-k" . key)))))
687
688(ert-deftest use-package-test/:bind-keymap-1 ()
689 (match-expansion
690 (use-package foo :bind-keymap ("C-k" . key))
691 `(bind-key "C-k"
692 #'(lambda nil
693 (interactive)
694 (use-package-autoload-keymap 'key 'foo nil)))))
695
696(ert-deftest use-package-test/:bind-keymap*-1 ()
697 (match-expansion
698 (use-package foo :bind-keymap* ("C-k" . key))
699 `(bind-key* "C-k"
700 #'(lambda ()
701 (interactive)
702 (use-package-autoload-keymap 'key 'foo t)))))
703
704(ert-deftest use-package-test/:interpreter-1 ()
705 (match-expansion
706 (use-package foo :interpreter "interp")
707 `(progn
708 (unless (fboundp 'foo)
709 (autoload #'foo "foo" nil t))
710 (add-to-list 'interpreter-mode-alist '("interp" . foo)))))
711
712(ert-deftest use-package-test/:interpreter-2 ()
713 (match-expansion
714 (use-package foo :interpreter ("interp" . fun))
715 `(progn
716 (unless (fboundp 'fun)
717 (autoload #'fun "foo" nil t))
718 (add-to-list 'interpreter-mode-alist '("interp" . fun)))))
719
720(ert-deftest use-package-test-normalize/:mode ()
721 (cl-flet ((norm (&rest args)
722 (apply #'use-package-normalize/:mode
723 'foopkg :mode args)))
724 (should (equal (norm '(".foo"))
725 '((".foo" . foopkg))))
726 (should (equal (norm '(".foo" ".bar"))
727 '((".foo" . foopkg) (".bar" . foopkg))))
728 (should (equal (norm '((".foo" ".bar")))
729 '((".foo" . foopkg) (".bar" . foopkg))))
730 (should (equal (norm '((".foo")))
731 '((".foo" . foopkg))))
732 (should (equal (norm '((".foo" . foo) (".bar" . bar)))
733 '((".foo" . foo) (".bar" . bar))))))
734
735(ert-deftest use-package-test/:mode-1 ()
736 (match-expansion
737 (use-package foo :mode "interp")
738 `(progn
739 (unless (fboundp 'foo)
740 (autoload #'foo "foo" nil t))
741 (add-to-list 'auto-mode-alist '("interp" . foo)))))
742
743(ert-deftest use-package-test/:mode-2 ()
744 (match-expansion
745 (use-package foo :mode ("interp" . fun))
746 `(progn
747 (unless (fboundp 'fun)
748 (autoload #'fun "foo" nil t))
749 (add-to-list 'auto-mode-alist '("interp" . fun)))))
750
751(ert-deftest use-package-test/:magic-1 ()
752 (match-expansion
753 (use-package foo :magic "interp")
754 `(progn
755 (unless (fboundp 'foo)
756 (autoload #'foo "foo" nil t))
757 (add-to-list 'magic-mode-alist '("interp" . foo)))))
758
759(ert-deftest use-package-test/:magic-2 ()
760 (match-expansion
761 (use-package foo :magic ("interp" . fun))
762 `(progn
763 (unless (fboundp 'fun)
764 (autoload #'fun "foo" nil t))
765 (add-to-list 'magic-mode-alist '("interp" . fun)))))
766
767(ert-deftest use-package-test/:magic-fallback-1 ()
768 (match-expansion
769 (use-package foo :magic-fallback "interp")
770 `(progn
771 (unless (fboundp 'foo)
772 (autoload #'foo "foo" nil t))
773 (add-to-list 'magic-fallback-mode-alist '("interp" . foo)))))
774
775(ert-deftest use-package-test/:magic-fallback-2 ()
776 (match-expansion
777 (use-package foo :magic-fallback ("interp" . fun))
778 `(progn
779 (unless (fboundp 'fun)
780 (autoload #'fun "foo" nil t))
781 (add-to-list 'magic-fallback-mode-alist '("interp" . fun)))))
782
783(ert-deftest use-package-test/:commands-1 ()
784 (match-expansion
785 (use-package foo :commands bar)
786 `(unless (fboundp 'bar)
787 (autoload #'bar "foo" nil t))))
788
789(ert-deftest use-package-test/:commands-2 ()
790 (match-expansion
791 (use-package foo :commands (bar quux))
792 `(progn
793 (unless (fboundp 'bar)
794 (autoload #'bar "foo" nil t))
795 (unless (fboundp 'quux)
796 (autoload #'quux "foo" nil t)))))
797
798(ert-deftest use-package-test/:commands-3 ()
799 (let ((byte-compile-current-file t))
800 (match-expansion
801 (use-package foo :commands (bar quux))
802 `(progn
803 (eval-and-compile
804 (eval-when-compile
805 (with-demoted-errors "Cannot load foo: %S" nil
806 (unless (featurep 'foo)
807 (load "foo" nil t)))))
808 (unless (fboundp 'bar)
809 (autoload #'bar "foo" nil t))
810 (eval-when-compile
811 (declare-function bar "foo"))
812 (unless (fboundp 'quux)
813 (autoload #'quux "foo" nil t))
814 (eval-when-compile
815 (declare-function quux "foo"))))))
816
817(ert-deftest use-package-test/:commands-4 ()
818 (match-expansion
819 (use-package foo :commands bar :init (bar))
820 `(progn
821 (unless
822 (fboundp 'bar)
823 (autoload #'bar "foo" nil t))
824 (bar))))
825
826(ert-deftest use-package-test/:commands-5 ()
827 (match-expansion
828 (use-package gnus-harvest
829 :load-path "foo"
830 :commands gnus-harvest-install
831 :demand t
832 :config
833 (if (featurep 'message-x)
834 (gnus-harvest-install 'message-x)
835 (gnus-harvest-install)))
836 `(progn
837 (eval-and-compile
838 (add-to-list 'load-path ,(pred stringp)))
839 (require 'gnus-harvest nil nil)
840 (if (featurep 'message-x)
841 (gnus-harvest-install 'message-x)
842 (gnus-harvest-install))
843 t)))
844
845(ert-deftest use-package-test/:commands-6 ()
846 (let ((byte-compile-current-file t))
847 (match-expansion
848 (use-package gnus-harvest
849 :load-path "foo"
850 :commands gnus-harvest-install
851 :demand t
852 :config
853 (if (featurep 'message-x)
854 (gnus-harvest-install 'message-x)
855 (gnus-harvest-install)))
856 `(progn
857 (eval-and-compile
858 (add-to-list 'load-path ,(pred stringp)))
859 (eval-and-compile
860 (eval-when-compile
861 (with-demoted-errors "Cannot load gnus-harvest: %S" nil
862 (unless (featurep 'gnus-harvest)
863 (load "gnus-harvest" nil t)))))
864 (eval-when-compile
865 (declare-function gnus-harvest-install "gnus-harvest"))
866 (require 'gnus-harvest nil nil)
867 (if
868 (featurep 'message-x)
869 (gnus-harvest-install 'message-x)
870 (gnus-harvest-install))
871 t))))
872
873(ert-deftest use-package-test/:autoload-1 ()
874 (match-expansion
875 (use-package foo :autoload bar)
876 `(unless (fboundp 'bar)
877 (autoload #'bar "foo"))))
878
879(ert-deftest use-package-test/:defines-1 ()
880 (match-expansion
881 (use-package foo :defines bar)
882 `(require 'foo nil nil)))
883
884(ert-deftest use-package-test/:defines-2 ()
885 (let ((byte-compile-current-file t))
886 (match-expansion
887 (use-package foo :defines bar)
888 `(progn
889 (eval-and-compile
890 (defvar bar)
891 (eval-when-compile
892 (with-demoted-errors
893 "Cannot load foo: %S" nil
894 (unless (featurep 'foo)
895 (load "foo" nil t)))))
896 (require 'foo nil nil)))))
897
898(ert-deftest use-package-test/:functions-1 ()
899 (match-expansion
900 (use-package foo :functions bar)
901 `(require 'foo nil nil)))
902
903(ert-deftest use-package-test/:functions-2 ()
904 (let ((byte-compile-current-file t))
905 (match-expansion
906 (use-package foo :functions bar)
907 `(progn
908 (eval-and-compile
909 (declare-function bar "foo")
910 (eval-when-compile
911 (with-demoted-errors
912 "Cannot load foo: %S" nil
913 (unless (featurep 'foo)
914 (load "foo" nil t)))))
915 (require 'foo nil nil)))))
916
917(ert-deftest use-package-test/:functions-3 ()
918 (match-expansion
919 (use-package foo :defer t :functions bar)
920 `nil))
921
922(ert-deftest use-package-test/:functions-4 ()
923 (let ((byte-compile-current-file t))
924 (match-expansion
925 (use-package foo :defer t :functions bar)
926 `(eval-and-compile
927 (declare-function bar "foo")
928 (eval-when-compile
929 (with-demoted-errors "Cannot load foo: %S" nil
930 (unless (featurep 'foo)
931 (load "foo" nil t))))))))
932
933(ert-deftest use-package-test/:functions-5 ()
934 (let ((byte-compile-current-file t))
935 (match-expansion
936 (use-package foo :defer t :config (config) :functions bar)
937 `(progn
938 (eval-and-compile
939 (declare-function bar "foo")
940 (eval-when-compile
941 (with-demoted-errors
942 "Cannot load foo: %S" nil
943 (unless (featurep 'foo)
944 (load "foo" nil t)))))
945 (eval-after-load 'foo
946 '(progn
947 (config)
948 t))))))
949
950(ert-deftest use-package-test/:defer-1 ()
951 (match-expansion
952 (use-package foo)
953 `(require 'foo nil nil)))
954
955(ert-deftest use-package-test/:defer-2 ()
956 (let ((byte-compile-current-file t))
957 (match-expansion
958 (use-package foo)
959 `(progn
960 (eval-and-compile
961 (eval-when-compile
962 (with-demoted-errors "Cannot load foo: %S" nil
963 (unless (featurep 'foo)
964 (load "foo" nil t)))))
965 (require 'foo nil nil)))))
966
967(ert-deftest use-package-test/:defer-3 ()
968 (match-expansion
969 (use-package foo :defer t)
970 `nil))
971
972(ert-deftest use-package-test/:defer-4 ()
973 (let ((byte-compile-current-file t))
974 (match-expansion
975 (use-package foo :defer t)
976 `(eval-and-compile
977 (eval-when-compile
978 (with-demoted-errors "Cannot load foo: %S" nil
979 (unless (featurep 'foo)
980 (load "foo" nil t))))))))
981
982(ert-deftest use-package-test-normalize/:hook ()
983 (cl-flet ((norm (&rest args)
984 (apply #'use-package-normalize/:hook
985 'foopkg :hook args)))
986 (should-error (norm nil))
987 (should (equal (norm '(bar))
988 '((bar . foopkg-mode))))
989 (should (equal (norm '((bar . foopkg)))
990 '((bar . foopkg))))
991 (should (equal (norm '((bar . baz)))
992 '((bar . baz))))
993 (should (equal (norm '(((bar baz) . quux)))
994 '(((bar baz) . quux))))
995 (should (equal (norm '(bar baz))
996 '(((bar baz) . foopkg-mode))))
997 (should (equal (norm '((bar baz) (quux bow)))
998 '(((bar baz) . foopkg-mode) ((quux bow) . foopkg-mode))))
999 (should (equal (norm '((bar . baz) (quux . bow)))
1000 '((bar . baz) (quux . bow))))
1001 (should (equal (norm '(((bar1 bar2) . baz) ((quux1 quux2) . bow)))
1002 '(((bar1 bar2) . baz) ((quux1 quux2) . bow))))))
1003
1004(ert-deftest use-package-test/:hook-1 ()
1005 (let ((byte-compile-current-file t))
1006 (match-expansion
1007 (use-package foo
1008 :bind (("C-a" . key))
1009 :hook (hook . fun))
1010 `(progn
1011 (eval-and-compile
1012 (eval-when-compile
1013 (with-demoted-errors
1014 "Cannot load foo: %S" nil
1015 (unless (featurep 'foo)
1016 (load "foo" nil t)))))
1017 (unless
1018 (fboundp 'key)
1019 (autoload #'key "foo" nil t))
1020 (eval-when-compile
1021 (declare-function key "foo"))
1022 (unless
1023 (fboundp 'fun)
1024 (autoload #'fun "foo" nil t))
1025 (eval-when-compile
1026 (declare-function fun "foo"))
1027 (add-hook 'hook-hook #'fun)
1028 (bind-keys :package foo ("C-a" . key))))))
1029
1030(ert-deftest use-package-test/:hook-2 ()
1031 (match-expansion
1032 (use-package foo
1033 :hook (hook . fun))
1034 `(progn
1035 (unless (fboundp 'fun)
1036 (autoload #'fun "foo" nil t))
1037 (add-hook 'hook-hook #'fun))))
1038
1039(ert-deftest use-package-test/:hook-3 ()
1040 (let ((use-package-hook-name-suffix nil))
1041 (match-expansion
1042 (use-package foo
1043 :hook (hook . fun))
1044 `(progn
1045 (unless (fboundp 'fun)
1046 (autoload #'fun "foo" nil t))
1047 (add-hook 'hook #'fun)))))
1048
1049(ert-deftest use-package-test/:hook-4 ()
1050 (let ((use-package-hook-name-suffix "-special"))
1051 (match-expansion
1052 (use-package foo
1053 :hook (hook . fun))
1054 `(progn
1055 (unless (fboundp 'fun)
1056 (autoload #'fun "foo" nil t))
1057 (add-hook 'hook-special #'fun)))))
1058
1059(ert-deftest use-package-test/:hook-5 ()
1060 (match-expansion
1061 (use-package erefactor
1062 :load-path "foo"
1063 :after elisp-mode
1064 :load t
1065 :hook (emacs-lisp-mode
1066 . (lambda ()
1067 (bind-key "\C-c\C-v" erefactor-map emacs-lisp-mode-map))))
1068 `(progn
1069 (eval-and-compile
1070 (add-to-list 'load-path ,(pred stringp)))
1071 (eval-after-load 'elisp-mode
1072 '(progn
1073 (require 'erefactor nil nil)
1074 (add-hook
1075 'emacs-lisp-mode-hook
1076 #'(lambda nil
1077 (bind-key "" erefactor-map emacs-lisp-mode-map))))))))
1078
1079(ert-deftest use-package-test/:hook-6 ()
1080 (match-expansion
1081 (use-package erefactor
1082 :load-path "foo"
1083 :after elisp-mode
1084 :hook (emacs-lisp-mode . function))
1085 `(progn
1086 (eval-and-compile
1087 (add-to-list 'load-path ,(pred stringp)))
1088 (eval-after-load 'elisp-mode
1089 '(progn
1090 (unless (fboundp 'function)
1091 (autoload #'function "erefactor" nil t))
1092 (add-hook 'emacs-lisp-mode-hook #'function))))))
1093
1094(ert-deftest use-package-test/:hook-7 ()
1095 (match-expansion
1096 (use-package erefactor
1097 :load-path "foo"
1098 :after elisp-mode
1099 :hook (emacs-lisp-mode . (lambda () (function))))
1100 `(progn
1101 (eval-and-compile
1102 (add-to-list 'load-path ,(pred stringp)))
1103 (eval-after-load 'elisp-mode
1104 '(progn
1105 (require 'erefactor nil nil)
1106 (add-hook 'emacs-lisp-mode-hook #'(lambda nil (function))))))))
1107
1108(ert-deftest use-package-test-normalize/:custom ()
1109 (cl-flet ((norm (&rest args)
1110 (apply #'use-package-normalize/:custom
1111 'foopkg :custom args)))
1112 (should-error (norm nil))
1113 (should-error (norm '(bar)))
1114 ;; (should-error (norm '((foo bar baz quux))))
1115 (should (equal (norm '(foo bar)) '((foo bar))))
1116 ;; (should-error (norm '(foo bar baz)))
1117 ;; (should (equal (norm '(foo bar "baz"))
1118 ;; '((foo bar baz))))
1119 ))
1120
1121
1122(ert-deftest use-package-test/:custom-1 ()
1123 (match-expansion
1124 (use-package foo :custom (foo bar))
1125 `(progn
1126 (let
1127 ((custom--inhibit-theme-enable nil))
1128 (unless (memq 'use-package custom-known-themes)
1129 (deftheme use-package)
1130 (enable-theme 'use-package)
1131 (setq custom-enabled-themes (remq 'use-package custom-enabled-themes)))
1132 (custom-theme-set-variables 'use-package
1133 '(foo bar nil nil "Customized with use-package foo")))
1134 (require 'foo nil nil))))
1135
1136(ert-deftest use-package-test/:custom-with-comment1 ()
1137 (match-expansion
1138 (use-package foo :custom (foo bar "commented"))
1139 `(progn
1140 (let
1141 ((custom--inhibit-theme-enable nil))
1142 (unless (memq 'use-package custom-known-themes)
1143 (deftheme use-package)
1144 (enable-theme 'use-package)
1145 (setq custom-enabled-themes (remq 'use-package custom-enabled-themes)))
1146 (custom-theme-set-variables 'use-package
1147 '(foo bar nil nil "commented")))
1148 (require 'foo nil nil))))
1149
1150(ert-deftest use-package-test/:custom-face-1 ()
1151 (match-expansion
1152 (use-package foo :custom-face (foo ((t (:background "#e4edfc")))))
1153 `(progn
1154 (apply #'face-spec-set (backquote (foo ((t (:background "#e4edfc"))))))
1155 (require 'foo nil nil))))
1156
1157(ert-deftest use-package-test/:custom-face-2 ()
1158 (match-expansion
1159 (use-package example
1160 :custom-face
1161 (example-1-face ((t (:foreground "LightPink"))))
1162 (example-2-face ((t (:foreground "LightGreen")))))
1163 `(progn
1164 (apply #'face-spec-set
1165 (backquote (example-1-face ((t (:foreground "LightPink"))))))
1166 (apply #'face-spec-set
1167 (backquote (example-2-face ((t (:foreground "LightGreen"))))))
1168 (require 'example nil nil))))
1169
1170(ert-deftest use-package-test/:custom-face-3 ()
1171 (match-expansion
1172 (use-package foo :custom-face (foo ((t (:background "#e4edfc"))) face-defspec-spec))
1173 `(progn
1174 (apply #'face-spec-set (backquote (foo ((t (:background "#e4edfc"))) face-defspec-spec)))
1175 (require 'foo nil nil))))
1176
1177(ert-deftest use-package-test/:init-1 ()
1178 (match-expansion
1179 (use-package foo :init (init))
1180 `(progn
1181 (init)
1182 (require 'foo nil nil))))
1183
1184(ert-deftest use-package-test/:init-2 ()
1185 (let ((byte-compile-current-file t))
1186 (match-expansion
1187 (use-package foo :init (init))
1188 `(progn
1189 (eval-and-compile
1190 (eval-when-compile
1191 (with-demoted-errors "Cannot load foo: %S" nil
1192 (unless (featurep 'foo)
1193 (load "foo" nil t)))))
1194 (init)
1195 (require 'foo nil nil)))))
1196
1197(ert-deftest use-package-test/:catch-1 ()
1198 (match-expansion
1199 (use-package foo :catch t)
1200 `(progn
1201 (defvar ,_
1202 #'(lambda (keyword err)
1203 (let ((msg (format "%s/%s: %s" 'foo keyword
1204 (error-message-string err))))
1205 (display-warning 'use-package msg :error))))
1206 (condition-case-unless-debug err
1207 (require 'foo nil nil)
1208 (error
1209 (funcall ,_ :catch err))))))
1210
1211(ert-deftest use-package-test/:catch-2 ()
1212 (match-expansion
1213 (use-package foo :catch nil)
1214 `(require 'foo nil nil)))
1215
1216(ert-deftest use-package-test/:catch-3 ()
1217 (match-expansion
1218 (use-package foo :catch (lambda (keyword error)))
1219 `(progn
1220 (defvar ,_ (lambda (keyword error)))
1221 (condition-case-unless-debug err
1222 (require 'foo nil nil)
1223 (error
1224 (funcall ,_ :catch err))))))
1225
1226(ert-deftest use-package-test/:after-1 ()
1227 (match-expansion
1228 (use-package foo :after bar)
1229 `(eval-after-load 'bar
1230 '(require 'foo nil nil))))
1231
1232(ert-deftest use-package-test/:after-2 ()
1233 (let ((byte-compile-current-file t))
1234 (match-expansion
1235 (use-package foo :after bar)
1236 `(progn
1237 (eval-and-compile
1238 (eval-when-compile
1239 (with-demoted-errors "Cannot load foo: %S" nil
1240 (unless (featurep 'foo)
1241 (load "foo" nil t)))))
1242 (eval-after-load 'bar
1243 '(require 'foo nil nil))))))
1244
1245(ert-deftest use-package-test/:after-3 ()
1246 (match-expansion
1247 (use-package foo :after (bar quux))
1248 `(eval-after-load 'quux
1249 '(eval-after-load 'bar
1250 '(require 'foo nil nil)))))
1251
1252(ert-deftest use-package-test/:after-4 ()
1253 (match-expansion
1254 (use-package foo :after (:all bar quux))
1255 `(eval-after-load 'quux
1256 '(eval-after-load 'bar
1257 '(require 'foo nil nil)))))
1258
1259(ert-deftest use-package-test/:after-5 ()
1260 (match-expansion
1261 (use-package foo :after (:any bar quux))
1262 `(progn
1263 (defvar ,_ nil)
1264 (defvar ,_ nil)
1265 (defvar ,_
1266 #'(lambda nil
1267 (if ,_ ,_
1268 (setq ,_ t ,_
1269 (require 'foo nil nil)))))
1270 (eval-after-load 'bar
1271 '(funcall ,_))
1272 (eval-after-load 'quux
1273 '(funcall ,_)))))
1274
1275(ert-deftest use-package-test/:after-6 ()
1276 (match-expansion
1277 (use-package foo :after (:all (:any bar quux) bow))
1278 `(progn
1279 (defvar ,_ nil)
1280 (defvar ,_ nil)
1281 (defvar ,_
1282 #'(lambda nil
1283 (if ,_ ,_
1284 (setq ,_ t ,_
1285 (require 'foo nil nil)))))
1286 (eval-after-load 'bow
1287 '(progn
1288 (eval-after-load 'bar
1289 '(funcall ,_))
1290 (eval-after-load 'quux
1291 '(funcall ,_)))))))
1292
1293(ert-deftest use-package-test/:after-7 ()
1294 (match-expansion
1295 (use-package foo :after (:any (:all bar quux) bow))
1296 `(progn
1297 (defvar ,_ nil)
1298 (defvar ,_ nil)
1299 (defvar ,_
1300 #'(lambda nil
1301 (if ,_ ,_
1302 (setq ,_ t ,_
1303 (require 'foo nil nil)))))
1304 (eval-after-load 'quux
1305 '(eval-after-load 'bar
1306 '(funcall ,_)))
1307 (eval-after-load 'bow
1308 '(funcall ,_)))))
1309
1310(ert-deftest use-package-test/:after-8 ()
1311 (match-expansion
1312 (use-package foo :after (:all (:any bar quux) (:any bow baz)))
1313 `(progn
1314 (defvar ,_ nil)
1315 (defvar ,_ nil)
1316 (defvar ,_
1317 #'(lambda nil
1318 (if ,_ ,_
1319 (setq ,_ t ,_
1320 (require 'foo nil nil)))))
1321 (eval-after-load 'bow
1322 '(progn
1323 (eval-after-load 'bar
1324 '(funcall ,_))
1325 (eval-after-load 'quux
1326 '(funcall ,_))))
1327 (eval-after-load 'baz
1328 '(progn
1329 (eval-after-load 'bar
1330 '(funcall ,_))
1331 (eval-after-load 'quux
1332 '(funcall ,_)))))))
1333
1334(ert-deftest use-package-test/:after-9 ()
1335 (match-expansion
1336 (use-package foo :after (:any (:all bar quux) (:all bow baz)))
1337 `(progn
1338 (defvar ,_ nil)
1339 (defvar ,_ nil)
1340 (defvar ,_
1341 #'(lambda nil
1342 (if ,_ ,_
1343 (setq ,_ t ,_
1344 (require 'foo nil nil)))))
1345 (eval-after-load 'quux
1346 '(eval-after-load 'bar
1347 '(funcall ,_)))
1348 (eval-after-load 'baz
1349 '(eval-after-load 'bow
1350 '(funcall ,_))))))
1351
1352(ert-deftest use-package-test/:after-10 ()
1353 (match-expansion
1354 (use-package foo :after (:any (:all bar quux) (:any bow baz)))
1355 `(progn
1356 (defvar ,_ nil)
1357 (defvar ,_ nil)
1358 (defvar ,_
1359 #'(lambda nil
1360 (if ,_ ,_
1361 (setq ,_ t ,_
1362 (require 'foo nil nil)))))
1363 (eval-after-load 'quux
1364 '(eval-after-load 'bar
1365 '(funcall ,_)))
1366 (eval-after-load 'bow
1367 '(funcall ,_))
1368 (eval-after-load 'baz
1369 '(funcall ,_)))))
1370
1371(ert-deftest use-package-test/:demand-1 ()
1372 (match-expansion
1373 (use-package foo :demand t)
1374 `(require 'foo nil nil)))
1375
1376(ert-deftest use-package-test/:demand-2 ()
1377 (let ((byte-compile-current-file t))
1378 (match-expansion
1379 (use-package foo :demand t)
1380 `(progn
1381 (eval-and-compile
1382 (eval-when-compile
1383 (with-demoted-errors "Cannot load foo: %S" nil
1384 (unless (featurep 'foo)
1385 (load "foo" nil t)))))
1386 (require 'foo nil nil)))))
1387
1388(ert-deftest use-package-test/:demand-3 ()
1389 (match-expansion
1390 (use-package foo :demand t :config (config))
1391 `(progn
1392 (require 'foo nil nil)
1393 (config)
1394 t)))
1395
1396(ert-deftest use-package-test/:demand-4 ()
1397 (let ((byte-compile-current-file t))
1398 (match-expansion
1399 (use-package foo :demand t :config (config))
1400 `(progn
1401 (eval-and-compile
1402 (eval-when-compile
1403 (with-demoted-errors "Cannot load foo: %S" nil
1404 (unless (featurep 'foo)
1405 (load "foo" nil t)))))
1406 (require 'foo nil nil)
1407 (config)
1408 t))))
1409
1410(ert-deftest use-package-test/:demand-5 ()
1411 ;; #529 - :demand should not override an explicit use of :after
1412 (match-expansion
1413 (use-package foo :demand t :after bar)
1414 `(eval-after-load 'bar
1415 '(require 'foo nil nil))))
1416
1417(ert-deftest use-package-test/:demand-6 ()
1418 (let ((byte-compile-current-file t))
1419 (match-expansion
1420 (use-package foo :demand t :after bar)
1421 `(progn
1422 (eval-and-compile
1423 (eval-when-compile
1424 (with-demoted-errors "Cannot load foo: %S" nil
1425 (unless (featurep 'foo)
1426 (load "foo" nil t)))))
1427 (eval-after-load 'bar
1428 '(require 'foo nil nil))))))
1429
1430(ert-deftest use-package-test/:demand-7 ()
1431 (match-expansion
1432 (use-package counsel
1433 :load-path "foo"
1434 :after ivy
1435 :demand t
1436 :diminish
1437 :bind (("C-*" . counsel-org-agenda-headlines)
1438 ("M-x" . counsel-M-x))
1439 :commands (counsel-minibuffer-history
1440 counsel-find-library
1441 counsel-unicode-char)
1442 :preface (preface-code)
1443 :init
1444 ;; This is actually wrong, but it's just part of the example.
1445 (define-key minibuffer-local-map (kbd "M-r")
1446 'counsel-minibuffer-history))
1447 `(progn
1448 (eval-and-compile
1449 (add-to-list 'load-path ,(pred stringp)))
1450 (eval-and-compile
1451 (preface-code))
1452 (eval-after-load 'ivy
1453 '(progn
1454 (define-key minibuffer-local-map (kbd "M-r")
1455 'counsel-minibuffer-history)
1456 (require 'counsel nil nil)
1457 (if (fboundp 'diminish)
1458 (diminish 'counsel-mode))
1459 (bind-keys :package counsel
1460 ("C-*" . counsel-org-agenda-headlines)
1461 ("M-x" . counsel-M-x)))))))
1462
1463(ert-deftest use-package-test/:config-1 ()
1464 (match-expansion
1465 (use-package foo :config (config))
1466 `(progn
1467 (require 'foo nil nil)
1468 (config)
1469 t)))
1470
1471(ert-deftest use-package-test/:config-2 ()
1472 (let ((byte-compile-current-file t))
1473 (match-expansion
1474 (use-package foo :config (config))
1475 `(progn
1476 (eval-and-compile
1477 (eval-when-compile
1478 (with-demoted-errors "Cannot load foo: %S" nil
1479 (unless (featurep 'foo)
1480 (load "foo" nil t)))))
1481 (require 'foo nil nil)
1482 (config)
1483 t))))
1484
1485(ert-deftest use-package-test/:config-3 ()
1486 (match-expansion
1487 (use-package foo :defer t :config (config))
1488 `(eval-after-load 'foo
1489 '(progn
1490 (config)
1491 t))))
1492
1493(ert-deftest use-package-test/:config-4 ()
1494 (let ((byte-compile-current-file t))
1495 (match-expansion
1496 (use-package foo :defer t :config (config))
1497 `(progn
1498 (eval-and-compile
1499 (eval-when-compile
1500 (with-demoted-errors "Cannot load foo: %S" nil
1501 (unless (featurep 'foo)
1502 (load "foo" nil t)))))
1503 (eval-after-load 'foo
1504 '(progn
1505 (config)
1506 t))))))
1507
1508(ert-deftest use-package-test-normalize/:diminish ()
1509 (should (equal (use-package-normalize-diminish 'foopkg :diminish nil)
1510 '(foopkg-mode)))
1511 (should (equal (use-package-normalize-diminish 'foopkg :diminish 'bar)
1512 '(bar)))
1513 (should (equal (use-package-normalize-diminish 'foopkg :diminish "bar")
1514 '((foopkg-mode . "bar"))))
1515 (should (equal (use-package-normalize-diminish 'foopkg :diminish 'foo-mode)
1516 '(foo-mode)))
1517 (should (equal (use-package-normalize-diminish 'foopkg :diminish '(foo . "bar"))
1518 '((foo . "bar")))))
1519
1520(ert-deftest use-package-test/:diminish-1 ()
1521 (match-expansion
1522 (use-package foo :diminish nil)
1523 `(progn
1524 (require 'foo nil nil)
1525 (if (fboundp 'diminish)
1526 (diminish 'foo-mode)))))
1527
1528(ert-deftest use-package-test/:diminish-2 ()
1529 (match-expansion
1530 (use-package foo :diminish bar)
1531 `(progn
1532 (require 'foo nil nil)
1533 (if (fboundp 'diminish)
1534 (diminish 'bar)))))
1535
1536(ert-deftest use-package-test/:diminish-3 ()
1537 (match-expansion
1538 (use-package foo :diminish "bar")
1539 `(progn
1540 (require 'foo nil nil)
1541 (if (fboundp 'diminish)
1542 (diminish 'foo-mode "bar")))))
1543
1544(ert-deftest use-package-test/:diminish-4 ()
1545 (match-expansion
1546 (use-package foo :diminish (foo . "bar"))
1547 `(progn
1548 (require 'foo nil nil)
1549 (if (fboundp 'diminish)
1550 (diminish 'foo "bar")))))
1551
1552(ert-deftest use-package-test-normalize/:delight ()
1553 (should (equal `((foo-mode nil foo))
1554 (use-package-normalize/:delight 'foo :delight nil)))
1555 (should (equal `((foo-mode nil foo-mode))
1556 (use-package-normalize/:delight 'foo-mode :delight nil)))
1557 (should (equal `((bar-mode nil foo))
1558 (use-package-normalize/:delight 'foo :delight '(bar-mode))))
1559 (should (equal `((bar-mode nil :major))
1560 (use-package-normalize/:delight 'foo :delight '((bar-mode nil :major)))))
1561 (should (equal `((foo-mode "abc" foo))
1562 (use-package-normalize/:delight 'foo :delight '("abc"))))
1563 (should (equal `((foo-mode (:eval 1) foo))
1564 (use-package-normalize/:delight 'foo :delight '('(:eval 1)))))
1565 (should (equal (use-package-normalize/:delight 'foo :delight '((a-mode) (b-mode " b")))
1566 `((a-mode nil foo) (b-mode " b" foo))))
1567 (should-error (use-package-normalize/:delight 'foo :delight '((:eval 1)))))
1568
1569(ert-deftest use-package-test/:delight-1 ()
1570 (match-expansion
1571 (use-package foo :delight)
1572 `(progn
1573 (require 'foo nil nil)
1574 (if (fboundp 'delight)
1575 (delight '((foo-mode nil foo)))))))
1576
1577(ert-deftest use-package-test/:delight-2 ()
1578 (should-error
1579 (match-expansion
1580 (use-package foo :delight nil)
1581 `(progn
1582 (require 'foo nil nil)
1583 (if (fboundp 'diminish)
1584 (diminish 'foo-mode))))))
1585
1586(ert-deftest use-package-test/:delight-3 ()
1587 (match-expansion
1588 (use-package foo :delight bar)
1589 `(progn
1590 (require 'foo nil nil)
1591 (if (fboundp 'delight)
1592 (delight '((bar nil foo)))))))
1593
1594(ert-deftest use-package-test/:delight-4 ()
1595 (match-expansion
1596 (use-package foo :delight "bar")
1597 `(progn
1598 (require 'foo nil nil)
1599 (if (fboundp 'delight)
1600 (delight '((foo-mode "bar" foo)))))))
1601
1602(ert-deftest use-package-test/:delight-5 ()
1603 (should-error
1604 (match-expansion
1605 (use-package foo :delight (foo . "bar"))
1606 `(progn
1607 (require 'foo nil nil)
1608 (if (fboundp 'diminish)
1609 (diminish 'foo "bar"))))))
1610
1611(ert-deftest use-package-test/:delight-6 ()
1612 (match-expansion
1613 (use-package foo :delight (foo "bar"))
1614 `(progn
1615 (require 'foo nil nil)
1616 (if (fboundp 'delight)
1617 (delight '((foo "bar" foo)))))))
1618
1619(ert-deftest use-package-test/334-1 ()
1620 (let (foo1-map foo2-map
1621 bar1-func1
1622 bar1-func2
1623 bar2-func1
1624 bar2-func2
1625 bar3-func1
1626 bar3-func2
1627 bar4-func1
1628 bar4-func2)
1629 (match-expansion
1630 (bind-keys :map foo1-map
1631 ("Y" . foo1)
1632 :prefix "y"
1633 :prefix-map bar1-prefix-map
1634 ("y" . bar1-func1)
1635 ("f" . bar1-func2)
1636 :prefix "y"
1637 :prefix-map bar2-prefix-map
1638 ("y" . bar2-func1)
1639 ("f" . bar2-func2)
1640 :map foo2-map
1641 ("Y" . foo2)
1642 :prefix "y"
1643 :prefix-map bar3-prefix-map
1644 ("y" . bar3-func1)
1645 ("f" . bar3-func2)
1646 :prefix "y"
1647 :prefix-map bar4-prefix-map
1648 ("y" . bar4-func1)
1649 ("f" . bar4-func2))
1650 `(progn
1651 (bind-key "Y" #'foo1 foo1-map nil)
1652 (defvar bar1-prefix-map)
1653 (define-prefix-command 'bar1-prefix-map)
1654 (bind-key "y" 'bar1-prefix-map foo1-map nil)
1655 (bind-key "y" #'bar1-func1 bar1-prefix-map nil)
1656 (bind-key "f" #'bar1-func2 bar1-prefix-map nil)
1657 (defvar bar2-prefix-map)
1658 (define-prefix-command 'bar2-prefix-map)
1659 (bind-key "y" 'bar2-prefix-map foo1-map nil)
1660 (bind-key "y" #'bar2-func1 bar2-prefix-map nil)
1661 (bind-key "f" #'bar2-func2 bar2-prefix-map nil)
1662 (bind-key "Y" #'foo2 foo2-map nil)
1663 (defvar bar3-prefix-map)
1664 (define-prefix-command 'bar3-prefix-map)
1665 (bind-key "y" 'bar3-prefix-map foo2-map nil)
1666 (bind-key "y" #'bar3-func1 bar3-prefix-map nil)
1667 (bind-key "f" #'bar3-func2 bar3-prefix-map nil)
1668 (defvar bar4-prefix-map)
1669 (define-prefix-command 'bar4-prefix-map)
1670 (bind-key "y" 'bar4-prefix-map foo2-map nil)
1671 (bind-key "y" #'bar4-func1 bar4-prefix-map nil)
1672 (bind-key "f" #'bar4-func2 bar4-prefix-map nil)))))
1673
1674(ert-deftest use-package-test/334-2 ()
1675 (let (w3m-lnum-mode-map
1676 w3m-print-current-url
1677 w3m-lnum-print-this-url
1678 w3m-print-this-url)
1679 (match-expansion
1680 (bind-keys :map w3m-lnum-mode-map
1681 :prefix "y"
1682 :prefix-map w3m-y-prefix-map
1683 ("y" . w3m-print-current-url)
1684 ("f" . w3m-lnum-print-this-url)
1685 ("t" . w3m-print-this-url))
1686 `(progn
1687 (defvar w3m-y-prefix-map)
1688 (define-prefix-command 'w3m-y-prefix-map)
1689 (bind-key "y" 'w3m-y-prefix-map w3m-lnum-mode-map nil)
1690 (bind-key "y" #'w3m-print-current-url w3m-y-prefix-map nil)
1691 (bind-key "f" #'w3m-lnum-print-this-url w3m-y-prefix-map nil)
1692 (bind-key "t" #'w3m-print-this-url w3m-y-prefix-map nil)))))
1693
1694(ert-deftest use-package-test/482-1 ()
1695 (match-expansion
1696 (use-package simple
1697 :bind-keymap ("C-t " . my/transpose-map)
1698 :bind (:map my/transpose-map
1699 ("w" . transpose-words)))
1700 `(progn
1701 (unless (fboundp 'transpose-words)
1702 (autoload #'transpose-words "simple" nil t))
1703 (bind-key "C-t "
1704 #'(lambda nil
1705 (interactive)
1706 (use-package-autoload-keymap 'my/transpose-map 'simple nil)))
1707 (bind-keys :package simple :map my/transpose-map
1708 ("w" . transpose-words)))))
1709
1710(ert-deftest use-package-test/482-2 ()
1711 (match-expansion
1712 (use-package simple
1713 :bind (:prefix-map my/transpose-map
1714 :prefix "C-t"
1715 ("w" . transpose-words)))
1716 `(progn
1717 (unless (fboundp 'transpose-words)
1718 (autoload #'transpose-words "simple" nil t))
1719 (bind-keys :package simple
1720 :prefix-map my/transpose-map
1721 :prefix "C-t"
1722 ("w" . transpose-words)))))
1723
1724(ert-deftest use-package-test/482-3 ()
1725 (match-expansion
1726 (bind-keys :package simple
1727 :prefix-map my/transpose-map
1728 :prefix "C-t"
1729 ("w" . transpose-words))
1730 `(progn
1731 (defvar my/transpose-map)
1732 (define-prefix-command 'my/transpose-map)
1733 (bind-key "C-t" 'my/transpose-map nil nil)
1734 (bind-key "w" #'transpose-words my/transpose-map nil))))
1735
1736(ert-deftest use-package-test/538 ()
1737 (match-expansion
1738 (use-package mu4e
1739 :commands (mu4e)
1740 :bind (("<f9>" . mu4e))
1741 :init
1742 :config
1743 (config))
1744 `(progn
1745 (unless (fboundp 'mu4e)
1746 (autoload #'mu4e "mu4e" nil t))
1747 (eval-after-load 'mu4e
1748 '(progn (config) t))
1749 (bind-keys :package mu4e ("<f9>" . mu4e)))))
1750
1751(ert-deftest use-package-test/543 ()
1752 (match-expansion
1753 (use-package hydra
1754 :ensure)
1755 `(progn
1756 (use-package-ensure-elpa 'hydra '(t) 'nil)
1757 (require 'hydra nil nil))))
1758
1759(ert-deftest use-package-test/545 ()
1760 (match-expansion
1761 (use-package spacemacs-theme
1762 :ensure t
1763 :init ; or :config
1764 (load-theme 'spacemacs-dark t)
1765 )
1766 `(progn
1767 (use-package-ensure-elpa 'spacemacs-theme '(t) 'nil)
1768 (load-theme 'spacemacs-dark t)
1769 (require 'spacemacs-theme nil nil))
1770 ))
1771
1772(ert-deftest use-package-test/550 ()
1773 (match-expansion
1774 (use-package company-try-hard
1775 :ensure t
1776 :bind
1777 ("C-c M-/" . company-try-hard)
1778 (:map company-active-map
1779 ("C-c M-/" . company-try-hard)))
1780 `(progn
1781 (use-package-ensure-elpa 'company-try-hard
1782 '(t)
1783 'nil)
1784 (unless
1785 (fboundp 'company-try-hard)
1786 (autoload #'company-try-hard "company-try-hard" nil t))
1787 (bind-keys :package company-try-hard
1788 ("C-c M-/" . company-try-hard)
1789 :map company-active-map
1790 ("C-c M-/" . company-try-hard)))))
1791
1792(ert-deftest use-package-test/558 ()
1793 (match-expansion
1794 (bind-keys* :package org-ref
1795 ("C-c C-r" . org-ref-helm-insert-cite-link))
1796 `(bind-key "C-c C-r" #'org-ref-helm-insert-cite-link override-global-map nil)))
1797
1798(ert-deftest use-package-test/560 ()
1799 (cl-letf (((symbol-function #'executable-find) #'ignore))
1800 (let (notmuch-command)
1801 (match-expansion
1802 (use-package notmuch
1803 :preface (setq-default notmuch-command (executable-find "notmuch"))
1804 :if notmuch-command
1805 :requires foo
1806 :load-path "foo"
1807 :defines var)
1808 `(progn
1809 (eval-and-compile
1810 (add-to-list 'load-path ,(pred stringp)))
1811 (when (featurep 'foo)
1812 (eval-and-compile
1813 (setq-default notmuch-command
1814 (executable-find "notmuch")))
1815 (when (symbol-value 'notmuch-command)
1816 (require 'notmuch nil nil))))))))
1817
1818(ert-deftest use-package-test/572-1 ()
1819 (let ((use-package-always-defer t))
1820 (match-expansion
1821 (use-package auth-password-store
1822 :after auth-source
1823 :init
1824 (setq auth-sources '(password-store)))
1825 `(eval-after-load 'auth-source
1826 '(setq auth-sources '(password-store))))))
1827
1828(ert-deftest use-package-test/572-2 ()
1829 (let ((use-package-always-defer t))
1830 (match-expansion
1831 (use-package ivy-hydra :after ivy)
1832 `nil)))
1833
1834(ert-deftest use-package-test/572-3 ()
1835 (let ((use-package-always-defer t)
1836 (use-package-defaults
1837 (let ((defaults (copy-alist use-package-defaults)))
1838 (setcdr (assq :defer defaults)
1839 '(use-package-always-defer
1840 (lambda (name args)
1841 (and use-package-always-defer
1842 (not (plist-member args :after))
1843 (not (plist-member args :defer))
1844 (not (plist-member args :demand))))))
1845 defaults)))
1846 (match-expansion
1847 (use-package ivy-hydra :after ivy)
1848 `(eval-after-load 'ivy
1849 '(require 'ivy-hydra nil nil)))))
1850
1851(ert-deftest use-package-test/575-1 ()
1852 (match-expansion
1853 (use-package helm
1854 :defer t
1855 :after (:any ido dired)
1856 :config
1857 (message "test. helm start"))
1858 `(progn
1859 (defvar ,_ nil)
1860 (defvar ,_ nil)
1861 (defvar ,_
1862 #'(lambda nil
1863 (if ,_ ,_
1864 (setq ,_ t ,_
1865 (eval-after-load 'helm
1866 '(progn
1867 (message "test. helm start")
1868 t))))))
1869 (eval-after-load 'ido
1870 '(funcall ,_))
1871 (eval-after-load 'dired
1872 '(funcall ,_)))))
1873
1874(ert-deftest use-package-test/575-2 ()
1875 (match-expansion
1876 (use-package helm
1877 :defer t
1878 :bind ("C-c d" . helm-mini)
1879 :config
1880 (message "test. helm start"))
1881 `(progn
1882 (unless (fboundp 'helm-mini)
1883 (autoload #'helm-mini "helm" nil t))
1884 (eval-after-load 'helm
1885 '(progn
1886 (message "test. helm start")
1887 t))
1888 (bind-keys :package helm ("C-c d" . helm-mini)))))
1889
1890(ert-deftest use-package-test/585 ()
1891 (match-expansion
1892 (use-package bug
1893 :bind (:map bug-map ("C-a" . alpha))
1894 :bind (("C-b" . beta)))
1895 `(progn
1896 (unless (fboundp 'alpha)
1897 (autoload #'alpha "bug" nil t))
1898 (unless (fboundp 'beta)
1899 (autoload #'beta "bug" nil t))
1900 (bind-keys :package bug :map bug-map
1901 ("C-a" . alpha))
1902 (bind-keys :package bug
1903 ("C-b" . beta)))))
1904
1905(ert-deftest use-package-test/589 ()
1906 (let ((use-package-verbose t)
1907 (use-package-expand-minimally t)
1908 debug-on-error
1909 warnings)
1910 (cl-letf (((symbol-function #'display-warning)
1911 (lambda (_ msg _) (push msg warnings))))
1912 (progn
1913 (macroexpand-1
1914 '(use-package ediff :defer t (setq my-var t)))
1915 (should (= (and (> (length warnings) 0)
1916 (string-match ":defer wants exactly one argument"
1917 (car warnings))) 44))))))
1918
1919(ert-deftest use-package-test/591 ()
1920 (let ((use-package-defaults
1921 (cons '(:if (lambda (name _) `(locate-library ,name)) t)
1922 use-package-defaults)))
1923 (match-expansion
1924 (use-package nonexistent
1925 :hook lisp-mode)
1926 `(when (locate-library nonexistent)
1927 (unless (fboundp 'nonexistent-mode)
1928 (autoload #'nonexistent-mode "nonexistent" nil t))
1929 (add-hook 'lisp-mode-hook #'nonexistent-mode)))))
1930
1931(ert-deftest bind-key/:prefix-map ()
1932 (match-expansion
1933 (bind-keys :prefix "<f1>"
1934 :prefix-map my/map)
1935 `(progn
1936 (defvar my/map)
1937 (define-prefix-command 'my/map)
1938 (bind-key "<f1>" 'my/map nil nil))))
1939
1940
1941(ert-deftest bind-key/845 ()
1942 (defvar test-map (make-keymap))
1943 (bind-key "<f1>" 'ignore 'test-map)
1944 (should (eq (lookup-key test-map (kbd "<f1>")) 'ignore))
1945 (let ((binding (cl-find "<f1>" personal-keybindings :test 'string= :key 'caar)))
1946 (message "test-map %s" test-map)
1947 (message "binding %s" binding)
1948 (should (eq (cdar binding) 'test-map))
1949 (should (eq (nth 1 binding) 'ignore))
1950 (should (eq (nth 2 binding) nil))))
1951
1952;; Local Variables:
1953;; no-byte-compile: t
1954;; no-update-autoloads: t
1955;; End:
1956
1957;;; use-package-tests.el ends here