emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

emacs-29 e950f5a663a: Merge branch 'feature/use-package' into emacs-29


From: Stefan Kangas
Subject: emacs-29 e950f5a663a: Merge branch 'feature/use-package' into emacs-29
Date: Thu, 8 Dec 2022 12:04:04 -0500 (EST)

branch: emacs-29
commit e950f5a663ad3501e50f43ef6c0a7fd220e0c1f2
Merge: 9c21eae60c4 5bcd0cee0fc
Author: Stefan Kangas <stefankangas@gmail.com>
Commit: Stefan Kangas <stefankangas@gmail.com>

    Merge branch 'feature/use-package' into emacs-29
---
 admin/git-bisect-start                             |    8 +-
 doc/misc/Makefile.in                               |   16 +-
 doc/misc/use-package.texi                          | 1821 ++++++++++++++++++
 etc/NEWS                                           |    7 +
 lisp/use-package/bind-key.el                       |  562 ++++++
 lisp/use-package/use-package-bind-key.el           |  171 ++
 lisp/use-package/use-package-core.el               | 1692 +++++++++++++++++
 lisp/use-package/use-package-delight.el            |   83 +
 lisp/use-package/use-package-diminish.el           |   72 +
 .../use-package-ensure-system-package.el           |  101 +
 lisp/use-package/use-package-ensure.el             |  208 +++
 lisp/use-package/use-package-jump.el               |   70 +
 lisp/use-package/use-package-lint.el               |   76 +
 lisp/use-package/use-package.el                    |   51 +
 test/lisp/use-package/use-package-tests.el         | 1957 ++++++++++++++++++++
 15 files changed, 6885 insertions(+), 10 deletions(-)

diff --git a/admin/git-bisect-start b/admin/git-bisect-start
index cf0c8cde410..7a715b4261d 100755
--- a/admin/git-bisect-start
+++ b/admin/git-bisect-start
@@ -35,6 +35,10 @@
 
 git bisect start
 
-# Prune commits 1e5b753bf4..806734c1b1 introduced by 0186faf2a1 (Eglot
-# merge on Oct 20 2022)
+# Prune commits 1e5b753bf4..806734c1b1 introduced by 0186faf2a1
+# (Eglot merge on Oct 20 2022)
 git bisect good 806734c1b1f433de43d59d9a5e3a1e89d64315f6
+
+# Prune commits 31ea42e15e..a6cbfdd8f1 introduced by 4a1e9d61b5
+# (use-package merge on Nov 30 2022)
+git bisect good 4a1e9d61b57c36255752437a2668e037e79fe870
diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in
index a7dbbbb48fe..49cd8e13b03 100644
--- a/doc/misc/Makefile.in
+++ b/doc/misc/Makefile.in
@@ -67,14 +67,14 @@ MAKEINFO_OPTS = --force -I$(emacsdir)
 DOCMISC_W32 = @DOCMISC_W32@
 
 ## Info files to build and install on all platforms.
-INFO_COMMON = auth autotype bovine calc ccmode cl \
-       dbus dired-x ebrowse ede ediff edt efaq eglot eieio \
-       emacs-gnutls emacs-mime epa erc ert eshell eudc eww \
-       flymake forms gnus htmlfontify idlwave ido info.info \
-       mairix-el message mh-e modus-themes newsticker nxml-mode \
-       octave-mode org pcl-cvs pgg rcirc reftex remember sasl \
-       sc semantic ses sieve smtpmail speedbar srecode todo-mode \
-       tramp transient url vhdl-mode vip viper vtable widget wisent woman
+INFO_COMMON = auth autotype bovine calc ccmode cl dbus dired-x         \
+       ebrowse ede ediff edt efaq eglot eieio emacs-gnutls             \
+       emacs-mime epa erc ert eshell eudc eww flymake forms gnus       \
+       htmlfontify idlwave ido info.info mairix-el message mh-e        \
+       modus-themes newsticker nxml-mode octave-mode org pcl-cvs pgg   \
+       rcirc reftex remember sasl sc semantic ses sieve smtpmail       \
+       speedbar srecode todo-mode tramp transient url use-package      \
+       vhdl-mode vip viper vtable widget wisent woman
 
 ## Info files to install on current platform.
 INFO_INSTALL = $(INFO_COMMON) $(DOCMISC_W32)
