Commit 1b961a9d170a

Vincent Demeester <vincent@sbr.pm>
2017-09-09 14:23:55
Update use-package
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
1 parent cf803aa
Changed files (4)
.emacs.d/lisp/use-package/bind-key.el
@@ -91,6 +91,8 @@
 ;; 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)
 
@@ -241,9 +243,9 @@ function symbol (unquoted)."
       (cl-flet
           ((wrap (map bindings)
                  (if (and map pkg (not (eq map 'global-map)))
-                     (if (boundp map)
-                         bindings
-                       `((eval-after-load
+                     `((if (boundp ',map)
+                           (progn ,@bindings)
+                         (eval-after-load
                              ,(if (symbolp pkg) `',pkg pkg)
                            '(progn ,@bindings))))
                    bindings)))
@@ -407,6 +409,7 @@ function symbol (unquoted)."
 (provide 'bind-key)
 
 ;; Local Variables:
+;; outline-regexp: ";;;\\(;* [^\s\t\n]\\|###autoload\\)\\|("
 ;; indent-tabs-mode: nil
 ;; End:
 
.emacs.d/lisp/use-package/LICENSE
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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 2 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, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
.emacs.d/lisp/use-package/README.md
@@ -1,97 +1,15 @@
-# Note to users upgrading to 2.0
-
-## Semantics of :init is now consistent
-
-The meaning of `:init` has been changed: It now *always* happens before
-package load, whether `:config` has been deferred or not.  This means that
-some uses of `:init` in your configuration may need to be changed to `:config`
-(in the non-deferred case).  For the deferred case, the behavior is unchanged
-from before.
-
-Also, because `:init` and `:config` now mean "before" and "after", the `:pre-`
-and `:post-` keywords are gone, as they should no longer be necessary.
-
-Lastly, an effort has been made to make your Emacs start even in the presence
-of use-package configuration failures.  So after this change, be sure to check
-your `*Messages*` buffer.  Most likely, you will have several instances where
-you are using `:init`, but should be using `:config` (this was the case for me
-in a number of places).
-
-## :idle has been removed
-
-I am removing this feature for now because it can result in a nasty
-inconsistency.  Consider the following definition:
-
-``` elisp
-(use-package vkill
-  :commands vkill
-  :idle (some-important-configuration-here)
-  :bind ("C-x L" . vkill-and-helm-occur)
-  :init
-  (defun vkill-and-helm-occur ()
-    (interactive)
-    (vkill)
-    (call-interactively #'helm-occur))
-
-  :config
-  (setq vkill-show-all-processes t))
-```
-
-If I load my Emacs and wait until the idle timer fires, then this is the
-sequence of events:
-
-    :init :idle <load> :config
-
-But if I load Emacs and immediately type C-x L without waiting for the idle
-timer to fire, this is the sequence of events:
-
-    :init <load> :config :idle
-
-It's possible that the user could use `featurep` in their idle to test for
-this case, but that's a subtlety I'd rather avoid.
-
-## :defer now accepts an optional integer argument
-
-`:defer [N]` causes the package to be loaded -- if it has not already been --
-after `N` seconds of idle time.
-
-## Add :preface, occurring before everything except :disabled
-
-`:preface` can be used to establish function and variable definitions that
-will 1) make the byte-compiler happy (it won't complain about functions whose
-definitions are unknown because you have them within a guard block), and 2)
-allow you to define code that can be used in an `:if` test.
-
-Note that whatever is specified within `: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, so you should avoid
-having any side-effects in your preface, and restrict it merely to symbol
-declarations and definitions.
-
-## Add :functions, for declaring functions to the byte-compiler
-
-What `:defines` does for variables, `:functions` does for functions.
-
-## use-package.el is no longer needed at runtime
-
-This means you should put the following at the top of your Emacs, to further
-reduce load time:
-
-``` elisp
-(eval-when-compile
-  (require 'use-package))
-(require 'diminish)                ;; if you use :diminish
-(require 'bind-key)                ;; if you use any :bind variant
-```
-
 # `use-package`
 
+[![Build Status](https://travis-ci.org/jwiegley/use-package.svg?branch=master)](https://travis-ci.org/jwiegley/use-package)
+
 The `use-package` macro allows you to isolate package configuration in your
 `.emacs` file in a way that is both performance-oriented and, well, 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
 around 2 seconds, with no loss of functionality!
 
+Notes for users upgrading to 2.x are located [at the bottom](#upgrading-to-2x).
+
 ## The basics
 
 Here is the simplest `use-package` declaration:
@@ -106,7 +24,7 @@ succeeds, a message about `"Loading foo"` is logged, along with the time it
 took to load, if it took over 0.1s.
 
 Use the `:init` keyword to execute code before a package is loaded.  It
-accepts one or more form, up until the next keyword:
+accepts one or more forms, up until the next keyword:
 
 ``` elisp
 (use-package foo
@@ -131,10 +49,12 @@ As you might expect, you can use `:init` and `:config` together:
 ``` elisp
 (use-package color-moccur
   :commands (isearch-moccur isearch-all)
-  :bind ("M-s O" . moccur)
+  :bind (("M-s O" . moccur)
+         :map isearch-mode-map
+         ("M-o" . isearch-moccur)
+         ("M-O" . isearch-moccur-all))
   :init
-  (bind-key "M-o" 'isearch-moccur isearch-mode-map)
-  (bind-key "M-O" 'isearch-moccur-all isearch-mode-map)
+  (setq isearch-lazy-highlight t)
   :config
   (use-package moccur-edit))
 ```
@@ -142,7 +62,7 @@ As you might expect, you can use `:init` and `:config` together:
 In this case, I want to autoload the commands `isearch-moccur` and
 `isearch-all` from `color-moccur.el`, and bind keys both at the global level
 and within the `isearch-mode-map` (see next section).  When the package is
-actually loaded (by using one of these commands), `moccur-edit` is also be
+actually loaded (by using one of these commands), `moccur-edit` is also
 loaded, to allow editing of the `moccur` buffer.
 
 ## Key-binding
@@ -186,6 +106,67 @@ The `:bind` keyword takes either a cons or a list of conses:
 
 The `:commands` keyword likewise takes either a symbol or a list of symbols.
 
+NOTE: Special keys like `tab` or `F1`-`Fn` can be written in square brackets,
+i.e. `[tab]` instead of `"tab"`. The syntax for the keybindings is similar to
+the "kbd" syntax: see [https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-Rebinding.html](https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-Rebinding.html)
+for more information.
+
+Examples:
+
+``` elisp
+(use-package helm
+  :bind (("M-x" . helm-M-x)
+         ("M-<f5>" . helm-find-files)
+         ([f10] . helm-buffers-list)
+         ([S-f10] . helm-recentf)))
+```
+
+
+### Binding to keymaps
+
+Normally `: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 Emacs' `autoload` mechanism.
+
+To handle this case, `use-package` offers a special, limited variant of
+`:bind` called `:bind-keymap`. The only difference is that the "commands"
+bound to by `: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.
+
+### Binding within local keymaps
+
+Slightly different from binding a key to a keymap, is binding a key *within* a
+local keymap that only exists after the package is loaded.  `use-package`
+supports this with a `:map` modifier, taking the local keymap to bind to:
+
+``` elisp
+(use-package helm
+  :bind (:map helm-command-map
+         ("C-c h" . helm-execute-persistent-action)))
+```
+
+The effect of this statement is to wait until `helm` has loaded, and then to
+bind the key `C-c h` to `helm-execute-persistent-action` within Helm's local
+keymap, `helm-mode-map`.
+
+Multiple uses of `:map` may be specified. Any binding occurring before the
+first use of `:map` are applied to the global keymap:
+
+``` elisp
+(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)))
+```
+
 ## Modes and interpreters
 
 Similar to `:bind`, you can use `:mode` and `:interpreter` to establish a
@@ -217,7 +198,12 @@ still defer loading with the `:defer` keyword:
   (bind-key "C-." 'ace-jump-mode))
 ```
 
-This does exactly the same thing as the other two commands above.
+This does exactly the same thing as the following:
+
+``` elisp
+(use-package ace-jump-mode
+  :bind ("C-." . ace-jump-mode))
+```
 
 ## Notes about lazy loading
 
@@ -234,13 +220,14 @@ not establish an autoload for the bound key.
 
 ## Information about package loads
 
-When a package is loaded, and if you have `use-package-verbose` set t or if
-the package takes longer than 0.1s to load, you will see a message to indicate
-this loading activity in the `*Messages*` buffer.  The same will happen for
-configuration, or `:config` blocks that take longer than 0.1s to execute.  In
-general, you should keep `:init` forms as simple and quick as possible, and
-put as much as you can get away with into the `:config` block.  This way,
-deferred loading can help your Emacs to start as quickly as possible.
+When a package is loaded, and if you have `use-package-verbose` set to `t`, or
+if the package takes longer than 0.1s to load, you will see a message to
+indicate this loading activity in the `*Messages*` buffer.  The same will
+happen for configuration, or `:config` blocks that take longer than 0.1s to
+execute.  In general, you should keep `:init` forms as simple and quick as
+possible, and put as much as you can get away with into the `:config` block.
+This way, deferred loading can help your Emacs to start as quickly as
+possible.
 
 Additionally, if an error occurs while initializing or configuring a package,
 this will not stop your Emacs from loading.  Rather, the error will be
@@ -250,7 +237,9 @@ buffer, so that you can debug the situation in an otherwise functional Emacs.
 ## Conditional loading
 
 You can use the `:if` keyword to predicate the loading and initialization of
-modules.  For example, I only want `edit-server` running for my main,
+modules.
+
+For example, I only want `edit-server` running for my main,
 graphical Emacs, not for other Emacsen I may start at the command line:
 
 ``` elisp
@@ -260,13 +249,22 @@ graphical Emacs, not for other Emacsen I may start at the command line:
   (add-hook 'after-init-hook 'server-start t)
   (add-hook 'after-init-hook 'edit-server-start t))
 ```
+In another example, we can load things conditional on the operating system:
+
+```
+(use-package exec-path-from-shell
+  :if (memq window-system '(mac ns))
+  :ensure t
+  :config
+  (exec-path-from-shell-initialize))
+```
 
 The `:disabled` keyword can turn off a module you're having difficulties with,
-or to stop loading something you're not using at the present time:
+or stop loading something you're not using at the present time:
 
 ``` elisp
 (use-package ess-site
-  :disabled t
+  :disabled
   :commands R)
 ```
 
@@ -352,15 +350,17 @@ looking up the same information again on each startup:
   :commands R)
 ```
 
-## Diminishing minor modes
+## Diminishing and delighting minor modes
 
-`use-package` also provides built-in support for the diminish utility -- if
-you have that installed.  Its purpose is to remove strings from your mode-line
-that provide no useful information.  It is invoked with the `:diminish`
-keyword, which is passed 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 "-mode" appended at the
-end:
+`use-package` also provides built-in support for the diminish and
+delight utilities -- if you have them installed. Their purpose is to
+remove or change minor mode strings in your mode-line.
+
+[diminish](https://github.com/myrjola/diminish.el) is invoked with
+the `:diminish` keyword, which is passed 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 "-mode" appended at the end:
 
 ``` elisp
 (use-package abbrev
@@ -370,13 +370,45 @@ end:
       (quietly-read-abbrev-file)))
 ```
 
+[delight](https://elpa.gnu.org/packages/delight.html) is invoked with
+the `:delight` keyword, which is passed a minor mode symbol, a
+replacement string or
+quoted
+[mode-line data](https://www.gnu.org/software/emacs/manual/html_node/elisp/Mode-Line-Data.html) (in
+which case the minor mode symbol is guessed to be the package name
+with "-mode" appended at the end), both of these, or several lists of
+both. If no arguments are provided, the default mode name is hidden
+completely.
+
+``` elisp
+;; 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))
+```
+
 ## For `package.el` users
 
 You can use `use-package` to load packages from ELPA with `package.el`. This
 is particularly useful if you share your `.emacs` among several machines; the
-relevant packages are download automatically once declared in your `.emacs`.
+relevant packages are downloaded automatically once declared in your `.emacs`.
 The `:ensure` keyword causes the package(s) to be installed automatically if
-not already present on your system:
+not already present on your system (set `(setq use-package-always-ensure t)`
+if you wish this behavior to be global for all packages):
 
 ``` elisp
 (use-package magit
@@ -387,7 +419,7 @@ If you need to install a different package from the one named by
 `use-package`, you can specify it like this:
 
 ``` elisp
-(use-package tex-site
+(use-package tex
   :ensure auctex)
 ```
 
@@ -396,12 +428,13 @@ a specific archive, allowing you to mix and match packages from different
 archives.  The primary use-case for this is preferring packages from the
 `melpa-stable` and `gnu` archives, but using specific packages from `melpa`
 when you need to track newer versions than what is available in the `stable`
-archives.
+archives is also a valid use-case.
 
 By default `package.el` prefers `melpa` over `melpa-stable` due to the
 versioning `(> evil-20141208.623 evil-1.0.9)`, so even if you are tracking
 only a single package from `melpa`, you will need to tag all the non-`melpa`
-packages with the appropriate archive.
+packages with the appropriate archive. If this really annoys you, then you can
+set `use-package-always-pin` to set a default.
 
 If you want to manually keep a package updated and ignore upstream updates,
 you can pin it to `manual`, which as long as there is no repository by that
@@ -441,12 +474,6 @@ Example:
 
 **NOTE**: the `:pin` argument has no effect on emacs versions < 24.4.
 
-**NOTE**: if you pin a lot of packages, it will be slightly slower to start
-Emacs compared to manually adding all packages to the
-`package-pinned-packages` variable.  However, should you do it this way, you
-need to keep track of when `(package-initialize)` is called, so letting
-`use-package` handle it for you is arguably worth the cost.
-
 ## Extending use-package with new or modified keywords
 
 Starting with version 2.0, `use-package` is based on an extensible framework
@@ -499,7 +526,7 @@ Once you have a normalizer, you must create a handler for the keyword:
                package-pinned-packages))))))
 ```
 
-Handlers can effect on the handling of keywords in two ways.  First, it can
+Handlers can affect the handling of keywords in two ways.  First, it can
 modify the `state` plist before recursively processing the remaining keywords,
 to influence keywords that pay attention to the state (one example is the
 state keyword `:deferred`, not to be confused with the `use-package` keyword
@@ -541,3 +568,99 @@ time emacs -l init.elc -batch --eval '(message "Hello, world!")'
 
 On the Mac I see an average of 0.36s for the same configuration, and on Linux
 0.26s.
+
+# Upgrading to 2.x
+
+## Semantics of :init is now consistent
+
+The meaning of `:init` has been changed: It now *always* happens before
+package load, whether `:config` has been deferred or not.  This means that
+some uses of `:init` in your configuration may need to be changed to `:config`
+(in the non-deferred case).  For the deferred case, the behavior is unchanged
+from before.
+
+Also, because `:init` and `:config` now mean "before" and "after", the `:pre-`
+and `:post-` keywords are gone, as they should no longer be necessary.
+
+Lastly, an effort has been made to make your Emacs start even in the presence
+of use-package configuration failures.  So after this change, be sure to check
+your `*Messages*` buffer.  Most likely, you will have several instances where
+you are using `:init`, but should be using `:config` (this was the case for me
+in a number of places).
+
+## :idle has been removed
+
+I am removing this feature for now because it can result in a nasty
+inconsistency.  Consider the following definition:
+
+``` elisp
+(use-package vkill
+  :commands vkill
+  :idle (some-important-configuration-here)
+  :bind ("C-x L" . vkill-and-helm-occur)
+  :init
+  (defun vkill-and-helm-occur ()
+    (interactive)
+    (vkill)
+    (call-interactively #'helm-occur))
+
+  :config
+  (setq vkill-show-all-processes t))
+```
+
+If I load my Emacs and wait until the idle timer fires, then this is the
+sequence of events:
+
+    :init :idle <load> :config
+
+But if I load Emacs and immediately type C-x L without waiting for the idle
+timer to fire, this is the sequence of events:
+
+    :init <load> :config :idle
+
+It's possible that the user could use `featurep` in their idle to test for
+this case, but that's a subtlety I'd rather avoid.
+
+## :defer now accepts an optional integer argument
+
+`:defer [N]` causes the package to be loaded -- if it has not already been --
+after `N` seconds of idle time.
+
+```
+(use-package back-button
+  :commands (back-button-mode)
+  :defer 2
+  :init
+  (setq back-button-show-toolbar-buttons nil)
+  :config
+  (back-button-mode 1))
+```
+
+## Add :preface, occurring before everything except :disabled
+
+`:preface` can be used to establish function and variable definitions that
+will 1) make the byte-compiler happy (it won't complain about functions whose
+definitions are unknown because you have them within a guard block), and 2)
+allow you to define code that can be used in an `:if` test.
+
+Note that whatever is specified within `: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, so you should avoid
+having any side-effects in your preface, and restrict it merely to symbol
+declarations and definitions.
+
+## Add :functions, for declaring functions to the byte-compiler
+
+What `:defines` does for variables, `:functions` does for functions.
+
+## use-package.el is no longer needed at runtime
+
+This means you should put the following at the top of your Emacs, to further
+reduce load time:
+
+``` elisp
+(eval-when-compile
+  (require 'use-package))
+(require 'diminish)                ;; if you use :diminish
+(require 'bind-key)                ;; if you use any :bind variant
+```
.emacs.d/lisp/use-package/use-package.el
@@ -5,8 +5,8 @@
 ;; Author: John Wiegley <jwiegley@gmail.com>
 ;; Maintainer: John Wiegley <jwiegley@gmail.com>
 ;; Created: 17 Jun 2012
-;; Modified: 26 Sep 2015
-;; Version: 2.1
+;; Modified: 17 Oct 2016
+;; Version: 2.3
 ;; Package-Requires: ((bind-key "1.0") (diminish "0.44"))
 ;; Keywords: dotemacs startup speed config package
 ;; URL: https://github.com/jwiegley/use-package
@@ -46,7 +46,8 @@
 (eval-when-compile (require 'cl))
 (eval-when-compile (require 'regexp-opt))
 
-(declare-function package-installed-p 'package)
+(declare-function package-installed-p "package")
+(declare-function package-read-all-archive-contents "package" ())
 
 (defgroup use-package nil
   "A use-package declaration for simplifying your `.emacs'."
@@ -79,13 +80,23 @@ The check is performed by looking for the module using `locate-library'."
   :type 'boolean
   :group 'use-package)
 
+(defcustom use-package-always-demand nil
+  "If non-nil, assume `:demand t` unless `:defer t` is given."
+  :type 'boolean
+  :group 'use-package)
+
+(defcustom use-package-always-defer-install nil
+  "If non-nil, assume `:defer-install t` unless `:defer-install nil` is given."
+  :type 'boolean
+  :group 'use-package)
+
 (defcustom use-package-always-ensure nil
   "Treat every package as though it had specified `:ensure SEXP`."
   :type 'sexp
   :group 'use-package)
 
 (defcustom use-package-always-pin nil
-  "Treat every package as though it had specified `:pin SYM."
+  "Treat every package as though it had specified `:pin SYM`."
   :type 'symbol
   :group 'use-package)
 
@@ -125,14 +136,15 @@ the user specified."
 
 (defcustom use-package-keywords
   '(:disabled
+    :preface
     :pin
+    :defer-install
     :ensure
     :if
     :when
     :unless
     :requires
     :load-path
-    :preface
     :no-require
     :bind
     :bind*
@@ -140,13 +152,15 @@ the user specified."
     :bind-keymap*
     :interpreter
     :mode
+    :magic
+    :magic-fallback
     :commands
     :defines
     :functions
     :defer
+    :init
     :after
     :demand
-    :init
     :config
     :diminish
     :delight)
@@ -176,24 +190,132 @@ Must be set before loading use-package."
   :type 'boolean
   :group 'use-package)
 
+(defcustom use-package-ensure-function 'use-package-ensure-elpa
+  "Function that ensures a package is installed.
+This function is called with four arguments: the name of the
+package declared in the `use-package' form; the argument passed
+to `:ensure'; the current `state' plist created by previous
+handlers; and a keyword indicating the context in which the
+installation is occurring.
+
+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.
+
+Possible values for the context keyword are:
+
+:byte-compile - package installed during byte-compilation
+:ensure - package installed normally by :ensure
+:autoload - deferred installation triggered by an autoloaded
+            function
+:after - deferred installation triggered by the loading of a
+         feature listed in the :after declaration
+:config - deferred installation was specified at the same time
+          as :demand, so the installation was triggered
+          immediately
+:unknown - context not provided
+
+Note that third-party code can provide other values for the
+context keyword by calling `use-package-install-deferred-package'
+with the appropriate value."
+  :type '(choice (const :tag "package.el" use-package-ensure-elpa)
+                 (function :tag "Custom"))
+  :group 'use-package)
+
+(defcustom use-package-pre-ensure-function 'ignore
+  "Function that is called upon installation deferral.
+It is called immediately with the first three arguments that
+would be passed to `use-package-ensure-function' (the context
+keyword is omitted), but only if installation has been deferred.
+It is intended for package managers other than package.el which
+might want to activate the autoloads of a package immediately, if
+it's installed, but otherwise defer installation until later (if
+`:defer-install' is specified). The reason it is set to `ignore'
+by default is that package.el activates the autoloads for all
+known packages at initialization time, rather than one by one
+when the packages are actually requested."
+  :type '(choice (const :tag "None" ignore)
+                 (function :tag "Custom"))
+  :group 'use-package)
+
+(defcustom use-package-defaults
+  '((:config '(t) t)
+    (:ensure use-package-always-ensure use-package-always-ensure)
+    (:defer-install
+     use-package-always-defer-install
+     use-package-always-defer-install)
+    (:pin use-package-always-pin use-package-always-pin))
+  "Alist of default values for `use-package' keywords.
+Each entry in the alist is a list of three elements. The first
+element is the `use-package' keyword and the second is a form
+that can be evaluated to get the default value. 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."
+  :type '(repeat (list symbol sexp sexp)))
+
 (when use-package-enable-imenu-support
-  ;; Not defined in Emacs 24
-  (defvar lisp-mode-symbol-regexp
-    "\\(?:\\sw\\|\\s_\\|\\\\.\\)+")
-  (add-to-list
-   'lisp-imenu-generic-expression
-   (list "Package"
-         (purecopy (concat "^\\s-*("
-                           (eval-when-compile
-                             (regexp-opt
-                              '("use-package" "require")
-                              t))
-                           "\\s-+\\(" lisp-mode-symbol-regexp "\\)"))
-         2)))
+  (eval-after-load 'lisp-mode
+    `(let ((sym-regexp (or (bound-and-true-p lisp-mode-symbol-regexp)
+                           "\\(?:\\sw\\|\\s_\\|\\\\.\\)+")))
+       (add-to-list
+        'lisp-imenu-generic-expression
+        (list "Packages"
+              (concat "^\\s-*("
+                      ,(eval-when-compile
+                         (regexp-opt '("use-package" "require") t))
+                      "\\s-+\\(" sym-regexp "\\)")
+              2)))))
+
+(defvar use-package-form-regexp "^\\s-*(\\s-*use-package\\s-+\\_<%s\\_>"
+  "Regexp used in `use-package-jump-to-package-form' to find use
+package forms in user files.")
+
+(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)))))))
+
+(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 orginally 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 that requires this feature.")
+      (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 use-package-form-regexp package) nil t)))
+        (if (null location)
+            (message "No use-package form found.")
+          (goto-char location)
+          (beginning-of-line))))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; Utility functions
+;;; Utility functions
 ;;
 
 (defun use-package-as-symbol (string-or-symbol)
@@ -208,12 +330,20 @@ convert it to a string and return that."
   (if (stringp string-or-symbol) string-or-symbol
     (symbol-name string-or-symbol)))
 
+(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")))))
+
 (defun use-package-load-name (name &optional noerror)
   "Return a form which will load or require NAME depending on
 whether it's a string or symbol."
   (if (stringp name)
-      `(load ,name 'noerror)
-    `(require ',name nil 'noerror)))
+      `(load ,name ',noerror)
+    `(require ',name nil ',noerror)))
 
 (defun use-package-expand (name label form)
   "FORM is a list of forms, so `((foo))' if only `foo' is being called."
@@ -298,7 +428,7 @@ 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 p (plist-put p (car plist) (nth 1 plist))))
       (setq plist (cddr plist)))
     p))
 
@@ -350,14 +480,36 @@ This is in contrast to merely setting it to 0."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; Keyword processing
+;;; Keyword processing
 ;;
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; Normalization functions
+;;; Normalization functions
 ;;
 
+(defun use-package-regex-p (re)
+  "Return t if RE is some regexp-like thing."
+  (cond
+   ((and (listp re)
+         (eq (car re) 'rx))
+    t)
+   ((stringp re)
+    t)
+   (t
+    nil)))
+
+(defun use-package-normalize-regex (re)
+  "Given some regexp-like thing, resolve it down 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))))
+
 (defun use-package-normalize-plist (name input)
   "Given a pseudo-plist, normalize it to a regular plist."
   (unless (null input)
@@ -413,7 +565,7 @@ next value for the STATE."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :pin
+;;; :pin
 ;;
 
 (defun use-package-only-one (label args f)
@@ -483,7 +635,84 @@ manually updated package."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :ensure
+;;; :defer-install
+;;
+
+(defvar use-package--deferred-packages (make-hash-table)
+  "Hash mapping packages to data about their installation.
+
+The keys are not actually symbols naming packages, but rather
+symbols naming the features which are the names of \"packages\"
+required by `use-package' forms. Since
+`use-package-ensure-function' could be set to anything, it is
+actually impossible for `use-package' to determine what package
+is supposed to provide the feature being ensured just based on
+the value of `:ensure'.
+
+Each value is a cons, with the car being the the value passed to
+`:ensure' and the cdr being the `state' plist. See
+`use-package-install-deferred-package' for information about how
+these values are used to call `use-package-ensure-function'.")
+
+(defun use-package-install-deferred-package (name &optional context)
+  "Install a package whose installation has been deferred.
+NAME should be a symbol naming a package (actually, a feature).
+This is done by calling `use-package-ensure-function' is called
+with four arguments: the key (NAME) and the two elements of the
+cons in `use-package--deferred-packages' (the value passed to
+`:ensure', and the `state' plist), and a keyword providing
+information about the context in which the installation is
+happening. (This defaults to `:unknown' but can be overridden by
+providing CONTEXT.)
+
+Return t if the package is installed, nil otherwise. (This is
+determined by the return value of `use-package-ensure-function'.)
+If the package is installed, its entry is removed from
+`use-package--deferred-packages'. If the package has no entry in
+`use-package--deferred-packages', do nothing and return t."
+  (interactive
+   (let ((packages nil))
+     (maphash (lambda (package info)
+                (push package packages))
+              use-package--deferred-packages)
+     (if packages
+         (list
+          (intern
+           (completing-read
+            "Select package: "
+            packages
+            nil
+            'require-match))
+          :interactive)
+       (user-error "No packages with deferred installation"))))
+  (let ((spec (gethash name use-package--deferred-packages)))
+    (if spec
+        (when (funcall use-package-ensure-function
+                       name (car spec) (cdr spec)
+                       (or context :unknown))
+          (remhash name use-package--deferred-packages)
+          t)
+      t)))
+
+(defalias 'use-package-normalize/:defer-install 'use-package-normalize-test)
+
+(defun use-package-handler/:defer-install (name keyword defer rest state)
+  (use-package-process-keywords name rest
+    ;; Just specifying `:defer-install' does not do anything; this
+    ;; sets up a marker so that if `:ensure' is specified as well then
+    ;; it knows to set up deferred installation. But then later, when
+    ;; `:config' is processed, it might turn out that `:demand' was
+    ;; specified as well, and the deferred installation needs to be
+    ;; run immediately. For this we need to know if the deferred
+    ;; installation was actually set up or not, so we need to set one
+    ;; marker value in `:defer-install', and then change it to a
+    ;; different value in `:ensure', if the first one is present. (The
+    ;; first marker is `:defer-install', and the second is `:ensure'.)
+    (plist-put state :defer-install (when defer :defer-install))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; :ensure
 ;;
 (defvar package-archive-contents)
 (defun use-package-normalize/:ensure (name keyword args)
@@ -497,38 +726,71 @@ manually updated package."
            (concat ":ensure wants an optional package name "
                    "(an unquoted symbol name)")))))))
 
-(defun use-package-ensure-elpa (package &optional no-refresh)
-  (if (package-installed-p package)
-      t
-    (if (or (assoc package package-archive-contents) no-refresh)
-        (package-install package)
-      (progn
-        (package-refresh-contents)
-        (use-package-ensure-elpa package t)))))
+(defun use-package-ensure-elpa (name ensure state context &optional no-refresh)
+  (let ((package (or (when (eq ensure t) (use-package-as-symbol name))
+                     ensure)))
+    (when package
+      (require 'package)
+      (or (package-installed-p package)
+          (not (or
+                ;; Contexts in which the confirmation prompt is
+                ;; bypassed.
+                (member context '(:byte-compile :ensure :config))
+                (y-or-n-p (format "Install package %S?" package))))
+          (with-demoted-errors (format "Cannot load %s: %%S" name)
+            (when (assoc package (bound-and-true-p package-pinned-packages))
+              (package-read-all-archive-contents))
+            (if (assoc package package-archive-contents)
+                (progn (package-install package) t)
+              (progn
+                (package-refresh-contents)
+                (when (assoc package (bound-and-true-p
+                                      package-pinned-packages))
+                  (package-read-all-archive-contents))
+                (package-install package))))))))
 
 (defun use-package-handler/:ensure (name keyword ensure rest state)
-  (let* ((body (use-package-process-keywords name rest state))
-         (package-name (or (and (eq ensure t) (use-package-as-symbol name)) ensure))
-         (ensure-form (if package-name
-                          `(progn (require 'package)
-                                  (use-package-ensure-elpa ',package-name)))))
+  (let* ((body (use-package-process-keywords name rest
+                 ;; Here we are conditionally updating the marker
+                 ;; value for deferred installation; this will be
+                 ;; checked later by `:config'. For more information
+                 ;; see `use-package-handler/:defer-install'.
+                 (if (eq (plist-get state :defer-install)
+                         :defer-install)
+                     (plist-put state :defer-install :ensure)
+                   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 do install packages when
     ;; byte-compiling to avoid requiring `package' at runtime.
-    (if (bound-and-true-p byte-compile-current-file)
-        (eval ensure-form)              ; Eval when byte-compiling,
-      (push ensure-form body))          ; or else wait until runtime.
+    (cond
+     ((plist-get state :defer-install)
+      (push
+       `(puthash ',name '(,ensure . ,state)
+                 use-package--deferred-packages)
+       body)
+      (push `(,use-package-pre-ensure-function
+              ',name ',ensure ',state)
+            body))
+     ((bound-and-true-p byte-compile-current-file)
+      ;; Eval when byte-compiling,
+      (funcall use-package-ensure-function
+               name ensure state :byte-compile))
+     ;;  or else wait until runtime.
+     (t (push `(,use-package-ensure-function
+                ',name ',ensure ',state :ensure)
+              body)))
     body))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :if, :when and :unless
+;;; :if, :when and :unless
 ;;
 
 (defsubst use-package-normalize-value (label arg)
   "Normalize a value."
-  (cond ((symbolp arg)
+  (cond ((null arg) nil)
+        ((symbolp arg)
          `(symbol-value ',arg))
         ((functionp arg)
          `(funcall #',arg))
@@ -554,7 +816,7 @@ manually updated package."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :requires
+;;; :requires
 ;;
 
 (defun use-package-as-one (label args f)
@@ -584,6 +846,22 @@ manually updated package."
   (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
+   ((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))
+
 (defalias 'use-package-normalize/:requires 'use-package-normalize-symlist)
 
 (defun use-package-handler/:requires (name keyword requires rest state)
@@ -597,7 +875,7 @@ manually updated package."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :load-path
+;;; :load-path
 ;;
 
 (defun use-package-normalize-paths (label arg &optional recursed)
@@ -631,7 +909,7 @@ manually updated package."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :no-require
+;;; :no-require
 ;;
 
 (defun use-package-normalize-predicate (name keyword args)
@@ -648,7 +926,7 @@ manually updated package."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :preface
+;;; :preface
 ;;
 
 (defun use-package-normalize-form (label args)
@@ -675,50 +953,69 @@ manually updated package."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :bind, :bind*
+;;; :bind, :bind*
 ;;
 
-(defsubst use-package-is-sympair (x &optional allow-vector)
-  "Return t if X has the type (STRING . SYMBOL)."
+(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)
-       (or (stringp (car x))
-           (and allow-vector (vectorp (car x))))
-       (symbolp (cdr x))))
-
-(defsubst use-package-is-string-pair (x)
-  "Return t if X has the type (STRING . STRING)."
-  (and (consp x)
-       (stringp (car x))
-       (stringp (cdr x))))
+       (funcall car-pred (car x))
+       (funcall cdr-pred (cdr x))))
 
 (defun use-package-normalize-pairs
-    (name label arg &optional recursed allow-vector allow-string-cdrs)
-  "Normalize a list of string/symbol pairs.
-If RECURSED is non-nil, recurse into sublists.
-If ALLOW-VECTOR is non-nil, then the key to bind may specify a
-vector of keys, as accepted by `define-key'.
-If ALLOW-STRING-CDRS is non-nil, then the command name to bind to
-may also be a string, as accepted by `define-key'."
+    (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
-   ((or (stringp arg) (and allow-vector (vectorp arg)))
+   ((funcall key-pred arg)
     (list (cons arg (use-package-as-symbol name))))
-   ((use-package-is-sympair arg allow-vector)
+   ((use-package-is-pair arg key-pred val-pred)
     (list arg))
    ((and (not recursed) (listp arg) (listp (cdr arg)))
-    (mapcar #'(lambda (x)
-                (let ((ret (use-package-normalize-pairs
-                            name label x t allow-vector allow-string-cdrs)))
-                  (if (listp ret)
-                      (car ret)
-                    ret))) arg))
-   ((and allow-string-cdrs (use-package-is-string-pair arg))
-    (list arg))
+    (let ((last-item nil))
+      (mapcar #'(lambda (x)
+                  (prog1
+                      (let ((ret (use-package-normalize-pairs
+                                  key-pred val-pred name label x t)))
+                        ;; Currently, the handling of keyword
+                        ;; arguments by `use-package' and `bind-key'
+                        ;; is non-uniform and undocumented. As a
+                        ;; result, `use-package-normalize-pairs' (as
+                        ;; it is currently implemented) does not
+                        ;; correctly handle the keyword-argument
+                        ;; syntax of `bind-keys'. A permanent solution
+                        ;; to this problem will require a careful
+                        ;; consideration of the desired
+                        ;; keyword-argument interface for
+                        ;; `use-package' and `bind-key'. However, in
+                        ;; the meantime, we have a quick patch to fix
+                        ;; a serious bug in the handling of keyword
+                        ;; arguments. Namely, the code below would
+                        ;; normally unwrap lists that were passed as
+                        ;; keyword arguments (for example, the
+                        ;; `:filter' argument in `:bind') without
+                        ;; the (not (keywordp last-item)) clause. See
+                        ;; #447 for further discussion.
+                        (if (and (listp ret) (not (keywordp last-item)))
+                            (car ret)
+                          ret))
+                    (setq last-item x))) arg)))
    (t arg)))
 
 (defun use-package-normalize-binder (name keyword args)
   (use-package-as-one (symbol-name keyword) args
     (lambda (label arg)
-      (use-package-normalize-pairs name label arg nil t t))))
+      (unless (consp arg)
+        (use-package-error
+         (concat label " a (<string or vector> . <symbol or string>)"
+                 " or list of these")))
+      (use-package-normalize-pairs (lambda (k) (or (stringp k) (vectorp k)))
+                                   (lambda (b) (or (symbolp b) (stringp b)))
+                                   name label arg))))
 
 (defalias 'use-package-normalize/:bind 'use-package-normalize-binder)
 (defalias 'use-package-normalize/:bind* 'use-package-normalize-binder)
@@ -744,12 +1041,13 @@ may also be a string, as accepted by `define-key'."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :bind-keymap, :bind-keymap*
+;;; :bind-keymap, :bind-keymap*
 ;;
 
 (defalias 'use-package-normalize/:bind-keymap 'use-package-normalize-binder)
 (defalias 'use-package-normalize/:bind-keymap* 'use-package-normalize-binder)
 
+;;;###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
@@ -801,20 +1099,25 @@ deferred until the prefix key sequence is pressed."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :interpreter
+;;; :interpreter
 ;;
 
 (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 name)))
+    (apply-partially #'use-package-normalize-pairs
+                     #'use-package-regex-p
+                     (lambda (m) (and (not (null m)) (symbolp m)))
+                     name)))
 
-(defalias 'use-package-normalize/:interpreter 'use-package-normalize-mode)
-
-(defun use-package-handler/:interpreter (name keyword arg rest state)
+(defun use-package-handle-mode (name alist arg rest state)
+  "Handle keywords which add regexp/mode pairs to an alist."
   (let* (commands
-         (form (mapcar #'(lambda (interpreter)
-                           (push (cdr interpreter) commands)
-                           `(add-to-list 'interpreter-mode-alist ',interpreter)) arg)))
+         (form (mapcar #'(lambda (thing)
+                           (push (cdr thing) commands)
+                           (setcar thing
+                                   (use-package-normalize-regex (car thing)))
+                           `(add-to-list ',alist ',thing)) arg)))
     (use-package-concat
      (use-package-process-keywords name
        (use-package-sort-keywords
@@ -822,28 +1125,44 @@ deferred until the prefix key sequence is pressed."
        (use-package-plist-append state :commands commands))
      `((ignore ,@form)))))
 
+(defalias 'use-package-normalize/:interpreter 'use-package-normalize-mode)
+
+(defun use-package-handler/:interpreter (name keyword arg rest state)
+  (use-package-handle-mode name 'interpreter-mode-alist arg rest state))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :mode
+;;; :mode
 ;;
 
 (defalias 'use-package-normalize/:mode 'use-package-normalize-mode)
 
 (defun use-package-handler/:mode (name keyword arg rest state)
-  (let* (commands
-         (form (mapcar #'(lambda (mode)
-                           (push (cdr mode) commands)
-                           `(add-to-list 'auto-mode-alist ',mode)) arg)))
-    (use-package-concat
-     (use-package-process-keywords name
-       (use-package-sort-keywords
-        (use-package-plist-maybe-put rest :defer t))
-       (use-package-plist-append state :commands commands))
-     `((ignore ,@form)))))
+  (use-package-handle-mode name 'auto-mode-alist arg rest state))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :commands
+;;; :magic
+;;
+
+(defalias 'use-package-normalize/:magic 'use-package-normalize-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)
+
+(defun use-package-handler/:magic-fallback (name keyword arg rest state)
+  (use-package-handle-mode name 'magic-fallback-mode-alist arg rest state))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; :commands
 ;;
 
 (defalias 'use-package-normalize/:commands 'use-package-normalize-symlist)
@@ -857,7 +1176,7 @@ deferred until the prefix key sequence is pressed."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :defines
+;;; :defines
 ;;
 
 (defalias 'use-package-normalize/:defines 'use-package-normalize-symlist)
@@ -868,7 +1187,7 @@ deferred until the prefix key sequence is pressed."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :functions
+;;; :functions
 ;;
 
 (defalias 'use-package-normalize/:functions 'use-package-normalize-symlist)
@@ -887,11 +1206,40 @@ deferred until the prefix key sequence is pressed."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :defer
+;;; :defer
 ;;
 
 (defalias 'use-package-normalize/:defer 'use-package-normalize-predicate)
 
+(defun use-package--autoload-with-deferred-install
+    (command package-name)
+  "Return a form defining an autoload supporting deferred install."
+  `(let* ((load-list-item '(defun . ,command))
+          (already-loaded (member load-list-item current-load-list)))
+     (defun ,command (&rest args)
+       "[Arg list not available until function definition is loaded.]
+
+\(fn ...)"
+       (interactive)
+       (if (bound-and-true-p use-package--recursive-autoload)
+           (use-package-error
+            (format "Autoloading failed to define function %S"
+                    ',command))
+         (when (use-package-install-deferred-package
+                ',package-name :autoload)
+           (require ',package-name)
+           (let ((use-package--recursive-autoload t))
+             (if (called-interactively-p 'any)
+                 (call-interactively ',command)
+               (apply ',command args))))))
+     ;; This prevents the user's init-file from being recorded as the
+     ;; definition location for the function before it is actually
+     ;; loaded. (Our goal is to leave the `current-load-list'
+     ;; unchanged, so we only remove the entry for this function if it
+     ;; was not already present.)
+     (unless already-loaded
+       (setq current-load-list (remove load-list-item current-load-list)))))
+
 (defun use-package-handler/:defer (name keyword arg rest state)
   (let ((body (use-package-process-keywords name rest
                 (plist-put state :deferred t)))
@@ -906,48 +1254,84 @@ deferred until the prefix key sequence is pressed."
      ;; keep the byte-compiler happy.
      (apply
       #'nconc
-      (mapcar #'(lambda (command)
-                  (when (not (stringp command))
-                    (append
-                     `((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 (plist-get state :commands))))
+      (mapcar
+       #'(lambda (command)
+           (when (not (stringp command))
+             (append
+              `((unless (fboundp ',command)
+                  ;; Here we are checking the marker value set in
+                  ;; `use-package-handler/:ensure' to see if deferred
+                  ;; installation is actually happening. See
+                  ;; `use-package-handler/:defer-install' for more
+                  ;; information.
+                  ,(if (eq (plist-get state :defer-install) :ensure)
+                       (use-package--autoload-with-deferred-install
+                        command name)
+                     `(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 (plist-get state :commands))))
 
      body)))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :after
+;;; :after
 ;;
 
-(defalias 'use-package-normalize/:after 'use-package-normalize-symlist)
+(defalias 'use-package-normalize/:after 'use-package-normalize-recursive-symlist)
 
-(defun use-package-require-after-load (features name)
+(defun use-package-require-after-load
+    (features)
   "Return form for after any of FEATURES require NAME."
-  `(progn
-     ,@(mapcar
-        (lambda (feat)
-          `(eval-after-load
-               (quote ,feat)
-             (quote (require (quote ,name) nil t))))
-        features)))
+  (pcase features
+    ((and (pred symbolp) feat)
+     `(lambda (body)
+        (list 'eval-after-load (list 'quote ',feat)
+              (list 'quote body))))
+    (`(,(or :or  :any) . ,rest)
+     `(lambda (body)
+        (append (list 'progn)
+                (mapcar (lambda (form)
+                          (funcall form body))
+                        (list ,@(use-package-require-after-load rest))))))
+    (`(,(or :and :all) . ,rest)
+     `(lambda (body)
+        (let ((result body))
+          (dolist (form (list ,@(use-package-require-after-load rest)))
+            (setq result (funcall form result)))
+          result)))
+    (`(,feat . ,rest)
+     (if rest
+         (cons (use-package-require-after-load feat)
+               (use-package-require-after-load rest))
+       (list (use-package-require-after-load feat))))))
 
 (defun use-package-handler/:after (name keyword arg rest state)
   (let ((body (use-package-process-keywords name rest
                 (plist-put state :deferred t)))
         (name-string (use-package-as-string name)))
+    (if (and (consp arg)
+             (not (memq (car arg) '(:or :any :and :all))))
+        (setq arg (cons :all arg)))
     (use-package-concat
      (when arg
-       (list (use-package-require-after-load arg name)))
+       (list (funcall (use-package-require-after-load arg)
+                      (macroexp-progn
+                       ;; Here we are checking the marker value for deferred
+                       ;; installation set in `use-package-handler/:ensure'.
+                       ;; See also `use-package-handler/:defer-install'.
+                       `(,@(when (eq (plist-get state :defer-install) :ensure)
+                             `((use-package-install-deferred-package
+                                'name :after)))
+                         (require (quote ,name) nil t))))))
      body)))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :demand
+;;; :demand
 ;;
 
 (defalias 'use-package-normalize/:demand 'use-package-normalize-predicate)
@@ -958,7 +1342,7 @@ deferred until the prefix key sequence is pressed."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :init
+;;; :init
 ;;
 
 (defalias 'use-package-normalize/:init 'use-package-normalize-forms)
@@ -978,7 +1362,7 @@ deferred until the prefix key sequence is pressed."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :config
+;;; :config
 ;;
 
 (defalias 'use-package-normalize/:config 'use-package-normalize-forms)
@@ -1000,6 +1384,11 @@ deferred until the prefix key sequence is pressed."
         (unless (or (null config-body) (equal config-body '(t)))
           `((eval-after-load ,(if (symbolp name) `',name name)
               ',(macroexp-progn config-body))))
+      ;; Here we are checking the marker value for deferred
+      ;; installation set in `use-package-handler/:ensure'. See also
+      ;; `use-package-handler/:defer-install'.
+      (when (eq (plist-get state :defer-install) :ensure)
+        (use-package-install-deferred-package name :config))
       (use-package--with-elapsed-timer
           (format "Loading package %s" name)
         (if use-package-expand-minimally
@@ -1013,7 +1402,8 @@ deferred until the prefix key sequence is pressed."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :diminish
+;;; :diminish
+;;
 
 (defun use-package-normalize-diminish (name label arg &optional recursed)
   "Normalize the arguments to diminish down to a list of one of two forms:
@@ -1051,33 +1441,55 @@ deferred until the prefix key sequence is pressed."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; :delight
+;;; :delight
 ;;
 
+(defun use-package--normalize-delight-1 (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) (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"))))
+
 (defun use-package-normalize/:delight (name keyword args)
   "Normalize arguments to delight."
-  (cond
-   ((and (= (length args) 1)
-         (symbolp (car args)))
-    (list (car args) nil name))
-   ((and (= (length args) 2)
-         (symbolp (car args)))
-    (list (car args) (cadr args) (use-package-as-symbol name)))
-   ((and (= (length args) 3)
-         (symbolp (car args)))
-    args)
-   (t
-    (use-package-error ":delight expects same args as delight function"))))
+  (cond ((null args)
+         `((,(use-package-as-mode name) nil ,name)))
+        ((and (= (length args) 1)
+              (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-1 name)
+            (if (symbolp (car args)) (list args) args)))))
 
 (defun use-package-handler/:delight (name keyword args rest state)
   (let ((body (use-package-process-keywords name rest state)))
     (use-package-concat
      body
-     `((delight (quote ,(nth 0 args)) ,(nth 1 args) (quote ,(nth 2 args))) t))))
+     `((delight '(,@args))))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
-;; The main macro
+;;; The main macro
 ;;
 
 ;;;###autoload
@@ -1090,84 +1502,86 @@ 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.
+: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'.
-:interpreter   Form to be added to `interpreter-mode-alist'.
+: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'.
+:mode            Form to be added to `auto-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.
+: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.
 
-: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
+: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' or `:interpreter'.
-               This can be an integer, to force loading after N seconds of
-               idle time, if the package has not already been loaded.
+:defer           Defer loading of a package -- this is implied when using
+                 `:commands', `:bind', `:bind*', `:mode', `:magic',
+                 `: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         Defer loading of a package until after any of the named
-               features are loaded.
+:after           Defer loading of a package until after any of the named
+                 features are loaded.
 
-:demand        Prevent deferred loading in all cases.
+:demand          Prevent deferred loading in all cases.
 
-: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).
-:ensure        Loads the package using package.el if necessary.
-:pin           Pin the package to an archive."
+: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).
+:ensure          Loads the package using package.el if necessary.
+:pin             Pin the package to an archive."
   (declare (indent 1))
   (unless (member :disabled args)
-    (let* ((name-symbol (if (stringp name) (intern name) name))
-           (args0 (use-package-plist-maybe-put
-                   (use-package-normalize-plist name args)
-                   :config '(t)))
-           (args* (use-package-sort-keywords
-                   (if use-package-always-ensure
-                       (use-package-plist-maybe-put
-                        args0 :ensure use-package-always-ensure)
-                     args0)))
-           (args* (use-package-sort-keywords
-                   (if use-package-always-pin
-                       (use-package-plist-maybe-put
-                        args* :pin use-package-always-pin)
-                     args*))))
+    (let ((name-symbol (if (stringp name) (intern name) name))
+          (args (use-package-normalize-plist name args)))
+      (dolist (spec use-package-defaults)
+        (setq args (use-package-sort-keywords
+                    (if (eval (nth 2 spec))
+                        (use-package-plist-maybe-put
+                         args (nth 0 spec) (eval (nth 1 spec)))
+                      args))))
 
       ;; When byte-compiling, pre-load the package so all its symbols are in
       ;; scope.
       (if (bound-and-true-p byte-compile-current-file)
-          (setq args*
+          (setq args
                 (use-package-plist-cons
-                 args* :preface
+                 args :preface
                  `(eval-when-compile
                     ,@(mapcar #'(lambda (var) `(defvar ,var))
-                              (plist-get args* :defines))
+                              (plist-get args :defines))
                     (with-demoted-errors
                         ,(format "Cannot load %s: %%S" name)
                       ,(if (eq use-package-verbose 'debug)
                            `(message "Compiling package %s" ',name-symbol))
-                      ,(unless (plist-get args* :no-require)
+                      ,(unless (plist-get args :no-require)
                          (use-package-load-name name)))))))
 
       (let ((body
              (macroexp-progn
-              (use-package-process-keywords name args*
-                (and use-package-always-defer '(:deferred t))))))
+              (use-package-process-keywords name
+                (if use-package-always-demand
+                    (append args '(:demand t))
+                  args)
+                (and use-package-always-defer (list :deferred t))))))
         (if use-package-debug
             (display-buffer
              (save-current-buffer
@@ -1185,6 +1599,7 @@ this file.  Usage:
 (provide 'use-package)
 
 ;; Local Variables:
+;; outline-regexp: ";;;\\(;* [^\s\t\n]\\|###autoload\\)\\|("
 ;; indent-tabs-mode: nil
 ;; End: