diff options
| -rw-r--r-- | doc/misc/use-package.texi | 946 | ||||
| -rw-r--r-- | etc/USE-PACKAGE-NEWS | 277 | ||||
| -rw-r--r-- | lisp/use-package/bind-chord.el | 113 | ||||
| -rw-r--r-- | lisp/use-package/bind-key.el | 544 | ||||
| -rw-r--r-- | lisp/use-package/use-package-bind-key.el | 171 | ||||
| -rw-r--r-- | lisp/use-package/use-package-chords.el | 54 | ||||
| -rw-r--r-- | lisp/use-package/use-package-core.el | 1690 | ||||
| -rw-r--r-- | lisp/use-package/use-package-delight.el | 83 | ||||
| -rw-r--r-- | lisp/use-package/use-package-diminish.el | 72 | ||||
| -rw-r--r-- | lisp/use-package/use-package-ensure-system-package.el | 99 | ||||
| -rw-r--r-- | lisp/use-package/use-package-ensure.el | 206 | ||||
| -rw-r--r-- | lisp/use-package/use-package-jump.el | 70 | ||||
| -rw-r--r-- | lisp/use-package/use-package-lint.el | 76 | ||||
| -rw-r--r-- | lisp/use-package/use-package.el | 51 | ||||
| -rw-r--r-- | test/lisp/use-package/use-package-chords-tests.el | 153 | ||||
| -rw-r--r-- | test/lisp/use-package/use-package-tests.el | 1957 |
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 | ||
| 11 | Copyright (C) 2012-2022 Free Software Foundation, Inc. | ||
| 12 | |||
| 13 | You can redistribute this document and/or modify it under the terms | ||
| 14 | of the GNU General Public License as published by the Free Software | ||
| 15 | Foundation, either version 3 of the License, or (at your option) any | ||
| 16 | later version. | ||
| 17 | |||
| 18 | This document 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 GNU | ||
| 21 | General 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 | |||
| 47 | The @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 | ||
| 49 | created it because I have over 80 packages that I use in Emacs, and things | ||
| 50 | were getting difficult to manage. Yet with this utility my total load time is | ||
| 51 | around 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 | |||
| 68 | Installation | ||
| 69 | |||
| 70 | * Installing from GNU ELPA:: | ||
| 71 | * Installing from the Git Repository:: | ||
| 72 | * Post-Installation Tasks:: | ||
| 73 | |||
| 74 | Keywords | ||
| 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 | |||
| 107 | The @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 | ||
| 109 | created it because I have over 80 packages that I use in Emacs, and things | ||
| 110 | were getting difficult to manage. Yet with this utility my total load time is | ||
| 111 | around 2 seconds, with no loss of functionality! | ||
| 112 | |||
| 113 | More text to come@dots{} | ||
| 114 | |||
| 115 | @node Installation | ||
| 116 | @chapter Installation | ||
| 117 | |||
| 118 | use-package can be installed using Emacs' package manager or manually from | ||
| 119 | its 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 | |||
| 130 | use-package is available from GNU ELPA. If you haven't used | ||
| 131 | Emacs' package manager before, then it is high time you familiarize yourself | ||
| 132 | with 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 | |||
| 135 | First, you need to update the local package list using: | ||
| 136 | |||
| 137 | @example | ||
| 138 | M-x package-refresh-contents RET | ||
| 139 | @end example | ||
| 140 | |||
| 141 | Once you have done that, you can install use-package and its | ||
| 142 | dependencies using: | ||
| 143 | |||
| 144 | @example | ||
| 145 | M-x package-install RET use-package RET | ||
| 146 | @end example | ||
| 147 | |||
| 148 | Now see @ref{Post-Installation Tasks}. | ||
| 149 | |||
| 150 | @node Installing from the Git Repository | ||
| 151 | @section Installing from the Git Repository | ||
| 152 | |||
| 153 | First, 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 | |||
| 160 | Then compile the libraries and generate the info manuals: | ||
| 161 | |||
| 162 | @example | ||
| 163 | $ make | ||
| 164 | @end example | ||
| 165 | |||
| 166 | You may need to create @code{/path/to/use-package/config.mk} with the following | ||
| 167 | content before running @code{make}: | ||
| 168 | |||
| 169 | @example | ||
| 170 | LOAD_PATH = -L /path/to/use-package | ||
| 171 | @end example | ||
| 172 | |||
| 173 | Finally 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 | |||
| 185 | Note that elements of @code{load-path} should not end with a slash, while those of | ||
| 186 | @code{Info-directory-list} should. | ||
| 187 | |||
| 188 | Instead of running use-package directly from the repository by adding it to | ||
| 189 | the @code{load-path}, you might want to instead install it in some other directory | ||
| 190 | using @code{sudo make install} and setting @code{load-path} accordingly. | ||
| 191 | |||
| 192 | To update use-package use: | ||
| 193 | |||
| 194 | @example | ||
| 195 | $ git pull | ||
| 196 | $ make | ||
| 197 | @end example | ||
| 198 | |||
| 199 | At times it might be necessary to run @code{make clean all} instead. | ||
| 200 | |||
| 201 | To view all available targets use @code{make help}. | ||
| 202 | |||
| 203 | Now see @ref{Post-Installation Tasks}. | ||
| 204 | |||
| 205 | @node Post-Installation Tasks | ||
| 206 | @section Post-Installation Tasks | ||
| 207 | |||
| 208 | After installing use-package you should verify that you are indeed using the | ||
| 209 | use-package release you think you are using. It's best to restart Emacs before | ||
| 210 | doing so, to make sure you are not using an outdated value for @code{load-path}. | ||
| 211 | |||
| 212 | @example | ||
| 213 | C-h v use-package-version RET | ||
| 214 | @end example | ||
| 215 | |||
| 216 | should display something like | ||
| 217 | |||
| 218 | @example | ||
| 219 | use-package-version’s value is "2.4.3" | ||
| 220 | @end example | ||
| 221 | |||
| 222 | If you are completely new to use-package then see @ref{Getting Started}. | ||
| 223 | |||
| 224 | If you run into problems, then please see the @ref{Debugging Tools}. | ||
| 225 | |||
| 226 | @node Getting Started | ||
| 227 | @chapter Getting Started | ||
| 228 | |||
| 229 | TODO@. 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 | ||
| 235 | design in various ways. Understanding these reasons may help make some of | ||
| 236 | those decisions clearer: | ||
| 237 | |||
| 238 | @itemize | ||
| 239 | @item | ||
| 240 | To gather all configuration details of a package into one place, | ||
| 241 | making it easier to copy, disable, or move it elsewhere in the init | ||
| 242 | file. | ||
| 243 | |||
| 244 | @item | ||
| 245 | To reduce duplication and boilerplate, capturing several common | ||
| 246 | practices as mere keywords both easy and intuitive to use. | ||
| 247 | |||
| 248 | @item | ||
| 249 | To make startup time of Emacs as quick as possible, without | ||
| 250 | sacrificing the quantity of add-on packages used. | ||
| 251 | |||
| 252 | @item | ||
| 253 | To make it so errors encountered during startup disable only the | ||
| 254 | package raising the error, and as little else as possible, leaving a | ||
| 255 | close to a functional Emacs as possible. | ||
| 256 | |||
| 257 | @item | ||
| 258 | To allow byte-compilation of one's init file so that any warnings or | ||
| 259 | errors seen are meaningful. In this way, even if byte-compilation is not | ||
| 260 | used 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 | |||
| 294 | Sometimes it only makes sense to configure a package after another has been | ||
| 295 | loaded, because certain variables or functions are not in scope until that | ||
| 296 | time. This can achieved using an @code{:after} keyword that allows a fairly rich | ||
| 297 | description of the exact conditions when loading should occur. Here is an | ||
| 298 | example: | ||
| 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 | |||
| 311 | In this case, because all of these packages are demand-loaded in the order | ||
| 312 | they occur, the use of @code{:after} is not strictly necessary. By using it, | ||
| 313 | however, the above code becomes order-independent, without an implicit | ||
| 314 | depedence on the nature of your init file. | ||
| 315 | |||
| 316 | By default, @code{:after (foo bar)} is the same as @code{:after (:all foo bar)}, meaning | ||
| 317 | that loading of the given package will not happen until both @code{foo} and @code{bar} | ||
| 318 | have 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 | |||
| 328 | When you nest selectors, such as @code{(:any (:all foo bar) (:all baz quux))}, it | ||
| 329 | means that the package will be loaded when either both @code{foo} and @code{bar} have | ||
| 330 | been 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 | ||
| 333 | the @code{:after} keyword, as you will need to specify how the declared package is | ||
| 334 | to be loaded: e.g., by some @code{:bind}. If you're not using one of the mechanisms | ||
| 335 | that registers autoloads, such as @code{:bind} or @code{:hook}, and your package manager | ||
| 336 | does not provide autoloads, it's possible that without adding @code{:demand t} to | ||
| 337 | those 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 | |||
| 342 | Normally @code{:bind} expects that commands are functions that will be autoloaded | ||
| 343 | from the given package. However, this does not work if one of those commands | ||
| 344 | is actually a keymap, since keymaps are not functions, and cannot be | ||
| 345 | autoloaded using Emacs' @code{autoload} mechanism. | ||
| 346 | |||
| 347 | To 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" | ||
| 349 | bound to by @code{:bind-keymap} must be keymaps defined in the package, rather than | ||
| 350 | command functions. This is handled behind the scenes by generating custom code | ||
| 351 | that loads the package containing the keymap, and then re-executes your | ||
| 352 | keypress after the first load, to reinterpret that keypress as a prefix key. | ||
| 353 | |||
| 354 | For 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 | |||
| 365 | Another common thing to do when loading a module is to bind a key to primary | ||
| 366 | commands within that module: | ||
| 367 | |||
| 368 | @lisp | ||
| 369 | (use-package ace-jump-mode | ||
| 370 | :bind ("C-." . ace-jump-mode)) | ||
| 371 | @end lisp | ||
| 372 | |||
| 373 | This does two things: first, it creates an autoload for the @code{ace-jump-mode} | ||
| 374 | command and defers loading of @code{ace-jump-mode} until you actually use it. | ||
| 375 | Second, 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 | ||
| 377 | throughout your @code{.emacs} file. | ||
| 378 | |||
| 379 | A 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 | |||
| 388 | When you use the @code{:commands} keyword, it creates autoloads for those commands | ||
| 389 | and defers loading of the module until they are used. Since the @code{:init} form | ||
| 390 | is always run---even if @code{ace-jump-mode} might not be on your system---remember | ||
| 391 | to restrict @code{:init} code to only what would succeed either way. | ||
| 392 | |||
| 393 | The @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 | |||
| 402 | The @code{:commands} keyword likewise takes either a symbol or a list of symbols. | ||
| 403 | |||
| 404 | NOTE: Special keys like @code{tab} or @code{F1}-@code{Fn} can be written in square brackets, | ||
| 405 | i.e. @code{[tab]} instead of @code{"tab"}. The syntax for the keybindings is similar to | ||
| 406 | the "kbd" syntax: see @uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-Rebinding.html, the Emacs Manual} for more information. | ||
| 407 | |||
| 408 | Examples: | ||
| 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 | |||
| 425 | Slightly different from binding a key to a keymap, is binding a key @strong{within} a | ||
| 426 | local keymap that only exists after the package is loaded. @code{use-package} | ||
| 427 | supports 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 | |||
| 435 | The effect of this statement is to wait until @code{helm} has loaded, and then to | ||
| 436 | bind the key @code{C-c h} to @code{helm-execute-persistent-action} within Helm's local | ||
| 437 | keymap, @code{helm-mode-map}. | ||
| 438 | |||
| 439 | Multiple uses of @code{:map} may be specified. Any binding occurring before the | ||
| 440 | first 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 | |||
| 460 | Here 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 | |||
| 472 | This loads in the package @code{foo}, but only if @code{foo} is available on your | ||
| 473 | system. If not, a warning is logged to the @code{*Messages*} buffer. If it | ||
| 474 | succeeds, a message about @code{"Loading foo"} is logged, along with the time it | ||
| 475 | took to load, if it took over 0.1 seconds. | ||
| 476 | |||
| 477 | Use the @code{:init} keyword to execute code before a package is loaded. It | ||
| 478 | accepts 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 | |||
| 486 | Similarly, @code{:config} can be used to execute code after a package is loaded. | ||
| 487 | In cases where loading is done lazily (see more about autoloading below), this | ||
| 488 | execution 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 | |||
| 498 | As 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 | |||
| 513 | In 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 | ||
| 515 | and within the @code{isearch-mode-map} (see next section). When the package is | ||
| 516 | actually loaded (by using one of these commands), @code{moccur-edit} is also | ||
| 517 | loaded, to allow editing of the @code{moccur} buffer. | ||
| 518 | |||
| 519 | @node @code{custom} | ||
| 520 | @section @code{:custom} | ||
| 521 | |||
| 522 | The @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 | |||
| 531 | The documentation string is not mandatory. | ||
| 532 | |||
| 533 | @node @code{custom-face} | ||
| 534 | @section @code{:custom-face} | ||
| 535 | |||
| 536 | The @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 | |||
| 547 | In almost all cases you don't need to manually specify @code{:defer t}. This is | ||
| 548 | implied whenever @code{:bind} or @code{:mode} or @code{:interpreter} is used. Typically, you | ||
| 549 | only need to specify @code{:defer} if you know for a fact that some other package | ||
| 550 | will do something to cause your package to load at the appropriate time, and | ||
| 551 | thus you would like to defer loading even though use-package isn't creating | ||
| 552 | any autoloads for you. | ||
| 553 | |||
| 554 | You can override package deferral with the @code{:demand} keyword. Thus, even if | ||
| 555 | you use @code{:bind}, using @code{:demand} will force loading to occur immediately and | ||
| 556 | not establish an autoload for the bound key. | ||
| 557 | |||
| 558 | @node @code{defines} @code{functions} | ||
| 559 | @section @code{:defines}, @code{:functions} | ||
| 560 | |||
| 561 | Another feature of @code{use-package} is that it always loads every file that it | ||
| 562 | can when @code{.emacs} is being byte-compiled. This helps to silence spurious | ||
| 563 | warnings about unknown variables and functions. | ||
| 564 | |||
| 565 | However, there are times when this is just not enough. For those times, use | ||
| 566 | the @code{:defines} and @code{:functions} keywords to introduce dummy variable and | ||
| 567 | function 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 | |||
| 577 | If 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 | ||
| 596 | utilities---if you have them installed. Their purpose is to remove or change | ||
| 597 | minor 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 | ||
| 600 | minor mode symbol, a cons of the symbol and its replacement string, or just a | ||
| 601 | replacement string, in which case the minor mode symbol is guessed to be the | ||
| 602 | package 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 | ||
| 613 | symbol, 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 | ||
| 614 | mode symbol is guessed to be the package name with "-mode" appended at the | ||
| 615 | end), both of these, or several lists of both. If no arguments are provided, | ||
| 616 | the 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 | |||
| 642 | The @code{:disabled} keyword can turn off a module you're having difficulties with, | ||
| 643 | or 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 | |||
| 651 | When byte-compiling your @code{.emacs} file, disabled declarations are omitted | ||
| 652 | from the output entirely, to accelerate startup times. | ||
| 653 | |||
| 654 | @node @code{ensure} @code{pin} | ||
| 655 | @section @code{:ensure}, @code{:pin} | ||
| 656 | |||
| 657 | You can use @code{use-package} to load packages from ELPA with @code{package.el}. This | ||
| 658 | is particularly useful if you share your @code{.emacs} among several machines; the | ||
| 659 | relevant packages are downloaded automatically once declared in your @code{.emacs}. | ||
| 660 | The @code{:ensure} keyword causes the package(s) to be installed automatically if | ||
| 661 | not already present on your system (set @code{(setq use-package-always-ensure t)} | ||
| 662 | if you wish this behavior to be global for all packages): | ||
| 663 | |||
| 664 | @lisp | ||
| 665 | (use-package magit | ||
| 666 | :ensure t) | ||
| 667 | @end lisp | ||
| 668 | |||
| 669 | If 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 | |||
| 677 | Lastly, when running on Emacs 24.4 or later, use-package can pin a package to | ||
| 678 | a specific archive, allowing you to mix and match packages from different | ||
| 679 | archives. 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} | ||
| 681 | when you need to track newer versions than what is available in the @code{stable} | ||
| 682 | archives is also a valid use-case. | ||
| 683 | |||
| 684 | By default @code{package.el} prefers @code{melpa} over @code{melpa-stable} due to the | ||
| 685 | versioning @code{(> evil-20141208.623 evil-1.0.9)}, so even if you are tracking | ||
| 686 | only a single package from @code{melpa}, you will need to tag all the non-@code{melpa} | ||
| 687 | packages with the appropriate archive. If this really annoys you, then you can | ||
| 688 | set @code{use-package-always-pin} to set a default. | ||
| 689 | |||
| 690 | If you want to manually keep a package updated and ignore upstream updates, | ||
| 691 | you can pin it to @code{manual}, which as long as there is no repository by that | ||
| 692 | name, will Just Work(tm). | ||
| 693 | |||
| 694 | @code{use-package} throws an error if you try to pin a package to an archive that | ||
| 695 | has not been configured using @code{package-archives} (apart from the magic | ||
| 696 | @code{manual} archive mentioned above): | ||
| 697 | |||
| 698 | @example | ||
| 699 | Archive 'foo' requested for package 'bar' is not available. | ||
| 700 | @end example | ||
| 701 | |||
| 702 | Example: | ||
| 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 | |||
| 731 | The @code{:hook} keyword allows adding functions onto hooks, here only the basename | ||
| 732 | of 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 | |||
| 747 | And likewise, when multiple hooks should be applied, the following are also | ||
| 748 | equivalent: | ||
| 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 | |||
| 768 | The use of @code{:hook}, as with @code{:bind}, @code{:mode}, @code{:interpreter}, etc., causes the | ||
| 769 | functions being hooked to implicitly be read as @code{:commands} (meaning they will | ||
| 770 | establish interactive @code{autoload} definitions for that module, if not already | ||
| 771 | defined 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 | |||
| 776 | You can use the @code{:if} keyword to predicate the loading and initialization of | ||
| 777 | modules. | ||
| 778 | |||
| 779 | For example, I only want @code{edit-server} running for my main, graphical Emacs, | ||
| 780 | not 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 | |||
| 790 | In 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 | |||
| 800 | Note that @code{:when} is provided as an alias for @code{:if}, and @code{:unless foo} means | ||
| 801 | the same thing as @code{:if (not foo)}. | ||
| 802 | |||
| 803 | @node @code{load-path} | ||
| 804 | @section @code{:load-path} | ||
| 805 | |||
| 806 | If your package needs a directory added to the @code{load-path} in order to load, | ||
| 807 | use @code{:load-path}. This takes a symbol, a function, a string or a list of | ||
| 808 | strings. 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 | |||
| 817 | Note that when using a symbol or a function to provide a dynamically generated | ||
| 818 | list of paths, you must inform the byte-compiler of this definition so the | ||
| 819 | value is available at byte-compilation time. This is done by using the special | ||
| 820 | form @code{eval-and-compile} (as opposed to @code{eval-when-compile}). Further, this | ||
| 821 | value is fixed at whatever was determined during compilation, to avoid looking | ||
| 822 | up 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 | |||
| 837 | Similar to @code{:bind}, you can use @code{:mode} and @code{:interpreter} to establish a | ||
| 838 | deferred binding within the @code{auto-mode-alist} and @code{interpreter-mode-alist} | ||
| 839 | variables. The specifier to either keyword can be a cons cell, a list of cons | ||
| 840 | cells, 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 | |||
| 853 | If 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 | ||
| 855 | the docstring for @code{use-package} for a brief description of each), you can | ||
| 856 | still 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 | |||
| 866 | This 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 | |||
| 876 | Similar 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 | ||
| 878 | file matches a given regular expression. The difference between the two is | ||
| 879 | that @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 | |||
| 889 | This 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 | ||
| 891 | string @code{"%PDF"}. | ||
| 892 | |||
| 893 | @node @code{no-require} | ||
| 894 | @section @code{:no-require} | ||
| 895 | |||
| 896 | Normally, @code{use-package} will load each package at compile time before | ||
| 897 | compiling the configuration, to ensure that any necessary symbols are in scope | ||
| 898 | to satisfy the byte-compiler. At times this can cause problems, since a | ||
| 899 | package 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 | ||
| 901 | such 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 | |||
| 913 | While the @code{:after} keyword delays loading until the dependencies are loaded, | ||
| 914 | the somewhat simpler @code{:requires} keyword simply never loads the package if the | ||
| 915 | dependencies are not available at the time the @code{use-package} declaration is | ||
| 916 | encountered. By "available" in this context it means that @code{foo} is available | ||
| 917 | of @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 | |||
| 924 | This is the same as: | ||
| 925 | |||
| 926 | @lisp | ||
| 927 | (use-package abbrev | ||
| 928 | :if (featurep 'foo)) | ||
| 929 | @end lisp | ||
| 930 | |||
| 931 | As 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 | |||
| 938 | For more complex logic, such as that supported by @code{:after}, simply use @code{:if} | ||
| 939 | and the appropriate Lisp expression. | ||
| 940 | |||
| 941 | @node Debugging Tools | ||
| 942 | @chapter Debugging Tools | ||
| 943 | |||
| 944 | TODO | ||
| 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 | |||
| 5 | This release prepares for inclusion to GNU ELPA and includes no other changes | ||
| 6 | |||
| 7 | ## 2.4.1 | ||
| 8 | |||
| 9 | This 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 | |||
| 46 | Accepts keyword arguments: | ||
| 47 | :map MAP - a keymap into which the keybindings should be | ||
| 48 | added | ||
| 49 | |||
| 50 | The rest of the arguments are conses of keybinding string and a | ||
| 51 | function 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 | |||
| 104 | Accepts keyword argument: | ||
| 105 | :map - a keymap into which the keybindings should be added | ||
| 106 | |||
| 107 | The rest of the arguments are conses of keybinding string and a | ||
| 108 | function 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 | |||
| 143 | Elements 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 | |||
| 149 | KEY-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 | ||
| 151 | spelled-out keystrokes, e.g., `C-c C-z'. See documentation of | ||
| 152 | `edmacro-mode' for details. | ||
| 153 | |||
| 154 | COMMAND must be an interactive function or lambda form. | ||
| 155 | |||
| 156 | KEYMAP, if present, should be a keymap variable or symbol. | ||
| 157 | For 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 | |||
| 163 | If PREDICATE is non-nil, it is a form evaluated to determine when | ||
| 164 | a key should be bound. It must return non-nil in such cases. | ||
| 165 | Emacs can evaluate this form at any time that it does redisplay | ||
| 166 | or operates on menu data structures, so you should write it so it | ||
| 167 | can 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). | ||
| 201 | See `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 | |||
| 221 | In 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 | |||
| 252 | Accepts 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 | |||
| 275 | The rest of the arguments are conses of keybinding string and a | ||
| 276 | function 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 | |||
| 399 | Accepts 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 | |||
| 422 | The rest of the arguments are conses of keybinding string and a | ||
| 423 | function 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 | ||
| 36 | this function to KEYMAP-SYMBOL. It then simulates pressing the | ||
| 37 | same key sequence a again, so that the next key pressed is routed | ||
| 38 | to the newly loaded keymap. | ||
| 39 | |||
| 40 | This function supports use-package's :bind-keymap keyword. It | ||
| 41 | works by binding the given key sequence to an invocation of this | ||
| 42 | function for a particular keymap. The keymap is expected to be | ||
| 43 | defined by the package. In this way, loading the package is | ||
| 44 | deferred 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. | ||
| 105 | The order of this list is *very important*, so it is only | ||
| 106 | advisable to insert new keywords, never to delete or reorder | ||
| 107 | them. Further, attention should be paid to the NEWS.md if the | ||
| 108 | default order ever changes, as they may have subtle effects on | ||
| 109 | the semantics of `use-package' declarations and may necessitate | ||
| 110 | changing where you had inserted a new keyword earlier. | ||
| 111 | |||
| 112 | Note that `:disabled' is special in this list, as it causes | ||
| 113 | nothing at all to happen, even if the rest of the `use-package' | ||
| 114 | declaration 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. | ||
| 124 | The reason keywords like `:hook' are not in this list is that | ||
| 125 | they only imply deferred loading if they reference actual | ||
| 126 | function symbols that can be autoloaded from the module; whereas | ||
| 127 | the default keywords provided here always defer loading unless | ||
| 128 | otherwise 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. | ||
| 134 | The unknown keyword and its associated arguments will be ignored | ||
| 135 | in 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 | ||
| 141 | variables twice (once in the Custom file, once in the use-package | ||
| 142 | call)." | ||
| 143 | :type 'boolean | ||
| 144 | :group 'use-package) | ||
| 145 | |||
| 146 | (defcustom use-package-verbose nil | ||
| 147 | "Whether to report about loading and configuration details. | ||
| 148 | If you customize this, then you should require the `use-package' | ||
| 149 | feature in files that use `use-package', even if these files only | ||
| 150 | contain compiled expansions of the macros. If you don't do so, | ||
| 151 | then 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. | ||
| 160 | This 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. | ||
| 166 | See 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. | ||
| 172 | See 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. | ||
| 193 | Each entry in the alist is a list of three elements: | ||
| 194 | The first element is the `use-package' keyword. | ||
| 195 | |||
| 196 | The second is a form that can be evaluated to get the default | ||
| 197 | value. It can also be a function that will receive the name of | ||
| 198 | the `use-package' declaration and the keyword plist given to | ||
| 199 | `use-package', in normalized form. The value it returns should | ||
| 200 | also be in normalized form (which is sometimes *not* what one | ||
| 201 | would normally write in a `use-package' declaration, so use | ||
| 202 | caution). | ||
| 203 | |||
| 204 | The third element is a form that can be evaluated to determine | ||
| 205 | whether or not to assign a default value; if it evaluates to nil, | ||
| 206 | then the default value is not assigned even if the keyword is not | ||
| 207 | present in the `use-package' form. This third element may also be | ||
| 208 | a function, in which case it receives the name of the package (as | ||
| 209 | a symbol) and a list of keywords (in normalized form). It should | ||
| 210 | return nil or non-nil depending on whether defaulting should be | ||
| 211 | attempted." | ||
| 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. | ||
| 226 | For example, if the following form is provided: | ||
| 227 | |||
| 228 | (use-package foo :if pred1 :if pred2) | ||
| 229 | |||
| 230 | Then based on the above defaults, the merged result will be: | ||
| 231 | |||
| 232 | (use-package foo :if (and pred1 pred2)) | ||
| 233 | |||
| 234 | This is done so that, at the stage of invoking handlers, each | ||
| 235 | handler 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. | ||
| 246 | Set to nil if you don't want this to happen; it's only a | ||
| 247 | convenience." | ||
| 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. | ||
| 253 | Note that `use-package-verbose' has to be set to a non-nil value | ||
| 254 | for 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. | ||
| 260 | In particular, for a given package `foo', the following hooks | ||
| 261 | become 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 | |||
| 268 | This way, you can add to these hooks before evaluation of a | ||
| 269 | `use-package` declaration, and exercise some control over what | ||
| 270 | happens. | ||
| 271 | |||
| 272 | NOTE: These hooks are run even if the user does not specify an | ||
| 273 | `:init' or `:config' block, and they will happen at the regular | ||
| 274 | time when initialization and configuration would have been | ||
| 275 | performed. | ||
| 276 | |||
| 277 | NOTE: If the `pre-init' hook return a nil value, that block's | ||
| 278 | user-supplied configuration is not evaluated, so be certain to | ||
| 279 | return t if you only wish to add behavior to what the user had | ||
| 280 | specified." | ||
| 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. | ||
| 286 | This 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 | |||
| 292 | The main advantage to this variable is that, if you know your | ||
| 293 | configuration works, it will make the byte-compiled file as | ||
| 294 | minimal as possible. It can also help with reading macro-expanded | ||
| 295 | definitions, 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. | ||
| 307 | This 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. | ||
| 314 | This is done by adjusting `lisp-imenu-generic-expression' to | ||
| 315 | include support for finding `use-package' and `require' forms. | ||
| 316 | |||
| 317 | Must 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. | ||
| 340 | View the statistical report using `use-package-report'. Note that | ||
| 341 | if this option is enabled, you must require `use-package' in your | ||
| 342 | user init file at loadup time, or you will see errors concerning | ||
| 343 | undefined 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. | ||
| 367 | Otherwise 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. | ||
| 373 | Otherwise 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. | ||
| 391 | CAR-PRED and CDR-PRED are applied to X's `car' and `cdr', | ||
| 392 | respectively." | ||
| 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 | ||
| 399 | it as a symbol. Otherwise, return it as a symbol with `-mode' | ||
| 400 | appended." | ||
| 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. | ||
| 408 | It does the right thing no matter if NAME is a string or symbol. | ||
| 409 | Argument 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. | ||
| 416 | The 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. | ||
| 471 | This 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. | ||
| 481 | This 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. | ||
| 537 | The normalized key/value pairs from input are added to PLIST, | ||
| 538 | extending 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. | ||
| 705 | The values in the PLIST have each been normalized by the function | ||
| 706 | use-package-normalize/KEYWORD (minus the colon). | ||
| 707 | |||
| 708 | STATE is a property list that the function may modify and/or | ||
| 709 | query. This is useful if a package defines multiple keywords and | ||
| 710 | wishes them to have some kind of stateful interaction. | ||
| 711 | |||
| 712 | Unless the KEYWORD being processed intends to ignore remaining | ||
| 713 | keywords, it must call this function recursively, passing in the | ||
| 714 | plist with its keyword and argument removed, and passing in the | ||
| 715 | next 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. | ||
| 734 | If ANCHOR is also a keyword, place the new KEYWORD before that | ||
| 735 | one. | ||
| 736 | If AFTER is non-nil, insert KEYWORD either at the end of the | ||
| 737 | keywords list, or after the ANCHOR if one has been provided. | ||
| 738 | If TEST is non-nil, it is the test used to compare ELEM to list | ||
| 739 | elements. The default is `eq'. | ||
| 740 | The 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. | ||
| 776 | If 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 | ||
| 791 | no 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. | ||
| 803 | The 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. | ||
| 885 | KEY-PRED and VAL-PRED are predicates recognizing valid keys and | ||
| 886 | values, respectively. | ||
| 887 | If 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'. | ||
| 991 | See 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. | ||
| 1004 | The 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 | |||
| 1020 | The 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. | ||
| 1035 | In the table that's generated, the status field has the following | ||
| 1036 | meaning: | ||
| 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*. | ||
| 1417 | FEATURES* is a list containing keywords `:and' and `:all', where | ||
| 1418 | no 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 | |||
| 1612 | For full documentation, please see the README file that came with | ||
| 1613 | this 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. | ||
| 79 | If 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'. | ||
| 41 | See 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'. | ||
| 47 | See 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. | ||
| 53 | This function is called with three arguments: the name of the | ||
| 54 | package declared in the `use-package' form; the arguments passed | ||
| 55 | to all `:ensure' keywords (always a list, even if only one); and | ||
| 56 | the current `state' plist created by previous handlers. | ||
| 57 | |||
| 58 | Note that this function is called whenever `:ensure' is provided, | ||
| 59 | even if it is nil. It is up to the function to decide on the | ||
| 60 | semantics of the various values for `:ensure'. | ||
| 61 | |||
| 62 | This function should return non-nil if the package is installed. | ||
| 63 | |||
| 64 | The 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 | |||
| 88 | ARCHIVE can be a string or a symbol or `manual' to indicate a | ||
| 89 | manually 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'. | ||
| 34 | Returns 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. | ||
| 44 | This will only find the form if that form actually required | ||
| 45 | PACKAGE. If PACKAGE was previously required then this function | ||
| 46 | will 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. | ||
| 59 | For example, if the module's `:if' condition is met, but even | ||
| 60 | with 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 | ||