diff --git a/doc/misc/use-package.texi b/doc/misc/use-package.texi
new file mode 100644
index 00000000000..e7bddd628c9
--- /dev/null
+++ b/doc/misc/use-package.texi
@@ -0,0 +1,1821 @@
+\input texinfo    @c -*- texinfo -*-
+@c %**start of header
+@setfilename ../../use-package.info
+@settitle use-package User Manual
+@include docstyle.texi
+@syncodeindex vr cp
+@syncodeindex fn cp
+@c %**end of header
+
+@copying
+This manual is for use-package, a configuration macro for simplifying
+your init file.
+
+Copyright @copyright{} 2022 Free Software Foundation, Inc.
+
+@quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.3 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover Texts being ``A GNU Manual'',
+and with the Back-Cover Texts as in (a) below.  A copy of the license
+is included in the section entitled ``GNU Free Documentation License''.
+
+(a) The FSF's Back-Cover Text is: ``You have the freedom to copy and
+modify this GNU manual.''
+@end quotation
+@end copying
+
+@dircategory Emacs misc features
+@direntry
+* use-package: (use-package). Declarative package configuration for Emacs.
+@end direntry
+
+@finalout
+@titlepage
+@title use-package User Manual
+@subtitle for version 2.4.5
+@author John Wiegley & Stefan Kangas
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+@end titlepage
+
+@contents
+
+@ifnottex
+@node Top
+@top use-package User Manual
+
+The @code{use-package} macro allows you to isolate package
+customization in your init file in a declarative way.  It takes care
+of a lot of things for you that would otherwise require a lot of
+repetitive boilerplate code.  It can help with common customization,
+such as binding keys, setting up hooks, customizing user options and
+faces, autoloading, and more.  It also helps you keep Emacs startup
+fast, even when you use many (even hundreds) of packages.
+
+Note that use-package is not a package manager.  Although use-package
+does have the useful capability to interface with the Emacs package
+manager, its primary purpose is for the configuration and loading of
+packages.
+
+@insertcopying
+
+@menu
+* Basic Concepts::              Basic concepts of use-package.
+* Getting Started::             A gentle introduction to use-package.
+* Loading Packages::            How and when packages are loaded.
+* Configuring Packages::        Package configuration keywords.
+* Installing packages::         Ensuring packages are available.
+* Byte-compiling::              Byte-compiling your init file.
+* Troubleshooting::             What to do when there's trouble.
+
+Appendices
+* Keyword extensions::          Adding new use-package keywords.
+* History::                     History and acknowledgments.
+* GNU Free Documentation License::  The license for this manual.
+* Index::
+@end menu
+@end ifnottex
+
+@c ----------------------------------------------------------------------------
+@node Basic Concepts
+@chapter Basic Concepts
+
+use-package provides the @code{use-package} macro, that simplifies the
+customization and use of packages in Emacs.  It was created for a few
+basic reasons, each of which drove the design.  Understanding these
+reasons may help make some of those decisions clearer:
+
+@enumerate
+@item
+To gather all configuration details of a package into one place,
+making it easier to copy, disable, or move it elsewhere in the init
+file.
+
+@item
+To reduce duplication and boilerplate, capturing several common
+practices as mere keywords both easy and intuitive to use.
+
+@item
+To make startup time of Emacs as quick as possible, without
+sacrificing the quantity of add-on packages used.
+
+@item
+To make it so errors encountered during startup disable only the
+package raising the error, and as little else as possible, leaving as
+close to a functional Emacs as possible.
+
+@item
+To allow byte-compilation of one's init file so that any warnings or
+errors seen are meaningful.  In this way, even if byte-compilation is
+not used for speed (reason 3), it can still be used as a sanity check.
+@end enumerate
+
+It is worth noting that use-package is not intended to replace the
+standard @w{@code{M-x customize}}.  On the contrary, it is designed to
+work together with it, for things that customize cannot do.
+
+@c ----------------------------------------------------------------------------
+@node Getting Started
+@chapter Getting Started
+
+This chapter provides instructions and examples for quickly getting
+started with use-package.  The first thing you need to do is make sure
+that @samp{use-package} itself is loaded.  To do that, put this at the
+top of your init file:
+
+@lisp
+(require 'use-package)
+(require 'bind-key)            ; if you use any :bind variant
+@end lisp
+
+The above makes the @code{use-macro} for in the rest of your init
+file.  In this manual, we call each call to @code{use-macro} a
+@dfn{declaration}, to highlight the declarative nature of its
+semantic.
+
+To unconditionally load a package named @samp{foo}, add the following
+declaration to your init file:
+
+@lisp
+(use-package foo)
+@end lisp
+
+@noindent
+This declaration is equivalent to using @code{require}, with some
+use-package specific error handling added in.  Just like require, it
+needs the package @samp{foo} to be installed and available in your
+@code{load-path} (@pxref{Installing packages}).
+
+To evaluate Lisp code @emph{before} the @samp{foo} package is loaded,
+use the @code{:init} keyword:
+
+@lisp
+(use-package foo
+  :init
+  (setq foo-variable t))
+@end lisp
+
+Similarly, @code{:config} can be used to execute code @emph{after} a
+package is loaded.  In cases where loading is done lazily
+(@pxref{Loading Packages}), this execution is deferred until after the
+autoload occurs.  As you might expect, you can use @code{:init} and
+@code{:config} together:
+
+@lisp
+(use-package foo
+  :init
+  (setq foo-variable t)
+  :config
+  (foo-mode 1))
+@end lisp
+
+The above declarations will all load the @samp{foo} package
+immediately.  In most cases, this is not necessary or desirable, as
+that will slow down Emacs startup.  Instead, you should try to set
+things up so that packages are only loaded when they are actually
+needed (autoloading).  If you have installed a package from
+@acronym{GNU ELPA} that provides it's own autoloads, it is often
+enough to say:
+
+@lisp
+(use-package foo
+  :defer t)
+@end lisp
+
+@noindent
+This will avoid loading the package.  Now, when you run any autoloaded
+command, the package @samp{foo} is loaded automatically.  Package
+authors will make their own decisions about which commands are marked
+to autoload by default.
+
+In some cases, you might need or want to provide your own autoloads.
+The below more complex example autoloads the commands
+@code{isearch-moccur} and @code{isearch-all} from
+@file{color-moccur.el}, and binds keys both globally and in
+@code{isearch-mode-map}.  When one of these commands are used, the
+package is loaded.  At that point, @code{moccur-edit} is also loaded,
+to allow editing of the @code{moccur} buffer.
+
+@lisp
+(use-package color-moccur
+  :commands (isearch-moccur isearch-all)
+  :bind (("M-s O" . moccur)
+         :map isearch-mode-map
+         ("M-o" . isearch-moccur)
+         ("M-O" . isearch-moccur-all))
+  :init
+  (setq isearch-lazy-highlight t)
+  :config
+  (use-package moccur-edit))
+@end lisp
+
+Some packages will suggest ready-made @code{use-package} declarations
+that you can use.  Where possible, it is a good idea to copy them, and
+use that as a starting point.
+
+That should be enough to get you started!
+
+@c ----------------------------------------------------------------------------
+@node Loading Packages
+@chapter Loading Packages
+
+@cindex loading packages
+Before use-package can load an Emacs Lisp package, it must be
+available in a directory on your @code{load-path}.  When you install
+packages using the built-in @code{install-package} command, it will do
+this automatically for you.  Packages shipped with Emacs (built-in
+packages) are always available.
+
+If you install packages manually, you must make sure they are
+available on your @code{load-path}.  @xref{Lisp Libraries,,, emacs,
+GNU Emacs Manual} for details.
+
+Some packages have more than one library.  In those cases, you might
+need more than one @code{use-package} declaration to make sure it is
+properly loaded.  For complex configurations, you might also need more
+than one declaration for a package with the same name.
+
+use-package can interface with @samp{package.el} to install packages
+on Emacs start.  @xref{Installing packages} for details.
+
+@menu
+* Loading basics::              How and when packages are loaded.
+* Deferring loading::           Loading packages later.
+* Forcing loading::             Loading packages immediately.
+* Conditional loading::         Loading packages conditionally.
+* Loading sequentially::        Loading packages in sequence.
+* Load dependencies::           Don't load without dependencies.
+* Load path::                   Using a custom @code{load-path}.
+* Manual autoloads::            Setting up autoloads manually.
+@end menu
+
+@node Loading basics
+@section How and when use-package loads packages
+
+The @code{use-package} macro either will either load a package
+immediately, or when they are first used (autoloading).  In the
+simplest case, a @code{use-package} declaration loads a package when
+it is evaluated.@footnote{This happens both at run-time and at
+compile-time.  @xref{Byte-compiling}.}  If the declaration is in your
+init file, this happens automatically each time Emacs is started.
+
+For example, the below declaration immediately loads the library
+@code{foo}, just like @code{require} would.  If the library @samp{foo}
+is not available in your @code{load-path}, it logs a warning to the
+@samp{*Messages*} buffer:
+
+@lisp
+(use-package foo)
+@end lisp
+
+Note that a ``package'' is different from an Emacs Lisp ``library''.
+The above declaration tells use-package to load the @emph{library}
+@file{foo.el}, which the overwhelming majority of cases also resides
+in a @emph{package} named @code{foo}.  But the @code{foo} package
+might also contain a library named @file{foo-extra.el}.  If that
+library is not loaded automatically, you will need a separate
+@code{use-package} declaration to make sure that it is.  This manual
+will often use these terms interchangeably, as this distinction does
+not usually matter, but you should keep it in mind for the cases when
+it does.
+
+The details of how and when you should load a package might differ
+from one package to another.  When in doubt, refer to the package
+documentation for details.
+
+@node Deferring loading
+@section Deferring package loading
+
+@cindex autoloading packages
+@cindex loading lazily
+In the examples we have seen so far, use-package loads packages every
+time you start Emacs, even if that package is never used.  That will
+make starting Emacs slower.  use-package therefore tries to set things
+up in such a way that it only loads packages when a command is first
+used (either with @kbd{M-x} or some key binding).  This is based on
+autoloading, a full description of which is outside the scope of this
+manual.  @xref{Autoload,,, elisp, GNU Emacs Lisp Reference Manual} for
+the full story.
+
+@cindex triggers, for loading packages
+Some @code{use-package} keywords provide autoload @dfn{triggers} that
+cause a package to be loaded when certain events occur.  For example,
+the @code{:hook} keyword sets up a trigger that fires when the
+specified hook is run, and then loads the package automatically.  The
+other trigger keywords, all of which are described later in this
+manual, are @code{:commands}, @code{:bind}, @code{:bind*},
+@code{:bind-keymap}, @code{:bind-keymap*}, @code{:mode}, and
+@code{:interpreter}.
+
+@subheading The @code{:defer} keyword
+
+@findex :defer
+If you did not specify any autoloading keyword, use-package will fall
+back to loading the package immediately (typically when Emacs is
+starting up).  This can be overridden using the @code{:defer} keyword.
+It takes one boolean argument: a non-@code{nil} value means to stop
+this package from being immediately loaded.  Here is an example of
+using @code{:defer} to postpone loading the package @samp{foo}:
+
+@lisp
+(use-package foo
+  :defer t)
+@end lisp
+
+Using @code{:defer t} by itself like this is rarely useful.
+Typically, you would only use it together with a keyword like
+@code{:config} (@pxref{Lisp Configuration}), or @code{:ensure}
+(@pxref{Installing packages}).
+
+@subheading Defer loading until idle for N seconds
+
+You can also give a numeric argument @var{N} to @w{@code{:defer}} to
+specify that a package should be loaded (if it hasn't already) after
+Emacs has been idle for @var{N} seconds.  For example, use this to
+make use-package load @samp{foo} after 30 seconds of idle time:
+
+@lisp
+(use-package foo
+  :defer 30)
+@end lisp
+
+@subheading When to use @code{:defer}
+
+When using autoloading keywords, there is no need to also use
+@code{:defer}.  It doesn't hurt anything to add it in this case,
+perhaps for extra clarity, but it is redundant.
+
+You should use @code{:defer} to force deferred loading, in cases when
+use-package isn't creating any autoloads for you.  For example, you
+might know that some other package will already do something to cause
+your package to load at the appropriate time.  This is usually the
+case when you install a package using @code{package-install}, as
+packages installed in this way normally always have their own
+autoloads already set up.
+
+@subheading Making @w{@code{:defer t}} the default
+
+@vindex use-package-always-defer
+If you customize the user option @code{use-package-always-defer} to
+non-@code{nil}, the @code{use-package} macro will behave as if
+@w{@code{:defer t}} is always specified.  This can be overridden for
+individual declarations using either @w{@code{:defer nil}} or
+@w{@code{:demand t}} (@pxref{Forcing loading}).
+
+@node Forcing loading
+@section Forcing package to load immediately
+
+@findex :demand
+The presence of autoloading trigger keywords can be overridden using
+@code{:demand t}, which forces the package to load immediately.  Thus,
+even if you use an autoloading keyword such as @code{:bind}
+(@pxref{Key bindings}), adding @code{:demand} will force loading to
+occur immediately.  It will also avoid creating an autoload for the
+bound key, as it would be redundant.
+
+If you specify both @w{@code{:demand t}} and @w{@code{:defer t}}, the
+@code{:defer} keyword will take precedence.
+
+@node Conditional loading
+@section Loading packages conditionally
+
+@findex :if
+@findex :when
+@findex :unless
+The @code{:if}, @code{:when}, and @code{:unless} keywords predicates
+the loading and initialization of packages.  They all accept one
+argument, an Emacs Lisp form that is evaluated at run-time.
+
+If the argument of the @code{:if} keyword evaluates to non-@code{nil},
+the package will be loaded and initialized.  The @code{:when} keyword
+is provided as an alias for @code{:if}.  Finally, the @code{:unless}
+keyword is the inverse of @code{:if}, such that @w{@code{:unless foo}}
+means the same thing as @w{@code{:if (not foo)}}.
+
+For example, if you only want @samp{foo} in graphical Emacs sessions,
+you could use the following:
+
+@lisp
+(use-package foo
+  :if (display-graphic-p))
+@end lisp
+
+Another common use case is to make it conditional on the operating
+system:
+
+@lisp
+(use-package foo
+  :if (memq window-system '(mac ns)))
+@end lisp
+
+@cindex conditional loading before @code{:preface} or @code{:ensure}
+If you need to conditionalize a use-package form so that the condition
+occurs before even @code{:ensure} or @code{:preface}, use @code{when}
+around the use-package form itself.  For example:
+
+@lisp
+(when (memq window-system '(mac ns))
+  (use-package foo
+    :ensure t))
+@end lisp
+
+@node Loading sequentially
+@section Loading packages in sequence
+
+@findex :after
+Sometimes it only makes sense to configure a package after another one
+has been loaded, because certain variables or functions are not in
+scope until that time.  This can achieved with the @code{:after}
+keyword, which allows a fairly rich description of the exact
+conditions when loading should occur.  It takes either a symbol
+indicating the package name, a list of such symbols, or a list of
+selectors (see below).
+
+Here is an example of using the @acronym{GNU ELPA} packages hydra,
+ivy, and ivy-hydra.  Note that ivy-hydra will always be loaded last:
+
+@lisp
+(use-package hydra)
+
+(use-package ivy)
+
+(use-package ivy-hydra
+  :after (ivy hydra))
+@end lisp
+
+In this case, because the declarations are evaluated in the order they
+occur, the use of @code{:after} is not strictly necessary.  However,
+if @samp{hydra} and @samp{ivy} were to be autoloaded, using
+@code{:after} guarantees that @samp{ivy-hydra} is not loaded until it
+is actually needed.  By using @code{:after}, the above code will also
+work even if the order of the declaration changes.  This means that
+moving things around in your init file is less likely to break things.
+
+@subheading Using @code{:after} selectors
+
+@findex :all (with :after)
+@findex :any (with :after)
+The @code{:after} keyword also accepts a list of selectors.  By
+default, @code{:after (foo bar)} is the same as @w{@code{:after (:all
+foo bar)}}, meaning that loading of the given package will not happen
+until both @code{foo} and @code{bar} have been loaded.  Here are some
+of the other possibilities:
+
+@verbatim
+:after (foo bar)
+:after (:all foo bar)
+:after (:any foo bar)
+:after (:all (:any foo bar) (:any baz quux))
+:after (:any (:all foo bar) (:all baz quux))
+@end verbatim
+
+When you nest selectors, such as @code{(:any (:all foo bar) (:all baz
+quux))}, it means that the package will be loaded when either both
+@code{foo} and @code{bar} have been loaded, or when both @code{baz}
+and @code{quux} have been loaded.
+
+Pay attention when setting @code{use-package-always-defer} to a
+non-@code{nil} value, and also using the @code{:after} keyword.  In
+this case, you will need to specify how the declared package is to be
+loaded: for example, by some @code{:bind}.  If you are not using one
+of the keywords that registers autoloads, such as @code{:bind} or
+@code{:hook}, and your package manager does not provide autoloads, it
+is possible that your package will never be loaded if you do not add
+@code{:demand t} to those declarations.
+
+@node Load dependencies
+@section Prevent loading if dependencies are missing
+
+@findex :requires
+While the @code{:after} keyword delays loading until the dependencies
+are loaded, the somewhat simpler @code{:requires} keyword @emph{never}
+loads the package if the dependencies are not available when the
+@code{use-package} declaration is evaluated.  In this context,
+``available'' means that @code{foo} is available if @w{@code{(featurep
+'foo)}} evaluates to a non-@code{nil} value.  For example:
+
+@lisp
+(use-package abbrev
+  :requires foo)
+@end lisp
+
+This is the same as:
+
+@lisp
+(use-package abbrev
+  :if (featurep 'foo))
+@end lisp
+
+As a convenience, a list of such packages may be specified:
+
+@lisp
+(use-package abbrev
+  :requires (foo bar baz))
+@end lisp
+
+For more complex logic, such as that supported by @code{:after},
+simply use @code{:if} and the appropriate Lisp expression.
+
+@node Load path
+@section Setting a custom @code{load-path}
+
+@findex :load-path
+If a package resides in some directory that is not in your
+@code{load-path}, use the @code{:load-path} keyword to add it.  It
+takes a symbol, a function, a string or a list of strings.  If the
+path is relative, it is expanded within @code{user-emacs-directory}.
+
+For example:
+
+@lisp
+(use-package ess-site
+  :load-path "site-lisp/ess/lisp/"
+  :commands R)
+@end lisp
+
+Note that when using a symbol or a function to provide a dynamically
+generated list of paths, you must inform the byte-compiler of this
+definition so that the value is available at byte-compilation time.
+This is done by using the special form @code{eval-and-compile} (as
+opposed to @code{eval-when-compile}).  Further, this value is fixed at
+whatever was determined during compilation, to avoid looking up the
+same information again on each startup.  For example:
+
+@lisp
+(eval-and-compile
+  (defun ess-site-load-path ()
+    (shell-command "find ~ -path ess/lisp")))
+
+(use-package ess-site
+  :load-path (lambda () (list (ess-site-load-path)))
+  :commands R)
+@end lisp
+
+@node Manual autoloads
+@section Setting up autoloads manually
+
+@findex :commands
+@findex :autoload
+To autoload an interactive command, use the @code{:commands} keyword.
+When you use the @code{:commands} keyword, it creates autoloads for
+those commands (which defers loading of the module until they are
+used).  The @code{:commands} keyword takes either a symbol or a list
+of symbols.
+
+The @code{:autoload} keyword works like @code{:commands}, but is used
+to autoload non-interactive functions.  Here is an example:
+
+@lisp
+(use-package org-crypt
+  :autoload org-crypt-use-before-save-magic)
+@end lisp
+
+@c ----------------------------------------------------------------------------
+@node Configuring Packages
+@chapter Configuring Packages
+
+This chapter describes the various keywords provided by
+@code{use-package} that helps you configure packages.
+
+@menu
+* Lisp Configuration::          Using Lisp to configure packages.
+* Key bindings::                Making your own keybindings.
+* Hooks::                       Adding functions to hooks.
+* Modes and interpreters::      Enabling modes automatically.
+* Magic handlers::              Using regexps to enable modes.
+* User options::                Setting user options.
+* Faces::                       Customizing faces.
+* Hiding minor modes::          Tidying up the mode line.
+@end menu
+
+@node Lisp Configuration
+@section Using Lisp code for configuring packages
+
+The most general way to add customizations are the @code{:preface},
+@code{:init}, and @code{:config} keywords.  They all accept one or
+more Emacs Lisp forms, up to the next keyword, that are evaluated in
+order.  This lets you add arbitrary Lisp code to your
+@code{use-package} declarations.
+
+The only difference between these keywords is when they are evaluated.
+
+@menu
+* Preface keyword::             Evaluate code before anything else.
+* Init keyword::                Evaluate code before loading package.
+* Config keyword::              Evaluate code after loading package.
+* Best practices::              When to use @code{:config}, @code{:init}, and 
@code{:preface}.
+@end menu
+
+@node Preface keyword
+@subsection @code{:preface} is evaluated first
+
+@findex :preface
+The @code{:preface} section is evaluated before anything else, except
+@code{:disabled} and @code{:ensure}.  It can be used to establish
+function and variable definitions that will:
+
+@enumerate
+@item
+Make the byte-compiler happy.  It will not complain about functions
+whose definitions are unknown because you have them within a guard
+block.
+
+@item
+Define code that can be used in an @code{:if} test.
+@end enumerate
+
+Note that whatever is specified within @code{:preface} is evaluated
+both at load time and at byte-compilation time, in order to ensure
+that definitions are seen by both the Lisp evaluator and the
+byte-compiler.  Therefore, you should avoid having any side-effects in
+your preface, and restrict it to symbol declarations and definitions.
+
+@node Init keyword
+@subsection @code{:init} is evaluated before loading package
+
+@findex :init
+The @code{:init} section is evaluated just before the package is
+loaded.  Note that the @code{:init} form is run unconditionally --
+even if the @code{foo} package happens to not exist on your system.
+You must therefore remember to restrict @code{:init} code to only what
+would succeed either way.  @code{:init} also always happens before
+package load, whether @code{:config} has been deferred or not.
+
+@node Config keyword
+@subsection @code{:config} is evaluated after loading package
+
+@findex :config
+The @code{:config} section is evaluated after the package has been
+loaded.  If the package is loaded immediately, this happens
+immediately after that, but if loading is done lazily (@pxref{Loading
+Packages}), this is deferred until after the package has been loaded.
+
+In general, you should keep @code{:init} forms as simple and quick as
+possible, and put as much as you can get away with into the
+@code{:config} section.  That way, deferred loading can help your
+Emacs start as quickly as possible.
+
+@node Best practices
+@subheading When to use @code{:preface}, @code{:config} and @code{:init}?
+
+Where possible, it is better to avoid @code{:preface}, @code{:config}
+and @code{:init}.  Instead, prefer autoloading keywords such as
+@code{:bind}, @code{:hook}, and @code{:mode}, as they will take care
+of setting up autoloads for you without any need for boilerplate code.
+For example, consider the following declaration:
+
+@lisp
+(use-package foo
+  :init
+  (add-hook 'some-hook 'foo-mode))
+@end lisp
+
+This has two problems.  First, it will unconditionally load the
+package @samp{foo} on startup, which will make things slower.  You can
+fix this by adding @code{:defer t}:
+
+@lisp
+(use-package foo
+  :defer t
+  :init
+  (add-hook 'some-hook 'foo-mode))
+@end lisp
+
+This is better, as @samp{foo} is now only loaded when it is actually
+needed (that is, when the hook @samp{some-hook} is run).
+
+The second problem is that there is a lot of boilerplate that you have
+to write.  In this case, it might not be so bad, but avoiding that was
+what use-package was made to avoid.  The better option in this case is
+therefore to use @code{:hook} (@xref{Hooks}), which also implies
+@w{@code{:defer t}}.  The above is thereby reduced down to:
+
+@lisp
+(use-package foo
+  :hook some-hook)
+@end lisp
+
+use-package will set up autoloading for you, and your Emacs startup
+time will not suffer one bit.
+
+@node Key bindings
+@section Key bindings
+
+@cindex :bind
+@cindex binding keys
+@cindex key bindings
+One common thing to do when loading a package is to bind a key to
+commands within that module.  Without use-package, this would be done
+using a combination of @code{keymap-local-set},
+@code{keymap-global-set} and various autoloads.  With use-package, you
+can simplify this using the @code{:bind} keyword.
+
+@menu
+* Global keybindings::          Bindings you can use anywhere.
+* Binding in keymaps::          Bindings for particular modes.
+* Binding to a keymap::         Binding a key to a keymap.
+* Binding to repeat-maps::      Binding repeating keys.
+* Displaying keybindings::      Displaying personal key bindings.
+@end menu
+
+@node Global keybindings
+@subsection Global keybindings
+
+@findex :bind
+To bind keys globally, the @code{:bind} keyword takes either a single
+cons or a list of conses.  Every cons has the form @code{(@var{key}
+. @var{command}}, where @var{key} is a string indicating the key to
+bind, and @var{command} is the name of a command (a symbol).  The
+syntax for the keys is similar to the syntax used by the @code{kbd}
+function (@pxref{Init Rebinding,,, emacs, GNU Emacs Manual} for more
+information).
+
+@subheading Using @code{:bind} with a single cons
+
+Here is an example of using a single cons:
+
+@lisp
+(use-package ace-jump-mode
+  :bind ("C-." . ace-jump-mode))
+@end lisp
+
+This does two things: first, it creates an autoload for the
+@code{ace-jump-mode} command and defers loading of the
+@code{ace-jump-mode} package until you actually use it.  Second, it
+binds the key @code{C-.} to that command globally.
+
+@subheading Using @code{:bind} with a list of conses
+
+Here is an example of using @code{:bind} with a list of conses:
+
+@lisp
+(use-package hi-lock
+  :bind (("M-o l" . highlight-lines-matching-regexp)
+         ("M-o r" . highlight-regexp)
+         ("M-o w" . highlight-phrase)))
+@end lisp
+
+@subheading Using special keys
+
+Inside key strings, special keys like @kbd{TAB} or @kbd{F1}--@kbd{F12}
+have to be written inside angle brackets, e.g.  @code{"C-<up>"}.
+Standalone special keys (and some combinations) can be written in
+square brackets, e.g.@ @code{[tab]} instead of @code{"<tab>"}.
+
+Examples:
+
+@lisp
+(use-package helm
+  :bind (("M-x" . helm-M-x)
+         ("M-<f5>" . helm-find-files)
+         ([f10] . helm-buffers-list)
+         ([S-f10] . helm-recentf)))
+@end lisp
+
+@subheading Remapping commands
+
+Remapping commands with @code{:bind} and @code{bind-key} works as
+expected, because when the binding is a vector, it is passed straight
+to @code{define-key}.  @xref{Remapping Commands,,, elisp, GNU Emacs
+Lisp Reference Manual}) for more information about command remapping.
+For example, the following declaration will rebind
+@code{fill-paragraph} (bound to @kbd{M-q} by default) to
+@code{unfill-toggle}:
+
+@lisp
+(use-package unfill
+  :bind ([remap fill-paragraph] . unfill-toggle))
+@end lisp
+
+@subheading What @code{:bind} does behind the scenes
+
+To understand what @code{:bind} does behind the scenes, it might be
+useful to consider an example:
+
+@lisp
+(use-package ace-jump-mode
+  :bind ("C-." . ace-jump-mode))
+@end lisp
+
+This could be expressed in a much more verbose way with the
+@code{:commands} and @code{:init} keywords.
+
+@lisp
+(use-package ace-jump-mode
+  :commands ace-jump-mode
+  :init
+  (bind-key "C-." 'ace-jump-mode))
+@end lisp
+
+Without using even the @code{:commands} keyword, we could also write
+the above like so:
+
+@lisp
+(use-package ace-jump-mode
+  :defer t
+  :init
+  (autoload 'ace-jump-mode "ace-jump-mode" nil t)
+  (bind-key "C-." 'ace-jump-mode))
+@end lisp
+
+Although these three forms are all equivalent, the first form is
+usually the best, as it will save some typing.
+
+@node Binding in keymaps
+@subsection Key bindings in local keymaps
+
+@findex :map, inside :bind
+Slightly different from binding a key to a keymap, is binding a key
+@emph{within} a local keymap that only exists after the package is
+loaded.  @code{use-package} supports this with a @code{:map} modifier,
+taking the local keymap to bind to:
+
+@lisp
+(use-package helm
+  :bind (:map helm-command-map
+         ("C-c h" . helm-execute-persistent-action)))
+@end lisp
+
+The effect of this statement is to wait until @code{helm} has loaded,
+and then to bind the key @code{C-c h} to
+@code{helm-execute-persistent-action} within Helm's local keymap,
+@code{helm-command-map}.
+
+Multiple uses of @code{:map} may be specified. Any binding occurring
+before the first use of @code{:map} are applied to the global keymap:
+
+@lisp
+(use-package term
+  :bind (("C-c t" . term)
+         :map term-mode-map
+         ("M-p" . term-send-up)
+         ("M-n" . term-send-down)
+         :map term-raw-map
+         ("M-o" . other-window)
+         ("M-p" . term-send-up)
+         ("M-n" . term-send-down)))
+@end lisp
+
+@node Binding to a keymap
+@subsection Binding to keymaps
+
+@findex :bind-keymap, inside :bind
+Normally @code{:bind} expects that commands are functions that will be
+autoloaded from the given package. However, this does not work if one of
+those commands is actually a keymap, since keymaps are not functions,
+and cannot be autoloaded using the built-in @code{autoload} function.
+
+To handle this case, @code{use-package} offers a special, limited
+variant of @code{:bind} called @code{:bind-keymap}. The only difference
+is that the ``commands'' bound to by @code{:bind-keymap} must be keymaps
+defined in the package, rather than command functions. This is handled
+behind the scenes by generating custom code that loads the package
+containing the keymap, and then re-executes your keypress after the
+first load, to reinterpret that keypress as a prefix key.
+
+For example:
+
+@lisp
+(use-package foo
+  :bind-keymap ("C-c p" . foo-command-map))
+@end lisp
+
+@node Binding to repeat-maps
+@subsection Binding to repeat-maps
+
+@findex :repeat-map, inside :bind
+@cindex repeat-mode and use-package, using
+A special case of binding within a local keymap is when that keymap is
+used by @code{repeat-mode} @pxref{Repeating,,, emacs, GNU Emacs
+Manual}.  These keymaps are usually defined specifically for
+this.  Using the @code{:repeat-map} keyword, and passing it a name for
+the map it defines, will bind all following keys inside that map, and
+(by default) set the @code{repeat-map} property of each bound command
+to that map.
+
+The following example creates a keymap called
+@code{git-gutter+-repeat-map}, makes four bindings in it as above,
+then sets the @code{repeat-map} property of each bound command
+(@code{git-gutter+-next-hunk} @code{git-gutter+-previous-hunk},
+@code{git-gutter+-stage-hunks} and @code{git-gutter+-revert-hunk}) to
+that keymap.
+
+@lisp
+(use-package git-gutter+
+  :bind
+  (:repeat-map git-gutter+-repeat-map
+   ("n" . git-gutter+-next-hunk)
+   ("p" . git-gutter+-previous-hunk)
+   ("s" . git-gutter+-stage-hunks)
+   ("r" . git-gutter+-revert-hunk)))
+@end lisp
+
+@findex :exit, inside :repeat-map and :bind
+Specifying @code{:exit} inside the scope of @code{:repeat-map} will
+prevent the @code{repeat-map} property being set, so that the command
+can be used from within the repeat map, but after it using it the repeat
+map will no longer be available.  This is useful for commands often used
+at the end of a series of repeated commands:
+
+@lisp
+(use-package git-gutter+
+  :bind
+  (:repeat-map my/git-gutter+-repeat-map
+   ("n" . git-gutter+-next-hunk)
+   ("p" . git-gutter+-previous-hunk)
+   ("s" . git-gutter+-stage-hunks)
+   ("r" . git-gutter+-revert-hunk)
+   :exit
+   ("c" . magit-commit-create)
+   ("C" . magit-commit)
+   ("b" . magit-blame)))
+@end lisp
+
+@findex :continue, inside :repeat-map and :bind
+Specifying @code{:continue} @emph{forces} setting the
+@code{repeat-map} property (just like @emph{not} specifying
+@code{:exit}), so the above snippet is equivalent to:
+
+@lisp
+(use-package git-gutter+
+  :bind
+  (:repeat-map my/git-gutter+-repeat-map
+   :exit
+   ("c" . magit-commit-create)
+   ("C" . magit-commit)
+   ("b" . magit-blame)
+   :continue
+   ("n" . git-gutter+-next-hunk)
+   ("p" . git-gutter+-previous-hunk)
+   ("s" . git-gutter+-stage-hunks)
+   ("r" . git-gutter+-revert-hunk)))
+@end lisp
+
+@node Displaying keybindings
+@subsection Displaying personal keybinding
+
+@findex describe-personal-keybindings
+The @code{:bind} keyword uses the @code{bind-keys} macro from the
+@samp{bind-key.el} library to set up keybindings.  It keeps track of
+all keybindings you make, so that you can display them separately from
+the default keybindings.
+
+Use @w{@code{M-x describe-personal-keybindings}} to see all
+keybindings you've set using either the @code{:bind} keyword or the
+@code{bind-keys} macro.
+
+@node Hooks
+@section Hooks
+
+@cindex hooks
+@findex :hook
+The @code{:hook} keyword allows adding functions onto hooks.  It takes
+one argument of the form @var{hooks}, specifying one or more functions
+to add to one or more hooks.  For the purposes of @code{:hook}, the
+name of hook variables should always exclude the @samp{-hook} suffix.
+It is appended automatically for you, to save some typing.
+
+For example, consider the following @code{use-package} declaration
+that sets up autoloads for @code{company-mode} from the @samp{company}
+package, and adds @samp{company-mode} to @code{prog-mode-hook}:
+
+@lisp
+(use-package company
+  :commands company-mode
+  :init
+  (add-hook 'prog-mode-hook #'company-mode))
+@end lisp
+
+Using @code{:hook}, this can be simplified to:
+
+@lisp
+(use-package company
+  :hook (prog-mode . company-mode))
+@end lisp
+
+Here, @code{:hook} will automatically set up autoloads for the
+@code{company-mode} command, so there is no need to use
+@code{:commands}.
+
+The @code{:hook} keyword will also assume that the name of the
+function you want to add is the same as the package name with
+@samp{-mode} appended to it.  Taking this into account, you can
+simplify the above to the equivalent:
+
+@lisp
+(use-package company
+  :hook prog-mode)
+@end lisp
+
+@cindex multiple hooks
+You can also provide a list of hooks.  When multiple hooks should be
+applied, the following examples are all equivalent:
+
+@lisp
+(use-package company
+  :hook (prog-mode text-mode))
+
+(use-package company
+  :hook ((prog-mode text-mode) . company-mode))
+
+(use-package company
+  :hook ((prog-mode . company-mode)
+         (text-mode . company-mode)))
+
+(use-package company
+  :commands company-mode
+  :init
+  (add-hook 'prog-mode-hook #'company-mode)
+  (add-hook 'text-mode-hook #'company-mode))
+@end lisp
+
+One common mistake when using @code{:hook} is to forget to omit the
+@samp{-hook} suffix, which, as already explained, is appended
+automatically.  Therefore, the following will not work, as it attempts
+to add a function to non-existent @code{prog-mode-hook-hook}:
+
+@lisp
+;; DOES NOT WORK
+(use-package ace-jump-mode
+  :hook (prog-mode-hook . ace-jump-mode))
+@end lisp
+
+@vindex use-package-hook-name-suffix
+If you do not like this behavior, you can customize the user option
+@code{use-package-hook-name-suffix} to @code{nil}.  The value of this
+variable is @samp{"-hook"} by default.
+
+The use of @code{:hook}, as with @code{:bind}, @code{:mode},
+@code{:interpreter}, etc., causes the functions being hooked to
+implicitly be read as @code{:commands}.  This means that they will
+establish interactive @code{autoload} definitions for that module, if
+not already defined as functions), and so @code{:defer t} is also
+implied by @code{:hook}.
+
+@node Modes and interpreters
+@section Modes and interpreters
+
+@findex :mode
+@findex :interpreter
+Similar to @code{:bind}, you can use @code{:mode} and
+@code{:interpreter} to establish a deferred binding within the
+@code{auto-mode-alist} and @code{interpreter-mode-alist} variables.
+The specifier to either keyword can be a cons cell, a list of cons
+cells, or a string or regexp.
+
+The following example reproduces the default @code{ruby-mode}
+configuration, exactly as it is in Emacs out-of-the-box.  That mode is
+enabled automatically when a file whose name matches the regexp
+@code{"\\.rb\\'"} (a file with the @samp{.rb} extension), or when the
+first line of the file (known as the ``shebang'') matches the string
+@code{"ruby"}:
+
+@lisp
+(use-package ruby-mode
+  :mode "\\.rb\\'"
+  :interpreter "ruby")
+@end lisp
+
+The default @code{python-mode} configuration can be reproduced using
+the below declaration.  Note that the package that should be loaded
+differs from the mode name in this case, so we must use a cons:
+
+@lisp
+;; The package is "python" but the mode is "python-mode":
+(use-package python
+  :mode ("\\.py\\'" . python-mode)
+  :interpreter ("python" . python-mode))
+@end lisp
+
+Both the @code{:mode} and @code{:interpreter} keywords also accept a
+list of regexps:
+
+@lisp
+(use-package foo
+  ;; Equivalent to "\\(ba[rz]\\)\\'":
+  :mode ("\\.bar\\'" "\\.baz\\'")
+  ;; Equivalent to "\\(foo[ab]\\)":
+  :interpreter ("fooa" "foob"))
+@end lisp
+
+@node Magic handlers
+@section Magic handlers
+
+@findex :magic
+@findex :magic-fallback
+Similar to @code{:mode} and @code{:interpreter}, you can also use
+@code{:magic} and @code{:magic-fallback} to cause certain function to
+be run if the beginning of a file matches a given regular expression.
+The difference between @code{:magic} and @code{:magic-fallback}, is
+that the latter has a lower priority than @code{:mode}.
+
+Here is an example:
+
+@lisp
+(use-package pdf-tools
+  :magic ("%PDF" . pdf-view-mode)
+  :config
+  (pdf-tools-install :no-query))
+@end lisp
+
+This registers an autoloaded command for @code{pdf-view-mode}, defers
+loading of @code{pdf-tools}, and runs @code{pdf-view-mode} if the
+beginning of a buffer matches the string @code{"%PDF"}.
+
+@node User options
+@section User options
+
+@findex :custom
+In Emacs, you normally set customizable variables (user options) using
+the @code{M-x customize} interface (@pxref{Easy Customization,,,
+emacs, GNU Emacs Manual}).  We recommended this method for most users.
+However, it is also possible to set them in your @code{use-package}
+declarations by using the @code{:custom} keyword.
+
+@lisp
+(use-package comint
+  :defer t
+  :custom
+  (comint-buffer-maximum-size 20000 "Increase comint buffer size.")
+  (comint-prompt-read-only t "Make the prompt read only."))
+@end lisp
+
+This is better than using @code{setq} in a @code{:config} block, as
+customizable variables might have some code associated with it that
+Emacs will execute when you assign values to them.  In Emacs 29, there
+is also the new @code{setopt} macro that does this for you.
+
+Note that the values customized using this keyword are @emph{not}
+saved in the standard Emacs @code{custom-file}.  You should therefore
+set each user option using either the @code{:custom} keyword @emph{or}
+@w{@code{M-x customize-option}}, which will save customized values in
+the Emacs @code{custom-file}.  Do not use both for the same variable,
+as this risk having conflicting values in your use-package declaration
+and your @code{custom-file}.  This can lead to problems that are both
+tricky and tedious to debug.
+
+@node Faces
+@section Faces
+
+@findex :custom-face
+The @code{:custom-face} keyword allows customization of package custom
+faces.
+
+@lisp
+(use-package eruby-mode
+  :custom-face
+  (eruby-standard-face ((t (:slant italic)))))
+
+(use-package example
+  :custom-face
+  (example-1-face ((t (:foreground "LightPink"))))
+  (example-2-face ((t (:foreground "LightGreen"))) face-defspec-spec))
+
+(use-package zenburn-theme
+  :preface
+  (setq my/zenburn-colors-alist
+        '((fg . "#DCDCCC") (bg . "#1C1C1C") (cyan . "#93E0E3")))
+  :custom-face
+  (region ((t (:background ,(alist-get my/zenburn-colors-alist 'cyan)))))
+  :config
+  (load-theme 'zenburn t))
+@end lisp
+
+@node Hiding minor modes
+@section Hiding minor modes with diminish and delight
+
+@code{use-package} supports the diminish and delight packages, both of
+which make it possible remove or change minor mode strings in your
+mode-line.  Which one to use is up to you, but you should normally
+only use one or the other -- never both.@footnote{When in doubt, you
+might as well use diminish.}  To use either of them, you must first
+install the corresponding package from @acronym{GNU ELPA}.
+
+@menu
+* Diminish::                    Hiding minor modes with Diminish.
+* Delight::                     Hiding minor modes with Delight.
+@end menu
+
+@node Diminish
+@subsection Diminish
+
+@findex :diminish
+When diminish@footnote{The diminish package is installable from
+@acronym{GNU ELPA}.} is installed, you can use the @code{:diminish}
+keyword.  First, add the following declaration to the beginning of
+your init file.  The optional @w{@code{:ensure t}} makes sure the
+package is installed if it isn't already (@pxref{Installing
+packages}).
+
+@lisp
+(use-package diminish :ensure t)
+@end lisp
+
+The @code{:diminish} keyword takes either a minor mode symbol, a cons
+of the symbol and its replacement string, or just a replacement
+string, in which case the minor mode symbol is guessed to be the
+package name with @samp{-mode} appended at the end:
+
+@lisp
+(use-package abbrev
+  :diminish abbrev-mode
+  :config
+  (if (file-exists-p abbrev-file-name)
+      (quietly-read-abbrev-file)))
+@end lisp
+
+@node Delight
+@subsection Delight
+
+@findex :delight
+When delight@footnote{The @samp{delight} package is installable from
+GNU ELPA.} is installed, you can use the @code{:delight} keyword.
+First, add the following declaration to the beginning of your init
+file.  The optional @w{@code{:ensure t}} makes sure the package is
+installed if it isn't already (@pxref{Installing packages}).
+
+@lisp
+(use-package delight :ensure t)
+@end lisp
+
+The @code{:delight} keyword takes a minor mode symbol, a replacement
+string, or quoted mode line data (in which case the minor mode symbol
+is guessed to be the package name with @samp{-mode} appended at the
+end), both of these, or several lists of both.  @xref{Mode Line
+Data,,, elisp, GNU Emacs Lisp Reference Manual}.  If no arguments are
+provided, the default mode name is hidden completely.
+
+@lisp
+;; Don't show anything for rainbow-mode.
+(use-package rainbow-mode
+  :delight)
+
+;; Don't show anything for auto-revert-mode, which doesn't match
+;; its package name.
+(use-package autorevert
+  :delight auto-revert-mode)
+
+;; Remove the mode name for projectile-mode, but show the project name.
+(use-package projectile
+  :delight '(:eval (concat " " (projectile-project-name))))
+
+;; Completely hide visual-line-mode and change auto-fill-mode to " AF".
+(use-package emacs
+  :delight
+  (auto-fill-function " AF")
+  (visual-line-mode))
+@end lisp
+
+@c ----------------------------------------------------------------------------
+@node Installing packages
+@chapter Installing packages automatically
+
+The standard Emacs package manager is documented in the Emacs manual
+(@pxref{Package Installation,,, emacs, GNU Emacs Manual}).  The
+@code{use-package} macro provides the @code{:ensure} and @code{:pin}
+keywords, that interface with that package manager to automatically
+install packages.  This is particularly useful if you use your init
+file on more than one system.
+
+@menu
+* Install package::
+* Pinning packages::
+* Other package managers::
+@end menu
+
+@node Install package
+@section Installing package
+
+@findex :ensure
+The @code{:ensure} keyword makes use-package ask the Emacs package
+manager to install a package if it is not already present on your
+system.
+
+For example:
+
+@lisp
+(use-package magit
+  :ensure t)
+@end lisp
+
+If you need to install a different package from the one named by
+@code{use-package}, you can use a symbol:
+
+@lisp
+(use-package tex
+  :ensure auctex)
+@end lisp
+
+You can customize the user option @code{use-package-always-ensure} to
+non-@code{nil} if you want this behavior to be global for all
+packages.
+
+@lisp
+(require 'use-package-ensure)
+(setq use-package-always-ensure t)
+@end lisp
+
+@noindent
+You can override the above setting for a single package by adding
+@w{@code{:ensure nil}} to its declaration.
+
+@node Pinning packages
+@section Pinning packages using @code{:pin}
+
+@findex :pin
+use-package can pin a package to a specific archive using the
+@code{:pin} keyword.@footnote{The @code{:pin} keyword has no effect on
+Emacs versions older than 24.4.}  This allows you to mix and match
+packages from different archives.  The primary use-case for this is
+preferring to install packages from @acronym{GNU ELPA} or
+@acronym{NonGNU ELPA} (indicated by @code{gnu} and @code{nongnu},
+respectively), while installing specific packages from third-party
+archives.
+
+For example:
+
+@lisp
+(use-package company
+  :ensure t
+  :pin gnu)   ; GNU ELPA
+@end lisp
+
+@vindex use-package-always-pin
+Unfortunately, the third-party archive @acronym{MELPA} uses a
+versioning scheme based on dates, which means that packages from that
+archive are always preferred.  If you are using that archive, we
+strongly encourage you to customize @code{use-package-always-pin} to
+@code{nongnu}.  This guarantees that you are using a version of that
+package that has been specifically marked for release by its
+developer, and not a development snapshot.
+
+@c FIXME: This needs clarifying.  AFAIK, :ensure does not update packages.
+If you want to manually keep a package updated and ignore upstream
+updates, you can pin it to @samp{manual}.  This will work as long as
+you have not customized a repository to use that name in the
+@code{package-archives} variable.
+
+Example:
+
+@lisp
+(use-package org
+  :ensure t
+  ;; ignore org-mode from upstream and use a manually installed version
+  :pin manual)
+@end lisp
+
+@code{use-package} signals an error if you try to pin a package to an
+archive that is not configured using @code{package-archives} (except
+from the special @samp{manual} archive).
+
+@node Other package managers
+@section Non-standard package managers
+
+By default, use-package assumes that you are using the built-in
+@code{package.el} package manager.  We expect that most users will
+find that it is more than capable enough, even for advanced use cases.
+
+@vindex use-package-ensure-function
+However, some users might prefer to use a third-party package manager
+for a specific circumstance or use case.  By setting the user option
+@code{use-package-ensure-function} to the name of a function, you can
+direct @code{:ensure} to use a different package manager for
+installing packages.
+
+For more details, please see the documentation of the package manager
+you are using.  If you run into any bugs, it is often best to report
+them directly to the developers of that package manager.
+
+@c ----------------------------------------------------------------------------
+@node Byte-compiling
+@chapter Byte-compiling your init file
+
+Some users might want to byte-compile their init file to make Emacs
+startup even faster.  This is not recommended in most cases, as the
+speed-up is often too small to be worth it, and can lead to confusion
+if the byte-compiled files are out-of-date.  If you still want to do
+it, read on.
+
+@code{use-package} always loads every library that it can while a file
+is being byte-compiled.  This helps silence spurious warnings about
+unknown variables and functions.
+
+@findex :defines
+@findex :functions
+However, there are times when this is just not enough.  For those
+times, use the @code{:defines} and @code{:functions} keywords to
+introduce dummy variable and function declarations solely for the sake
+of silencing byte-compiler warnings.  For example:
+
+@lisp
+(use-package texinfo
+  :defines texinfo-section-list
+  :commands texinfo-mode
+  :init
+  (add-to-list 'auto-mode-alist '("\\.texi$" . texinfo-mode)))
+@end lisp
+
+If you need to silence a missing function warning, you can use
+@code{:functions}:
+
+@lisp
+(use-package ruby-mode
+  :mode "\\.rb\\'"
+  :interpreter "ruby"
+  :functions inf-ruby-keys
+  :config
+  (defun my-ruby-mode-hook ()
+    (require 'inf-ruby)
+    (inf-ruby-keys))
+
+  (add-hook 'ruby-mode-hook 'my-ruby-mode-hook))
+@end lisp
+
+@findex :no-require
+@cindex prevent a package from loading at compile-time
+Normally, @code{use-package} will load each package at compile time
+before compiling the configuration, to ensure that any necessary
+symbols are in scope to satisfy the byte-compiler.  At times this can
+cause problems, since a package may have special loading requirements,
+and all that you want to use @code{use-package} for is to add a
+configuration to the @code{eval-after-load} hook.  In such cases, use
+the @code{:no-require} keyword:
+
+@lisp
+(use-package foo
+  :no-require t
+  :config
+  (message "Evaluate this immediately after loading `foo'"))
+@end lisp
+
+@c ----------------------------------------------------------------------------
+@node Troubleshooting
+@chapter Troubleshooting
+
+@cindex troubleshooting
+@cindex debugging
+If an error occurs while initializing or configuring a package, this
+will not stop your Emacs from loading.  Instead, @code{use-package}
+captures the error and reports it in a special @code{*Warnings*} popup
+buffer, so that you can debug the situation in an otherwise functional
+Emacs.
+
+If you are having trouble when starting Emacs, you can pass Emacs the
+@samp{--debug-init} command line flag.  @xref{Initial Options,,,
+emacs, GNU Emacs Manual}.  To get even more information when using
+that flag, add the following to your init file (these options are
+documented below):
+
+@lisp
+(when init-file-debug
+  (setq use-package-verbose t
+        use-package-expand-minimally nil
+        use-package-compute-statistics t
+        debug-on-error t))
+@end lisp
+
+@cindex reporting bugs
+@cindex expanding macro, for troubleshooting
+Since @code{use-package} is a macro, the first step when you need to
+dig deeper is usually to see what Emacs Lisp code your declaration
+expands to.  You can either use the command @w{@kbd{M-x
+pp-macroexpand-last-sexp}}, or wrap the use-package declaration in
+@code{macroexpand} and evaluate it.  It is a good idea to include
+their output in any bugs you file for use-package.
+
+@menu
+* Troubleshooting Options::
+* Gathering Statistics::
+* Disabling a package::
+@end menu
+
+@node Troubleshooting Options
+@section Options that help when troubleshooting
+
+@vindex use-package-expand-minimally
+By default, use-package will attempts to catch and report errors that
+occur during expansion of use-package declarations in your init file.
+Customize the user option @code{use-package-expand-minimally} to a
+non-@code{nil} value to disable this checking.
+
+@findex :catch
+This behavior may be overridden locally using the @code{:catch}
+keyword.  If @code{t} or @code{nil}, it enables or disables catching
+errors at load time.  It can also be a function taking two arguments:
+the keyword being processed at the time the error was encountered, and
+the error object (as generated by @code{condition-case}).  For
+example:
+
+@lisp
+(use-package example
+  ;; Note that errors are never trapped in the preface, since doing so would
+  ;; hide definitions from the byte-compiler.
+  :preface (message "I'm here at byte-compile and load time")
+  :init (message "I'm always here at startup")
+  :config
+  (message "I'm always here after the package is loaded")
+  (error "oops")
+  ;; Don't try to (require 'example), this is just an example!
+  :no-require t
+  :catch (lambda (keyword err)
+           (message (error-message-string err))))
+@end lisp
+
+Evaluating the above form will print these messages:
+
+@verbatim
+I’m here at byte-compile and load time
+I’m always here at startup
+Configuring package example...
+I’m always here after the package is loaded
+oops
+@end verbatim
+
+@node Gathering Statistics
+@section Gathering Statistics
+
+@vindex use-package-verbose
+When a package is loaded, and if you have @code{use-package-verbose}
+set to @code{t}, or if the package takes longer than 0.1 seconds to
+load, you will see a message to indicate this loading activity in the
+@code{*Messages*} buffer.  The same will happen for configuration, or
+@code{:config} blocks, that take longer than 0.1 seconds to execute.
+
+@vindex use-package-compute-statistics
+If you'd like to see a summary how many packages you've loaded, what
+stage of initialization they've reached, and how much aggregate time
+they've spent (roughly), you can customize the user option
+@code{use-package-compute-statistics} to a non-@code{nil} value.  Then
+reload your packages, normally by restarting Emacs, to make sure that
+use-package can gather statistics for all your packages.
+
+@cindex use-package-report
+Run the command @kbd{M-x use-package-report} to see the results.  The
+buffer displayed is a tabulated list.  To sort rows based on a
+particular column, move point to it and type @kbd{S}, or click the
+column name at the top of the buffer on graphical displays.
+
+@cindex use-package-reset-statistics
+To reset all statistics that use-package has gathered for the current
+Emacs invocation, run the command @kbd{M-x use-package-reset-statistics}.
+
+Note that, if you are setting @code{use-package-compute-statistics}
+directly in your init file, and not with @code{customize}, you must do
+this after loading @code{use-package}, but before any
+@code{use-package} forms.
+
+@node Disabling a package
+@section Disabling a package
+
+@cindex disable package
+@findex :disabled
+The @code{:disabled} keyword inhibits loading a package, and all it's
+customizations.  It is equivalent to commenting out or deleting the
+definition.
+
+You could use this, for example, to temporarily disable a package that
+you're having difficulties with, or to avoid loading a package that
+you're not currently using.
+
+This example disables the @samp{foo} package:
+
+@lisp
+(use-package foo
+  :disabled)
+@end lisp
+
+When byte-compiling your init file, use-package omits disabled
+declarations from the output entirely, in order to make Emacs startup
+faster.
+
+@c ----------------------------------------------------------------------------
+@node Keyword extensions
+@appendix Keyword extensions
+
+use-package is based on an extensible framework that makes it easy for
+package authors to add new keywords, or modify the behavior of
+existing keywords.
+
+Some keyword extensions are included with @code{use-package}, and can
+be optionally enabled.
+
+@menu
+* use-package-ensure-system-package::
+* Creating an extension::
+@end menu
+
+@node use-package-ensure-system-package
+@section :use-package-ensure-system-package
+
+@findex :ensure-system-package
+The @code{:ensure-system-package} keyword allows you to ensure certain
+executables are available on your system alongside your package
+declarations.@footnote{On macOS, you will want to make sure
+@code{exec-path} is cognisant of all binary package names that you
+would like to ensure are installed.  The
+@uref{https://github.com/purcell/exec-path-from-shell,@samp{exec-path-from-shell}}
+package is often a good way to do this.}
+
+To use this extension, add this immediately after loading
+@code{use-package}:
+
+@lisp
+(use-package use-package-ensure-system-package)
+@end lisp
+
+Now you can use the @code{:ensure-system-package} keyword.
+Here's an example usage:
+
+@lisp
+(use-package foo
+  :ensure-system-package foo)
+@end lisp
+
+This will expect a global binary package to exist called @code{foo}.
+If it does not, it will use your system package manager to attempt an
+install of a binary by the same name asynchronously.  This requires
+the GNU ELPA package
+@uref{https://gitlab.com/jabranham/system-packages,@samp{system-packages}},
+so for this to work you must install that first.
+
+One way of making sure it is installed is with @code{use-package}
+together with @code{:ensure}.
+
+@lisp
+(use-package system-packages
+  :ensure t)
+@end lisp
+
+For example, on a @code{Debian GNU/Linux} system, this would call
+@samp{apt-get install foo}.
+
+If the package is named differently than the binary, you can use a
+cons in the form of @code{(binary . package-name)}.  For example:
+
+@lisp
+(use-package foo
+  :ensure-system-package
+  (foocmd . foo))
+@end lisp
+
+On a @code{Debian GNU/Linux} system, this would call @code{apt install
+foo} if Emacs could not locate the executable
+@code{foocmd}.@footnote{For manual testing, you could use the
+@code{executable-find} function, which is what @samp{system-packages}
+uses internally.}
+
+@code{:ensure-system-package} can also take a cons where its
+@code{cdr} is a string that will get called by
+@code{(async-shell-command)} to install if it isn't found.  This does
+not depend upon any external package.
+
+@lisp
+(use-package tern
+  :ensure-system-package (tern . "npm i -g tern"))
+@end lisp
+
+To install several packages, you can pass in a list of conses:
+
+@lisp
+(use-package ruby-mode
+  :ensure-system-package
+  ((rubocop     . "gem install rubocop")
+   (ruby-lint   . "gem install ruby-lint")
+   (ripper-tags . "gem install ripper-tags")
+   (pry         . "gem install pry")))
+@end lisp
+
+Finally, in case the package dependency does not provide a global
+executable, you can ensure packages exist by checking the presence of a
+file path by providing a string like so:
+
+@lisp
+(use-package dash-at-point
+  :if (eq system-type 'darwin)
+  :ensure-system-package
+  ("/Applications/Dash.app" . "brew cask install dash"))
+@end lisp
+
+@code{:ensure-system-package} will use @code{system-packages-install}
+to install system packages, except where a custom command has been
+specified, in which case it will be executed verbatim by
+@code{async-shell-command}.
+
+The user options @code{system-packages-package-manager} and
+@code{system-packages-use-sudo} are honored, but not for custom
+commands.  Custom commands should include the call to sudo in the
+command if needed.
+
+@node Creating an extension
+@section How to create an extension keyword
+
+This section describes how to create a new keyword.
+
+@enumerate
+@item
+Add the keyword.
+
+The first step is to add your keyword at the right place in
+@code{use-package-keywords}.  This list determines the order in which
+things will happen in the expanded code.  You should never change this
+order, but it gives you a framework within which to decide when your
+keyword should fire.
+
+@item
+Create a normalizer.
+
+The job of the normalizer is take a list of arguments (possibly
+@code{nil}), and turn it into the single argument (which could still
+be a list) that should appear in the final property list used by
+@code{use-package}.
+
+Define a normalizer for your keyword by defining a function named
+after the keyword, for example:
+
+@lisp
+(defun use-package-normalize/:pin (name-symbol keyword args)
+  (use-package-only-one (symbol-name keyword) args
+    (lambda (label arg)
+      (cond
+       ((stringp arg) arg)
+       ((symbolp arg) (symbol-name arg))
+       (t
+        (use-package-error
+         ":pin wants an archive name (a string)"))))))
+@end lisp
+
+@item
+Create a handler.
+
+Once you have a normalizer, you must create a handler for the keyword.
+
+Handlers can affect the handling of keywords in two ways.  First, it
+can modify the @code{state} plist before recursively processing the
+remaining keywords, to influence keywords that pay attention to the
+state (one example is the state keyword @code{:deferred}, not to be
+confused with the @code{use-package} keyword @code{:defer}).  Then,
+once the remaining keywords have been handled and their resulting
+forms returned, the handler may manipulate, extend, or just ignore
+those forms.
+
+The task of each handler is to return a @emph{list of forms}
+representing code to be inserted.  It does not need to be a
+@code{progn} list, as this is handled automatically in other places.
+Thus it is common to see the idiom of using @code{use-package-concat}
+to add new functionality before or after a code body, so that only the
+minimum code necessary is emitted as the result of a
+@code{use-package} expansion.
+
+This is an example handler:
+
+@lisp
+(defun use-package-handler/:pin (name-symbol keyword archive-name rest state)
+  (let ((body (use-package-process-keywords name-symbol rest state)))
+    ;; This happens at macro expansion time, not when the expanded code is
+    ;; compiled or evaluated.
+    (if (null archive-name)
+        body
+      (use-package-pin-package name-symbol archive-name)
+      (use-package-concat
+       body
+       `((push '(,name-symbol . ,archive-name)
+               package-pinned-packages))))))
+@end lisp
+
+@item
+Test it.
+
+After the keyword has been inserted into @code{use-package-keywords},
+and a normalizer and a handler defined, you can now test it by seeing
+how usages of the keyword will expand.  For this, use @code{M-x
+pp-macroexpand-last-sexp} with the cursor set immediately after the
+@code{(use-package ...)} expression.
+@end enumerate
+
+@c ----------------------------------------------------------------------------
+@node History
+@appendix History and acknowledgments
+
+use-package was written by John Wiegley.  Its development started in
+2012, and it got merged into Emacs in 2022, in preparation of the
+release of Emacs 29.1.
+
+Dozens of people have contributed to use-package over the years with
+bug reports, documentation and code.  They are too many to list here,
+but we thank them all for their contributions.
+
+This Texinfo manual was written by Stefan Kangas, as a significant
+rewrite of the old use-package manual and @file{README}.
+
+@node GNU Free Documentation License
+@appendix GNU Free Documentation License
+@include doclicense.texi
+
+@node Index
+@unnumbered Index
+@printindex cp
+
+@bye
diff --git a/etc/NEWS b/etc/NEWS
index a8e0ead4a44..67711fd7666 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2962,6 +2962,13 @@ features, such as completion, documentation, error 
detection, etc.,
 based on data provided by language servers using the Language Server
 Protocol (LSP).
 
++++
+*** use-package: Declarative package configuration.
+use-package is shipped with Emacs.  It provides the 'use-package'
+macro, which allows you to isolate package configuration in your init
+file in a way that is declarative, tidy, and performance-oriented.
+See the new Info manual 'use-package' for more.
+
 +++
 ** New commands 'image-crop' and 'image-cut'.
 These commands allow interactively cropping/cutting the image at
diff --git a/lisp/use-package/bind-key.el b/lisp/use-package/bind-key.el
new file mode 100644
index 00000000000..bbe3319d9bb
--- /dev/null
+++ b/lisp/use-package/bind-key.el
@@ -0,0 +1,562 @@
+;;; bind-key.el --- A simple way to manage personal keybindings  -*- 
lexical-binding: t; -*-
+
+;; Copyright (c) 2012-2022 Free Software Foundation, Inc.
+
+;; Author: John Wiegley <johnw@newartisans.com>
+;; Maintainer: John Wiegley <johnw@newartisans.com>
+;; Created: 16 Jun 2012
+;; Version: 2.4.1
+;; Package-Requires: ((emacs "24.3"))
+;; Keywords: keys keybinding config dotemacs extensions
+;; URL: https://github.com/jwiegley/use-package
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; If you have lots of keybindings set in your .emacs file, it can be hard to
+;; know which ones you haven't set yet, and which may now be overriding some
+;; new default in a new Emacs version.  This module aims to solve that
+;; problem.
+;;
+;; Bind keys as follows in your .emacs:
+;;
+;;   (require 'bind-key)
+;;
+;;   (bind-key "C-c x" 'my-ctrl-c-x-command)
+;;
+;; If the keybinding argument is a vector, it is passed straight to
+;; `define-key', so remapping a key with `[remap COMMAND]' works as
+;; expected:
+;;
+;;   (bind-key [remap original-ctrl-c-x-command] 'my-ctrl-c-x-command)
+;;
+;; If you want the keybinding to override all minor modes that may also bind
+;; the same key, use the `bind-key*' form:
+;;
+;;   (bind-key* "<C-return>" 'other-window)
+;;
+;; If you want to rebind a key only in a particular keymap, use:
+;;
+;;   (bind-key "C-c x" 'my-ctrl-c-x-command some-other-mode-map)
+;;
+;; To unbind a key within a keymap (for example, to stop your favorite major
+;; mode from changing a binding that you don't want to override everywhere),
+;; use `unbind-key':
+;;
+;;   (unbind-key "C-c x" some-other-mode-map)
+;;
+;; To bind multiple keys at once, or set up a prefix map, a `bind-keys' macro
+;; is provided.  It accepts keyword arguments, please see its documentation
+;; for a detailed description.
+;;
+;; To add keys into a specific map, use :map argument
+;;
+;;    (bind-keys :map dired-mode-map
+;;               ("o" . dired-omit-mode)
+;;               ("a" . some-custom-dired-function))
+;;
+;; To set up a prefix map, use `:prefix-map' and `:prefix' arguments (both are
+;; required)
+;;
+;;    (bind-keys :prefix-map my-customize-prefix-map
+;;               :prefix "C-c c"
+;;               ("f" . customize-face)
+;;               ("v" . customize-variable))
+;;
+;; You can combine all the keywords together.  Additionally,
+;; `:prefix-docstring' can be specified to set documentation of created
+;; `:prefix-map' variable.
+;;
+;; To bind multiple keys in a `bind-key*' way (to be sure that your bindings
+;; will not be overridden by other modes), you may use `bind-keys*' macro:
+;;
+;;    (bind-keys*
+;;     ("C-o" . other-window)
+;;     ("C-M-n" . forward-page)
+;;     ("C-M-p" . backward-page))
+;;
+;; After Emacs loads, you can see a summary of all your personal keybindings
+;; currently in effect with this command:
+;;
+;;   M-x describe-personal-keybindings
+;;
+;; This display will tell you if you've overridden a default keybinding, and
+;; what the default was.  Also, it will tell you if the key was rebound after
+;; your binding it with `bind-key', and what it was rebound it to.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'easy-mmode)
+
+(defgroup bind-key nil
+  "A simple way to manage personal keybindings."
+  :group 'keyboard
+  :group 'convenience
+  :link '(emacs-commentary-link :tag "Commentary" "bind-key.el")
+  :version "29.1")
+
+(defcustom bind-key-column-widths '(18 . 40)
+  "Width of columns in `describe-personal-keybindings'."
+  :type '(cons integer integer)
+  :group 'bind-key)
+
+(defcustom bind-key-segregation-regexp
+  "\\`\\(\\(C-[chx] \\|M-[gso] \\)\\([CM]-\\)?\\|.+-\\)"
+  "Regexp used by \\[describe-personal-keybindings] to divide key sets."
+  :type 'regexp
+  :group 'bind-key)
+
+(defcustom bind-key-describe-special-forms nil
+  "If non-nil, extract docstrings from lambdas, closures and keymaps if 
possible."
+  :type 'boolean
+  :group 'bind-key)
+
+;; Create override-global-mode to force key remappings
+
+(defvar override-global-map (make-keymap)
+  "Keymap for `override-global-mode'.")
+
+(define-minor-mode override-global-mode
+  "A minor mode for allowing keybindings to override other modes.
+The main purpose of this mode is to simplify bindings keys in
+such a way that they take precedence over other modes.
+
+To achieve this, the keymap `override-global-map' is added to
+`emulation-mode-map-alists', which makes it take precedence over
+keymaps in `minor-mode-map-alist'.  Thereby, key bindings get an
+even higher precedence than global key bindings defined with
+`keymap-global-set' (or, in Emacs 28 or older, `global-set-key').
+
+The macro `bind-key*' (which see) provides a convenient way to
+add keys to that keymap."
+  :init-value t
+  :lighter "")
+
+;; the keymaps in `emulation-mode-map-alists' take precedence over
+;; `minor-mode-map-alist'
+(add-to-list 'emulation-mode-map-alists
+             `((override-global-mode . ,override-global-map)))
+
+(defvar personal-keybindings nil
+  "List of bindings performed by `bind-key'.
+
+Elements have the form ((KEY . [MAP]) CMD ORIGINAL-CMD)")
+
+;;;###autoload
+(defmacro bind-key (key-name command &optional keymap predicate)
+  "Bind KEY-NAME to COMMAND in KEYMAP (`global-map' if not passed).
+
+KEY-NAME may be a vector, in which case it is passed straight to
+`define-key'.  Or it may be a string to be interpreted as
+spelled-out keystrokes, e.g., \"C-c C-z\".  See the documentation
+of `edmacro-mode' for details.
+
+COMMAND must be an interactive function or lambda form.
+
+KEYMAP, if present, should be a keymap variable or symbol.
+For example:
+
+  (bind-key \"M-h\" #\\='some-interactive-function my-mode-map)
+
+  (bind-key \"M-h\" #\\='some-interactive-function \\='my-mode-map)
+
+If PREDICATE is non-nil, it is a form evaluated to determine when
+a key should be bound. It must return non-nil in such cases.
+Emacs can evaluate this form at any time that it does redisplay
+or operates on menu data structures, so you should write it so it
+can safely be called at any time."
+  (let ((namevar (make-symbol "name"))
+        (keyvar (make-symbol "key"))
+        (kmapvar (make-symbol "kmap"))
+        (kdescvar (make-symbol "kdesc"))
+        (bindingvar (make-symbol "binding")))
+    `(let* ((,namevar ,key-name)
+            (,keyvar ,(if (stringp key-name) (read-kbd-macro key-name)
+                        `(if (vectorp ,namevar) ,namevar
+                           (read-kbd-macro ,namevar))))
+            (,kmapvar (or (if (and ,keymap (symbolp ,keymap))
+                              (symbol-value ,keymap) ,keymap)
+                          global-map))
+            (,kdescvar (cons (if (stringp ,namevar) ,namevar
+                               (key-description ,namevar))
+                             (if (symbolp ,keymap) ,keymap (quote ,keymap))))
+            (,bindingvar (lookup-key ,kmapvar ,keyvar)))
+       (let ((entry (assoc ,kdescvar personal-keybindings))
+             (details (list ,command
+                            (unless (numberp ,bindingvar)
+                              ,bindingvar))))
+         (if entry
+             (setcdr entry details)
+           (add-to-list 'personal-keybindings (cons ,kdescvar details))))
+       ,(if predicate
+            `(define-key ,kmapvar ,keyvar
+               '(menu-item "" nil :filter (lambda (&optional _)
+                                            (when ,predicate
+                                              ,command))))
+          `(define-key ,kmapvar ,keyvar ,command)))))
+
+;;;###autoload
+(defmacro unbind-key (key-name &optional keymap)
+  "Unbind the given KEY-NAME, within the KEYMAP (if specified).
+See `bind-key' for more details."
+  (let ((namevar (make-symbol "name"))
+        (kdescvar (make-symbol "kdesc")))
+    `(let* ((,namevar ,key-name)
+            (,kdescvar (cons (if (stringp ,namevar) ,namevar
+                               (key-description ,namevar))
+                             (if (symbolp ,keymap) ,keymap (quote ,keymap)))))
+       (bind-key--remove (if (vectorp ,namevar) ,namevar
+                           (read-kbd-macro ,namevar))
+                         (or (if (and ,keymap (symbolp ,keymap))
+                                 (symbol-value ,keymap) ,keymap)
+                             global-map))
+       (setq personal-keybindings
+             (cl-delete-if (lambda (k) (equal (car k) ,kdescvar))
+                           personal-keybindings))
+       nil)))
+
+(defun bind-key--remove (key keymap)
+  "Remove KEY from KEYMAP.
+
+In contrast to `define-key', this function removes the binding from the 
keymap."
+  (define-key keymap key nil)
+  ;; Split M-key in ESC key
+  (setq key (cl-mapcan (lambda (k)
+                         (if (and (integerp k) (/= (logand k ?\M-\0) 0))
+                             (list ?\e (logxor k ?\M-\0))
+                           (list k)))
+                       key))
+  ;; Delete single keys directly
+  (if (= (length key) 1)
+      (delete key keymap)
+    ;; Lookup submap and delete key from there
+    (let* ((prefix (vconcat (butlast key)))
+           (submap (lookup-key keymap prefix)))
+      (unless (keymapp submap)
+        (error "Not a keymap for %s" key))
+      (when (symbolp submap)
+        (setq submap (symbol-function submap)))
+      (delete (last key) submap)
+      ;; Delete submap if it is empty
+      (when (= 1 (length submap))
+        (bind-key--remove prefix keymap)))))
+
+;;;###autoload
+(defmacro bind-key* (key-name command &optional predicate)
+  "Similar to `bind-key', but overrides any mode-specific bindings."
+  `(bind-key ,key-name ,command override-global-map ,predicate))
+
+(defun bind-keys-form (args keymap)
+  "Bind multiple keys at once.
+
+Accepts keyword arguments:
+:map MAP               - a keymap into which the keybindings should be
+                         added
+:prefix KEY            - prefix key for these bindings
+:prefix-map MAP        - name of the prefix map that should be created
+                         for these bindings
+:prefix-docstring STR  - docstring for the prefix-map variable
+:menu-name NAME        - optional menu string for prefix map
+:repeat-docstring STR  - docstring for the repeat-map variable
+:repeat-map MAP        - name of the repeat map that should be created
+                         for these bindings. If specified, the
+                         `repeat-map' property of each command bound
+                         (within the scope of the `:repeat-map' keyword)
+                         is set to this map.
+:exit BINDINGS         - Within the scope of `:repeat-map' will bind the
+                         key in the repeat map, but will not set the
+                         `repeat-map' property of the bound command.
+:continue BINDINGS     - Within the scope of `:repeat-map' forces the
+                         same behaviour as if no special keyword had
+                         been used (that is, the command is bound, and
+                         it's `repeat-map' property set)
+:filter FORM           - optional form to determine when bindings apply
+
+The rest of the arguments are conses of keybinding string and a
+function symbol (unquoted)."
+  (let (map
+        prefix-doc
+        prefix-map
+        prefix
+        repeat-map
+        repeat-doc
+        repeat-type ;; Only used internally
+        filter
+        menu-name
+        pkg)
+
+    ;; Process any initial keyword arguments
+    (let ((cont t)
+          (arg-change-func 'cddr))
+      (while (and cont args)
+        (if (cond ((and (eq :map (car args))
+                        (not prefix-map))
+                   (setq map (cadr args)))
+                  ((eq :prefix-docstring (car args))
+                   (setq prefix-doc (cadr args)))
+                  ((and (eq :prefix-map (car args))
+                        (not (memq map '(global-map
+                                         override-global-map))))
+                   (setq prefix-map (cadr args)))
+                  ((eq :repeat-docstring (car args))
+                   (setq repeat-doc (cadr args)))
+                  ((and (eq :repeat-map (car args))
+                        (not (memq map '(global-map
+                                         override-global-map))))
+                   (setq repeat-map (cadr args))
+                   (setq map repeat-map))
+                  ((eq :continue (car args))
+                   (setq repeat-type :continue
+                         arg-change-func 'cdr))
+                  ((eq :exit (car args))
+                   (setq repeat-type :exit
+                         arg-change-func 'cdr))
+                  ((eq :prefix (car args))
+                   (setq prefix (cadr args)))
+                  ((eq :filter (car args))
+                   (setq filter (cadr args)) t)
+                  ((eq :menu-name (car args))
+                   (setq menu-name (cadr args)))
+                  ((eq :package (car args))
+                   (setq pkg (cadr args))))
+            (setq args (funcall arg-change-func args))
+          (setq cont nil))))
+
+    (when (or (and prefix-map (not prefix))
+              (and prefix (not prefix-map)))
+      (error "Both :prefix-map and :prefix must be supplied"))
+
+    (when repeat-type
+      (unless repeat-map
+        (error ":continue and :exit require specifying :repeat-map")))
+
+    (when (and menu-name (not prefix))
+      (error "If :menu-name is supplied, :prefix must be too"))
+
+    (unless map (setq map keymap))
+
+    ;; Process key binding arguments
+    (let (first next)
+      (while args
+        (if (keywordp (car args))
+            (progn
+              (setq next args)
+              (setq args nil))
+          (if first
+              (nconc first (list (car args)))
+            (setq first (list (car args))))
+          (setq args (cdr args))))
+
+      (cl-flet
+          ((wrap (map bindings)
+                 (if (and map pkg (not (memq map '(global-map
+                                                   override-global-map))))
+                     `((if (boundp ',map)
+                           ,(macroexp-progn bindings)
+                         (eval-after-load
+                             ,(if (symbolp pkg) `',pkg pkg)
+                           ',(macroexp-progn bindings))))
+                   bindings)))
+
+        (append
+         (when prefix-map
+           `((defvar ,prefix-map)
+             ,@(when prefix-doc `((put ',prefix-map 'variable-documentation 
,prefix-doc)))
+             ,@(if menu-name
+                   `((define-prefix-command ',prefix-map nil ,menu-name))
+                 `((define-prefix-command ',prefix-map)))
+             ,@(if (and map (not (eq map 'global-map)))
+                   (wrap map `((bind-key ,prefix ',prefix-map ,map ,filter)))
+                 `((bind-key ,prefix ',prefix-map nil ,filter)))))
+         (when repeat-map
+           `((defvar ,repeat-map (make-sparse-keymap)
+               ,@(when repeat-doc `(,repeat-doc)))))
+         (wrap map
+               (cl-mapcan
+                (lambda (form)
+                  (let ((fun (and (cdr form) (list 'function (cdr form)))))
+                    (if prefix-map
+                        `((bind-key ,(car form) ,fun ,prefix-map ,filter))
+                      (if (and map (not (eq map 'global-map)))
+                          ;; Only needed in this branch, since when
+                          ;; repeat-map is non-nil, map is always
+                          ;; non-nil
+                          `(,@(when (and repeat-map (not (eq repeat-type 
:exit)))
+                                `((put ,fun 'repeat-map ',repeat-map)))
+                            (bind-key ,(car form) ,fun ,map ,filter))
+                        `((bind-key ,(car form) ,fun nil ,filter))))))
+                first))
+         (when next
+           (bind-keys-form `(,@(when repeat-map `(:repeat-map ,repeat-map))
+                             ,@(if pkg
+                                   (cons :package (cons pkg next))
+                                 next)) map)))))))
+
+;;;###autoload
+(defmacro bind-keys (&rest args)
+  "Bind multiple keys at once.
+
+Accepts keyword arguments:
+:map MAP               - a keymap into which the keybindings should be
+                         added
+:prefix KEY            - prefix key for these bindings
+:prefix-map MAP        - name of the prefix map that should be created
+                         for these bindings
+:prefix-docstring STR  - docstring for the prefix-map variable
+:menu-name NAME        - optional menu string for prefix map
+:repeat-docstring STR  - docstring for the repeat-map variable
+:repeat-map MAP        - name of the repeat map that should be created
+                         for these bindings. If specified, the
+                         `repeat-map' property of each command bound
+                         (within the scope of the `:repeat-map' keyword)
+                         is set to this map.
+:exit BINDINGS         - Within the scope of `:repeat-map' will bind the
+                         key in the repeat map, but will not set the
+                         `repeat-map' property of the bound command.
+:continue BINDINGS     - Within the scope of `:repeat-map' forces the
+                         same behaviour as if no special keyword had
+                         been used (that is, the command is bound, and
+                         it's `repeat-map' property set)
+:filter FORM           - optional form to determine when bindings apply
+
+The rest of the arguments are conses of keybinding string and a
+function symbol (unquoted)."
+  (macroexp-progn (bind-keys-form args nil)))
+
+;;;###autoload
+(defmacro bind-keys* (&rest args)
+  "Bind multiple keys at once, in `override-global-map'.
+Accepts the same keyword arguments as `bind-keys' (which see).
+
+This binds keys in such a way that bindings are not overridden by
+other modes.  See `override-global-mode'."
+  (macroexp-progn (bind-keys-form args 'override-global-map)))
+
+(defun get-binding-description (elem)
+  (cond
+   ((listp elem)
+    (cond
+     ((memq (car elem) '(lambda function))
+      (if (and bind-key-describe-special-forms
+               (stringp (nth 2 elem)))
+          (nth 2 elem)
+        "#<lambda>"))
+     ((eq 'closure (car elem))
+      (if (and bind-key-describe-special-forms
+               (stringp (nth 3 elem)))
+          (nth 3 elem)
+        "#<closure>"))
+     ((eq 'keymap (car elem))
+      "#<keymap>")
+     (t
+      elem)))
+   ;; must be a symbol, non-symbol keymap case covered above
+   ((and bind-key-describe-special-forms (keymapp elem))
+    (let ((doc (get elem 'variable-documentation)))
+      (if (stringp doc) doc elem)))
+   ((symbolp elem)
+    elem)
+   (t
+    "#<byte-compiled lambda>")))
+
+(defun compare-keybindings (l r)
+  (let* ((regex bind-key-segregation-regexp)
+         (lgroup (and (string-match regex (caar l))
+                      (match-string 0 (caar l))))
+         (rgroup (and (string-match regex (caar r))
+                      (match-string 0 (caar r))))
+         (lkeymap (cdar l))
+         (rkeymap (cdar r)))
+    (cond
+     ((and (null lkeymap) rkeymap)
+      (cons t t))
+     ((and lkeymap (null rkeymap))
+      (cons nil t))
+     ((and lkeymap rkeymap
+           (not (string= (symbol-name lkeymap) (symbol-name rkeymap))))
+      (cons (string< (symbol-name lkeymap) (symbol-name rkeymap)) t))
+     ((and (null lgroup) rgroup)
+      (cons t t))
+     ((and lgroup (null rgroup))
+      (cons nil t))
+     ((and lgroup rgroup)
+      (if (string= lgroup rgroup)
+          (cons (string< (caar l) (caar r)) nil)
+        (cons (string< lgroup rgroup) t)))
+     (t
+      (cons (string< (caar l) (caar r)) nil)))))
+
+;;;###autoload
+(defun describe-personal-keybindings ()
+  "Display all the personal keybindings defined by `bind-key'."
+  (interactive)
+  (with-output-to-temp-buffer "*Personal Keybindings*"
+    (princ (format (concat "Key name%s Command%s Comments\n%s %s "
+                           "---------------------\n")
+                   (make-string (- (car bind-key-column-widths) 9) ? )
+                   (make-string (- (cdr bind-key-column-widths) 8) ? )
+                   (make-string (1- (car bind-key-column-widths)) ?-)
+                   (make-string (1- (cdr bind-key-column-widths)) ?-)))
+    (let (last-binding)
+      (dolist (binding
+               (setq personal-keybindings
+                     (sort personal-keybindings
+                           (lambda (l r)
+                             (car (compare-keybindings l r))))))
+
+        (if (not (eq (cdar last-binding) (cdar binding)))
+            (princ (format "\n\n%s: %s\n%s\n\n"
+                           (cdar binding) (caar binding)
+                           (make-string (+ 21 (car bind-key-column-widths)
+                                           (cdr bind-key-column-widths)) ?-)))
+          (if (and last-binding
+                   (cdr (compare-keybindings last-binding binding)))
+              (princ "\n")))
+
+        (let* ((key-name (caar binding))
+               (at-present (lookup-key (or (symbol-value (cdar binding))
+                                           (current-global-map))
+                                       (read-kbd-macro key-name)))
+               (command (nth 1 binding))
+               (was-command (nth 2 binding))
+               (command-desc (get-binding-description command))
+               (was-command-desc (and was-command
+                                      (get-binding-description was-command)))
+               (at-present-desc (get-binding-description at-present)))
+          (let ((line
+                 (format
+                  (format "%%-%ds%%-%ds%%s\n" (car bind-key-column-widths)
+                          (cdr bind-key-column-widths))
+                  key-name (format "`%s\'" command-desc)
+                  (if (string= command-desc at-present-desc)
+                      (if (or (null was-command)
+                              (string= command-desc was-command-desc))
+                          ""
+                        (format "was `%s\'" was-command-desc))
+                    (format "[now: `%s\']" at-present)))))
+            (princ (if (string-match "[ \t]+\n" line)
+                       (replace-match "\n" t t line)
+                     line))))
+
+        (setq last-binding binding)))))
+
+(provide 'bind-key)
+
+;; Local Variables:
+;; outline-regexp: ";;;\\(;* [^\s\t\n]\\|###autoload\\)\\|("
+;; End:
+
+;;; 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 @@
+;;; use-package-bind-key.el --- Support for the :bind/:bind-keymap keywords  
-*- lexical-binding: t; -*-
+
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+;; Author: John Wiegley <johnw@newartisans.com>
+;; Maintainer: John Wiegley <johnw@newartisans.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Provides support for the :bind, :bind*, :bind-keymap and :bind-keymap*
+;; keywords.  Note that these are currently still baked into
+;; `use-package-keywords' and `use-package-deferring-keywords', although this
+;; is harmless if they are never used.
+
+;;; Code:
+
+(require 'use-package-core)
+(require 'bind-key)
+
+;;;###autoload
+(defun use-package-autoload-keymap (keymap-symbol package override)
+  "Loads PACKAGE and then binds the key sequence used to invoke
+this function to KEYMAP-SYMBOL. It then simulates pressing the
+same key sequence a again, so that the next key pressed is routed
+to the newly loaded keymap.
+
+This function supports use-package's :bind-keymap keyword. It
+works by binding the given key sequence to an invocation of this
+function for a particular keymap. The keymap is expected to be
+defined by the package. In this way, loading the package is
+deferred until the prefix key sequence is pressed."
+  (if (not (require package nil t))
+      (use-package-error (format "Cannot load package.el: %s" package))
+    (if (and (boundp keymap-symbol)
+             (keymapp (symbol-value keymap-symbol)))
+        (let* ((kv (this-command-keys-vector))
+               (key (key-description kv))
+               (keymap (symbol-value keymap-symbol)))
+          (if override
+              (bind-key* key keymap)
+            (bind-key key keymap))
+          (setq unread-command-events
+                (mapcar (lambda (ev) (cons t ev))
+                        (listify-key-sequence kv))))
+      (use-package-error
+       (format "package.el %s failed to define keymap %s"
+               package keymap-symbol)))))
+
+;;;###autoload
+(defun use-package-normalize-binder (name keyword args)
+  (let ((arg args)
+        args*)
+    (while arg
+      (let ((x (car arg)))
+        (cond
+         ;; (KEY . COMMAND)
+         ((and (consp x)
+               (or (stringp (car x))
+                   (vectorp (car x)))
+               (or (use-package-recognize-function (cdr x) t #'stringp)))
+          (setq args* (nconc args* (list x)))
+          (setq arg (cdr arg)))
+         ;; KEYWORD
+         ;;   :map KEYMAP
+         ;;   :prefix-docstring STRING
+         ;;   :prefix-map SYMBOL
+         ;;   :prefix STRING
+        ;;   :repeat-docstring STRING
+         ;;   :repeat-map SYMBOL
+         ;;   :filter SEXP
+         ;;   :menu-name STRING
+         ;;   :package SYMBOL
+        ;;   :continue and :exit are used within :repeat-map
+         ((or (and (eq x :map) (symbolp (cadr arg)))
+              (and (eq x :prefix) (stringp (cadr arg)))
+              (and (eq x :prefix-map) (symbolp (cadr arg)))
+              (and (eq x :prefix-docstring) (stringp (cadr arg)))
+             (and (eq x :repeat-map) (symbolp (cadr arg)))
+             (eq x :continue)
+             (eq x :exit)
+              (and (eq x :repeat-docstring) (stringp (cadr arg)))
+              (eq x :filter)
+              (and (eq x :menu-name) (stringp (cadr arg)))
+              (and (eq x :package) (symbolp (cadr arg))))
+          (setq args* (nconc args* (list x (cadr arg))))
+          (setq arg (cddr arg)))
+         ((listp x)
+          (setq args*
+                (nconc args* (use-package-normalize-binder name keyword x)))
+          (setq arg (cdr arg)))
+         (t
+          ;; Error!
+          (use-package-error
+           (concat (symbol-name name)
+                   " wants arguments acceptable to the `bind-keys' macro,"
+                   " or a list of such values"))))))
+    args*))
+
+;;;; :bind, :bind*
+
+;;;###autoload
+(defalias 'use-package-normalize/:bind 'use-package-normalize-binder)
+;;;###autoload
+(defalias 'use-package-normalize/:bind* 'use-package-normalize-binder)
+
+;; jww (2017-12-07): This is too simplistic. It will fail to determine
+;; autoloads in this situation:
+;;   (use-package foo
+;;     :bind (:map foo-map (("C-a" . func))))
+;;;###autoload
+(defalias 'use-package-autoloads/:bind 'use-package-autoloads-mode)
+;;;###autoload
+(defalias 'use-package-autoloads/:bind* 'use-package-autoloads-mode)
+
+;;;###autoload
+(defun use-package-handler/:bind
+    (name _keyword args rest state &optional bind-macro)
+  (use-package-concat
+   (use-package-process-keywords name rest state)
+   `(,@(mapcar
+        #'(lambda (xs)
+            `(,(if bind-macro bind-macro 'bind-keys)
+              :package ,name ,@(use-package-normalize-commands xs)))
+        (use-package-split-list-at-keys :break args)))))
+
+(defun use-package-handler/:bind* (name keyword arg rest state)
+  (use-package-handler/:bind name keyword arg rest state 'bind-keys*))
+
+;;;; :bind-keymap, :bind-keymap*
+
+;;;###autoload
+(defalias 'use-package-normalize/:bind-keymap 'use-package-normalize-binder)
+;;;###autoload
+(defalias 'use-package-normalize/:bind-keymap* 'use-package-normalize-binder)
+
+;;;###autoload
+(defun use-package-handler/:bind-keymap
+    (name _keyword args rest state &optional override)
+  (use-package-concat
+   (use-package-process-keywords name rest state)
+   (mapcar
+    #'(lambda (binding)
+        `(,(if override 'bind-key* 'bind-key)
+          ,(car binding)
+          #'(lambda ()
+              (interactive)
+              (use-package-autoload-keymap
+               ',(cdr binding) ',(use-package-as-symbol name)
+               ,override))))
+    args)))
+
+;;;###autoload
+(defun use-package-handler/:bind-keymap* (name keyword arg rest state)
+  (use-package-handler/:bind-keymap name keyword arg rest state t))
+
+(provide 'use-package-bind-key)
+
+;;; use-package-bind-key.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..5ebe6576190
--- /dev/null
+++ b/lisp/use-package/use-package-core.el
@@ -0,0 +1,1692 @@
+;;; use-package-core.el --- A configuration macro for simplifying your .emacs  
-*- lexical-binding: t; -*-
+
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+;; Author: John Wiegley <johnw@newartisans.com>
+;; Maintainer: John Wiegley <johnw@newartisans.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The `use-package' declaration macro allows you to isolate package
+;; configuration in your ".emacs" in a way that is performance-oriented and,
+;; well, just tidy.  I created it because I have over 80 packages that I use
+;; in Emacs, and things were getting difficult to manage.  Yet with this
+;; utility my total load time is just under 1 second, with no loss of
+;; functionality!
+;;
+;; Please see README.md from the same repository for documentation.
+
+;;; Code:
+
+(require 'bytecomp)
+(require 'cl-lib)
+(require 'tabulated-list)
+
+(eval-and-compile
+  ;; Declare a synthetic theme for :custom variables.
+  ;; Necessary in order to avoid having those variables saved by custom.el.
+  (deftheme use-package))
+
+(enable-theme 'use-package)
+;; Remove the synthetic use-package theme from the enabled themes, so
+;; iterating over them to "disable all themes" won't disable it.
+(setq custom-enabled-themes (remq 'use-package custom-enabled-themes))
+
+(eval-when-compile
+  (if (and (eq emacs-major-version 24) (eq emacs-minor-version 3))
+      (progn
+        (defsubst hash-table-keys (hash-table)
+          "Return a list of keys in HASH-TABLE."
+          (cl-loop for k being the hash-keys of hash-table collect k))
+        (defsubst string-suffix-p (suffix string  &optional ignore-case)
+          (let ((start-pos (- (length string) (length suffix))))
+            (and (>= start-pos 0)
+                 (eq t (compare-strings suffix nil nil
+                                        string start-pos nil ignore-case))))))
+    (require 'subr-x)))
+
+(eval-when-compile
+  (require 'regexp-opt))
+
+(defgroup use-package nil
+  "A `use-package' declaration for simplifying your `.emacs'."
+  :group 'initialization
+  :link '(custom-manual "(use-package) Top")
+  :version "29.1")
+
+(defconst use-package-version "2.4.4"
+  "This version of `use-package'.")
+
+(defcustom use-package-keywords
+  '(:disabled
+    :load-path
+    :requires
+    :defines
+    :functions
+    :preface
+    :if :when :unless
+    :no-require
+    :catch
+    :after
+    :custom
+    :custom-face
+    :bind
+    :bind*
+    :bind-keymap
+    :bind-keymap*
+    :interpreter
+    :mode
+    :magic
+    :magic-fallback
+    :hook
+    ;; Any other keyword that also declares commands to be autoloaded (such as
+    ;; :bind) must appear before this keyword.
+    :commands
+    :autoload
+    :init
+    :defer
+    :demand
+    :load
+    ;; This must occur almost last; the only forms which should appear after
+    ;; are those that must happen directly after the config forms.
+    :config)
+  "The set of valid keywords, in the order they are processed in.
+The order of this list is *very important*, so it is only
+advisable to insert new keywords, never to delete or reorder
+them.  Further, attention should be paid to the NEWS.md if the
+default order ever changes, as they may have subtle effects on
+the semantics of `use-package' declarations and may necessitate
+changing where you had inserted a new keyword earlier.
+
+Note that `:disabled' is special in this list, as it causes
+nothing at all to happen, even if the rest of the `use-package'
+declaration is incorrect."
+  :type '(repeat symbol)
+  :group 'use-package)
+
+(defcustom use-package-deferring-keywords
+  '(:bind-keymap
+    :bind-keymap*
+    :commands
+    :autoload)
+  "Unless `:demand' is used, keywords in this list imply deferred loading.
+The reason keywords like `:hook' are not in this list is that
+they only imply deferred loading if they reference actual
+function symbols that can be autoloaded from the module; whereas
+the default keywords provided here always defer loading unless
+otherwise requested."
+  :type '(repeat symbol)
+  :group 'use-package)
+
+(defcustom use-package-ignore-unknown-keywords nil
+  "If non-nil, warn instead of signaling error for unknown keywords.
+The unknown keyword and its associated arguments will be ignored
+in the `use-package' expansion."
+  :type 'boolean
+  :group 'use-package)
+
+(defcustom use-package-use-theme t
+  "If non-nil, use a custom theme to avoid saving :custom
+variables twice (once in the Custom file, once in the use-package
+call)."
+  :type 'boolean
+  :group 'use-package)
+
+(defcustom use-package-verbose nil
+  "Whether to report about loading and configuration details.
+If you customize this, then you should require the `use-package'
+feature in files that use `use-package', even if these files only
+contain compiled expansions of the macros.  If you don't do so,
+then the expanded macros do their job silently."
+  :type '(choice (const :tag "Quiet, without catching errors" errors)
+                 (const :tag "Quiet" nil)
+                 (const :tag "Verbose" t)
+                 (const :tag "Debug" debug))
+  :group 'use-package)
+
+(defcustom use-package-check-before-init nil
+  "If non-nil, check that package exists before executing its `:init' block.
+This check is performed by calling `locate-library'."
+  :type 'boolean
+  :group 'use-package)
+
+(defcustom use-package-always-defer nil
+  "If non-nil, assume `:defer t' unless `:demand' is used.
+See also `use-package-defaults', which uses this value."
+  :type 'boolean
+  :group 'use-package)
+
+(defcustom use-package-always-demand nil
+  "If non-nil, assume `:demand t' unless `:defer' is used.
+See also `use-package-defaults', which uses this value."
+  :type 'boolean
+  :group 'use-package)
+
+(defcustom use-package-defaults
+  '(;; this '(t) has special meaning; see `use-package-handler/:config'
+    (:config '(t) t)
+    (:init nil t)
+    (:catch t (lambda (name args)
+                (not use-package-expand-minimally)))
+    (:defer use-package-always-defer
+            (lambda (name args)
+              (and use-package-always-defer
+                   (not (plist-member args :defer))
+                   (not (plist-member args :demand)))))
+    (:demand use-package-always-demand
+             (lambda (name args)
+               (and use-package-always-demand
+                    (not (plist-member args :defer))
+                    (not (plist-member args :demand))))))
+  "Default values for specified `use-package' keywords.
+Each entry in the alist is a list of three elements:
+The first element is the `use-package' keyword.
+
+The second is a form that can be evaluated to get the default
+value.  It can also be a function that will receive the name of
+the `use-package' declaration and the keyword plist given to
+`use-package', in normalized form.  The value it returns should
+also be in normalized form (which is sometimes *not* what one
+would normally write in a `use-package' declaration, so use
+caution).
+
+The third element is a form that can be evaluated to determine
+whether or not to assign a default value; if it evaluates to nil,
+then the default value is not assigned even if the keyword is not
+present in the `use-package' form.  This third element may also be
+a function, in which case it receives the name of the package (as
+a symbol) and a list of keywords (in normalized form).  It should
+return nil or non-nil depending on whether defaulting should be
+attempted."
+  :type `(repeat
+          (list (choice :tag "Keyword"
+                        ,@(mapcar #'(lambda (k) (list 'const k))
+                                  use-package-keywords))
+                (choice :tag "Default value" sexp function)
+                (choice :tag "Enable if non-nil" sexp function)))
+  :group 'use-package)
+
+(defcustom use-package-merge-key-alist
+  '((:if    . (lambda (new old) `(and ,new ,old)))
+    (:after . (lambda (new old) `(:all ,new ,old)))
+    (:defer . (lambda (new old) old))
+    (:bind  . (lambda (new old) (append new (list :break) old))))
+  "Alist of keys and the functions used to merge multiple values.
+For example, if the following form is provided:
+
+  (use-package foo :if pred1 :if pred2)
+
+Then based on the above defaults, the merged result will be:
+
+  (use-package foo :if (and pred1 pred2))
+
+This is done so that, at the stage of invoking handlers, each
+handler is called only once."
+  :type `(repeat
+          (cons (choice :tag "Keyword"
+                        ,@(mapcar #'(lambda (k) (list 'const k))
+                                  use-package-keywords)
+                        (const :tag "Any" t))
+                function))
+  :group 'use-package)
+
+(defcustom use-package-hook-name-suffix "-hook"
+  "Text append to the name of hooks mentioned by :hook.
+Set to nil if you don't want this to happen; it's only a
+convenience."
+  :type '(choice string (const :tag "No suffix" nil))
+  :group 'use-package)
+
+(defcustom use-package-minimum-reported-time 0.1
+  "Minimal load time that will be reported.
+Note that `use-package-verbose' has to be set to a non-nil value
+for anything to be reported at all."
+  :type 'number
+  :group 'use-package)
+
+(defcustom use-package-inject-hooks nil
+  "If non-nil, add hooks to the `:init' and `:config' sections.
+In particular, for a given package `foo', the following hooks
+become available:
+
+  `use-package--foo--pre-init-hook'
+  `use-package--foo--post-init-hook'
+  `use-package--foo--pre-config-hook'
+  `use-package--foo--post-config-hook'
+
+This way, you can add to these hooks before evaluation of a
+`use-package` declaration, and exercise some control over what
+happens.
+
+NOTE: These hooks are run even if the user does not specify an
+`:init' or `:config' block, and they will happen at the regular
+time when initialization and configuration would have been
+performed.
+
+NOTE: If the `pre-init' hook return a nil value, that block's
+user-supplied configuration is not evaluated, so be certain to
+return t if you only wish to add behavior to what the user had
+specified."
+  :type 'boolean
+  :group 'use-package)
+
+(defcustom use-package-expand-minimally nil
+  "If non-nil, make the expanded code as minimal as possible.
+This disables:
+
+  - Printing to the *Messages* buffer of slowly-evaluating forms
+  - Capturing of load errors (normally redisplayed as warnings)
+  - Conditional loading of packages (load failures become errors)
+
+The main advantage to this variable is that, if you know your
+configuration works, it will make the byte-compiled file as
+minimal as possible.  It can also help with reading macro-expanded
+definitions, to understand the main intent of what's happening."
+  :type 'boolean
+  :group 'use-package)
+
+(defcustom use-package-form-regexp-eval
+  `(concat ,(eval-when-compile
+              (concat "^\\s-*("
+                      (regexp-opt '("use-package" "require") t)
+                      "\\s-+\\("))
+           (or (bound-and-true-p lisp-mode-symbol-regexp)
+               "\\(?:\\sw\\|\\s_\\|\\\\.\\)+") "\\)")
+  "Sexp providing regexp for finding `use-package' forms in user files.
+This is used by `use-package-jump-to-package-form' and
+`use-package-enable-imenu-support'."
+  :type 'sexp
+  :group 'use-package)
+
+(defcustom use-package-enable-imenu-support nil
+  "If non-nil, cause imenu to see `use-package' declarations.
+This is done by adjusting `lisp-imenu-generic-expression' to
+include support for finding `use-package' and `require' forms.
+
+Must be set before loading `use-package'."
+  :type 'boolean
+  :set
+  #'(lambda (sym value)
+      (eval-after-load 'lisp-mode
+        (if value
+            `(add-to-list 'lisp-imenu-generic-expression
+                          (list "Packages" ,use-package-form-regexp-eval 2))
+          `(setq lisp-imenu-generic-expression
+                 (remove (list "Packages" ,use-package-form-regexp-eval 2)
+                         lisp-imenu-generic-expression))))
+      (set-default sym value))
+  :group 'use-package)
+
+(defconst use-package-font-lock-keywords
+  '(("(\\(use-package\\)\\_>[ \t']*\\(\\(?:\\sw\\|\\s_\\)+\\)?"
+     (1 font-lock-keyword-face)
+     (2 font-lock-constant-face nil t))))
+
+(font-lock-add-keywords 'emacs-lisp-mode use-package-font-lock-keywords)
+
+(defcustom use-package-compute-statistics nil
+  "If non-nil, compute statistics concerned `use-package' declarations.
+View the statistical report using `use-package-report'.  Note that
+if this option is enabled, you must require `use-package' in your
+user init file at loadup time, or you will see errors concerning
+undefined variables."
+  :type 'boolean
+  :group 'use-package)
+
+(defvar use-package-statistics (make-hash-table))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Utility functions
+;;
+
+(defsubst use-package-error (msg)
+  "Report MSG as an error, so the user knows it came from this package."
+  (error "use-package: %s" msg))
+
+(defsubst use-package-concat (&rest elems)
+  "Delete all empty lists from ELEMS (nil or (list nil)), and append them."
+  (apply #'append (delete nil (delete (list nil) elems))))
+
+(defsubst use-package-non-nil-symbolp (sym)
+  (and sym (symbolp sym)))
+
+(defsubst use-package-as-symbol (string-or-symbol)
+  "If STRING-OR-SYMBOL is already a symbol, return it.
+Otherwise convert it to a symbol and return that."
+  (if (symbolp string-or-symbol) string-or-symbol
+    (intern string-or-symbol)))
+
+(defsubst use-package-as-string (string-or-symbol)
+  "If STRING-OR-SYMBOL is already a string, return it.
+Otherwise convert it to a string and return that."
+  (if (stringp string-or-symbol) string-or-symbol
+    (symbol-name string-or-symbol)))
+
+(defsubst use-package-regex-p (re)
+  "Return t if RE is some regexp-like thing."
+  (or (and (listp re) (eq (car re) 'rx))
+      (stringp re)))
+
+(defun use-package-normalize-regex (re)
+  "Given some regexp-like thing in RE, resolve to a regular expression."
+  (cond
+   ((and (listp re) (eq (car re) 'rx)) (eval re))
+   ((stringp re) re)
+   (t (error "Not recognized as regular expression: %s" re))))
+
+(defsubst use-package-is-pair (x car-pred cdr-pred)
+  "Return non-nil if X is a cons satisfying the given predicates.
+CAR-PRED and CDR-PRED are applied to X's `car' and `cdr',
+respectively."
+  (and (consp x)
+       (funcall car-pred (car x))
+       (funcall cdr-pred (cdr x))))
+
+(defun use-package-as-mode (string-or-symbol)
+  "If STRING-OR-SYMBOL ends in `-mode' (or its name does), return
+it as a symbol.  Otherwise, return it as a symbol with `-mode'
+appended."
+  (let ((string (use-package-as-string string-or-symbol)))
+    (intern (if (string-match "-mode\\'" string)
+                string
+              (concat string "-mode")))))
+
+(defsubst use-package-load-name (name &optional noerror)
+  "Return a form which will load or require NAME.
+It does the right thing no matter if NAME is a string or symbol.
+Argument NOERROR means to indicate load failures as a warning."
+  (if (stringp name)
+      `(load ,name ,noerror)
+    `(require ',name nil ,noerror)))
+
+(defun use-package-hook-injector (name-string keyword body)
+  "Wrap pre/post hook injections around the given BODY for KEYWORD.
+The BODY is a list of forms, so `((foo))' if only `foo' is being called."
+  (if (not use-package-inject-hooks)
+      body
+    (let ((keyword-name (substring (format "%s" keyword) 1)))
+      `((when (run-hook-with-args-until-failure
+               ',(intern (concat "use-package--" name-string
+                                 "--pre-" keyword-name "-hook")))
+          ,@body
+          (run-hooks
+           ',(intern (concat "use-package--" name-string
+                             "--post-" keyword-name "-hook"))))))))
+
+(defun use-package-with-elapsed-timer (text body)
+  "BODY is a list of forms, so `((foo))' if only `foo' is being called."
+  (declare (indent 1))
+  (if use-package-expand-minimally
+      body
+    (let ((nowvar (make-symbol "now")))
+      (if (bound-and-true-p use-package-verbose)
+          `((let ((,nowvar (current-time)))
+              (message "%s..." ,text)
+              (prog1
+                  ,(macroexp-progn body)
+                (let ((elapsed
+                       (float-time (time-subtract (current-time) ,nowvar))))
+                  (if (> elapsed ,use-package-minimum-reported-time)
+                      (message "%s...done (%.3fs)" ,text elapsed)
+                    (message "%s...done" ,text))))))
+        body))))
+
+(put 'use-package-with-elapsed-timer 'lisp-indent-function 1)
+
+(defun use-package-require (name &optional no-require body)
+  (if use-package-expand-minimally
+      (use-package-concat
+       (unless no-require
+         (list (use-package-load-name name)))
+       body)
+    (if no-require
+        body
+      (use-package-with-elapsed-timer
+          (format "Loading package %s" name)
+        `((if (not ,(use-package-load-name name t))
+              (display-warning 'use-package
+                               (format "Cannot load %s" ',name)
+                               :error)
+            ,@body))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Property lists
+;;
+
+(defun use-package-plist-delete (plist property)
+  "Delete PROPERTY from PLIST.
+This is in contrast to merely setting it to 0."
+  (let (p)
+    (while plist
+      (if (not (eq property (car plist)))
+          (setq p (plist-put p (car plist) (nth 1 plist))))
+      (setq plist (cddr plist)))
+    p))
+
+(defun use-package-plist-delete-first (plist property)
+  "Delete PROPERTY from PLIST.
+This is in contrast to merely setting it to 0."
+  (let (p)
+    (while plist
+      (if (eq property (car plist))
+          (setq p (nconc p (cddr plist))
+                plist nil)
+        (setq p (nconc p (list (car plist) (cadr plist)))
+              plist (cddr plist))))
+    p))
+
+(defsubst use-package-plist-maybe-put (plist property value)
+  "Add a VALUE for PROPERTY to PLIST, if it does not already exist."
+  (if (plist-member plist property)
+      plist
+    (plist-put plist property value)))
+
+(defsubst use-package-plist-cons (plist property value)
+  "Cons VALUE onto the head of the list at PROPERTY in PLIST."
+  (plist-put plist property (cons value (plist-get plist property))))
+
+(defsubst use-package-plist-append (plist property value)
+  "Append VALUE onto the front of the list at PROPERTY in PLIST."
+  (plist-put plist property (append value (plist-get plist property))))
+
+(defun use-package-split-list (pred xs)
+  (let ((ys (list nil)) (zs (list nil)) flip)
+    (cl-dolist (x xs)
+      (if flip
+          (nconc zs (list x))
+        (if (funcall pred x)
+            (progn
+              (setq flip t)
+              (nconc zs (list x)))
+          (nconc ys (list x)))))
+    (cons (cdr ys) (cdr zs))))
+
+(defun use-package-split-list-at-keys (key lst)
+  (and lst
+       (let ((xs (use-package-split-list (apply-partially #'eq key) lst)))
+         (cons (car xs) (use-package-split-list-at-keys key (cddr xs))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Keywords
+;;
+
+(defun use-package-keyword-index (keyword)
+  (cl-loop named outer
+           with index = 0
+           for k in use-package-keywords do
+           (if (eq k keyword)
+               (cl-return-from outer index))
+           (cl-incf index)))
+
+(defun use-package-normalize-plist (name input &optional plist merge-function)
+  "Given a pseudo-plist, normalize it to a regular plist.
+The normalized key/value pairs from input are added to PLIST,
+extending any keys already present."
+  (if (null input)
+      plist
+    (let* ((keyword (car input))
+           (xs (use-package-split-list #'keywordp (cdr input)))
+           (args (car xs))
+           (tail (cdr xs))
+           (normalizer
+            (intern-soft (concat "use-package-normalize/"
+                                 (symbol-name keyword))))
+           (arg (and (functionp normalizer)
+                     (funcall normalizer name keyword args)))
+           (error-string (format "Unrecognized keyword: %s" keyword)))
+      (if (memq keyword use-package-keywords)
+          (progn
+            (setq plist (use-package-normalize-plist
+                         name tail plist merge-function))
+            (plist-put plist keyword
+                       (if (plist-member plist keyword)
+                           (funcall merge-function keyword arg
+                                    (plist-get plist keyword))
+                         arg)))
+        (if use-package-ignore-unknown-keywords
+            (progn
+              (display-warning 'use-package error-string)
+              (use-package-normalize-plist
+               name tail plist merge-function))
+          (use-package-error error-string))))))
+
+(defun use-package-unalias-keywords (_name args)
+  (setq args (cl-nsubstitute :if :when args))
+  (let (temp)
+    (while (setq temp (plist-get args :unless))
+      (setq args (use-package-plist-delete-first args :unless)
+            args (append args `(:if (not ,temp))))))
+  args)
+
+(defun use-package-merge-keys (key new old)
+  (let ((merger (assq key use-package-merge-key-alist)))
+    (if merger
+        (funcall (cdr merger) new old)
+      (append new old))))
+
+(defun use-package-sort-keywords (plist)
+  (let (plist-grouped)
+    (while plist
+      (push (cons (car plist) (cadr plist))
+            plist-grouped)
+      (setq plist (cddr plist)))
+    (let (result)
+      (cl-dolist
+          (x
+           (nreverse
+            (sort plist-grouped
+                  #'(lambda (l r) (< (use-package-keyword-index (car l))
+                                (use-package-keyword-index (car r)))))))
+        (setq result (cons (car x) (cons (cdr x) result))))
+      result)))
+
+(defun use-package-normalize-keywords (name args)
+  (let* ((name-symbol (if (stringp name) (intern name) name))
+         (name-string (symbol-name name-symbol)))
+
+    ;; The function `elisp--local-variables' inserts this unbound variable into
+    ;; macro forms to determine the locally bound variables for
+    ;; `elisp-completion-at-point'. It ends up throwing a lot of errors since 
it
+    ;; can occupy the position of a keyword (or look like a second argument to 
a
+    ;; keyword that takes one). Deleting it when it's at the top level should 
be
+    ;; harmless since there should be no locally bound variables to discover
+    ;; here anyway.
+    (setq args (delq 'elisp--witness--lisp args))
+
+    ;; Reduce the set of keywords down to its most fundamental expression.
+    (setq args (use-package-unalias-keywords name-symbol args))
+
+    ;; Normalize keyword values, coalescing multiple occurrences.
+    (setq args (use-package-normalize-plist name-symbol args nil
+                                            #'use-package-merge-keys))
+
+    ;; Add default values for keywords not specified, when applicable.
+    (cl-dolist (spec use-package-defaults)
+      (when (let ((func (nth 2 spec)))
+              (if (and func (functionp func))
+                  (funcall func name args)
+                (eval func)))
+        (setq args (use-package-plist-maybe-put
+                    args (nth 0 spec)
+                    (let ((func (nth 1 spec)))
+                      (if (and func (functionp func))
+                          (funcall func name args)
+                        (eval func)))))))
+
+    ;; Determine any autoloads implied by the keywords used.
+    (let ((iargs args)
+          commands)
+      (while iargs
+        (when (keywordp (car iargs))
+          (let ((autoloads
+                 (intern-soft (concat "use-package-autoloads/"
+                                      (symbol-name (car iargs))))))
+            (when (functionp autoloads)
+              (setq commands
+                    ;; jww (2017-12-07): Right now we just ignored the type of
+                    ;; the autoload being requested, and assume they are all
+                    ;; `command'.
+                    (append (mapcar
+                             #'car
+                             (funcall autoloads name-symbol (car iargs)
+                                      (cadr iargs)))
+                            commands)))))
+        (setq iargs (cddr iargs)))
+      (when commands
+        (setq args
+              ;; Like `use-package-plist-append', but removing duplicates.
+              (plist-put args :commands
+                         (delete-dups
+                          (append commands (plist-get args :commands)))))))
+
+    ;; If byte-compiling, pre-load the package so all its symbols are in
+    ;; scope. This is done by prepending statements to the :preface.
+    (when (bound-and-true-p byte-compile-current-file)
+      (setq args
+            (use-package-plist-append
+             args :preface
+             (use-package-concat
+              (mapcar #'(lambda (var) `(defvar ,var))
+                      (plist-get args :defines))
+              (mapcar #'(lambda (fn) `(declare-function ,fn ,name-string))
+                      (plist-get args :functions))
+              `((eval-when-compile
+                  (with-demoted-errors
+                      ,(format "Cannot load %s: %%S" name-string)
+                    ,(when (eq use-package-verbose 'debug)
+                       `(message ,(format "Compiling package %s" name-string)))
+                    ,(unless (plist-get args :no-require)
+                       `(unless (featurep ',name-symbol)
+                          (load ,name-string nil t))))))))))
+
+    ;; Certain keywords imply :defer, if :demand was not specified.
+    (when (and (not (plist-member args :demand))
+               (not (plist-member args :defer))
+               (not (or (equal '(t) (plist-get args :load))
+                        (equal (list (use-package-as-string name))
+                               (mapcar #'use-package-as-string
+                                       (plist-get args :load)))))
+               (cl-some #'identity
+                        (mapcar (apply-partially #'plist-member args)
+                                use-package-deferring-keywords)))
+      (setq args (append args '(:defer t))))
+
+    ;; The :load keyword overrides :no-require
+    (when (and (plist-member args :load)
+               (plist-member args :no-require))
+      (setq args (use-package-plist-delete args :no-require)))
+
+    ;; If at this point no :load, :defer or :no-require has been seen, then
+    ;; :load the package itself.
+    (when (and (not (plist-member args :load))
+               (not (plist-member args :defer))
+               (not (plist-member args :no-require)))
+      (setq args (append args `(:load (,name)))))
+
+    ;; Sort the list of keywords based on the order of `use-package-keywords'.
+    (use-package-sort-keywords args)))
+
+(defun use-package-process-keywords (name plist &optional state)
+  "Process the next keyword in the free-form property list PLIST.
+The values in the PLIST have each been normalized by the function
+use-package-normalize/KEYWORD (minus the colon).
+
+STATE is a property list that the function may modify and/or
+query.  This is useful if a package defines multiple keywords and
+wishes them to have some kind of stateful interaction.
+
+Unless the KEYWORD being processed intends to ignore remaining
+keywords, it must call this function recursively, passing in the
+plist with its keyword and argument removed, and passing in the
+next value for the STATE."
+  (declare (indent 1))
+  (unless (null plist)
+    (let* ((keyword (car plist))
+           (arg (cadr plist))
+           (rest (cddr plist)))
+      (unless (keywordp keyword)
+        (use-package-error (format "%s is not a keyword" keyword)))
+      (let* ((handler (concat "use-package-handler/" (symbol-name keyword)))
+             (handler-sym (intern handler)))
+        (if (functionp handler-sym)
+            (funcall handler-sym name keyword arg rest state)
+          (use-package-error
+           (format "Keyword handler not defined: %s" handler)))))))
+
+(put 'use-package-process-keywords 'lisp-indent-function 'defun)
+
+(defun use-package-list-insert (elem xs &optional anchor after test)
+  "Insert ELEM into the list XS.
+If ANCHOR is also a keyword, place the new KEYWORD before that
+one.
+If AFTER is non-nil, insert KEYWORD either at the end of the
+keywords list, or after the ANCHOR if one has been provided.
+If TEST is non-nil, it is the test used to compare ELEM to list
+elements.  The default is `eq'.
+The modified list is returned.  The original list is not modified."
+  (let (result)
+    (dolist (k xs)
+      (if (funcall (or test #'eq) k anchor)
+          (if after
+              (setq result (cons k result)
+                    result (cons elem result))
+            (setq result (cons elem result)
+                  result (cons k result)))
+        (setq result (cons k result))))
+    (if anchor
+        (nreverse result)
+      (if after
+          (nreverse (cons elem result))
+        (cons elem (nreverse result))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Argument Processing
+;;
+
+(defun use-package-only-one (label args f)
+  "Call F on the first member of ARGS if it has exactly one element."
+  (declare (indent 1))
+  (cond
+   ((and (listp args) (listp (cdr args))
+         (= (length args) 1))
+    (funcall f label (car args)))
+   (t
+    (use-package-error
+     (concat label " wants exactly one argument")))))
+
+(put 'use-package-only-one 'lisp-indent-function 'defun)
+
+(defun use-package-as-one (label args f &optional allow-empty)
+  "Call F on the first element of ARGS if it has one element, or all of ARGS.
+If ALLOW-EMPTY is non-nil, it's OK for ARGS to be an empty list."
+  (declare (indent 1))
+  (if (if args
+          (and (listp args) (listp (cdr args)))
+        allow-empty)
+      (if (= (length args) 1)
+          (funcall f label (car args))
+        (funcall f label args))
+    (use-package-error
+     (concat label " wants a non-empty list"))))
+
+(put 'use-package-as-one 'lisp-indent-function 'defun)
+
+(defun use-package-memoize (f arg)
+  "Ensure the macro-expansion of F applied to ARG evaluates ARG
+no more than once."
+  (let ((loaded (cl-gentemp "use-package--loaded"))
+        (result (cl-gentemp "use-package--result"))
+        (next   (cl-gentemp "use-package--next")))
+    `((defvar ,loaded nil)
+      (defvar ,result nil)
+      (defvar ,next #'(lambda () (if ,loaded ,result
+                              (setq ,loaded t ,result ,arg))))
+      ,@(funcall f `((funcall ,next))))))
+
+(defsubst use-package-normalize-value (_label arg)
+  "Normalize the Lisp value given by ARG.
+The argument LABEL is ignored."
+  (cond ((null arg) nil)
+        ((eq t arg) t)
+        ((use-package-non-nil-symbolp arg)
+         `(symbol-value ',arg))
+        ((functionp arg)
+         `(funcall #',arg))
+        (t arg)))
+
+(defun use-package-normalize-symbols (label arg &optional recursed)
+  "Normalize a list of symbols."
+  (cond
+   ((use-package-non-nil-symbolp arg)
+    (list arg))
+   ((and (not recursed) (listp arg) (listp (cdr arg)))
+    (mapcar #'(lambda (x) (car (use-package-normalize-symbols label x t))) 
arg))
+   (t
+    (use-package-error
+     (concat label " wants a symbol, or list of symbols")))))
+
+(defun use-package-normalize-symlist (_name keyword args)
+  (use-package-as-one (symbol-name keyword) args
+    #'use-package-normalize-symbols))
+
+(defun use-package-normalize-recursive-symbols (label arg)
+  "Normalize a list of symbols."
+  (cond
+   ((use-package-non-nil-symbolp arg)
+    arg)
+   ((and (listp arg) (listp (cdr arg)))
+    (mapcar #'(lambda (x) (use-package-normalize-recursive-symbols label x))
+            arg))
+   (t
+    (use-package-error
+     (concat label " wants a symbol, or nested list of symbols")))))
+
+(defun use-package-normalize-recursive-symlist (_name keyword args)
+  (use-package-as-one (symbol-name keyword) args
+    #'use-package-normalize-recursive-symbols))
+
+(defun use-package-normalize-paths (label arg &optional recursed)
+  "Normalize a list of filesystem paths."
+  (cond
+   ((and arg (or (use-package-non-nil-symbolp arg) (functionp arg)))
+    (let ((value (use-package-normalize-value label arg)))
+      (use-package-normalize-paths label (eval value))))
+   ((stringp arg)
+    (let ((path (if (file-name-absolute-p arg)
+                    arg
+                  (expand-file-name arg user-emacs-directory))))
+      (list path)))
+   ((and (not recursed) (listp arg) (listp (cdr arg)))
+    (mapcar #'(lambda (x)
+                (car (use-package-normalize-paths label x t))) arg))
+   (t
+    (use-package-error
+     (concat label " wants a directory path, or list of paths")))))
+
+(defun use-package-normalize-predicate (_name keyword args)
+  (if (null args)
+      t
+    (use-package-only-one (symbol-name keyword) args
+      #'use-package-normalize-value)))
+
+(defun use-package-normalize-form (label args)
+  "Given a list of forms, return it wrapped in `progn'."
+  (unless (listp (car args))
+    (use-package-error (concat label " wants a sexp or list of sexps")))
+  (mapcar #'(lambda (form)
+              (if (and (consp form)
+                       (memq (car form)
+                             '(use-package bind-key bind-key*
+                                unbind-key bind-keys bind-keys*)))
+                  (macroexpand form)
+                form)) args))
+
+(defun use-package-normalize-forms (_name keyword args)
+  (use-package-normalize-form (symbol-name keyword) args))
+
+(defun use-package-normalize-pairs
+    (key-pred val-pred name label arg &optional recursed)
+  "Normalize a list of pairs.
+KEY-PRED and VAL-PRED are predicates recognizing valid keys and
+values, respectively.
+If RECURSED is non-nil, recurse into sublists."
+  (cond
+   ((funcall key-pred arg)
+    (list (cons arg (use-package-as-symbol name))))
+   ((use-package-is-pair arg key-pred val-pred)
+    (list arg))
+   ((and (not recursed) (listp arg) (listp (cdr arg)))
+    (let (last-item)
+      (mapcar
+       #'(lambda (x)
+           (prog1
+               (let ((ret (use-package-normalize-pairs
+                           key-pred val-pred name label x t)))
+                 (if (and (listp ret)
+                          (not (keywordp last-item)))
+                     (car ret)
+                   ret))
+             (setq last-item x))) arg)))
+   (t arg)))
+
+(defun use-package-recognize-function (v &optional binding additional-pred)
+  "A predicate that recognizes functional constructions:
+  nil
+  sym
+  \\='sym
+  (quote sym)
+  #\\='sym
+  (function sym)
+  (lambda () ...)
+  \\='(lambda () ...)
+  (quote (lambda () ...))
+  #\\='(lambda () ...)
+  (function (lambda () ...))"
+  (or (if binding
+          (symbolp v)
+        (use-package-non-nil-symbolp v))
+      (and (listp v)
+           (memq (car v) '(quote function))
+           (use-package-non-nil-symbolp (cadr v)))
+      (if binding (commandp v) (functionp v))
+      (and additional-pred
+           (funcall additional-pred v))))
+
+(defun use-package-normalize-function (v)
+  "Reduce functional constructions to one of two normal forms:
+  sym
+  #\\='(lambda () ...)"
+  (cond ((symbolp v) v)
+        ((and (listp v)
+              (memq (car v) '(quote function))
+              (use-package-non-nil-symbolp (cadr v)))
+         (cadr v))
+        ((and (consp v)
+              (eq 'lambda (car v)))
+         v)
+        ((and (listp v)
+              (memq (car v) '(quote function))
+              (eq 'lambda (car (cadr v))))
+         (cadr v))
+        (t v)))
+
+(defun use-package-normalize-commands (args)
+  "Map over ARGS of the form ((_ . F) ...), normalizing functional F's."
+  (mapcar #'(lambda (x)
+              (if (consp x)
+                  (cons (car x) (use-package-normalize-function (cdr x)))
+                x))
+          args))
+
+(defun use-package-normalize-mode (name keyword args)
+  "Normalize arguments for keywords which add regexp/mode pairs to an alist."
+  (use-package-as-one (symbol-name keyword) args
+    (apply-partially #'use-package-normalize-pairs
+                     #'use-package-regex-p
+                     #'use-package-recognize-function
+                     name)))
+
+(defun use-package-autoloads-mode (_name _keyword args)
+  (mapcar
+   #'(lambda (x) (cons (cdr x) 'command))
+   (cl-remove-if-not #'(lambda (x)
+                         (and (consp x)
+                              (use-package-non-nil-symbolp (cdr x))))
+                     args)))
+
+(defun use-package-handle-mode (name alist args rest state)
+  "Handle keywords which add regexp/mode pairs to an alist."
+  (use-package-concat
+   (use-package-process-keywords name rest state)
+   (mapcar
+    #'(lambda (thing)
+        `(add-to-list
+          ',alist
+          ',(cons (use-package-normalize-regex (car thing))
+                  (cdr thing))))
+    (use-package-normalize-commands args))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Statistics
+;;
+
+(defun use-package-reset-statistics ()
+  "Reset statistics for `use-package'.
+See also `use-package-statistics'."
+  (interactive)
+  (setq use-package-statistics (make-hash-table)))
+
+(defun use-package-statistics-status (package)
+  "Return loading configuration status of PACKAGE statistics."
+  (cond ((gethash :config package)      "Configured")
+        ((gethash :init package)        "Initialized")
+        ((gethash :preface package)     "Prefaced")
+        ((gethash :use-package package) "Declared")))
+
+(defun use-package-statistics-last-event (package)
+  "Return the date when PACKAGE's status last changed.
+The date is returned as a string."
+  (or (gethash :config package)
+      (gethash :init package)
+      (gethash :preface package)
+      (gethash :use-package package)))
+
+(defun use-package-statistics-time (package)
+  "Return the time is took for PACKAGE to load."
+  (+ (float-time (gethash :config-secs package '(0 0 0 0)))
+     (float-time (gethash :init-secs package '(0 0 0 0)))
+     (float-time (gethash :preface-secs package '(0 0 0 0)))
+     (float-time (gethash :use-package-secs package '(0 0 0 0)))))
+
+(defun use-package-statistics-convert (package)
+  "Return information about PACKAGE.
+
+The information is formatted in a way suitable for
+`use-package-statistics-mode'."
+  (let ((statistics (gethash package use-package-statistics)))
+    (list
+     package
+     (vector
+      (symbol-name package)
+      (use-package-statistics-status statistics)
+      (format-time-string
+       "%H:%M:%S.%6N"
+       (use-package-statistics-last-event statistics))
+      (format "%.2f" (use-package-statistics-time statistics))))))
+
+(defun use-package-report ()
+  "Show current statistics gathered about `use-package' declarations.
+In the table that's generated, the status field has the following
+meaning:
+  Configured        :config has been processed (the package is loaded!)
+  Initialized       :init has been processed (load status unknown)
+  Prefaced          :preface has been processed
+  Declared          the use-package declaration was seen"
+  (interactive)
+  (with-current-buffer (get-buffer-create "*use-package statistics*")
+    (setq tabulated-list-entries
+          (mapcar #'use-package-statistics-convert
+                  (hash-table-keys use-package-statistics)))
+    (use-package-statistics-mode)
+    (tabulated-list-print)
+    (display-buffer (current-buffer))))
+
+(defvar use-package-statistics-status-order
+  '(("Declared"    . 0)
+    ("Prefaced"    . 1)
+    ("Initialized" . 2)
+    ("Configured"  . 3)))
+
+(define-derived-mode use-package-statistics-mode tabulated-list-mode
+  "use-package statistics"
+  "Show current statistics gathered about `use-package' declarations."
+  (setq tabulated-list-format
+        ;; The sum of column width is 80 characters:
+        [("Package" 25 t)
+         ("Status" 13
+          (lambda (a b)
+            (< (assoc-default
+                (use-package-statistics-status
+                 (gethash (car a) use-package-statistics))
+                use-package-statistics-status-order)
+               (assoc-default
+                (use-package-statistics-status
+                 (gethash (car b) use-package-statistics))
+                use-package-statistics-status-order))))
+         ("Last Event" 23
+          (lambda (a b)
+            (< (float-time
+                (use-package-statistics-last-event
+                 (gethash (car a) use-package-statistics)))
+               (float-time
+                (use-package-statistics-last-event
+                 (gethash (car b) use-package-statistics))))))
+         ("Time" 10
+          (lambda (a b)
+            (< (use-package-statistics-time
+                (gethash (car a) use-package-statistics))
+               (use-package-statistics-time
+                (gethash (car b) use-package-statistics)))))])
+  (setq tabulated-list-sort-key '("Time" . t))
+  (tabulated-list-init-header))
+
+(defun use-package-statistics-gather (keyword name after)
+  (let* ((hash (gethash name use-package-statistics
+                        (make-hash-table)))
+         (before (and after (gethash keyword hash (current-time)))))
+    (puthash keyword (current-time) hash)
+    (when after
+      (puthash (intern (concat (symbol-name keyword) "-secs"))
+               (time-subtract (current-time) before) hash))
+    (puthash name hash use-package-statistics)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Handlers
+;;
+
+;;;; :disabled
+
+;; Don't alias this to `ignore', as that will cause the resulting
+;; function to be interactive.
+(defun use-package-normalize/:disabled (_name _keyword _arg)
+  "Do nothing, return nil.")
+
+(defun use-package-handler/:disabled (name _keyword _arg rest state)
+  (use-package-process-keywords name rest state))
+
+;;;; :if, :when and :unless
+
+(defun use-package-normalize-test (_name keyword args)
+  (use-package-only-one (symbol-name keyword) args
+    #'use-package-normalize-value))
+
+(defalias 'use-package-normalize/:if 'use-package-normalize-test)
+
+(defun use-package-handler/:if (name _keyword pred rest state)
+  (let ((body (use-package-process-keywords name rest state)))
+    `((when ,pred ,@body))))
+
+(defalias 'use-package-normalize/:when 'use-package-normalize-test)
+
+(defalias 'use-package-handler/:when 'use-package-handler/:if)
+
+(defalias 'use-package-normalize/:unless 'use-package-normalize-test)
+
+(defun use-package-handler/:unless (name _keyword pred rest state)
+  (let ((body (use-package-process-keywords name rest state)))
+    `((unless ,pred ,@body))))
+
+;;;; :requires
+
+(defalias 'use-package-normalize/:requires 'use-package-normalize-symlist)
+
+(defun use-package-handler/:requires (name _keyword requires rest state)
+  (let ((body (use-package-process-keywords name rest state)))
+    (if (null requires)
+        body
+      `((when ,(if (> (length requires) 1)
+                   `(not (member nil (mapcar #'featurep ',requires)))
+                 `(featurep ',(car requires)))
+          ,@body)))))
+
+;;;; :load-path
+
+(defun use-package-normalize/:load-path (_name keyword args)
+  (use-package-as-one (symbol-name keyword) args
+    #'use-package-normalize-paths))
+
+(defun use-package-handler/:load-path (name _keyword arg rest state)
+  (let ((body (use-package-process-keywords name rest state)))
+    (use-package-concat
+     (mapcar #'(lambda (path)
+                 `(eval-and-compile (add-to-list 'load-path ,path)))
+             arg)
+     body)))
+
+;;;; :no-require
+
+(defalias 'use-package-normalize/:no-require 'use-package-normalize-predicate)
+
+(defun use-package-handler/:no-require (name _keyword _arg rest state)
+  (use-package-process-keywords name rest state))
+
+;;;; :defines
+
+(defalias 'use-package-normalize/:defines 'use-package-normalize-symlist)
+
+(defun use-package-handler/:defines (name _keyword _arg rest state)
+  (use-package-process-keywords name rest state))
+
+;;;; :functions
+
+(defalias 'use-package-normalize/:functions 'use-package-normalize-symlist)
+
+(defun use-package-handler/:functions (name _keyword _arg rest state)
+  (use-package-process-keywords name rest state))
+
+;;;; :preface
+
+(defalias 'use-package-normalize/:preface 'use-package-normalize-forms)
+
+(defun use-package-handler/:preface (name _keyword arg rest state)
+  (let ((body (use-package-process-keywords name rest state)))
+    (use-package-concat
+     (when use-package-compute-statistics
+       `((use-package-statistics-gather :preface ',name nil)))
+     (when arg
+       `((eval-and-compile ,@arg)))
+     body
+     (when use-package-compute-statistics
+       `((use-package-statistics-gather :preface ',name t))))))
+
+;;;; :catch
+
+(defvar use-package--form)
+(defvar use-package--hush-function #'(lambda (_keyword body) body))
+
+(defsubst use-package-hush (context keyword body)
+  `((condition-case-unless-debug err
+        ,(macroexp-progn body)
+      (error (funcall ,context ,keyword err)))))
+
+(defun use-package-normalize/:catch (_name keyword args)
+  (if (null args)
+      t
+    (use-package-only-one (symbol-name keyword) args
+      use-package--hush-function)))
+
+(defun use-package-handler/:catch (name keyword arg rest state)
+  (let* ((context (cl-gentemp "use-package--warning")))
+    (cond
+     ((not arg)
+      (use-package-process-keywords name rest state))
+     ((eq arg t)
+      `((defvar ,context
+          #'(lambda (keyword err)
+              (let ((msg (format "%s/%s: %s" ',name keyword
+                                 (error-message-string err))))
+                ,@(when (eq use-package-verbose 'debug)
+                    `((with-current-buffer
+                          (get-buffer-create "*use-package*")
+                        (goto-char (point-max))
+                        (insert "-----\n" msg ,use-package--form)
+                        (emacs-lisp-mode))
+                      (setq msg
+                            (concat msg
+                                    " (see the *use-package* buffer)"))))
+                (display-warning 'use-package msg :error))))
+        ,@(let ((use-package--hush-function
+                 (apply-partially #'use-package-hush context)))
+            (funcall use-package--hush-function keyword
+                     (use-package-process-keywords name rest state)))))
+     ((functionp arg)
+      `((defvar ,context ,arg)
+        ,@(let ((use-package--hush-function
+                 (apply-partially #'use-package-hush context)))
+            (funcall use-package--hush-function keyword
+                     (use-package-process-keywords name rest state)))))
+     (t
+      (use-package-error "The :catch keyword expects 't' or a function")))))
+
+;;;; :interpreter
+
+(defalias 'use-package-normalize/:interpreter 'use-package-normalize-mode)
+(defalias 'use-package-autoloads/:interpreter 'use-package-autoloads-mode)
+
+(defun use-package-handler/:interpreter (name _keyword arg rest state)
+  (use-package-handle-mode name 'interpreter-mode-alist arg rest state))
+
+;;;; :mode
+
+(defalias 'use-package-normalize/:mode 'use-package-normalize-mode)
+(defalias 'use-package-autoloads/:mode 'use-package-autoloads-mode)
+
+(defun use-package-handler/:mode (name _keyword arg rest state)
+  (use-package-handle-mode name 'auto-mode-alist arg rest state))
+
+;;;; :magic
+
+(defalias 'use-package-normalize/:magic 'use-package-normalize-mode)
+(defalias 'use-package-autoloads/:magic 'use-package-autoloads-mode)
+
+(defun use-package-handler/:magic (name _keyword arg rest state)
+  (use-package-handle-mode name 'magic-mode-alist arg rest state))
+
+;;;; :magic-fallback
+
+(defalias 'use-package-normalize/:magic-fallback 'use-package-normalize-mode)
+(defalias 'use-package-autoloads/:magic-fallback 'use-package-autoloads-mode)
+
+(defun use-package-handler/:magic-fallback (name _keyword arg rest state)
+  (use-package-handle-mode name 'magic-fallback-mode-alist arg rest state))
+
+;;;; :hook
+
+(defun use-package-normalize/:hook (name keyword args)
+  (use-package-as-one (symbol-name keyword) args
+    #'(lambda (label arg)
+        (unless (or (use-package-non-nil-symbolp arg) (consp arg))
+          (use-package-error
+           (concat label " a <symbol> or (<symbol or list of symbols> . 
<symbol or function>)"
+                   " or list of these")))
+        (use-package-normalize-pairs
+         #'(lambda (k)
+             (or (use-package-non-nil-symbolp k)
+                 (and k (let ((every t))
+                          (while (and every k)
+                            (if (and (consp k)
+                                     (use-package-non-nil-symbolp (car k)))
+                                (setq k (cdr k))
+                              (setq every nil)))
+                          every))))
+         #'use-package-recognize-function
+         (if (string-suffix-p "-mode" (symbol-name name))
+             name
+           (intern (concat (symbol-name name) "-mode")))
+         label arg))))
+
+(defalias 'use-package-autoloads/:hook 'use-package-autoloads-mode)
+
+(defun use-package-handler/:hook (name _keyword args rest state)
+  "Generate use-package custom keyword code."
+  (use-package-concat
+   (use-package-process-keywords name rest state)
+   (cl-mapcan
+    #'(lambda (def)
+        (let ((syms (car def))
+              (fun (cdr def)))
+          (when fun
+            (mapcar
+             #'(lambda (sym)
+                 `(add-hook
+                   (quote ,(intern
+                            (concat (symbol-name sym)
+                                    use-package-hook-name-suffix)))
+                   (function ,fun)))
+             (use-package-hook-handler-normalize-mode-symbols syms)))))
+    (use-package-normalize-commands args))))
+
+(defun use-package-hook-handler-normalize-mode-symbols (syms)
+  "Ensure that `SYMS' turns into a list of modes."
+  (if (use-package-non-nil-symbolp syms) (list syms) syms))
+
+;;;; :commands
+
+(defalias 'use-package-normalize/:commands 'use-package-normalize-symlist)
+
+(defun use-package-handler/:commands (name _keyword arg rest state)
+  (use-package-concat
+   ;; Since we deferring load, establish any necessary autoloads, and also
+   ;; keep the byte-compiler happy.
+   (let ((name-string (use-package-as-string name)))
+     (cl-mapcan
+      #'(lambda (command)
+          (when (symbolp command)
+            (append
+             (unless (plist-get state :demand)
+               `((unless (fboundp ',command)
+                   (autoload #',command ,name-string nil t))))
+             (when (bound-and-true-p byte-compile-current-file)
+               `((eval-when-compile
+                   (declare-function ,command ,name-string)))))))
+      (delete-dups arg)))
+   (use-package-process-keywords name rest state)))
+
+;;;; :autoload
+
+(defalias 'use-package-normalize/:autoload 'use-package-normalize/:commands)
+
+(defun use-package-handler/:autoload (name _keyword arg rest state)
+  (use-package-concat
+   ;; Since we deferring load, establish any necessary autoloads, and also
+   ;; keep the byte-compiler happy.
+   (let ((name-string (use-package-as-string name)))
+     (cl-mapcan
+      #'(lambda (command)
+          (when (symbolp command)
+            (append
+             (unless (plist-get state :demand)
+               `((unless (fboundp ',command)
+                   (autoload #',command ,name-string))))
+             (when (bound-and-true-p byte-compile-current-file)
+               `((eval-when-compile
+                   (declare-function ,command ,name-string)))))))
+      (delete-dups arg)))
+   (use-package-process-keywords name rest state)))
+
+;;;; :defer
+
+(defalias 'use-package-normalize/:defer 'use-package-normalize-predicate)
+
+(defun use-package-handler/:defer (name _keyword arg rest state)
+  (let ((body (use-package-process-keywords name rest state)))
+    (use-package-concat
+     ;; Load the package after a set amount of idle time, if the argument to
+     ;; `:defer' was a number.
+     (when (numberp arg)
+       `((run-with-idle-timer ,arg nil #'require
+                              ',(use-package-as-symbol name) nil t)))
+     (if (or (not arg) (null body))
+         body
+       `((eval-after-load ',name ',(macroexp-progn body)))))))
+
+;;;; :after
+
+(defun use-package-normalize/:after (name keyword args)
+  (setq args (use-package-normalize-recursive-symlist name keyword args))
+  (if (consp args)
+      args
+    (list args)))
+
+(defun use-package-after-count-uses (features*)
+  "Count the number of time the body would appear in the result."
+  (cond ((use-package-non-nil-symbolp features*)
+         1)
+        ((and (consp features*)
+              (memq (car features*) '(:or :any)))
+         (let ((num 0))
+           (cl-dolist (next (cdr features*))
+             (setq num (+ num (use-package-after-count-uses next))))
+           num))
+        ((and (consp features*)
+              (memq (car features*) '(:and :all)))
+         (apply #'max (mapcar #'use-package-after-count-uses
+                              (cdr features*))))
+        ((listp features*)
+         (use-package-after-count-uses (cons :all features*)))))
+
+(defun use-package-require-after-load (features* body)
+  "Generate `eval-after-load' statements to represents FEATURES*.
+FEATURES* is a list containing keywords `:and' and `:all', where
+no keyword implies `:all'."
+  (cond
+   ((use-package-non-nil-symbolp features*)
+    `((eval-after-load ',features* ',(macroexp-progn body))))
+   ((and (consp features*)
+         (memq (car features*) '(:or :any)))
+    (cl-mapcan #'(lambda (x) (use-package-require-after-load x body))
+               (cdr features*)))
+   ((and (consp features*)
+         (memq (car features*) '(:and :all)))
+    (cl-dolist (next (cdr features*))
+      (setq body (use-package-require-after-load next body)))
+    body)
+   ((listp features*)
+    (use-package-require-after-load (cons :all features*) body))))
+
+(defun use-package-handler/:after (name _keyword arg rest state)
+  (let ((body (use-package-process-keywords name rest state))
+        (uses (use-package-after-count-uses arg)))
+    (if (or (null uses) (null body))
+        body
+      (if (<= uses 1)
+          (use-package-require-after-load arg body)
+        (use-package-memoize
+         (apply-partially #'use-package-require-after-load arg)
+         (macroexp-progn body))))))
+
+;;;; :demand
+
+(defalias 'use-package-normalize/:demand 'use-package-normalize-predicate)
+
+(defun use-package-handler/:demand (name _keyword _arg rest state)
+  (use-package-process-keywords name rest state))
+
+;;;; :custom
+
+(defun use-package-normalize/:custom (_name keyword args)
+  "Normalize use-package custom keyword."
+  (use-package-as-one (symbol-name keyword) args
+    #'(lambda (label arg)
+        (unless (listp arg)
+          (use-package-error
+           (concat label " a (<symbol> <value> [comment])"
+                   " or list of these")))
+        (if (use-package-non-nil-symbolp (car arg))
+            (list arg)
+          arg))))
+
+(defun use-package-handler/:custom (name _keyword args rest state)
+  "Generate use-package custom keyword code."
+  (use-package-concat
+   (if (bound-and-true-p use-package-use-theme)
+       `((let ((custom--inhibit-theme-enable nil))
+           ;; Declare the theme here so use-package can be required inside
+           ;; eval-and-compile without warnings about unknown theme.
+           (unless (memq 'use-package custom-known-themes)
+             (deftheme use-package)
+             (enable-theme 'use-package)
+             (setq custom-enabled-themes (remq 'use-package 
custom-enabled-themes)))
+           (custom-theme-set-variables
+            'use-package
+            ,@(mapcar
+               #'(lambda (def)
+                   (let ((variable (nth 0 def))
+                         (value (nth 1 def))
+                         (comment (nth 2 def)))
+                     (unless (and comment (stringp comment))
+                       (setq comment (format "Customized with use-package %s" 
name)))
+                     `'(,variable ,value nil () ,comment)))
+               args))))
+     (mapcar
+      #'(lambda (def)
+          (let ((variable (nth 0 def))
+                (value (nth 1 def))
+                (comment (nth 2 def)))
+            (unless (and comment (stringp comment))
+              (setq comment (format "Customized with use-package %s" name)))
+            `(customize-set-variable (quote ,variable) ,value ,comment)))
+      args))
+   (use-package-process-keywords name rest state)))
+
+;;;; :custom-face
+
+(defun use-package-normalize/:custom-face (name-symbol _keyword arg)
+  "Normalize use-package custom-face keyword."
+  (let ((error-msg
+         (format "%s wants a (<symbol> <face-spec> [spec-type]) or list of 
these"
+                 name-symbol)))
+    (unless (listp arg)
+      (use-package-error error-msg))
+    (cl-dolist (def arg arg)
+      (unless (listp def)
+        (use-package-error error-msg))
+      (let ((face (nth 0 def))
+            (spec (nth 1 def)))
+        (when (or (not face)
+                  (not spec)
+                  (> (length def) 3))
+          (use-package-error error-msg))))))
+
+(defun use-package-handler/:custom-face (name _keyword args rest state)
+  "Generate use-package custom-face keyword code."
+  (use-package-concat
+   (mapcar #'(lambda (def) `(apply #'face-spec-set (backquote ,def))) args)
+   (use-package-process-keywords name rest state)))
+
+;;;; :init
+
+(defalias 'use-package-normalize/:init 'use-package-normalize-forms)
+
+(defun use-package-handler/:init (name _keyword arg rest state)
+  (use-package-concat
+   (when use-package-compute-statistics
+     `((use-package-statistics-gather :init ',name nil)))
+   (let ((init-body
+          (use-package-hook-injector (use-package-as-string name)
+                                     :init arg)))
+     (when init-body
+       (funcall use-package--hush-function :init
+                (if use-package-check-before-init
+                    `((when (locate-library ,(use-package-as-string name))
+                        ,@init-body))
+                  init-body))))
+   (use-package-process-keywords name rest state)
+   (when use-package-compute-statistics
+     `((use-package-statistics-gather :init ',name t)))))
+
+;;;; :load
+
+(defun use-package-normalize/:load (name keyword args)
+  (setq args (use-package-normalize-recursive-symlist name keyword args))
+  (if (consp args)
+      args
+    (list args)))
+
+(defun use-package-handler/:load (name _keyword arg rest state)
+  (let ((body (use-package-process-keywords name rest state)))
+    (cl-dolist (pkg arg)
+      (setq body (use-package-require (if (eq t pkg) name pkg) nil body)))
+    body))
+
+;;;; :config
+
+(defalias 'use-package-normalize/:config 'use-package-normalize-forms)
+
+(defun use-package-handler/:config (name _keyword arg rest state)
+  (let* ((body (use-package-process-keywords name rest state))
+         (name-symbol (use-package-as-symbol name)))
+    (use-package-concat
+     (when use-package-compute-statistics
+       `((use-package-statistics-gather :config ',name nil)))
+     (if (and (or (null arg) (equal arg '(t))) (not use-package-inject-hooks))
+         body
+       (use-package-with-elapsed-timer
+           (format "Configuring package %s" name-symbol)
+         (funcall use-package--hush-function :config
+                  (use-package-concat
+                   (use-package-hook-injector
+                    (symbol-name name-symbol) :config arg)
+                   body
+                   (list t)))))
+     (when use-package-compute-statistics
+       `((use-package-statistics-gather :config ',name t))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; The main macro
+;;
+
+(defmacro use-package-core (name args)
+  `(let* ((args* (use-package-normalize-keywords ,name ,args))
+          (use-package--form
+           (if (eq use-package-verbose 'debug)
+               (concat "\n\n"
+                       (pp-to-string `(use-package ,name ,@,args))
+                       "\n  -->\n\n"
+                       (pp-to-string `(use-package ,name ,@args*))
+                       "\n  ==>\n\n"
+                       (pp-to-string
+                        (macroexp-progn
+                         (let ((use-package-verbose 'errors)
+                               (use-package-expand-minimally t))
+                           (use-package-process-keywords name args*
+                             (and (plist-get args* :demand)
+                                  (list :demand t)))))))
+             "")))
+     (use-package-process-keywords name args*
+       (and (plist-get args* :demand)
+            (list :demand t)))))
+
+;;;###autoload
+(defmacro use-package (name &rest args)
+  "Declare an Emacs package by specifying a group of configuration options.
+
+For full documentation, please see the README file that came with
+this file.  Usage:
+
+  (use-package package-name
+     [:keyword [option]]...)
+
+:init            Code to run before PACKAGE-NAME has been loaded.
+:config          Code to run after PACKAGE-NAME has been loaded.  Note that
+                 if loading is deferred for any reason, this code does not
+                 execute until the lazy load has occurred.
+:preface         Code to be run before everything except `:disabled'; this
+                 can be used to define functions for use in `:if', or that
+                 should be seen by the byte-compiler.
+
+:mode            Form to be added to `auto-mode-alist'.
+:magic           Form to be added to `magic-mode-alist'.
+:magic-fallback  Form to be added to `magic-fallback-mode-alist'.
+:interpreter     Form to be added to `interpreter-mode-alist'.
+
+:commands        Define autoloads for commands that will be defined by the
+                 package.  This is useful if the package is being lazily
+                 loaded, and you wish to conditionally call functions in your
+                 `:init' block that are defined in the package.
+:autoload        Similar to :commands, but it for no-interactive one.
+:hook            Specify hook(s) to attach this package to.
+
+:bind            Bind keys, and define autoloads for the bound commands.
+:bind*           Bind keys, and define autoloads for the bound commands,
+                 *overriding all minor mode bindings*.
+:bind-keymap     Bind a key prefix to an auto-loaded keymap defined in the
+                 package.  This is like `:bind', but for keymaps.
+:bind-keymap*    Like `:bind-keymap', but overrides all minor mode bindings
+
+:defer           Defer loading of a package -- this is implied when using
+                 `:commands', `:bind', `:bind*', `:mode', `:magic', `:hook',
+                 `:magic-fallback', or `:interpreter'.  This can be an integer,
+                 to force loading after N seconds of idle time, if the package
+                 has not already been loaded.
+:after           Delay the use-package declaration until after the named 
modules
+                 have loaded. Once load, it will be as though the use-package
+                 declaration (without `:after') had been seen at that moment.
+:demand          Prevent the automatic deferred loading introduced by 
constructs
+                 such as `:bind' (see `:defer' for the complete list).
+
+:if EXPR         Initialize and load only if EXPR evaluates to a non-nil value.
+:disabled        The package is ignored completely if this keyword is present.
+:defines         Declare certain variables to silence the byte-compiler.
+:functions       Declare certain functions to silence the byte-compiler.
+:load-path       Add to the `load-path' before attempting to load the package.
+:diminish        Support for diminish.el (if installed).
+:delight         Support for delight.el (if installed).
+:custom          Call `Custom-set' or `set-default' with each variable
+                 definition without modifying the Emacs `custom-file'.
+                 (compare with `custom-set-variables').
+:custom-face     Call `custom-set-faces' with each face definition.
+:ensure          Loads the package using package.el if necessary.
+:pin             Pin the package to an archive."
+  (declare (indent defun))
+  (unless (memq :disabled args)
+    (macroexp-progn
+     (use-package-concat
+      (when use-package-compute-statistics
+        `((use-package-statistics-gather :use-package ',name nil)))
+      (if (eq use-package-verbose 'errors)
+          (use-package-core name args)
+        (condition-case-unless-debug err
+            (use-package-core name args)
+          (error
+           (ignore
+            (display-warning
+             'use-package
+             (format "Failed to parse package %s: %s"
+                     name (error-message-string err)) :error)))))
+      (when use-package-compute-statistics
+        `((use-package-statistics-gather :use-package ',name t)))))))
+
+(provide 'use-package-core)
+
+;;; 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 @@
+;;; use-package-delight.el --- Support for the :delight keyword  -*- 
lexical-binding: t; -*-
+
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+;; Author: John Wiegley <johnw@newartisans.com>
+;; Maintainer: John Wiegley <johnw@newartisans.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Provides support for the :delight keyword, which is made available by
+;; default by requiring `use-package'.
+
+;;; Code:
+
+(require 'use-package-core)
+
+(defun use-package-normalize-delight (name args)
+  "Normalize ARGS for a single call to `delight'."
+  (when (eq :eval (car args))
+    ;; Handle likely common mistake.
+    (use-package-error ":delight mode line constructs must be quoted"))
+  (cond ((and (= (length args) 1)
+              (use-package-non-nil-symbolp (car args)))
+         `(,(nth 0 args) nil ,name))
+        ((= (length args) 2)
+         `(,(nth 0 args) ,(nth 1 args) ,name))
+        ((= (length args) 3)
+         args)
+        (t
+         (use-package-error
+          ":delight expects `delight' arguments or a list of them"))))
+
+;;;###autoload
+(defun use-package-normalize/:delight (name _keyword args)
+  "Normalize arguments to delight."
+  (cond ((null args)
+         `((,(use-package-as-mode name) nil ,name)))
+        ((and (= (length args) 1)
+              (use-package-non-nil-symbolp (car args)))
+         `((,(car args) nil ,name)))
+        ((and (= (length args) 1)
+              (stringp (car args)))
+         `((,(use-package-as-mode name) ,(car args) ,name)))
+        ((and (= (length args) 1)
+              (listp (car args))
+              (eq 'quote (caar args)))
+         `((,(use-package-as-mode name) ,@(cdar args) ,name)))
+        ((and (= (length args) 2)
+              (listp (nth 1 args))
+              (eq 'quote (car (nth 1 args))))
+         `((,(car args) ,@(cdr (nth 1 args)) ,name)))
+        (t (mapcar
+            (apply-partially #'use-package-normalize-delight name)
+            (if (use-package-non-nil-symbolp (car args))
+                (list args)
+              args)))))
+
+;;;###autoload
+(defun use-package-handler/:delight (name _keyword args rest state)
+  (let ((body (use-package-process-keywords name rest state)))
+    (use-package-concat
+     body
+     `((if (fboundp 'delight)
+           (delight '(,@args)))))))
+
+(add-to-list 'use-package-keywords :delight t)
+
+(provide 'use-package-delight)
+
+;;; 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 @@
+;;; use-package-diminish.el --- Support for the :diminish keyword  -*- 
lexical-binding: t; -*-
+
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+;; Author: John Wiegley <johnw@newartisans.com>
+;; Maintainer: John Wiegley <johnw@newartisans.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Provides support for the :diminish keyword, which is made available by
+;; default by requiring `use-package'.
+
+;;; Code:
+
+(require 'use-package-core)
+
+(defun use-package-normalize-diminish (name label arg &optional recursed)
+  "Normalize the arguments to diminish down to a list of one of two forms:
+     SYMBOL
+     (SYMBOL . STRING)"
+  (cond
+   ((not arg)
+    (list (use-package-as-mode name)))
+   ((use-package-non-nil-symbolp arg)
+    (list arg))
+   ((stringp arg)
+    (list (cons (use-package-as-mode name) arg)))
+   ((and (consp arg) (stringp (cdr arg)))
+    (list arg))
+   ((and (not recursed) (listp arg) (listp (cdr arg)))
+    (mapcar #'(lambda (x) (car (use-package-normalize-diminish
+                           name label x t))) arg))
+   (t
+    (use-package-error
+     (concat label " wants a string, symbol, "
+             "(symbol . string) or list of these")))))
+
+;;;###autoload
+(defun use-package-normalize/:diminish (name keyword args)
+  (use-package-as-one (symbol-name keyword) args
+    (apply-partially #'use-package-normalize-diminish name) t))
+
+;;;###autoload
+(defun use-package-handler/:diminish (name _keyword arg rest state)
+  (let ((body (use-package-process-keywords name rest state)))
+    (use-package-concat
+     (mapcar #'(lambda (var)
+                 `(if (fboundp 'diminish)
+                      ,(if (consp var)
+                           `(diminish ',(car var) ,(cdr var))
+                         `(diminish ',var))))
+             arg)
+     body)))
+
+(add-to-list 'use-package-keywords :diminish t)
+
+(provide 'use-package-diminish)
+
+;;; 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..c55bacaf817
--- /dev/null
+++ b/lisp/use-package/use-package-ensure-system-package.el
@@ -0,0 +1,101 @@
+;;; use-package-ensure-system-package.el --- auto install system packages  -*- 
lexical-binding: t; -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author: Justin Talbott <justin@waymondo.com>
+;; Keywords: convenience, tools, extensions
+;; URL: https://github.com/waymondo/use-package-ensure-system-package
+;; Version: 0.2
+;; Package-Requires: ((use-package "2.1") (system-packages "1.0.4"))
+;; Filename: use-package-ensure-system-package.el
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; The `:ensure-system-package` keyword allows you to ensure system
+;; binaries exist alongside your `use-package` declarations.
+;;
+
+;;; Code:
+
+(require 'use-package)
+(require 'system-packages nil t)
+
+(eval-when-compile
+  (declare-function system-packages-get-command "system-packages"))
+
+(defvar use-package-ensure-system-package--custom-packages '()
+  "List of commands used to install custom packages.")
+
+(defun use-package-ensure-system-package-consify (arg)
+  "Turn ARG into a cons of the form (PACKAGE-NAME . INSTALL-COMMAND')."
+  (cond
+   ((stringp arg)
+    (cons arg `(system-packages-install ,arg)))
+   ((symbolp arg)
+    (cons arg `(system-packages-install ,(symbol-name arg))))
+   ((consp arg)
+    (cond
+     ((not (cdr arg))
+      (use-package-ensure-system-package-consify (car arg)))
+     ((stringp (cdr arg))
+      (progn
+       (push (cdr arg) use-package-ensure-system-package--custom-packages)
+       (cons (car arg) `(async-shell-command ,(cdr arg)))))
+     (t
+      (cons (car arg)
+           `(system-packages-install ,(symbol-name (cdr arg)))))))))
+
+(defun use-package-ensure-system-package-update-custom-packages ()
+  "Update custom packages (not installed by system package manager).
+Run the same commands used for installing them."
+  (interactive)
+  (dolist (cmd use-package-ensure-system-package--custom-packages)
+    (async-shell-command cmd)))
+
+;;;###autoload
+(defun use-package-normalize/:ensure-system-package (_name-symbol keyword args)
+  "Turn ARGS into a list of conses of the form (PACKAGE-NAME . 
INSTALL-COMMAND)."
+  (use-package-as-one (symbol-name keyword) args
+    (lambda (_label arg)
+      (cond
+       ((and (listp arg) (listp (cdr arg)))
+        (mapcar #'use-package-ensure-system-package-consify arg))
+       (t
+        (list (use-package-ensure-system-package-consify arg)))))))
+
+(defun use-package-ensure-system-package-exists? (file-or-exe)
+  "If FILE-OR-EXE is a string, ensure the file path exists.
+If it is a symbol, ensure the binary exist."
+  (if (stringp file-or-exe)
+      (file-exists-p file-or-exe)
+    (executable-find (symbol-name file-or-exe))))
+
+
+;;;###autoload
+(defun use-package-handler/:ensure-system-package (name _keyword arg rest 
state)
+  "Execute the handler for `:ensure-system-package' keyword in `use-package'."
+  (let ((body (use-package-process-keywords name rest state)))
+    (use-package-concat
+     (mapcar #'(lambda (cons)
+                 `(unless (use-package-ensure-system-package-exists? ',(car 
cons))
+                   ,(cdr cons))) arg)
+     body)))
+
+(add-to-list 'use-package-keywords :ensure-system-package t)
+
+(provide 'use-package-ensure-system-package)
+
+;;; 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..bbb8e4175b8
--- /dev/null
+++ b/lisp/use-package/use-package-ensure.el
@@ -0,0 +1,208 @@
+;;; use-package-ensure.el --- Support for the :ensure and :pin keywords  -*- 
lexical-binding: t; -*-
+
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+;; Author: John Wiegley <johnw@newartisans.com>
+;; Maintainer: John Wiegley <johnw@newartisans.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Provides support for the :ensure and :pin keywords, which is made available
+;; by default by requiring `use-package'.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'use-package-core)
+
+(defgroup use-package-ensure nil
+  "Support for :ensure and :pin keywords in `use-package' declarations."
+  :group 'use-package
+  :link '(custom-manual "(use-package) Installing packages")
+  :version "29.1")
+
+(eval-when-compile
+  (declare-function package-installed-p "package")
+  (declare-function package-read-all-archive-contents "package" ()))
+
+(defcustom use-package-always-ensure nil
+  "Treat every package as though it had specified using `:ensure SEXP'.
+See also `use-package-defaults', which uses this value."
+  :type 'sexp
+  :group 'use-package-ensure)
+
+(defcustom use-package-always-pin nil
+  "Treat every package as though it had specified using `:pin SYM'.
+See also `use-package-defaults', which uses this value."
+  :type 'symbol
+  :group 'use-package-ensure)
+
+(defcustom use-package-ensure-function 'use-package-ensure-elpa
+  "Function that ensures a package is installed.
+This function is called with three arguments: the name of the
+package declared in the `use-package' form; the arguments passed
+to all `:ensure' keywords (always a list, even if only one); and
+the current `state' plist created by previous handlers.
+
+Note that this function is called whenever `:ensure' is provided,
+even if it is nil.  It is up to the function to decide on the
+semantics of the various values for `:ensure'.
+
+This function should return non-nil if the package is installed.
+
+The default value uses package.el to install the package."
+  :type '(choice (const :tag "package.el" use-package-ensure-elpa)
+                 (function :tag "Custom"))
+  :group 'use-package-ensure)
+
+;;;; :pin
+
+(defun use-package-normalize/:pin (_name keyword args)
+  (use-package-only-one (symbol-name keyword) args
+    #'(lambda (_label arg)
+        (cond
+         ((stringp arg) arg)
+         ((use-package-non-nil-symbolp arg) (symbol-name arg))
+         (t
+          (use-package-error
+           ":pin wants an archive name (a string)"))))))
+
+(eval-when-compile
+  (defvar package-pinned-packages)
+  (defvar package-archives))
+
+(defun use-package-archive-exists-p (archive)
+  "Check if a given ARCHIVE is enabled.
+
+ARCHIVE can be a string or a symbol or `manual' to indicate a
+manually updated package."
+  (if (member archive '(manual "manual"))
+      't
+    (let ((valid nil))
+      (dolist (pa package-archives)
+        (when (member archive (list (car pa) (intern (car pa))))
+          (setq valid 't)))
+      valid)))
+
+(defun use-package-pin-package (package archive)
+  "Pin PACKAGE to ARCHIVE."
+  (unless (boundp 'package-pinned-packages)
+    (setq package-pinned-packages ()))
+  (let ((archive-symbol (if (symbolp archive) archive (intern archive)))
+        (archive-name   (if (stringp archive) archive (symbol-name archive))))
+    (if (use-package-archive-exists-p archive-symbol)
+        (add-to-list 'package-pinned-packages (cons package archive-name))
+      (error "Archive '%s' requested for package '%s' is not available"
+             archive-name package))
+    (unless (bound-and-true-p package--initialized)
+      (package-initialize t))))
+
+(defun use-package-handler/:pin (name _keyword archive-name rest state)
+  (let ((body (use-package-process-keywords name rest state))
+        (pin-form (if archive-name
+                      `(use-package-pin-package ',(use-package-as-symbol name)
+                                                ,archive-name))))
+    ;; Pinning should occur just before ensuring
+    ;; See `use-package-handler/:ensure'.
+    (if (bound-and-true-p byte-compile-current-file)
+        (eval pin-form)              ; Eval when byte-compiling,
+      (push pin-form body))          ; or else wait until runtime.
+    body))
+
+;;;; :ensure
+
+(defvar package-archive-contents)
+
+;;;###autoload
+(defun use-package-normalize/:ensure (_name keyword args)
+  (if (null args)
+      (list t)
+    (use-package-only-one (symbol-name keyword) args
+      #'(lambda (_label arg)
+          (cond
+           ((symbolp arg)
+            (list arg))
+           ((and (listp arg) (= 3 (length arg))
+                 (symbolp (nth 0 arg))
+                 (eq :pin (nth 1 arg))
+                 (or (stringp (nth 2 arg))
+                     (symbolp (nth 2 arg))))
+            (list (cons (nth 0 arg) (nth 2 arg))))
+           (t
+            (use-package-error
+             (concat ":ensure wants an optional package name "
+                     "(an unquoted symbol name), or (<symbol> :pin 
<string>)"))))))))
+
+(defun use-package-ensure-elpa (name args _state &optional _no-refresh)
+  (dolist (ensure args)
+    (let ((package
+           (or (and (eq ensure t) (use-package-as-symbol name))
+               ensure)))
+      (when package
+        (require 'package)
+        (when (consp package)
+          (use-package-pin-package (car package) (cdr package))
+          (setq package (car package)))
+        (unless (package-installed-p package)
+          (condition-case-unless-debug err
+              (progn
+                (when (assoc package (bound-and-true-p
+                                      package-pinned-packages))
+                  (package-read-all-archive-contents))
+                (if (assoc package package-archive-contents)
+                    (package-install package)
+                  (package-refresh-contents)
+                  (when (assoc package (bound-and-true-p
+                                        package-pinned-packages))
+                    (package-read-all-archive-contents))
+                  (package-install package))
+                t)
+            (error
+             (display-warning 'use-package
+                              (format "Failed to install %s: %s"
+                                      name (error-message-string err))
+                              :error))))))))
+
+;;;###autoload
+(defun use-package-handler/:ensure (name _keyword ensure rest state)
+  (let* ((body (use-package-process-keywords name rest state)))
+    ;; We want to avoid installing packages when the `use-package' macro is
+    ;; being macro-expanded by elisp completion (see `lisp--local-variables'),
+    ;; but still install packages when byte-compiling, to avoid requiring
+    ;; `package' at runtime.
+    (if (bound-and-true-p byte-compile-current-file)
+        ;; Eval when byte-compiling,
+        (funcall use-package-ensure-function name ensure state)
+      ;;  or else wait until runtime.
+      (push `(,use-package-ensure-function ',name ',ensure ',state)
+            body))
+    body))
+
+(add-to-list 'use-package-defaults
+             '(:ensure (list use-package-always-ensure)
+                       (lambda (name args)
+                         (and use-package-always-ensure
+                              (not (plist-member args :load-path))))) t)
+
+(add-to-list 'use-package-defaults
+             '(:pin use-package-always-pin use-package-always-pin) t)
+
+(add-to-list 'use-package-keywords :ensure)
+(add-to-list 'use-package-keywords :pin)
+
+(provide 'use-package-ensure)
+
+;;; 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 @@
+;;; use-package-jump.el --- Attempt to jump to a use-package declaration  -*- 
lexical-binding: t; -*-
+
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+;; Author: John Wiegley <johnw@newartisans.com>
+;; Maintainer: John Wiegley <johnw@newartisans.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Provides the command `M-x use-package-jump-to-package-form', however it
+;; only works if the package being jumped to was required during
+;; initialization.  If it was delay-loaded, it will not work.
+;; Improvements are needed.
+
+;;; Code:
+
+(require 'use-package-core)
+
+(defun use-package-find-require (package)
+  "Find file that required PACKAGE by searching `load-history'.
+Returns an absolute file path or nil if none is found."
+  (catch 'suspect
+    (dolist (filespec load-history)
+      (dolist (entry (cdr filespec))
+        (when (equal entry (cons 'require package))
+          (throw 'suspect (car filespec)))))))
+
+;;;###autoload
+(defun use-package-jump-to-package-form (package)
+  "Attempt to find and jump to the `use-package' form that loaded PACKAGE.
+This will only find the form if that form actually required
+PACKAGE.  If PACKAGE was previously required then this function
+will jump to the file that originally required PACKAGE instead."
+  (interactive (list (completing-read "Package: " features)))
+  (let* ((package (if (stringp package) (intern package) package))
+         (requiring-file (use-package-find-require package))
+         file location)
+    (if (null requiring-file)
+        (user-error "Can't find file requiring file; may have been autoloaded")
+      (setq file (if (string= (file-name-extension requiring-file) "elc")
+                     (concat (file-name-sans-extension requiring-file) ".el")
+                   requiring-file))
+      (when (file-exists-p file)
+        (find-file-other-window file)
+        (save-excursion
+          (goto-char (point-min))
+          (setq location
+                (re-search-forward
+                 (format (eval use-package-form-regexp-eval) package) nil t)))
+        (if (null location)
+            (message "No use-package form found.")
+          (goto-char location)
+          (beginning-of-line))))))
+
+(provide 'use-package-jump)
+
+;;; 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 @@
+;;; use-package-lint.el --- Attempt to find errors in use-package declarations 
 -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+;; Author: John Wiegley <johnw@newartisans.com>
+;; Maintainer: John Wiegley <johnw@newartisans.com>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Provides the command `M-x use-package-lint'.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'use-package-core)
+
+(defun use-package-lint-declaration (name plist)
+  (dolist (path (plist-get plist :load-path))
+    (unless (file-exists-p path)
+      (display-warning
+       'use-package
+       (format "%s :load-path does not exist: %s"
+               name path) :error)))
+
+  (unless (or (plist-member plist :disabled)
+              (plist-get plist :no-require)
+              (locate-library (use-package-as-string name) nil
+                              (plist-get plist :load-path)))
+    (display-warning
+     'use-package
+     (format "%s module cannot be located" name) :error))
+
+  ;; (dolist (command (plist-get plist :commands))
+  ;;   (unless (string= (find-lisp-object-file-name command nil)
+  ;;                    (locate-library (use-package-as-string name) nil
+  ;;                                    (plist-get plist :load-path)))
+  ;;     (display-warning
+  ;;      'use-package
+  ;;      (format "%s :command is from different path: %s"
+  ;;              name (symbol-name command)) :error)))
+  )
+
+;;;###autoload
+(defun use-package-lint ()
+  "Check for errors in `use-package' declarations.
+For example, if the module's `:if' condition is met, but even
+with the specified `:load-path' the module cannot be found."
+  (interactive)
+  (save-excursion
+    (goto-char (point-min))
+    (let ((re (eval use-package-form-regexp-eval)))
+      (while (re-search-forward re nil t)
+        (goto-char (match-beginning 0))
+        (let ((decl (read (current-buffer))))
+          (when (eq (car decl) 'use-package)
+            (use-package-lint-declaration
+             (use-package-as-string (cadr decl))
+             (use-package-normalize-keywords
+              (cadr decl) (cddr decl)))))))))
+
+(provide 'use-package-lint)
+
+;;; 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 @@
+;;; use-package.el --- A configuration macro for simplifying your .emacs  -*- 
lexical-binding: t; -*-
+
+;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+;; Author: John Wiegley <johnw@newartisans.com>
+;; Maintainer: John Wiegley <johnw@newartisans.com>
+;; Created: 17 Jun 2012
+;; Version: 2.4.4
+;; Package-Requires: ((emacs "24.3") (bind-key "2.4"))
+;; Keywords: dotemacs startup speed config package extensions
+;; URL: https://github.com/jwiegley/use-package
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The `use-package' declaration macro allows you to isolate package
+;; configuration in your ".emacs" in a way that is performance-oriented and,
+;; well, just tidy.  I created it because I have over 80 packages that I use
+;; in Emacs, and things were getting difficult to manage.  Yet with this
+;; utility my total load time is just under 1 second, with no loss of
+;; functionality!
+;;
+;; Please see README.md from the same repository for documentation.
+
+;;; Code:
+
+(require 'use-package-core)
+
+(require 'use-package-bind-key)
+(require 'use-package-diminish)
+(require 'use-package-delight)
+(require 'use-package-ensure)
+
+(declare-function use-package-jump-to-package-form "use-package-jump")
+(autoload #'use-package-jump-to-package-form "use-package-jump" nil t)
+
+(provide 'use-package)
+
+;;; use-package.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..05969f5a95f
--- /dev/null
+++ b/test/lisp/use-package/use-package-tests.el
@@ -0,0 +1,1957 @@
+;;; use-package-tests.el --- Tests for use-package.el  -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'ert)
+(require 'use-package)
+
+(setq use-package-always-ensure nil
+      use-package-verbose 'errors
+      use-package-expand-minimally t
+      ;; These are needed for certain tests below where the `pcase' match
+      ;; expression is large and contains holes, such as the :after tests.
+      max-lisp-eval-depth 8000
+      max-specpdl-size 8000)
+
+(unless (fboundp 'macroexpand-1)
+  (defun macroexpand-1 (form &optional environment)
+    "Perform (at most) one step of macroexpansion."
+    (cond
+     ((consp form)
+      (let* ((head (car form))
+             (env-expander (assq head environment)))
+        (if env-expander
+            (if (cdr env-expander)
+                (apply (cdr env-expander) (cdr form))
+              form)
+          (if (not (and (symbolp head) (fboundp head)))
+              form
+            (let ((def (autoload-do-load (symbol-function head) head 'macro)))
+              (cond
+               ;; Follow alias, but only for macros, otherwise we may end up
+               ;; skipping an important compiler-macro (e.g. 
cl--block-wrapper).
+               ((and (symbolp def) (macrop def)) (cons def (cdr form)))
+               ((not (consp def)) form)
+               (t
+                (if (eq 'macro (car def))
+                    (apply (cdr def) (cdr form))
+                  form))))))))
+     (t form))))
+
+(defmacro expand-minimally (form)
+  `(let ((use-package-verbose 'errors)
+         (use-package-expand-minimally t))
+     (macroexpand-1 ',form)))
+
+(defmacro expand-maximally (form)
+  `(let ((use-package-verbose 'debug)
+         (use-package-expand-minimally nil))
+     (macroexpand-1 ',form)))
+
+(defmacro match-expansion (form &rest value)
+  `(should (pcase (expand-minimally ,form)
+             ,@(mapcar #'(lambda (x) (list x t)) value))))
+
+(defun fix-expansion ()
+  (interactive)
+  (save-excursion
+    (unless (looking-at "(match-expansion")
+      (backward-up-list))
+    (when (looking-at "(match-expansion")
+      (re-search-forward "(\\(use-package\\|bind-key\\)")
+      (goto-char (match-beginning 0))
+      (let ((decl (read (current-buffer))))
+        (kill-sexp)
+        (let (vars)
+          (catch 'exit
+            (save-excursion
+              (while (ignore-errors (backward-up-list) t)
+                (when (looking-at "(let\\s-+")
+                  (goto-char (match-end 0))
+                  (setq vars (read (current-buffer)))
+                  (throw 'exit t)))))
+          (eval
+           `(let (,@ (append vars
+                             '((use-package-verbose 'errors)
+                               (use-package-expand-minimally t))))
+              (insert ?\n ?\` (pp-to-string (macroexpand-1 decl))))))))))
+
+(bind-key "C-c C-u" #'fix-expansion emacs-lisp-mode-map)
+
+(ert-deftest use-package-test-recognize-function ()
+  (should (use-package-recognize-function nil t))
+  (should-not (use-package-recognize-function nil))
+  (should (use-package-recognize-function t))
+  (should (use-package-recognize-function 'sym))
+  (should (use-package-recognize-function #'sym))
+  (should (use-package-recognize-function (lambda () ...)))
+  (should (use-package-recognize-function '(lambda () ...)))
+  (should (use-package-recognize-function #'(lambda () ...)))
+
+  (should-not (use-package-recognize-function 1))
+  (should-not (use-package-recognize-function "Hello"))
+  (should-not (use-package-recognize-function '(nil . nil))))
+
+(ert-deftest use-package-test-normalize-function ()
+  (should (equal (use-package-normalize-function nil) nil))
+  (should (equal (use-package-normalize-function t) t))
+  (should (equal (use-package-normalize-function 'sym) 'sym))
+  (should (equal (use-package-normalize-function #'sym) 'sym))
+  (should (equal (use-package-normalize-function '(lambda () ...)) '(lambda () 
...)))
+  (should (equal (use-package-normalize-function ''(lambda () ...)) '(lambda 
() ...)))
+  (should (equal (use-package-normalize-function '#'(lambda () ...)) '(lambda 
() ...)))
+
+  (should (equal (use-package-normalize-function 1) 1))
+  (should (equal (use-package-normalize-function "Hello") "Hello"))
+  (should (equal (use-package-normalize-function '(nil . nil)) '(nil . nil))))
+
+(ert-deftest use-package-test/:disabled-1 ()
+  (match-expansion
+   (use-package foo :disabled t)
+   `()))
+
+(ert-deftest use-package-test/:preface-1 ()
+  (match-expansion
+   (use-package foo :preface (t))
+   `(progn
+      (eval-and-compile
+        (t))
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:preface-2 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :preface (t))
+     `(progn
+        (eval-and-compile
+          (eval-when-compile
+            (with-demoted-errors
+                "Cannot load foo: %S" nil
+                (unless (featurep 'foo)
+                  (load "foo" nil t))))
+          (t))
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:preface-3 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo
+       :preface (preface)
+       :init (init)
+       :config (config)
+       :functions func
+       :defines def)
+     `(progn
+        (eval-and-compile
+          (defvar def)
+          (declare-function func "foo")
+          (eval-when-compile
+            (with-demoted-errors
+                "Cannot load foo: %S" nil
+                (unless (featurep 'foo)
+                  (load "foo" nil t))))
+          (preface))
+        (init)
+        (require 'foo nil nil)
+        (config)
+        t))))
+
+(ert-deftest use-package-test/:preface-4 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo
+       :preface (preface)
+       :init (init)
+       :config (config)
+       :functions func
+       :defines def
+       :defer t)
+     `(progn
+        (eval-and-compile
+          (defvar def)
+          (declare-function func "foo")
+          (eval-when-compile
+            (with-demoted-errors
+                "Cannot load foo: %S" nil
+                (unless (featurep 'foo)
+                  (load "foo" nil t))))
+          (preface))
+        (init)
+        (eval-after-load 'foo
+          '(progn
+             (config)
+             t))))))
+
+(ert-deftest use-package-test/:pin-1 ()
+  (match-expansion
+   (use-package foo :pin foo)
+   `(progn
+      (use-package-pin-package 'foo "foo")
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:pin-2 ()
+  (match-expansion
+   (use-package foo :pin "foo")
+   `(progn
+      (use-package-pin-package 'foo "foo")
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test-normalize/:ensure ()
+  (cl-flet ((norm (&rest args)
+                  (apply #'use-package-normalize/:ensure
+                         'foopkg :ensure args)))
+    (should (equal (norm '(t)) '(t)))
+    (should (equal (norm '(nil)) '(nil)))
+    (should (equal (norm '(sym)) '(sym)))
+    (should-error (norm '(1)))
+    (should-error (norm '("Hello")))))
+
+(ert-deftest use-package-test/:ensure-1 ()
+  (let ((use-package-always-ensure nil))
+    (match-expansion
+     (use-package foo :ensure t)
+     `(progn
+        (use-package-ensure-elpa 'foo '(t) 'nil)
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:ensure-2 ()
+  (let ((use-package-always-ensure t))
+    (match-expansion
+     (use-package foo :ensure t)
+     `(progn
+        (use-package-ensure-elpa 'foo '(t) 'nil)
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:ensure-3 ()
+  (let ((use-package-always-ensure nil))
+    (match-expansion
+     (use-package foo :ensure nil)
+     `(progn
+        (use-package-ensure-elpa 'foo '(nil) 'nil)
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:ensure-4 ()
+  (let ((use-package-always-ensure t))
+    (match-expansion
+     (use-package foo :ensure nil)
+     `(progn
+        (use-package-ensure-elpa 'foo '(nil) 'nil)
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:ensure-5 ()
+  (let ((use-package-always-ensure nil))
+    (match-expansion
+     (use-package foo :load-path "foo")
+     `(progn
+        (eval-and-compile
+          (add-to-list 'load-path ,(pred stringp)))
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:ensure-6 ()
+  (let ((use-package-always-ensure t))
+    (match-expansion
+     (use-package foo :load-path "foo")
+     `(progn
+        (eval-and-compile
+          (add-to-list 'load-path ,(pred stringp)))
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:ensure-7 ()
+  (let ((use-package-always-ensure nil))
+    (match-expansion
+     (use-package foo :ensure nil :load-path "foo")
+     `(progn
+        (use-package-ensure-elpa 'foo '(nil) 'nil)
+        (eval-and-compile
+          (add-to-list 'load-path ,(pred stringp)))
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:ensure-8 ()
+  (let ((use-package-always-ensure t))
+    (match-expansion
+     (use-package foo :ensure nil :load-path "foo")
+     `(progn
+        (use-package-ensure-elpa 'foo '(nil) 'nil)
+        (eval-and-compile
+          (add-to-list 'load-path ,(pred stringp)))
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:ensure-9 ()
+  (let ((use-package-always-ensure nil))
+    (match-expansion
+     (use-package foo :ensure t :load-path "foo")
+     `(progn
+        (use-package-ensure-elpa 'foo '(t) 'nil)
+        (eval-and-compile
+          (add-to-list 'load-path ,(pred stringp)))
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:ensure-10 ()
+  (let ((use-package-always-ensure t))
+    (match-expansion
+     (use-package foo :ensure t :load-path "foo")
+     `(progn
+        (use-package-ensure-elpa 'foo '(t) 'nil)
+        (eval-and-compile
+          (add-to-list 'load-path ,(pred stringp)))
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:ensure-11 ()
+  (let (tried-to-install)
+    (cl-letf (((symbol-function #'use-package-ensure-elpa)
+               (lambda (name ensure state &optional no-refresh)
+                 (when ensure
+                   (setq tried-to-install name))))
+              ((symbol-function #'require) #'ignore))
+      (use-package foo :ensure t)
+      (should (eq tried-to-install 'foo)))))
+
+(ert-deftest use-package-test/:ensure-12 ()
+  (let ((use-package-always-ensure t))
+    (match-expansion
+     (use-package foo :ensure bar)
+     `(progn
+        (use-package-ensure-elpa 'foo '(bar) 'nil)
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:ensure-13 ()
+  (let ((use-package-always-ensure t))
+    (match-expansion
+     (use-package foo :ensure bar :ensure quux)
+     `(progn
+        (use-package-ensure-elpa 'foo '(bar quux) 'nil)
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:ensure-14 ()
+  (match-expansion
+   (use-package ess-site
+     :ensure ess1
+     :ensure ess2
+     :ensure (ess3 :pin "melpa-unstable")
+     :pin melpa-stable)
+   `(progn
+      (use-package-pin-package 'ess-site "melpa-stable")
+      (use-package-ensure-elpa 'ess-site
+                               '(ess1 ess2
+                                      (ess3 . "melpa-unstable"))
+                               'nil)
+      (require 'ess-site nil nil))))
+
+(ert-deftest use-package-test/:ensure-15 ()
+  (let ((use-package-always-ensure t))
+    (match-expansion
+     (use-package foo
+       :pin "elpa"
+       :ensure bar
+       :ensure (quux :pin "melpa"))
+     `(progn
+        (use-package-pin-package 'foo "elpa")
+        (use-package-ensure-elpa 'foo
+                                 '(bar
+                                   (quux . "melpa"))
+                                 'nil)
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:if-1 ()
+  (match-expansion
+   (use-package foo :if t)
+   `(when t
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:if-2 ()
+  (match-expansion
+   (use-package foo :if (and t t))
+   `(when (and t t)
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:if-3 ()
+  (match-expansion
+   (use-package foo :if nil)
+   `(when nil
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:when-1 ()
+  (match-expansion
+   (use-package foo :when t)
+   `(when t
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:when-2 ()
+  (match-expansion
+   (use-package foo :when (and t t))
+   `(when (and t t)
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:when-3 ()
+  (match-expansion
+   (use-package foo :when nil)
+   `(when nil
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:unless-1 ()
+  (match-expansion
+   (use-package foo :unless t)
+   `(when (not t)
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:unless-2 ()
+  (match-expansion
+   (use-package foo :unless (and t t))
+   `(when (not (and t t))
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:unless-3 ()
+  (match-expansion
+   (use-package foo :unless nil)
+   `(unless nil
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:requires-1 ()
+  (match-expansion
+   (use-package foo :requires bar)
+   `(when (featurep 'bar)
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:requires-2 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :requires bar)
+     `(when (featurep 'bar)
+        (eval-and-compile
+          (eval-when-compile
+            (with-demoted-errors
+                "Cannot load foo: %S" nil
+                (unless (featurep 'foo)
+                  (load "foo" nil t)))))
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:requires-3 ()
+  (match-expansion
+   (use-package foo :requires (bar quux))
+   `(when (not (member nil (mapcar #'featurep '(bar quux))))
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:requires-4 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :requires bar)
+     `(when (featurep 'bar)
+        (eval-and-compile
+          (eval-when-compile
+            (with-demoted-errors "Cannot load foo: %S" nil
+                                 (unless (featurep 'foo)
+                                   (load "foo" nil t)))))
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:load-path-1 ()
+  (match-expansion
+   (use-package foo :load-path "bar")
+   `(progn
+      (eval-and-compile
+        (add-to-list 'load-path
+                     ,(pred (apply-partially
+                             #'string=
+                             (expand-file-name
+                              "bar" user-emacs-directory)))))
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:load-path-2 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :load-path "bar")
+     `(progn
+        (eval-and-compile
+          (add-to-list 'load-path
+                       ,(pred (apply-partially
+                               #'string=
+                               (expand-file-name
+                                "bar" user-emacs-directory)))))
+        (eval-and-compile
+          (eval-when-compile
+            (with-demoted-errors "Cannot load foo: %S" nil
+                                 (unless (featurep 'foo)
+                                   (load "foo" nil t)))))
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:load-path-3 ()
+  (match-expansion
+   (use-package foo :load-path ("bar" "quux"))
+   `(progn
+      (eval-and-compile
+        (add-to-list 'load-path
+                     ,(pred (apply-partially
+                             #'string=
+                             (expand-file-name
+                              "bar" user-emacs-directory)))))
+      (eval-and-compile
+        (add-to-list 'load-path
+                     ,(pred (apply-partially
+                             #'string=
+                             (expand-file-name
+                              "quux" user-emacs-directory)))))
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:load-path-4 ()
+  (match-expansion
+   (use-package foo :load-path (lambda () (list "bar" "quux")))
+   `(progn
+      (eval-and-compile
+        (add-to-list 'load-path
+                     ,(pred (apply-partially
+                             #'string=
+                             (expand-file-name
+                              "bar" user-emacs-directory)))))
+      (eval-and-compile
+        (add-to-list 'load-path
+                     ,(pred (apply-partially
+                             #'string=
+                             (expand-file-name
+                              "quux" user-emacs-directory)))))
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:no-require-1 ()
+  (match-expansion
+   (use-package foo :no-require t)
+   `nil))
+
+(ert-deftest use-package-test/:no-require-2 ()
+  (match-expansion
+   (use-package foo :no-require t :config (config))
+   `(progn
+      (config)
+      t)))
+
+(ert-deftest use-package-test/:no-require-3 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :no-require t)
+     `(eval-and-compile
+        (eval-when-compile
+          (with-demoted-errors "Cannot load foo: %S" nil nil))))))
+
+(defun use-package-test-normalize-bind (&rest args)
+  (apply #'use-package-normalize-binder 'foo :bind args))
+
+(ert-deftest use-package-test-normalize/:bind-1 ()
+  (should (equal (use-package-test-normalize-bind
+                  '(("C-a" . alpha)))
+                 '(("C-a" . alpha)))))
+
+(ert-deftest use-package-test-normalize/:bind-2 ()
+  (should (equal (use-package-test-normalize-bind
+                  '(("C-a" . alpha)
+                    :map foo-map
+                    ("C-b" . beta)))
+                 '(("C-a" . alpha)
+                   :map foo-map
+                   ("C-b" . beta)))))
+
+(ert-deftest use-package-test-normalize/:bind-3 ()
+  (should (equal (use-package-test-normalize-bind
+                  '(:map foo-map
+                         ("C-a" . alpha)
+                         ("C-b" . beta)))
+                 '(:map foo-map
+                        ("C-a" . alpha)
+                        ("C-b" . beta)))))
+
+(ert-deftest use-package-test/:bind-1 ()
+  (match-expansion
+   (use-package foo :bind ("C-k" . key1) ("C-u" . key2))
+   `(progn
+      (unless
+          (fboundp 'key1)
+        (autoload #'key1 "foo" nil t))
+      (unless
+          (fboundp 'key2)
+        (autoload #'key2 "foo" nil t))
+      (bind-keys :package foo
+                 ("C-k" . key1)
+                 ("C-u" . key2)))))
+
+(ert-deftest use-package-test/:bind-2 ()
+  (match-expansion
+   (use-package foo :bind (("C-k" . key1) ("C-u" . key2)))
+   `(progn
+      (unless (fboundp 'key1)
+        (autoload #'key1 "foo" nil t))
+      (unless (fboundp 'key2)
+        (autoload #'key2 "foo" nil t))
+      (bind-keys :package foo
+                 ("C-k" . key1)
+                 ("C-u" . key2)))))
+
+(ert-deftest use-package-test/:bind-3 ()
+  (match-expansion
+   (use-package foo :bind (:map my-map ("C-k" . key1) ("C-u" . key2)))
+   `(progn
+      (unless
+          (fboundp 'key1)
+        (autoload #'key1 "foo" nil t))
+      (unless
+          (fboundp 'key2)
+        (autoload #'key2 "foo" nil t))
+      (bind-keys :package foo :map my-map
+                 ("C-k" . key1)
+                 ("C-u" . key2)))))
+
+(ert-deftest use-package-test/:bind-4 ()
+  (should-error
+   (match-expansion
+    (use-package foo :bind :map my-map ("C-k" . key1) ("C-u" . key2))
+    `(bind-keys :package foo))))
+
+(ert-deftest use-package-test/:bind-5 ()
+  (match-expansion
+   (use-package foo :bind ("C-k" . key1) (:map my-map ("C-u" . key2)))
+   `(progn
+      (unless (fboundp 'key1)
+        (autoload #'key1 "foo" nil t))
+      (unless (fboundp 'key2)
+        (autoload #'key2 "foo" nil t))
+      (bind-keys :package foo
+                 ("C-k" . key1)
+                 :map my-map
+                 ("C-u" . key2)))))
+
+(ert-deftest use-package-test/:bind-6 ()
+  (match-expansion
+   (use-package foo
+     :bind
+     ("C-k" . key1)
+     (:map my-map ("C-u" . key2))
+     (:map my-map2 ("C-u" . key3)))
+   `(progn
+      (unless (fboundp 'key1)
+        (autoload #'key1 "foo" nil t))
+      (unless (fboundp 'key2)
+        (autoload #'key2 "foo" nil t))
+      (unless (fboundp 'key3)
+        (autoload #'key3 "foo" nil t))
+      (bind-keys :package foo
+                 ("C-k" . key1)
+                 :map my-map ("C-u" . key2)
+                 :map my-map2 ("C-u" . key3)))))
+
+(ert-deftest use-package-test/:bind-7 ()
+  (match-expansion
+   (use-package foo
+     :ensure
+     :bind ("C-c r" . browse-at-remote))
+   `(progn
+      (use-package-ensure-elpa 'foo '(t) 'nil)
+      (unless (fboundp 'browse-at-remote)
+        (autoload #'browse-at-remote "foo" nil t))
+      (bind-keys :package foo ("C-c r" . browse-at-remote)))))
+
+(ert-deftest use-package-test/:bind-8 ()
+  (match-expansion
+   (use-package foo
+     :ensure
+     :bind (:map foo-map
+                 (("C-c r" . foo)
+                  ("C-c r" . bar))))
+   `(progn
+      (use-package-ensure-elpa 'foo '(t) 'nil)
+      (unless (fboundp 'foo)
+        (autoload #'foo "foo" nil t))
+      (unless (fboundp 'bar)
+        (autoload #'bar "foo" nil t))
+      (bind-keys :package foo :map foo-map
+                 ("C-c r" . foo)
+                 ("C-c r" . bar)))))
+
+(ert-deftest use-package-test/:bind*-1 ()
+  (match-expansion
+   (use-package foo :bind* ("C-k" . key))
+   `(progn
+      (unless (fboundp 'key)
+        (autoload #'key "foo" nil t))
+      (bind-keys* :package foo ("C-k" . key)))))
+
+(ert-deftest use-package-test/:bind-keymap-1 ()
+  (match-expansion
+   (use-package foo :bind-keymap ("C-k" . key))
+   `(bind-key "C-k"
+              #'(lambda nil
+                  (interactive)
+                  (use-package-autoload-keymap 'key 'foo nil)))))
+
+(ert-deftest use-package-test/:bind-keymap*-1 ()
+  (match-expansion
+   (use-package foo :bind-keymap* ("C-k" . key))
+   `(bind-key* "C-k"
+               #'(lambda ()
+                   (interactive)
+                   (use-package-autoload-keymap 'key 'foo t)))))
+
+(ert-deftest use-package-test/:interpreter-1 ()
+  (match-expansion
+   (use-package foo :interpreter "interp")
+   `(progn
+      (unless (fboundp 'foo)
+        (autoload #'foo "foo" nil t))
+      (add-to-list 'interpreter-mode-alist '("interp" . foo)))))
+
+(ert-deftest use-package-test/:interpreter-2 ()
+  (match-expansion
+   (use-package foo :interpreter ("interp" . fun))
+   `(progn
+      (unless (fboundp 'fun)
+        (autoload #'fun "foo" nil t))
+      (add-to-list 'interpreter-mode-alist '("interp" . fun)))))
+
+(ert-deftest use-package-test-normalize/:mode ()
+  (cl-flet ((norm (&rest args)
+                  (apply #'use-package-normalize/:mode
+                         'foopkg :mode args)))
+    (should (equal (norm '(".foo"))
+                   '((".foo" . foopkg))))
+    (should (equal (norm '(".foo" ".bar"))
+                   '((".foo" . foopkg) (".bar" . foopkg))))
+    (should (equal (norm '((".foo" ".bar")))
+                   '((".foo" . foopkg) (".bar" . foopkg))))
+    (should (equal (norm '((".foo")))
+                   '((".foo" . foopkg))))
+    (should (equal (norm '((".foo" . foo) (".bar" . bar)))
+                   '((".foo" . foo) (".bar" . bar))))))
+
+(ert-deftest use-package-test/:mode-1 ()
+  (match-expansion
+   (use-package foo :mode "interp")
+   `(progn
+      (unless (fboundp 'foo)
+        (autoload #'foo "foo" nil t))
+      (add-to-list 'auto-mode-alist '("interp" . foo)))))
+
+(ert-deftest use-package-test/:mode-2 ()
+  (match-expansion
+   (use-package foo :mode ("interp" . fun))
+   `(progn
+      (unless (fboundp 'fun)
+        (autoload #'fun "foo" nil t))
+      (add-to-list 'auto-mode-alist '("interp" . fun)))))
+
+(ert-deftest use-package-test/:magic-1 ()
+  (match-expansion
+   (use-package foo :magic "interp")
+   `(progn
+      (unless (fboundp 'foo)
+        (autoload #'foo "foo" nil t))
+      (add-to-list 'magic-mode-alist '("interp" . foo)))))
+
+(ert-deftest use-package-test/:magic-2 ()
+  (match-expansion
+   (use-package foo :magic ("interp" . fun))
+   `(progn
+      (unless (fboundp 'fun)
+        (autoload #'fun "foo" nil t))
+      (add-to-list 'magic-mode-alist '("interp" . fun)))))
+
+(ert-deftest use-package-test/:magic-fallback-1 ()
+  (match-expansion
+   (use-package foo :magic-fallback "interp")
+   `(progn
+      (unless (fboundp 'foo)
+        (autoload #'foo "foo" nil t))
+      (add-to-list 'magic-fallback-mode-alist '("interp" . foo)))))
+
+(ert-deftest use-package-test/:magic-fallback-2 ()
+  (match-expansion
+   (use-package foo :magic-fallback ("interp" . fun))
+   `(progn
+      (unless (fboundp 'fun)
+        (autoload #'fun "foo" nil t))
+      (add-to-list 'magic-fallback-mode-alist '("interp" . fun)))))
+
+(ert-deftest use-package-test/:commands-1 ()
+  (match-expansion
+   (use-package foo :commands bar)
+   `(unless (fboundp 'bar)
+      (autoload #'bar "foo" nil t))))
+
+(ert-deftest use-package-test/:commands-2 ()
+  (match-expansion
+   (use-package foo :commands (bar quux))
+   `(progn
+      (unless (fboundp 'bar)
+        (autoload #'bar "foo" nil t))
+      (unless (fboundp 'quux)
+        (autoload #'quux "foo" nil t)))))
+
+(ert-deftest use-package-test/:commands-3 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :commands (bar quux))
+     `(progn
+        (eval-and-compile
+          (eval-when-compile
+            (with-demoted-errors "Cannot load foo: %S" nil
+                                 (unless (featurep 'foo)
+                                   (load "foo" nil t)))))
+        (unless (fboundp 'bar)
+          (autoload #'bar "foo" nil t))
+        (eval-when-compile
+          (declare-function bar "foo"))
+        (unless (fboundp 'quux)
+          (autoload #'quux "foo" nil t))
+        (eval-when-compile
+          (declare-function quux "foo"))))))
+
+(ert-deftest use-package-test/:commands-4 ()
+  (match-expansion
+   (use-package foo :commands bar :init (bar))
+   `(progn
+      (unless
+          (fboundp 'bar)
+        (autoload #'bar "foo" nil t))
+      (bar))))
+
+(ert-deftest use-package-test/:commands-5 ()
+  (match-expansion
+   (use-package gnus-harvest
+     :load-path "foo"
+     :commands gnus-harvest-install
+     :demand t
+     :config
+     (if (featurep 'message-x)
+         (gnus-harvest-install 'message-x)
+       (gnus-harvest-install)))
+   `(progn
+      (eval-and-compile
+        (add-to-list 'load-path ,(pred stringp)))
+      (require 'gnus-harvest nil nil)
+      (if (featurep 'message-x)
+          (gnus-harvest-install 'message-x)
+        (gnus-harvest-install))
+      t)))
+
+(ert-deftest use-package-test/:commands-6 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package gnus-harvest
+       :load-path "foo"
+       :commands gnus-harvest-install
+       :demand t
+       :config
+       (if (featurep 'message-x)
+           (gnus-harvest-install 'message-x)
+         (gnus-harvest-install)))
+     `(progn
+        (eval-and-compile
+          (add-to-list 'load-path ,(pred stringp)))
+        (eval-and-compile
+          (eval-when-compile
+            (with-demoted-errors "Cannot load gnus-harvest: %S" nil
+                                 (unless (featurep 'gnus-harvest)
+                                   (load "gnus-harvest" nil t)))))
+        (eval-when-compile
+          (declare-function gnus-harvest-install "gnus-harvest"))
+        (require 'gnus-harvest nil nil)
+        (if
+            (featurep 'message-x)
+            (gnus-harvest-install 'message-x)
+          (gnus-harvest-install))
+        t))))
+
+(ert-deftest use-package-test/:autoload-1 ()
+  (match-expansion
+   (use-package foo :autoload bar)
+   `(unless (fboundp 'bar)
+      (autoload #'bar "foo"))))
+
+(ert-deftest use-package-test/:defines-1 ()
+  (match-expansion
+   (use-package foo :defines bar)
+   `(require 'foo nil nil)))
+
+(ert-deftest use-package-test/:defines-2 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :defines bar)
+     `(progn
+        (eval-and-compile
+          (defvar bar)
+          (eval-when-compile
+            (with-demoted-errors
+                "Cannot load foo: %S" nil
+                (unless (featurep 'foo)
+                  (load "foo" nil t)))))
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:functions-1 ()
+  (match-expansion
+   (use-package foo :functions bar)
+   `(require 'foo nil nil)))
+
+(ert-deftest use-package-test/:functions-2 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :functions bar)
+     `(progn
+        (eval-and-compile
+          (declare-function bar "foo")
+          (eval-when-compile
+            (with-demoted-errors
+                "Cannot load foo: %S" nil
+                (unless (featurep 'foo)
+                  (load "foo" nil t)))))
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:functions-3 ()
+  (match-expansion
+   (use-package foo :defer t :functions bar)
+   `nil))
+
+(ert-deftest use-package-test/:functions-4 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :defer t :functions bar)
+     `(eval-and-compile
+        (declare-function bar "foo")
+        (eval-when-compile
+          (with-demoted-errors "Cannot load foo: %S" nil
+                               (unless (featurep 'foo)
+                                 (load "foo" nil t))))))))
+
+(ert-deftest use-package-test/:functions-5 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :defer t :config (config) :functions bar)
+     `(progn
+        (eval-and-compile
+          (declare-function bar "foo")
+          (eval-when-compile
+            (with-demoted-errors
+                "Cannot load foo: %S" nil
+                (unless (featurep 'foo)
+                  (load "foo" nil t)))))
+        (eval-after-load 'foo
+          '(progn
+             (config)
+             t))))))
+
+(ert-deftest use-package-test/:defer-1 ()
+  (match-expansion
+   (use-package foo)
+   `(require 'foo nil nil)))
+
+(ert-deftest use-package-test/:defer-2 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo)
+     `(progn
+        (eval-and-compile
+          (eval-when-compile
+            (with-demoted-errors "Cannot load foo: %S" nil
+                                 (unless (featurep 'foo)
+                                   (load "foo" nil t)))))
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:defer-3 ()
+  (match-expansion
+   (use-package foo :defer t)
+   `nil))
+
+(ert-deftest use-package-test/:defer-4 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :defer t)
+     `(eval-and-compile
+        (eval-when-compile
+          (with-demoted-errors "Cannot load foo: %S" nil
+                               (unless (featurep 'foo)
+                                 (load "foo" nil t))))))))
+
+(ert-deftest use-package-test-normalize/:hook ()
+  (cl-flet ((norm (&rest args)
+                  (apply #'use-package-normalize/:hook
+                         'foopkg :hook args)))
+    (should-error (norm nil))
+    (should (equal (norm '(bar))
+                   '((bar . foopkg-mode))))
+    (should (equal (norm '((bar . foopkg)))
+                   '((bar . foopkg))))
+    (should (equal (norm '((bar . baz)))
+                   '((bar . baz))))
+    (should (equal (norm '(((bar baz) . quux)))
+                   '(((bar baz) . quux))))
+    (should (equal (norm '(bar baz))
+                   '(((bar baz) . foopkg-mode))))
+    (should (equal (norm '((bar baz) (quux bow)))
+                   '(((bar baz) . foopkg-mode) ((quux bow) . foopkg-mode))))
+    (should (equal (norm '((bar . baz) (quux . bow)))
+                   '((bar . baz) (quux . bow))))
+    (should (equal (norm '(((bar1 bar2) . baz) ((quux1 quux2) . bow)))
+                   '(((bar1 bar2) . baz) ((quux1 quux2) . bow))))))
+
+(ert-deftest use-package-test/:hook-1 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo
+       :bind (("C-a" . key))
+       :hook (hook . fun))
+     `(progn
+        (eval-and-compile
+          (eval-when-compile
+            (with-demoted-errors
+                "Cannot load foo: %S" nil
+                (unless (featurep 'foo)
+                  (load "foo" nil t)))))
+        (unless
+            (fboundp 'key)
+          (autoload #'key "foo" nil t))
+        (eval-when-compile
+          (declare-function key "foo"))
+        (unless
+            (fboundp 'fun)
+          (autoload #'fun "foo" nil t))
+        (eval-when-compile
+          (declare-function fun "foo"))
+        (add-hook 'hook-hook #'fun)
+        (bind-keys :package foo ("C-a" . key))))))
+
+(ert-deftest use-package-test/:hook-2 ()
+  (match-expansion
+   (use-package foo
+     :hook (hook . fun))
+   `(progn
+      (unless (fboundp 'fun)
+        (autoload #'fun "foo" nil t))
+      (add-hook 'hook-hook #'fun))))
+
+(ert-deftest use-package-test/:hook-3 ()
+  (let ((use-package-hook-name-suffix nil))
+    (match-expansion
+     (use-package foo
+       :hook (hook . fun))
+     `(progn
+        (unless (fboundp 'fun)
+          (autoload #'fun "foo" nil t))
+        (add-hook 'hook #'fun)))))
+
+(ert-deftest use-package-test/:hook-4 ()
+  (let ((use-package-hook-name-suffix "-special"))
+    (match-expansion
+     (use-package foo
+       :hook (hook . fun))
+     `(progn
+        (unless (fboundp 'fun)
+          (autoload #'fun "foo" nil t))
+        (add-hook 'hook-special #'fun)))))
+
+(ert-deftest use-package-test/:hook-5 ()
+  (match-expansion
+   (use-package erefactor
+     :load-path "foo"
+     :after elisp-mode
+     :load t
+     :hook (emacs-lisp-mode
+            . (lambda ()
+                (bind-key "\C-c\C-v" erefactor-map emacs-lisp-mode-map))))
+   `(progn
+      (eval-and-compile
+        (add-to-list 'load-path ,(pred stringp)))
+      (eval-after-load 'elisp-mode
+        '(progn
+           (require 'erefactor nil nil)
+           (add-hook
+            'emacs-lisp-mode-hook
+            #'(lambda nil
+                (bind-key "" erefactor-map emacs-lisp-mode-map))))))))
+
+(ert-deftest use-package-test/:hook-6 ()
+  (match-expansion
+   (use-package erefactor
+     :load-path "foo"
+     :after elisp-mode
+     :hook (emacs-lisp-mode . function))
+   `(progn
+      (eval-and-compile
+        (add-to-list 'load-path ,(pred stringp)))
+      (eval-after-load 'elisp-mode
+        '(progn
+           (unless (fboundp 'function)
+             (autoload #'function "erefactor" nil t))
+           (add-hook 'emacs-lisp-mode-hook #'function))))))
+
+(ert-deftest use-package-test/:hook-7 ()
+  (match-expansion
+   (use-package erefactor
+     :load-path "foo"
+     :after elisp-mode
+     :hook (emacs-lisp-mode . (lambda () (function))))
+   `(progn
+      (eval-and-compile
+        (add-to-list 'load-path ,(pred stringp)))
+      (eval-after-load 'elisp-mode
+        '(progn
+           (require 'erefactor nil nil)
+           (add-hook 'emacs-lisp-mode-hook #'(lambda nil (function))))))))
+
+(ert-deftest use-package-test-normalize/:custom ()
+  (cl-flet ((norm (&rest args)
+                  (apply #'use-package-normalize/:custom
+                         'foopkg :custom args)))
+    (should-error (norm nil))
+    (should-error (norm '(bar)))
+    ;; (should-error (norm '((foo bar baz quux))))
+    (should (equal (norm '(foo bar)) '((foo bar))))
+    ;; (should-error (norm '(foo bar baz)))
+    ;; (should (equal (norm '(foo bar "baz"))
+    ;;                '((foo bar baz))))
+    ))
+
+
+(ert-deftest use-package-test/:custom-1 ()
+  (match-expansion
+   (use-package foo :custom (foo bar))
+   `(progn
+      (let
+          ((custom--inhibit-theme-enable nil))
+        (unless (memq 'use-package custom-known-themes)
+          (deftheme use-package)
+          (enable-theme 'use-package)
+          (setq custom-enabled-themes (remq 'use-package 
custom-enabled-themes)))
+        (custom-theme-set-variables 'use-package
+                                    '(foo bar nil nil "Customized with 
use-package foo")))
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:custom-with-comment1 ()
+  (match-expansion
+   (use-package foo :custom (foo bar "commented"))
+   `(progn
+      (let
+          ((custom--inhibit-theme-enable nil))
+        (unless (memq 'use-package custom-known-themes)
+          (deftheme use-package)
+          (enable-theme 'use-package)
+          (setq custom-enabled-themes (remq 'use-package 
custom-enabled-themes)))
+        (custom-theme-set-variables 'use-package
+                                    '(foo bar nil nil "commented")))
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:custom-face-1 ()
+  (match-expansion
+   (use-package foo :custom-face (foo ((t (:background "#e4edfc")))))
+   `(progn
+      (apply #'face-spec-set (backquote (foo ((t (:background "#e4edfc"))))))
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:custom-face-2 ()
+  (match-expansion
+   (use-package example
+     :custom-face
+     (example-1-face ((t (:foreground "LightPink"))))
+     (example-2-face ((t (:foreground "LightGreen")))))
+   `(progn
+      (apply #'face-spec-set
+             (backquote (example-1-face ((t (:foreground "LightPink"))))))
+      (apply #'face-spec-set
+             (backquote (example-2-face ((t (:foreground "LightGreen"))))))
+      (require 'example nil nil))))
+
+(ert-deftest use-package-test/:custom-face-3 ()
+  (match-expansion
+   (use-package foo :custom-face (foo ((t (:background "#e4edfc"))) 
face-defspec-spec))
+   `(progn
+      (apply #'face-spec-set (backquote (foo ((t (:background "#e4edfc"))) 
face-defspec-spec)))
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:init-1 ()
+  (match-expansion
+   (use-package foo :init (init))
+   `(progn
+      (init)
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:init-2 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :init (init))
+     `(progn
+        (eval-and-compile
+          (eval-when-compile
+            (with-demoted-errors "Cannot load foo: %S" nil
+                                 (unless (featurep 'foo)
+                                   (load "foo" nil t)))))
+        (init)
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:catch-1 ()
+  (match-expansion
+   (use-package foo :catch t)
+   `(progn
+      (defvar ,_
+        #'(lambda (keyword err)
+            (let ((msg (format "%s/%s: %s" 'foo keyword
+                               (error-message-string err))))
+              (display-warning 'use-package msg :error))))
+      (condition-case-unless-debug err
+          (require 'foo nil nil)
+        (error
+         (funcall ,_ :catch err))))))
+
+(ert-deftest use-package-test/:catch-2 ()
+  (match-expansion
+   (use-package foo :catch nil)
+   `(require 'foo nil nil)))
+
+(ert-deftest use-package-test/:catch-3 ()
+  (match-expansion
+   (use-package foo :catch (lambda (keyword error)))
+   `(progn
+      (defvar ,_ (lambda (keyword error)))
+      (condition-case-unless-debug err
+          (require 'foo nil nil)
+        (error
+         (funcall ,_ :catch err))))))
+
+(ert-deftest use-package-test/:after-1 ()
+  (match-expansion
+   (use-package foo :after bar)
+   `(eval-after-load 'bar
+      '(require 'foo nil nil))))
+
+(ert-deftest use-package-test/:after-2 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :after bar)
+     `(progn
+        (eval-and-compile
+          (eval-when-compile
+            (with-demoted-errors "Cannot load foo: %S" nil
+                                 (unless (featurep 'foo)
+                                   (load "foo" nil t)))))
+        (eval-after-load 'bar
+          '(require 'foo nil nil))))))
+
+(ert-deftest use-package-test/:after-3 ()
+  (match-expansion
+   (use-package foo :after (bar quux))
+   `(eval-after-load 'quux
+      '(eval-after-load 'bar
+         '(require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:after-4 ()
+  (match-expansion
+   (use-package foo :after (:all bar quux))
+   `(eval-after-load 'quux
+      '(eval-after-load 'bar
+         '(require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:after-5 ()
+  (match-expansion
+   (use-package foo :after (:any bar quux))
+   `(progn
+      (defvar ,_ nil)
+      (defvar ,_ nil)
+      (defvar ,_
+        #'(lambda nil
+            (if ,_ ,_
+              (setq ,_ t ,_
+                    (require 'foo nil nil)))))
+      (eval-after-load 'bar
+        '(funcall ,_))
+      (eval-after-load 'quux
+        '(funcall ,_)))))
+
+(ert-deftest use-package-test/:after-6 ()
+  (match-expansion
+   (use-package foo :after (:all (:any bar quux) bow))
+   `(progn
+      (defvar ,_ nil)
+      (defvar ,_ nil)
+      (defvar ,_
+        #'(lambda nil
+            (if ,_ ,_
+              (setq ,_ t ,_
+                    (require 'foo nil nil)))))
+      (eval-after-load 'bow
+        '(progn
+           (eval-after-load 'bar
+             '(funcall ,_))
+           (eval-after-load 'quux
+             '(funcall ,_)))))))
+
+(ert-deftest use-package-test/:after-7 ()
+  (match-expansion
+   (use-package foo :after (:any (:all bar quux) bow))
+   `(progn
+      (defvar ,_ nil)
+      (defvar ,_ nil)
+      (defvar ,_
+        #'(lambda nil
+            (if ,_ ,_
+              (setq ,_ t ,_
+                    (require 'foo nil nil)))))
+      (eval-after-load 'quux
+        '(eval-after-load 'bar
+           '(funcall ,_)))
+      (eval-after-load 'bow
+        '(funcall ,_)))))
+
+(ert-deftest use-package-test/:after-8 ()
+  (match-expansion
+   (use-package foo :after (:all (:any bar quux) (:any bow baz)))
+   `(progn
+      (defvar ,_ nil)
+      (defvar ,_ nil)
+      (defvar ,_
+        #'(lambda nil
+            (if ,_ ,_
+              (setq ,_ t ,_
+                    (require 'foo nil nil)))))
+      (eval-after-load 'bow
+        '(progn
+           (eval-after-load 'bar
+             '(funcall ,_))
+           (eval-after-load 'quux
+             '(funcall ,_))))
+      (eval-after-load 'baz
+        '(progn
+           (eval-after-load 'bar
+             '(funcall ,_))
+           (eval-after-load 'quux
+             '(funcall ,_)))))))
+
+(ert-deftest use-package-test/:after-9 ()
+  (match-expansion
+   (use-package foo :after (:any (:all bar quux) (:all bow baz)))
+   `(progn
+      (defvar ,_ nil)
+      (defvar ,_ nil)
+      (defvar ,_
+        #'(lambda nil
+            (if ,_ ,_
+              (setq ,_ t ,_
+                    (require 'foo nil nil)))))
+      (eval-after-load 'quux
+        '(eval-after-load 'bar
+           '(funcall ,_)))
+      (eval-after-load 'baz
+        '(eval-after-load 'bow
+           '(funcall ,_))))))
+
+(ert-deftest use-package-test/:after-10 ()
+  (match-expansion
+   (use-package foo :after (:any (:all bar quux) (:any bow baz)))
+   `(progn
+      (defvar ,_ nil)
+      (defvar ,_ nil)
+      (defvar ,_
+        #'(lambda nil
+            (if ,_ ,_
+              (setq ,_ t ,_
+                    (require 'foo nil nil)))))
+      (eval-after-load 'quux
+        '(eval-after-load 'bar
+           '(funcall ,_)))
+      (eval-after-load 'bow
+        '(funcall ,_))
+      (eval-after-load 'baz
+        '(funcall ,_)))))
+
+(ert-deftest use-package-test/:demand-1 ()
+  (match-expansion
+   (use-package foo :demand t)
+   `(require 'foo nil nil)))
+
+(ert-deftest use-package-test/:demand-2 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :demand t)
+     `(progn
+        (eval-and-compile
+          (eval-when-compile
+            (with-demoted-errors "Cannot load foo: %S" nil
+                                 (unless (featurep 'foo)
+                                   (load "foo" nil t)))))
+        (require 'foo nil nil)))))
+
+(ert-deftest use-package-test/:demand-3 ()
+  (match-expansion
+   (use-package foo :demand t :config (config))
+   `(progn
+      (require 'foo nil nil)
+      (config)
+      t)))
+
+(ert-deftest use-package-test/:demand-4 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :demand t :config (config))
+     `(progn
+        (eval-and-compile
+          (eval-when-compile
+            (with-demoted-errors "Cannot load foo: %S" nil
+                                 (unless (featurep 'foo)
+                                   (load "foo" nil t)))))
+        (require 'foo nil nil)
+        (config)
+        t))))
+
+(ert-deftest use-package-test/:demand-5 ()
+  ;; #529 - :demand should not override an explicit use of :after
+  (match-expansion
+   (use-package foo :demand t :after bar)
+   `(eval-after-load 'bar
+      '(require 'foo nil nil))))
+
+(ert-deftest use-package-test/:demand-6 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :demand t :after bar)
+     `(progn
+        (eval-and-compile
+          (eval-when-compile
+            (with-demoted-errors "Cannot load foo: %S" nil
+                                 (unless (featurep 'foo)
+                                   (load "foo" nil t)))))
+        (eval-after-load 'bar
+          '(require 'foo nil nil))))))
+
+(ert-deftest use-package-test/:demand-7 ()
+  (match-expansion
+   (use-package counsel
+     :load-path "foo"
+     :after ivy
+     :demand t
+     :diminish
+     :bind (("C-*" . counsel-org-agenda-headlines)
+            ("M-x" . counsel-M-x))
+     :commands (counsel-minibuffer-history
+                counsel-find-library
+                counsel-unicode-char)
+     :preface (preface-code)
+     :init
+     ;; This is actually wrong, but it's just part of the example.
+     (define-key minibuffer-local-map (kbd "M-r")
+       'counsel-minibuffer-history))
+   `(progn
+      (eval-and-compile
+        (add-to-list 'load-path ,(pred stringp)))
+      (eval-and-compile
+        (preface-code))
+      (eval-after-load 'ivy
+        '(progn
+           (define-key minibuffer-local-map (kbd "M-r")
+             'counsel-minibuffer-history)
+           (require 'counsel nil nil)
+           (if (fboundp 'diminish)
+               (diminish 'counsel-mode))
+           (bind-keys :package counsel
+                      ("C-*" . counsel-org-agenda-headlines)
+                      ("M-x" . counsel-M-x)))))))
+
+(ert-deftest use-package-test/:config-1 ()
+  (match-expansion
+   (use-package foo :config (config))
+   `(progn
+      (require 'foo nil nil)
+      (config)
+      t)))
+
+(ert-deftest use-package-test/:config-2 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :config (config))
+     `(progn
+        (eval-and-compile
+          (eval-when-compile
+            (with-demoted-errors "Cannot load foo: %S" nil
+                                 (unless (featurep 'foo)
+                                   (load "foo" nil t)))))
+        (require 'foo nil nil)
+        (config)
+        t))))
+
+(ert-deftest use-package-test/:config-3 ()
+  (match-expansion
+   (use-package foo :defer t :config (config))
+   `(eval-after-load 'foo
+      '(progn
+         (config)
+         t))))
+
+(ert-deftest use-package-test/:config-4 ()
+  (let ((byte-compile-current-file t))
+    (match-expansion
+     (use-package foo :defer t :config (config))
+     `(progn
+        (eval-and-compile
+          (eval-when-compile
+            (with-demoted-errors "Cannot load foo: %S" nil
+                                 (unless (featurep 'foo)
+                                   (load "foo" nil t)))))
+        (eval-after-load 'foo
+          '(progn
+             (config)
+             t))))))
+
+(ert-deftest use-package-test-normalize/:diminish ()
+  (should (equal (use-package-normalize-diminish 'foopkg :diminish nil)
+                 '(foopkg-mode)))
+  (should (equal (use-package-normalize-diminish 'foopkg :diminish 'bar)
+                 '(bar)))
+  (should (equal (use-package-normalize-diminish 'foopkg :diminish "bar")
+                 '((foopkg-mode . "bar"))))
+  (should (equal (use-package-normalize-diminish 'foopkg :diminish 'foo-mode)
+                 '(foo-mode)))
+  (should (equal (use-package-normalize-diminish 'foopkg :diminish '(foo . 
"bar"))
+                 '((foo . "bar")))))
+
+(ert-deftest use-package-test/:diminish-1 ()
+  (match-expansion
+   (use-package foo :diminish nil)
+   `(progn
+      (require 'foo nil nil)
+      (if (fboundp 'diminish)
+          (diminish 'foo-mode)))))
+
+(ert-deftest use-package-test/:diminish-2 ()
+  (match-expansion
+   (use-package foo :diminish bar)
+   `(progn
+      (require 'foo nil nil)
+      (if (fboundp 'diminish)
+          (diminish 'bar)))))
+
+(ert-deftest use-package-test/:diminish-3 ()
+  (match-expansion
+   (use-package foo :diminish "bar")
+   `(progn
+      (require 'foo nil nil)
+      (if (fboundp 'diminish)
+          (diminish 'foo-mode "bar")))))
+
+(ert-deftest use-package-test/:diminish-4 ()
+  (match-expansion
+   (use-package foo :diminish (foo . "bar"))
+   `(progn
+      (require 'foo nil nil)
+      (if (fboundp 'diminish)
+          (diminish 'foo "bar")))))
+
+(ert-deftest use-package-test-normalize/:delight ()
+  (should (equal `((foo-mode nil foo))
+                 (use-package-normalize/:delight 'foo :delight nil)))
+  (should (equal `((foo-mode nil foo-mode))
+                 (use-package-normalize/:delight 'foo-mode :delight nil)))
+  (should (equal `((bar-mode nil foo))
+                 (use-package-normalize/:delight 'foo :delight '(bar-mode))))
+  (should (equal `((bar-mode nil :major))
+                 (use-package-normalize/:delight 'foo :delight '((bar-mode nil 
:major)))))
+  (should (equal `((foo-mode "abc" foo))
+                 (use-package-normalize/:delight 'foo :delight '("abc"))))
+  (should (equal `((foo-mode (:eval 1) foo))
+                 (use-package-normalize/:delight 'foo :delight '('(:eval 1)))))
+  (should (equal (use-package-normalize/:delight 'foo :delight '((a-mode) 
(b-mode " b")))
+                 `((a-mode nil foo) (b-mode " b" foo))))
+  (should-error (use-package-normalize/:delight 'foo :delight '((:eval 1)))))
+
+(ert-deftest use-package-test/:delight-1 ()
+  (match-expansion
+   (use-package foo :delight)
+   `(progn
+      (require 'foo nil nil)
+      (if (fboundp 'delight)
+          (delight '((foo-mode nil foo)))))))
+
+(ert-deftest use-package-test/:delight-2 ()
+  (should-error
+   (match-expansion
+    (use-package foo :delight nil)
+    `(progn
+       (require 'foo nil nil)
+       (if (fboundp 'diminish)
+           (diminish 'foo-mode))))))
+
+(ert-deftest use-package-test/:delight-3 ()
+  (match-expansion
+   (use-package foo :delight bar)
+   `(progn
+      (require 'foo nil nil)
+      (if (fboundp 'delight)
+          (delight '((bar nil foo)))))))
+
+(ert-deftest use-package-test/:delight-4 ()
+  (match-expansion
+   (use-package foo :delight "bar")
+   `(progn
+      (require 'foo nil nil)
+      (if (fboundp 'delight)
+          (delight '((foo-mode "bar" foo)))))))
+
+(ert-deftest use-package-test/:delight-5 ()
+  (should-error
+   (match-expansion
+    (use-package foo :delight (foo . "bar"))
+    `(progn
+       (require 'foo nil nil)
+       (if (fboundp 'diminish)
+           (diminish 'foo "bar"))))))
+
+(ert-deftest use-package-test/:delight-6 ()
+  (match-expansion
+   (use-package foo :delight (foo "bar"))
+   `(progn
+      (require 'foo nil nil)
+      (if (fboundp 'delight)
+          (delight '((foo "bar" foo)))))))
+
+(ert-deftest use-package-test/334-1 ()
+  (let (foo1-map foo2-map
+                 bar1-func1
+                 bar1-func2
+                 bar2-func1
+                 bar2-func2
+                 bar3-func1
+                 bar3-func2
+                 bar4-func1
+                 bar4-func2)
+    (match-expansion
+     (bind-keys :map foo1-map
+                ("Y" . foo1)
+                :prefix "y"
+                :prefix-map bar1-prefix-map
+                ("y" . bar1-func1)
+                ("f" . bar1-func2)
+                :prefix "y"
+                :prefix-map bar2-prefix-map
+                ("y" . bar2-func1)
+                ("f" . bar2-func2)
+                :map foo2-map
+                ("Y" . foo2)
+                :prefix "y"
+                :prefix-map bar3-prefix-map
+                ("y" . bar3-func1)
+                ("f" . bar3-func2)
+                :prefix "y"
+                :prefix-map bar4-prefix-map
+                ("y" . bar4-func1)
+                ("f" . bar4-func2))
+     `(progn
+        (bind-key "Y" #'foo1 foo1-map nil)
+        (defvar bar1-prefix-map)
+        (define-prefix-command 'bar1-prefix-map)
+        (bind-key "y" 'bar1-prefix-map foo1-map nil)
+        (bind-key "y" #'bar1-func1 bar1-prefix-map nil)
+        (bind-key "f" #'bar1-func2 bar1-prefix-map nil)
+        (defvar bar2-prefix-map)
+        (define-prefix-command 'bar2-prefix-map)
+        (bind-key "y" 'bar2-prefix-map foo1-map nil)
+        (bind-key "y" #'bar2-func1 bar2-prefix-map nil)
+        (bind-key "f" #'bar2-func2 bar2-prefix-map nil)
+        (bind-key "Y" #'foo2 foo2-map nil)
+        (defvar bar3-prefix-map)
+        (define-prefix-command 'bar3-prefix-map)
+        (bind-key "y" 'bar3-prefix-map foo2-map nil)
+        (bind-key "y" #'bar3-func1 bar3-prefix-map nil)
+        (bind-key "f" #'bar3-func2 bar3-prefix-map nil)
+        (defvar bar4-prefix-map)
+        (define-prefix-command 'bar4-prefix-map)
+        (bind-key "y" 'bar4-prefix-map foo2-map nil)
+        (bind-key "y" #'bar4-func1 bar4-prefix-map nil)
+        (bind-key "f" #'bar4-func2 bar4-prefix-map nil)))))
+
+(ert-deftest use-package-test/334-2 ()
+  (let (w3m-lnum-mode-map
+        w3m-print-current-url
+        w3m-lnum-print-this-url
+        w3m-print-this-url)
+    (match-expansion
+     (bind-keys :map w3m-lnum-mode-map
+                :prefix "y"
+                :prefix-map w3m-y-prefix-map
+                ("y" . w3m-print-current-url)
+                ("f" . w3m-lnum-print-this-url)
+                ("t" . w3m-print-this-url))
+     `(progn
+        (defvar w3m-y-prefix-map)
+        (define-prefix-command 'w3m-y-prefix-map)
+        (bind-key "y" 'w3m-y-prefix-map w3m-lnum-mode-map nil)
+        (bind-key "y" #'w3m-print-current-url w3m-y-prefix-map nil)
+        (bind-key "f" #'w3m-lnum-print-this-url w3m-y-prefix-map nil)
+        (bind-key "t" #'w3m-print-this-url w3m-y-prefix-map nil)))))
+
+(ert-deftest use-package-test/482-1 ()
+  (match-expansion
+   (use-package simple
+     :bind-keymap ("C-t " . my/transpose-map)
+     :bind (:map my/transpose-map
+                ("w" . transpose-words)))
+   `(progn
+      (unless (fboundp 'transpose-words)
+        (autoload #'transpose-words "simple" nil t))
+      (bind-key "C-t "
+                #'(lambda nil
+                    (interactive)
+                    (use-package-autoload-keymap 'my/transpose-map 'simple 
nil)))
+      (bind-keys :package simple :map my/transpose-map
+                 ("w" . transpose-words)))))
+
+(ert-deftest use-package-test/482-2 ()
+  (match-expansion
+   (use-package simple
+     :bind (:prefix-map my/transpose-map
+                        :prefix "C-t"
+                        ("w" . transpose-words)))
+   `(progn
+      (unless (fboundp 'transpose-words)
+        (autoload #'transpose-words "simple" nil t))
+      (bind-keys :package simple
+                 :prefix-map my/transpose-map
+                 :prefix "C-t"
+                 ("w" . transpose-words)))))
+
+(ert-deftest use-package-test/482-3 ()
+  (match-expansion
+   (bind-keys :package simple
+              :prefix-map my/transpose-map
+              :prefix "C-t"
+              ("w" . transpose-words))
+   `(progn
+      (defvar my/transpose-map)
+      (define-prefix-command 'my/transpose-map)
+      (bind-key "C-t" 'my/transpose-map nil nil)
+      (bind-key "w" #'transpose-words my/transpose-map nil))))
+
+(ert-deftest use-package-test/538 ()
+  (match-expansion
+   (use-package mu4e
+     :commands (mu4e)
+     :bind (("<f9>" . mu4e))
+     :init
+     :config
+     (config))
+   `(progn
+      (unless (fboundp 'mu4e)
+        (autoload #'mu4e "mu4e" nil t))
+      (eval-after-load 'mu4e
+        '(progn (config) t))
+      (bind-keys :package mu4e ("<f9>" . mu4e)))))
+
+(ert-deftest use-package-test/543 ()
+  (match-expansion
+   (use-package hydra
+     :ensure)
+   `(progn
+      (use-package-ensure-elpa 'hydra '(t) 'nil)
+      (require 'hydra nil nil))))
+
+(ert-deftest use-package-test/545 ()
+  (match-expansion
+   (use-package spacemacs-theme
+     :ensure t
+     :init                                 ; or :config
+     (load-theme 'spacemacs-dark t)
+     )
+   `(progn
+      (use-package-ensure-elpa 'spacemacs-theme '(t) 'nil)
+      (load-theme 'spacemacs-dark t)
+      (require 'spacemacs-theme nil nil))
+   ))
+
+(ert-deftest use-package-test/550 ()
+  (match-expansion
+   (use-package company-try-hard
+     :ensure t
+     :bind
+     ("C-c M-/" . company-try-hard)
+     (:map company-active-map
+           ("C-c M-/" . company-try-hard)))
+   `(progn
+      (use-package-ensure-elpa 'company-try-hard
+                               '(t)
+                               'nil)
+      (unless
+          (fboundp 'company-try-hard)
+        (autoload #'company-try-hard "company-try-hard" nil t))
+      (bind-keys :package company-try-hard
+                 ("C-c M-/" . company-try-hard)
+                 :map company-active-map
+                 ("C-c M-/" . company-try-hard)))))
+
+(ert-deftest use-package-test/558 ()
+  (match-expansion
+   (bind-keys* :package org-ref
+               ("C-c C-r" . org-ref-helm-insert-cite-link))
+   `(bind-key "C-c C-r" #'org-ref-helm-insert-cite-link override-global-map 
nil)))
+
+(ert-deftest use-package-test/560 ()
+  (cl-letf (((symbol-function #'executable-find) #'ignore))
+    (let (notmuch-command)
+      (match-expansion
+       (use-package notmuch
+         :preface (setq-default notmuch-command (executable-find "notmuch"))
+         :if notmuch-command
+         :requires foo
+         :load-path "foo"
+         :defines var)
+       `(progn
+          (eval-and-compile
+            (add-to-list 'load-path ,(pred stringp)))
+          (when (featurep 'foo)
+            (eval-and-compile
+              (setq-default notmuch-command
+                            (executable-find "notmuch")))
+            (when (symbol-value 'notmuch-command)
+              (require 'notmuch nil nil))))))))
+
+(ert-deftest use-package-test/572-1 ()
+  (let ((use-package-always-defer t))
+    (match-expansion
+     (use-package auth-password-store
+       :after auth-source
+       :init
+       (setq auth-sources '(password-store)))
+     `(eval-after-load 'auth-source
+        '(setq auth-sources '(password-store))))))
+
+(ert-deftest use-package-test/572-2 ()
+  (let ((use-package-always-defer t))
+    (match-expansion
+     (use-package ivy-hydra :after ivy)
+     `nil)))
+
+(ert-deftest use-package-test/572-3 ()
+  (let ((use-package-always-defer t)
+        (use-package-defaults
+         (let ((defaults (copy-alist use-package-defaults)))
+           (setcdr (assq :defer defaults)
+                   '(use-package-always-defer
+                     (lambda (name args)
+                       (and use-package-always-defer
+                            (not (plist-member args :after))
+                            (not (plist-member args :defer))
+                            (not (plist-member args :demand))))))
+           defaults)))
+    (match-expansion
+     (use-package ivy-hydra :after ivy)
+     `(eval-after-load 'ivy
+        '(require 'ivy-hydra nil nil)))))
+
+(ert-deftest use-package-test/575-1 ()
+  (match-expansion
+   (use-package helm
+     :defer t
+     :after (:any ido dired)
+     :config
+     (message "test. helm start"))
+   `(progn
+      (defvar ,_ nil)
+      (defvar ,_ nil)
+      (defvar ,_
+        #'(lambda nil
+            (if ,_ ,_
+              (setq ,_ t ,_
+                    (eval-after-load 'helm
+                      '(progn
+                         (message "test. helm start")
+                         t))))))
+      (eval-after-load 'ido
+        '(funcall ,_))
+      (eval-after-load 'dired
+        '(funcall ,_)))))
+
+(ert-deftest use-package-test/575-2 ()
+  (match-expansion
+   (use-package helm
+     :defer t
+     :bind ("C-c d" . helm-mini)
+     :config
+     (message "test. helm start"))
+   `(progn
+      (unless (fboundp 'helm-mini)
+        (autoload #'helm-mini "helm" nil t))
+      (eval-after-load 'helm
+        '(progn
+           (message "test. helm start")
+           t))
+      (bind-keys :package helm ("C-c d" . helm-mini)))))
+
+(ert-deftest use-package-test/585 ()
+  (match-expansion
+   (use-package bug
+     :bind (:map bug-map ("C-a" . alpha))
+     :bind (("C-b" . beta)))
+   `(progn
+      (unless (fboundp 'alpha)
+        (autoload #'alpha "bug" nil t))
+      (unless (fboundp 'beta)
+        (autoload #'beta "bug" nil t))
+      (bind-keys :package bug :map bug-map
+                 ("C-a" . alpha))
+      (bind-keys :package bug
+                 ("C-b" . beta)))))
+
+(ert-deftest use-package-test/589 ()
+  (let ((use-package-verbose t)
+        (use-package-expand-minimally t)
+        debug-on-error
+        warnings)
+    (cl-letf (((symbol-function #'display-warning)
+               (lambda (_ msg _) (push msg warnings))))
+      (progn
+        (macroexpand-1
+         '(use-package ediff :defer t (setq my-var t)))
+        (should (= (and (> (length warnings) 0)
+                        (string-match ":defer wants exactly one argument"
+                                      (car warnings))) 44))))))
+
+(ert-deftest use-package-test/591 ()
+  (let ((use-package-defaults
+         (cons '(:if (lambda (name _) `(locate-library ,name)) t)
+               use-package-defaults)))
+    (match-expansion
+     (use-package nonexistent
+       :hook lisp-mode)
+     `(when (locate-library nonexistent)
+        (unless (fboundp 'nonexistent-mode)
+          (autoload #'nonexistent-mode "nonexistent" nil t))
+        (add-hook 'lisp-mode-hook #'nonexistent-mode)))))
+
+(ert-deftest bind-key/:prefix-map ()
+  (match-expansion
+   (bind-keys :prefix "<f1>"
+              :prefix-map my/map)
+   `(progn
+      (defvar my/map)
+      (define-prefix-command 'my/map)
+      (bind-key "<f1>" 'my/map nil nil))))
+
+
+(ert-deftest bind-key/845 ()
+  (defvar test-map (make-keymap))
+  (bind-key "<f1>" 'ignore 'test-map)
+  (should (eq (lookup-key test-map (kbd "<f1>")) 'ignore))
+  (let ((binding (cl-find "<f1>" personal-keybindings :test 'string= :key 
'caar)))
+    (message "test-map %s" test-map)
+    (message "binding %s" binding)
+    (should (eq (cdar binding) 'test-map))
+    (should (eq (nth 1 binding) 'ignore))
+    (should (eq (nth 2 binding) nil))))
+
+;; Local Variables:
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; End:
+
+;;; use-package-tests.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]