]> git.eshelyaron.com Git - emacs.git/commitdiff
Break out ensure/diminish/delight into their own support files
authorJohn Wiegley <johnw@newartisans.com>
Sun, 3 Dec 2017 19:54:19 +0000 (11:54 -0800)
committerJohn Wiegley <johnw@newartisans.com>
Sun, 3 Dec 2017 19:54:19 +0000 (11:54 -0800)
etc/USE-PACKAGE-NEWS
lisp/use-package/use-package.el
test/lisp/use-package/use-package-tests.el [deleted file]
up-core.el [new file with mode: 0644]
up-delight.el [new file with mode: 0644]
up-diminish.el [new file with mode: 0644]
up-ensure.el [new file with mode: 0644]
up-tests.el [new file with mode: 0644]

index c65aae64f10925d552a40ef1c18ba4ea62462474..eeaf91bdb0a512f37e9695912f18e1a9cced02a7 100644 (file)
 ### Other changes
 
 - Upgrade license to GPL 3.
+
 - New `:hook` keyword.
+
 - New keywords `:custom (foo1 bar1) (foo2 bar2)` etc., and `:custom-face`.
+
 - New `:magic` and `:magic-fallback` keywords.
+
 - New `:defer-install` keyword.
+
 - New customization variable `use-package-enable-imenu-support`.
+
 - Allow `:diminish` to take no arguments.
+
 - Support multiple symbols passed to `:after`, and a mini-DSL using `:all` and
   `:any`.
+
 - `:mode` and `:interpreter` can now accept `(rx ...)` forms.
+
 - Using `:load-path` without also using `:ensure` now implies `:ensure nil`.
+
 - `:bind (:map foo-map ...)` now defers binding in the map until the package
   has been loaded.
+
 - Print key bindings for keymaps in `describe-personal-keybindings`.
+
 - When `use-package-inject-hooks` is non-nil, always fire `:init` and
   `:config` hooks.
+
 - Documentation added for the `:after`, `:defer-install`, `:delight`,
   `:requires`, `:when` and `:unless` keywords.
 
+- The source code is now broken into several files, so that certain optional
+  features (diminish, delight, ensure) may be maintained separately from the
+  core functionality.
+
 ### Bug fixes
 
 - Repeating a bind no longer causes duplicates in personal-keybindings.
index aa8a204fe0e6fca183fa7d2b7a0fa384b770111a..6169732614dd29a66f90850cded3ec51a64dc0ef 100644 (file)
 
 ;;; Code:
 
-(require 'bind-key)
-(require 'bytecomp)
-(require 'cl-lib)
-
-(eval-when-compile
-  (require 'cl)
-  (require 'regexp-opt)
-
-  (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'."
-  :group 'startup)
-
-(defconst use-package-version "2.4"
-  "This version of use-package.")
-
-(defcustom use-package-keywords
-  '(:disabled
-    :pin
-    :ensure
-    :if :when :unless
-    :requires
-    :load-path
-    :no-require
-    :preface :defines :functions
-    :after
-    :custom
-    :custom-face
-    :init
-    :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
-    :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
-    :diminish
-    :delight)
-  "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-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" 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-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)
-
-(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)
-
-(defcustom use-package-defaults
-  '(;; this '(t) has special meaning; see `use-package-handler/:config'
-    (:config '(t) t)
-    (:init nil t)
-    (:defer use-package-always-defer
-            (lambda (args)
-              (and use-package-always-defer
-                   (not (plist-member args :defer))
-                   (not (plist-member args :demand)))))
-    (:demand use-package-always-demand
-             (lambda (args)
-               (and use-package-always-demand
-                    (not (plist-member args :defer))
-                    (not (plist-member args :demand)))))
-    (:ensure use-package-always-ensure
-             (lambda (args)
-               (and use-package-always-ensure
-                    (not (plist-member args :load-path)))))
-    (: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. This third element may also be a function, in
-which case it receives the list of keywords (in normalized form),
-and should return nil or t according to 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)
-                (choice :tag "Enable if non-nil" sexp function)))
-  :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, adjust `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)
-      (if value
-          (eval-after-load 'lisp-mode
-            `(add-to-list 'lisp-imenu-generic-expression
-                          (list "Packages" ,use-package-form-regexp-eval 2)))
-        (eval-after-load 'lisp-mode
-          `(setq lisp-imenu-generic-expression
-                 (remove (list "Packages" ,use-package-form-regexp-eval 2)
-                         lisp-imenu-generic-expression)))))
-  :group 'use-package)
-
-(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 argument passed
-to `:ensure'; 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)
-
-(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)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; 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, 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))))
-
-(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 depending on
-whether it's a string or symbol."
-  (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 a given keyword form.
-ARGS 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))
-              (ignore
-               (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)
-    (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))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Keywords
-;;
-
-(defun use-package-keyword-index (keyword)
-  (loop named outer
-        with index = 0
-        for k in use-package-keywords do
-        (if (eq k keyword)
-            (return-from outer index))
-        (incf index)))
-
-(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)
-      (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-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)
-  (pcase key
-    (`:if `(and ,new ,old))
-    (`:after `(:all ,new ,old))
-    (`:defer old)
-    (_ (append new old))))
-
-(defun use-package-normalize-keywords (name args)
-  (let* ((name-symbol (if (stringp name) (intern name) name))
-         (name-string (symbol-name name-symbol)))
-
-    ;; 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.
-    (dolist (spec use-package-defaults)
-      (when (pcase (nth 2 spec)
-              ((and func (pred functionp)) (funcall func args))
-              (sexp (eval sexp)))
-        (setq args (use-package-plist-maybe-put
-                    args (nth 0 spec) (eval (nth 1 spec))))))
-
-    ;; 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)
-                       `(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))
-               (or (plist-member args :bind)
-                   (plist-member args :bind*)
-                   (plist-member args :bind-keymap)
-                   (plist-member args :bind-keymap*)
-                   (plist-member args :interpreter)
-                   (plist-member args :mode)
-                   (plist-member args :magic)
-                   (plist-member args :magic-fallback)
-                   (plist-member args :commands)
-                   (plist-member args :hook)))
-      (setq args (append args '(:defer t))))
-
-    (when (and (plist-member args :load)
-               (plist-member args :no-require))
-      (setq args (use-package-plist-delete args :no-require)))
-
-    (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-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."
-  (when input
-    (let* ((keyword (car input))
-           (xs (use-package-split-list #'keywordp (cdr input)))
-           (args (car xs))
-           (tail (cdr xs))
-           (normalizer (intern (concat "use-package-normalize/"
-                                       (symbol-name keyword))))
-           (arg (cond ((functionp normalizer)
-                       (funcall normalizer name keyword args))
-                      ((= (length args) 1)
-                       (car args))
-                      (t
-                       args))))
-      (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)))
-        (ignore
-         (display-warning 'use-package
-                          (format "Unrecognized keyword: %s" keyword)
-                          :warning))))))
-
-(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)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Arguments
-;;
-
-(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 (gensym "use-package--loaded"))
-        (result (gensym "use-package--result"))
-        (next (gensym "use-package--next")))
-    `((lexical-let (,loaded ,result)
-        (lexical-let ((,next (lambda ()
-                               (if ,loaded
-                                   ,result
-                                 (setq ,loaded t)
-                                 (setq ,result ,arg)))))
-          ,(funcall f ``(funcall ,,next)))))))
-
-(defsubst use-package-normalize-value (label arg)
-  "Normalize a value."
-  (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)
-                       (eq (car form) 'use-package))
-                  (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)))
-                 ;; 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-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 () ...))"
-  (pcase v
-    ((and x (guard (if binding
-                       (symbolp x)
-                     (use-package-non-nil-symbolp x)))) t)
-    (`(,(or `quote `function)
-       ,(pred use-package-non-nil-symbolp)) t)
-    ((and x (guard (if binding (commandp x) (functionp x)))) t)
-    (_ (and additional-pred
-            (funcall additional-pred v)))))
-
-(defun use-package-normalize-function (v)
-  "Reduce functional constructions to one of two normal forms:
-  sym
-  #'(lambda () ...)"
-  (pcase v
-    ((pred symbolp) v)
-    (`(,(or `quote `function)
-       ,(and sym (pred symbolp))) sym)
-    (`(lambda . ,_) v)
-    (`(quote ,(and lam `(lambda . ,_))) lam)
-    (`(function ,(and lam `(lambda . ,_))) lam)
-    (_ v)))
-
-(defun use-package-normalize-commands (args)
-  "Map over ARGS of the form ((_ . F) ...).
-Normalizing functional F's and returning a list of F's
-representing symbols (that may need to be autloaded)."
-  (let ((nargs (mapcar
-                #'(lambda (x)
-                    (if (consp x)
-                        (cons (car x)
-                              (use-package-normalize-function (cdr x)))
-                      x)) args)))
-    (cons nargs
-          (delete
-           nil (mapcar
-                #'(lambda (x)
-                    (and (consp x)
-                         (use-package-non-nil-symbolp (cdr x))
-                         (cdr x))) nargs)))))
-
-(defun use-package-normalize-binder (name keyword args)
-  (use-package-as-one (symbol-name keyword) args
-    #'(lambda (label arg)
-        (unless (consp arg)
-          (use-package-error
-           (concat label " a (<string or vector> . <symbol, string or function>)"
-                   " or list of these")))
-        (use-package-normalize-pairs
-         #'(lambda (k)
-             (pcase k
-               ((pred stringp) t)
-               ((pred vectorp) t)))
-         #'(lambda (v) (use-package-recognize-function v t #'stringp))
-         name label arg))))
-
-;;;###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
-                (listify-key-sequence kv)))
-      (use-package-error
-       (format "use-package: package.el %s failed to define keymap %s"
-               package keymap-symbol)))))
-
-(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)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Handlers
-;;
-
-;;;; :disabled
-
-(defalias 'use-package-normalize/:disabled 'ignore)
-
-(defun use-package-handler/:disabled (name keyword arg rest state)
-  (use-package-process-keywords name rest state))
-
-;;;; :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)
-
-(defun use-package-normalize/:ensure (name keyword args)
-  (if (null args)
-      t
-    (use-package-only-one (symbol-name keyword) args
-      #'(lambda (label arg)
-          (if (symbolp arg)
-              arg
-            (use-package-error
-             (concat ":ensure wants an optional package name "
-                     "(an unquoted symbol name)")))))))
-
-(defun use-package-ensure-elpa (name ensure state &optional no-refresh)
-  (let ((package
-         (or (and (eq ensure t) (use-package-as-symbol name))
-             ensure)))
-    (when package
-      (require '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
-           (ignore
-            (display-warning 'use-package
-                             (format "Failed to install %s: %s"
-                                     name (error-message-string err))
-                             :error))))))))
-
-(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))
-
-;;;; :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))
-
-;;;; :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 arg
-       `((eval-and-compile ,@arg)))
-     body)))
-
-;;;; :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))
-
-;;;; :bind, :bind*
-
-(defalias 'use-package-normalize/:bind 'use-package-normalize-binder)
-(defalias 'use-package-normalize/:bind* 'use-package-normalize-binder)
-
-(defun use-package-handler/:bind
-    (name keyword args rest state &optional bind-macro)
-  (cl-destructuring-bind (nargs . commands)
-      (use-package-normalize-commands args)
-    (use-package-concat
-     (use-package-process-keywords name
-       (use-package-sort-keywords
-        (use-package-plist-append rest :commands commands))
-       state)
-     `((ignore
-        (,(if bind-macro bind-macro 'bind-keys)
-         :package ,name ,@nargs))))))
-
-(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*
-
-(defalias 'use-package-normalize/:bind-keymap 'use-package-normalize-binder)
-(defalias 'use-package-normalize/:bind-keymap* 'use-package-normalize-binder)
-
-(defun use-package-handler/:bind-keymap
-    (name keyword arg rest state &optional override)
-  (let ((form
-         (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)))) arg)))
-    (use-package-concat
-     (use-package-process-keywords name rest state)
-     `((ignore ,@form)))))
-
-(defun use-package-handler/:bind-keymap* (name keyword arg rest state)
-  (use-package-handler/:bind-keymap name keyword arg rest state t))
-
-;;;; :interpreter
-
-(defun use-package-handle-mode (name alist args rest state)
-  "Handle keywords which add regexp/mode pairs to an alist."
-  (cl-destructuring-bind (nargs . commands)
-      (use-package-normalize-commands args)
-    (use-package-concat
-     (mapcar
-      #'(lambda (thing)
-          `(add-to-list
-            ',alist
-            ',(cons (use-package-normalize-regex (car thing))
-                    (cdr thing))))
-      nargs)
-     (use-package-process-keywords name
-       (use-package-sort-keywords
-        (use-package-plist-append rest :commands commands))
-       state))))
-
-(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
-
-(defalias 'use-package-normalize/:mode 'use-package-normalize-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)
-
-(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))
-
-;;;; :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
-         name label arg))))
-
-(defun use-package-handler/:hook (name keyword args rest state)
-  "Generate use-package custom keyword code."
-  (cl-destructuring-bind (nargs . commands)
-      (use-package-normalize-commands args)
-    (use-package-concat
-     (cl-mapcan
-      #'(lambda (def)
-          (let ((syms (car def))
-                (fun (cdr def)))
-            (when fun
-              (mapcar
-               #'(lambda (sym)
-                   `(add-hook (quote ,(intern (format "%s-hook" sym)))
-                              (function ,fun)))
-               (if (use-package-non-nil-symbolp syms) (list syms) syms)))))
-      nargs)
-     (use-package-process-keywords name
-       (use-package-sort-keywords
-        (use-package-plist-append rest :commands commands))
-       state))))
-
-;;;; :commands
-
-(defalias 'use-package-normalize/:commands 'use-package-normalize-symlist)
-
-(defun use-package-handler/:commands (name keyword arg rest state)
-  (use-package-concat
-   (unless (plist-get state :demand)
-     ;; 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 (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)))
-
-;;;; :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
-       (list (use-package-require-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."
-  (pcase features
-    ((and (pred use-package-non-nil-symbolp) feat)
-     1)
-    (`(,(or `:or `:any) . ,rest)
-     (let ((num 0))
-       (dolist (next rest)
-         (setq num (+ num (use-package-after-count-uses next))))
-       num))
-    (`(,(or `:and `:all) . ,rest)
-     (apply #'max (mapcar #'use-package-after-count-uses rest)))
-    (`(,feat . ,rest)
-     (use-package-after-count-uses (cons :all (cons feat rest))))))
-
-(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'."
-  (pcase features
-    ((and (pred use-package-non-nil-symbolp) feat)
-     `(eval-after-load ',feat
-        ,(if (member (car body) '(quote backquote \' \`))
-             body
-           (list 'quote body))))
-    (`(,(or `:or `:any) . ,rest)
-     (macroexp-progn
-      (mapcar #'(lambda (x) (use-package-require-after-load x body)) rest)))
-    (`(,(or `:and `:all) . ,rest)
-     (dolist (next rest)
-       (setq body (use-package-require-after-load next body)))
-     body)
-    (`(,feat . ,rest)
-     (use-package-require-after-load (cons :all (cons feat rest)) 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)
-          (list (use-package-require-after-load
-                 arg (list 'quote (macroexp-progn 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
-   (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>) or list of these"
-                 name-symbol)))
-    (unless (listp arg)
-      (use-package-error error-msg))
-    (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 arg) 2))
-          (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) `(custom-set-faces (quote ,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
-   (let ((init-body
-          (use-package-hook-injector (use-package-as-string name)
-                                     :init arg)))
-     (if use-package-check-before-init
-         `((if (locate-library ,(use-package-as-string name))
-               ,(macroexp-progn init-body)))
-       init-body))
-   (use-package-process-keywords name rest state)))
-
-;;;; :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)))
-    (dolist (pkg arg)
-      (setq body (use-package-require 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)))
-    (if (or (null arg)
-            (equal arg '(t)))
-        body
-      (use-package-with-elapsed-timer
-          (format "Configuring package %s" name-symbol)
-        (use-package-concat
-         (use-package-hook-injector
-          (symbol-name name-symbol) :config arg)
-         body
-         (list t))))))
-
-;;;; :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:
-     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")))))
-
-(defun use-package-normalize/:diminish (name keyword args)
-  (use-package-as-one (symbol-name keyword) args
-    (apply-partially #'use-package-normalize-diminish name) t))
-
-(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)))
-
-;;;; :delight
-
-(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"))))
-
-(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)))))
-
-(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)))))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; The main macro
-;;
-
-(defun use-package-core (name args)
-  (let ((orig-args (cl-copy-list args)))
-    (setq args (use-package-normalize-keywords name args))
-    (let ((body (macroexp-progn
-                 (use-package-process-keywords name args
-                   (and (plist-get args :demand)
-                        (list :demand t))))))
-      (if use-package-expand-minimally
-          body
-        `(condition-case-unless-debug err
-             ,body
-           (error
-            (let ((msg (format "%s: %s" ',name (error-message-string err))))
-              (when (eq use-package-verbose 'debug)
-                (setq msg (concat msg " (see the *use-package* buffer)"))
-                (with-current-buffer (get-buffer-create "*use-package*")
-                  (goto-char (point-max))
-                  (insert "-----\n" msg "\n\n"
-                          (pp-to-string ',`(use-package ,name ,@orig-args))
-                          "\n  -->\n\n"
-                          (pp-to-string ',`(use-package ,name ,@args))
-                          "\n  ==>\n\n"
-                          (pp-to-string
-                           ',(let ((use-package-verbose 'errors)
-                                   (use-package-expand-minimally t))
-                               (macroexp-progn
-                                (use-package-process-keywords name args
-                                  (and (plist-get args :demand)
-                                       (list :demand t)))))))
-                  (emacs-lisp-mode)))
-              (ignore (display-warning 'use-package msg :error)))))))))
-
-;;;###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.
-
-: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',
-                 `: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.
-: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).
-:delight         Support for delight.el (if installed).
-:custom          Call `customize-set-variable' with each variable definition.
-:custom-face     Call `customize-set-faces' with each face definition.
-:ensure          Loads the package using package.el if necessary.
-:pin             Pin the package to an archive."
-  (declare (indent 1))
-  (unless (memq :disabled args)
-    (if (eq use-package-verbose 'errors)
-        (use-package-core name args)
-      (condition-case-unless-debug err
-          (use-package-core name args)
-        (error
-         (ignore
-          (let ((msg (format "Failed to parse package %s %s: %s"
-                             name args (error-message-string err))))
-            (display-warning 'use-package msg :error))))))))
-
-(put 'use-package 'lisp-indent-function 'defun)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Jump to declaration
-;;
-
-(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 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))))))
+(require 'up-core)
+(require 'up-ensure)
+(require 'up-diminish)
+(require 'up-delight)
 
 (provide 'use-package)
 
diff --git a/test/lisp/use-package/use-package-tests.el b/test/lisp/use-package/use-package-tests.el
deleted file mode 100644 (file)
index 7f0dfe3..0000000
+++ /dev/null
@@ -1,1210 +0,0 @@
-;;; use-package-tests.el --- Tests for use-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 2, 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 GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-\f
-;;; Commentary:
-
-;; 
-
-\f
-;;; Code:
-
-(require 'ert)
-(require 'use-package)
-
-(setq use-package-always-ensure nil
-      use-package-verbose 'errors
-      use-package-expand-minimally t
-      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 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")
-      (search-forward "(use-package")
-      (goto-char (match-beginning 0))
-      (let ((decl (read (current-buffer))))
-        (kill-sexp)
-        (let ((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)
-
-(eval-when-compile
-  (defun plist-delete (plist property)
-    "Delete PROPERTY from PLIST"
-    (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))
-
-  ;; `cl-flet' does not work for some of the mocking we do below, while `flet'
-  ;; always does.
-  (setplist 'flet (plist-delete (symbol-plist 'flet) 'byte-obsolete-info)))
-
-(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
-                (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
-                (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
-                (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 ()
-  (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)
-    (flet ((use-package-ensure-elpa
-            (name ensure state &optional no-refresh)
-            (when ensure
-              (setq tried-to-install name)))
-           (require (&rest ignore)))
-      (use-package foo :ensure t)
-      (should (eq tried-to-install 'foo)))))
-
-(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
-                (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
-                                 (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
-                                 (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))))))
-
-(ert-deftest use-package-test-normalize/:bind ()
-  (flet ((norm (&rest args)
-               (apply #'use-package-normalize-binder
-                      'foopkg :bind args)))
-    (let ((good-values '(:map map-sym
-                              ("str" . sym) ("str" . "str")
-                              ([vec] . sym) ([vec] . "str"))))
-      (should (equal (norm good-values) good-values)))
-    (should-error (norm '("foo")))
-    (should-error (norm '("foo" . 99)))
-    (should-error (norm '(99 . sym)))))
-
-(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))
-      (ignore
-       (bind-keys :package foo ("C-k" . key))))))
-
-(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))
-      (ignore
-       (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))
-   `(ignore
-     (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))
-   `(ignore
-     (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
-      (add-to-list 'interpreter-mode-alist '("interp" . foo))
-      (unless (fboundp 'foo)
-        (autoload #'foo "foo" nil t)))))
-
-(ert-deftest use-package-test/:interpreter-2 ()
-  (match-expansion
-   (use-package foo :interpreter ("interp" . fun))
-   `(progn
-      (add-to-list 'interpreter-mode-alist '("interp" . fun))
-      (unless (fboundp 'fun)
-        (autoload #'fun "foo" nil t)))))
-
-(ert-deftest use-package-test-normalize/:mode ()
-  (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
-      (add-to-list 'auto-mode-alist '("interp" . foo))
-      (unless (fboundp 'foo)
-        (autoload #'foo "foo" nil t)))))
-
-(ert-deftest use-package-test/:mode-2 ()
-  (match-expansion
-   (use-package foo :mode ("interp" . fun))
-   `(progn
-      (add-to-list 'auto-mode-alist '("interp" . fun))
-      (unless (fboundp 'fun)
-        (autoload #'fun "foo" nil t)))))
-
-(ert-deftest use-package-test/:magic-1 ()
-  (match-expansion
-   (use-package foo :magic "interp")
-   `(progn
-      (add-to-list 'magic-mode-alist '("interp" . foo))
-      (unless (fboundp 'foo)
-        (autoload #'foo "foo" nil t)))))
-
-(ert-deftest use-package-test/:magic-2 ()
-  (match-expansion
-   (use-package foo :magic ("interp" . fun))
-   `(progn
-      (add-to-list 'magic-mode-alist '("interp" . fun))
-      (unless (fboundp 'fun)
-        (autoload #'fun "foo" nil t)))))
-
-(ert-deftest use-package-test/:magic-fallback-1 ()
-  (match-expansion
-   (use-package foo :magic-fallback "interp")
-   `(progn
-      (add-to-list 'magic-fallback-mode-alist '("interp" . foo))
-      (unless (fboundp 'foo)
-        (autoload #'foo "foo" nil t)))))
-
-(ert-deftest use-package-test/:magic-fallback-2 ()
-  (match-expansion
-   (use-package foo :magic-fallback ("interp" . fun))
-   `(progn
-      (add-to-list 'magic-fallback-mode-alist '("interp" . fun))
-      (unless (fboundp 'fun)
-        (autoload #'fun "foo" nil t)))))
-
-(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
-                                 (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/: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
-                (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
-                (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
-                               (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
-                (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
-                                 (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
-                               (load "foo" nil t)))))))
-
-(ert-deftest use-package-test-normalize/:hook ()
-  (flet ((norm (&rest args)
-               (apply #'use-package-normalize/:hook
-                      'foopkg :hook args)))
-    (should-error (norm nil))
-    (should (equal (norm '(bar))
-                   '((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))))
-    (should (equal (norm '((bar baz) (quux bow)))
-                   '(((bar baz) . foopkg) ((quux bow) . foopkg))))
-    (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))
-    (should
-     (equal
-      (expand-minimally
-       (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
-                 (load "foo" nil t))))
-         (add-hook 'hook-hook #'fun)
-         (unless (fboundp 'fun)
-           (autoload #'fun "foo" nil t))
-         (eval-when-compile
-           (declare-function fun "foo"))
-         (unless (fboundp 'key)
-           (autoload #'key "foo" nil t))
-         (eval-when-compile
-           (declare-function key "foo"))
-         (ignore
-          (bind-keys :package foo ("C-a" . key))))))))
-
-(ert-deftest use-package-test-normalize/:custom ()
-  (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
-      (customize-set-variable 'foo bar "Customized with use-package foo")
-      (require 'foo nil nil))))
-
-(ert-deftest use-package-test/:custom-face-1 ()
-  (match-expansion
-   (use-package foo :custom-face (foo ((t (:background "#e4edfc")))))
-   `(progn
-      (custom-set-faces '(foo ((t (:background "#e4edfc")))))
-      (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
-                                 (load "foo" nil t))))
-        (init)
-        (require 'foo nil nil)))))
-
-(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
-                                 (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))
-   `(lexical-let ,_
-      (lexical-let ,_
-        (progn
-          (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))
-   `(lexical-let ,_
-      (lexical-let ,_
-        (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))
-   `(lexical-let ,_
-      (lexical-let ,_
-        (progn
-          (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)))
-   `(lexical-let ,_
-      (lexical-let ,_
-        (progn
-          (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)))
-   `(lexical-let ,_
-      (lexical-let ,_
-        (progn
-          (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)))
-   `(lexical-let ,_
-      (lexical-let ,_
-        (progn
-          (eval-after-load 'quux
-            '(eval-after-load 'bar
-               `(funcall ,_)))
-          (progn
-            (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
-                                 (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
-                                 (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
-                                 (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 "site-lisp/swiper"
-;;      :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 "/Users/johnw/.emacs.d/site-lisp/swiper"))
-;;       (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))
-;;            (ignore
-;;             (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
-                                 (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
-                                 (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)))))))
-
-;; Local Variables:
-;; indent-tabs-mode: nil
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-
-;;; use-package-tests.el ends here
diff --git a/up-core.el b/up-core.el
new file mode 100644 (file)
index 0000000..d11c2d7
--- /dev/null
@@ -0,0 +1,1476 @@
+;;; up-core.el --- A configuration macro for simplifying your .emacs
+
+;; Copyright (C) 2012-2017 John Wiegley
+
+;; Author: John Wiegley <johnw@newartisans.com>
+;; Maintainer: John Wiegley <johnw@newartisans.com>
+;; Created: 17 Jun 2012
+;; Modified: 29 Nov 2017
+;; Version: 2.4
+;; Package-Requires: ((emacs "24.3") (bind-key "2.4"))
+;; Keywords: dotemacs startup speed config package
+;; 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, 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 GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; 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 'bind-key)
+(require 'bytecomp)
+(require 'cl-lib)
+
+(eval-when-compile
+  (require 'cl)
+  (require 'regexp-opt)
+
+  (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'."
+  :group 'startup)
+
+(defconst use-package-version "2.4"
+  "This version of use-package.")
+
+(defcustom use-package-keywords
+  '(:disabled
+    :if :when :unless
+    :requires
+    :load-path
+    :no-require
+    :preface :defines :functions
+    :after
+    :custom
+    :custom-face
+    :init
+    :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
+    :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-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" 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)
+    (:defer use-package-always-defer
+            (lambda (args)
+              (and use-package-always-defer
+                   (not (plist-member args :defer))
+                   (not (plist-member args :demand)))))
+    (:demand use-package-always-demand
+             (lambda (args)
+               (and use-package-always-demand
+                    (not (plist-member args :defer))
+                    (not (plist-member args :demand))))))
+  "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. This third element may also be a function, in
+which case it receives the list of keywords (in normalized form),
+and should return nil or t according to 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)
+                (choice :tag "Enable if non-nil" sexp function)))
+  :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, adjust `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)
+      (if value
+          (eval-after-load 'lisp-mode
+            `(add-to-list 'lisp-imenu-generic-expression
+                          (list "Packages" ,use-package-form-regexp-eval 2)))
+        (eval-after-load 'lisp-mode
+          `(setq lisp-imenu-generic-expression
+                 (remove (list "Packages" ,use-package-form-regexp-eval 2)
+                         lisp-imenu-generic-expression)))))
+  :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)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; 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, 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))))
+
+(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 depending on
+whether it's a string or symbol."
+  (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 a given keyword form.
+ARGS 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))
+              (ignore
+               (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)
+    (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))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Keywords
+;;
+
+(defun use-package-keyword-index (keyword)
+  (loop named outer
+        with index = 0
+        for k in use-package-keywords do
+        (if (eq k keyword)
+            (return-from outer index))
+        (incf index)))
+
+(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)
+      (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-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)
+  (pcase key
+    (`:if `(and ,new ,old))
+    (`:after `(:all ,new ,old))
+    (`:defer old)
+    (_ (append new old))))
+
+(defun use-package-normalize-keywords (name args)
+  (let* ((name-symbol (if (stringp name) (intern name) name))
+         (name-string (symbol-name name-symbol)))
+
+    ;; 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.
+    (dolist (spec use-package-defaults)
+      (when (pcase (nth 2 spec)
+              ((and func (pred functionp)) (funcall func args))
+              (sexp (eval sexp)))
+        (setq args (use-package-plist-maybe-put
+                    args (nth 0 spec) (eval (nth 1 spec))))))
+
+    ;; 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)
+                       `(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))
+               (or (plist-member args :bind)
+                   (plist-member args :bind*)
+                   (plist-member args :bind-keymap)
+                   (plist-member args :bind-keymap*)
+                   (plist-member args :interpreter)
+                   (plist-member args :mode)
+                   (plist-member args :magic)
+                   (plist-member args :magic-fallback)
+                   (plist-member args :commands)
+                   (plist-member args :hook)))
+      (setq args (append args '(:defer t))))
+
+    (when (and (plist-member args :load)
+               (plist-member args :no-require))
+      (setq args (use-package-plist-delete args :no-require)))
+
+    (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-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."
+  (when input
+    (let* ((keyword (car input))
+           (xs (use-package-split-list #'keywordp (cdr input)))
+           (args (car xs))
+           (tail (cdr xs))
+           (normalizer (intern (concat "use-package-normalize/"
+                                       (symbol-name keyword))))
+           (arg (cond ((functionp normalizer)
+                       (funcall normalizer name keyword args))
+                      ((= (length args) 1)
+                       (car args))
+                      (t
+                       args))))
+      (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)))
+        (ignore
+         (display-warning 'use-package
+                          (format "Unrecognized keyword: %s" keyword)
+                          :warning))))))
+
+(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)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Arguments
+;;
+
+(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 (gensym "use-package--loaded"))
+        (result (gensym "use-package--result"))
+        (next (gensym "use-package--next")))
+    `((lexical-let (,loaded ,result)
+        (lexical-let ((,next (lambda ()
+                               (if ,loaded
+                                   ,result
+                                 (setq ,loaded t)
+                                 (setq ,result ,arg)))))
+          ,(funcall f ``(funcall ,,next)))))))
+
+(defsubst use-package-normalize-value (label arg)
+  "Normalize a value."
+  (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)
+                       (eq (car form) 'use-package))
+                  (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)))
+                 ;; 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-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 () ...))"
+  (pcase v
+    ((and x (guard (if binding
+                       (symbolp x)
+                     (use-package-non-nil-symbolp x)))) t)
+    (`(,(or `quote `function)
+       ,(pred use-package-non-nil-symbolp)) t)
+    ((and x (guard (if binding (commandp x) (functionp x)))) t)
+    (_ (and additional-pred
+            (funcall additional-pred v)))))
+
+(defun use-package-normalize-function (v)
+  "Reduce functional constructions to one of two normal forms:
+  sym
+  #'(lambda () ...)"
+  (pcase v
+    ((pred symbolp) v)
+    (`(,(or `quote `function)
+       ,(and sym (pred symbolp))) sym)
+    (`(lambda . ,_) v)
+    (`(quote ,(and lam `(lambda . ,_))) lam)
+    (`(function ,(and lam `(lambda . ,_))) lam)
+    (_ v)))
+
+(defun use-package-normalize-commands (args)
+  "Map over ARGS of the form ((_ . F) ...).
+Normalizing functional F's and returning a list of F's
+representing symbols (that may need to be autloaded)."
+  (let ((nargs (mapcar
+                #'(lambda (x)
+                    (if (consp x)
+                        (cons (car x)
+                              (use-package-normalize-function (cdr x)))
+                      x)) args)))
+    (cons nargs
+          (delete
+           nil (mapcar
+                #'(lambda (x)
+                    (and (consp x)
+                         (use-package-non-nil-symbolp (cdr x))
+                         (cdr x))) nargs)))))
+
+(defun use-package-normalize-binder (name keyword args)
+  (use-package-as-one (symbol-name keyword) args
+    #'(lambda (label arg)
+        (unless (consp arg)
+          (use-package-error
+           (concat label " a (<string or vector> . <symbol, string or function>)"
+                   " or list of these")))
+        (use-package-normalize-pairs
+         #'(lambda (k)
+             (pcase k
+               ((pred stringp) t)
+               ((pred vectorp) t)))
+         #'(lambda (v) (use-package-recognize-function v t #'stringp))
+         name label arg))))
+
+;;;###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
+                (listify-key-sequence kv)))
+      (use-package-error
+       (format "use-package: package.el %s failed to define keymap %s"
+               package keymap-symbol)))))
+
+(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)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Handlers
+;;
+
+;;;; :disabled
+
+(defalias 'use-package-normalize/:disabled 'ignore)
+
+(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))
+
+;;;; :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 arg
+       `((eval-and-compile ,@arg)))
+     body)))
+
+;;;; :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))
+
+;;;; :bind, :bind*
+
+(defalias 'use-package-normalize/:bind 'use-package-normalize-binder)
+(defalias 'use-package-normalize/:bind* 'use-package-normalize-binder)
+
+(defun use-package-handler/:bind
+    (name keyword args rest state &optional bind-macro)
+  (cl-destructuring-bind (nargs . commands)
+      (use-package-normalize-commands args)
+    (use-package-concat
+     (use-package-process-keywords name
+       (use-package-sort-keywords
+        (use-package-plist-append rest :commands commands))
+       state)
+     `((ignore
+        (,(if bind-macro bind-macro 'bind-keys)
+         :package ,name ,@nargs))))))
+
+(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*
+
+(defalias 'use-package-normalize/:bind-keymap 'use-package-normalize-binder)
+(defalias 'use-package-normalize/:bind-keymap* 'use-package-normalize-binder)
+
+(defun use-package-handler/:bind-keymap
+    (name keyword arg rest state &optional override)
+  (let ((form
+         (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)))) arg)))
+    (use-package-concat
+     (use-package-process-keywords name rest state)
+     `((ignore ,@form)))))
+
+(defun use-package-handler/:bind-keymap* (name keyword arg rest state)
+  (use-package-handler/:bind-keymap name keyword arg rest state t))
+
+;;;; :interpreter
+
+(defun use-package-handle-mode (name alist args rest state)
+  "Handle keywords which add regexp/mode pairs to an alist."
+  (cl-destructuring-bind (nargs . commands)
+      (use-package-normalize-commands args)
+    (use-package-concat
+     (mapcar
+      #'(lambda (thing)
+          `(add-to-list
+            ',alist
+            ',(cons (use-package-normalize-regex (car thing))
+                    (cdr thing))))
+      nargs)
+     (use-package-process-keywords name
+       (use-package-sort-keywords
+        (use-package-plist-append rest :commands commands))
+       state))))
+
+(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
+
+(defalias 'use-package-normalize/:mode 'use-package-normalize-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)
+
+(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))
+
+;;;; :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
+         name label arg))))
+
+(defun use-package-handler/:hook (name keyword args rest state)
+  "Generate use-package custom keyword code."
+  (cl-destructuring-bind (nargs . commands)
+      (use-package-normalize-commands args)
+    (use-package-concat
+     (cl-mapcan
+      #'(lambda (def)
+          (let ((syms (car def))
+                (fun (cdr def)))
+            (when fun
+              (mapcar
+               #'(lambda (sym)
+                   `(add-hook (quote ,(intern (format "%s-hook" sym)))
+                              (function ,fun)))
+               (if (use-package-non-nil-symbolp syms) (list syms) syms)))))
+      nargs)
+     (use-package-process-keywords name
+       (use-package-sort-keywords
+        (use-package-plist-append rest :commands commands))
+       state))))
+
+;;;; :commands
+
+(defalias 'use-package-normalize/:commands 'use-package-normalize-symlist)
+
+(defun use-package-handler/:commands (name keyword arg rest state)
+  (use-package-concat
+   (unless (plist-get state :demand)
+     ;; 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 (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)))
+
+;;;; :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
+       (list (use-package-require-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."
+  (pcase features
+    ((and (pred use-package-non-nil-symbolp) feat)
+     1)
+    (`(,(or `:or `:any) . ,rest)
+     (let ((num 0))
+       (dolist (next rest)
+         (setq num (+ num (use-package-after-count-uses next))))
+       num))
+    (`(,(or `:and `:all) . ,rest)
+     (apply #'max (mapcar #'use-package-after-count-uses rest)))
+    (`(,feat . ,rest)
+     (use-package-after-count-uses (cons :all (cons feat rest))))))
+
+(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'."
+  (pcase features
+    ((and (pred use-package-non-nil-symbolp) feat)
+     `(eval-after-load ',feat
+        ,(if (member (car body) '(quote backquote \' \`))
+             body
+           (list 'quote body))))
+    (`(,(or `:or `:any) . ,rest)
+     (macroexp-progn
+      (mapcar #'(lambda (x) (use-package-require-after-load x body)) rest)))
+    (`(,(or `:and `:all) . ,rest)
+     (dolist (next rest)
+       (setq body (use-package-require-after-load next body)))
+     body)
+    (`(,feat . ,rest)
+     (use-package-require-after-load (cons :all (cons feat rest)) 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)
+          (list (use-package-require-after-load
+                 arg (list 'quote (macroexp-progn 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
+   (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>) or list of these"
+                 name-symbol)))
+    (unless (listp arg)
+      (use-package-error error-msg))
+    (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 arg) 2))
+          (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) `(custom-set-faces (quote ,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
+   (let ((init-body
+          (use-package-hook-injector (use-package-as-string name)
+                                     :init arg)))
+     (if use-package-check-before-init
+         `((if (locate-library ,(use-package-as-string name))
+               ,(macroexp-progn init-body)))
+       init-body))
+   (use-package-process-keywords name rest state)))
+
+;;;; :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)))
+    (dolist (pkg arg)
+      (setq body (use-package-require 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)))
+    (if (or (null arg)
+            (equal arg '(t)))
+        body
+      (use-package-with-elapsed-timer
+          (format "Configuring package %s" name-symbol)
+        (use-package-concat
+         (use-package-hook-injector
+          (symbol-name name-symbol) :config arg)
+         body
+         (list t))))))
+
+;;;; :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:
+     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")))))
+
+(defun use-package-normalize/:diminish (name keyword args)
+  (use-package-as-one (symbol-name keyword) args
+    (apply-partially #'use-package-normalize-diminish name) t))
+
+(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)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; The main macro
+;;
+
+(defun use-package-core (name args)
+  (let ((orig-args (cl-copy-list args)))
+    (setq args (use-package-normalize-keywords name args))
+    (let ((body (macroexp-progn
+                 (use-package-process-keywords name args
+                   (and (plist-get args :demand)
+                        (list :demand t))))))
+      (if use-package-expand-minimally
+          body
+        `(condition-case-unless-debug err
+             ,body
+           (error
+            (let ((msg (format "%s: %s" ',name (error-message-string err))))
+              (when (eq use-package-verbose 'debug)
+                (setq msg (concat msg " (see the *use-package* buffer)"))
+                (with-current-buffer (get-buffer-create "*use-package*")
+                  (goto-char (point-max))
+                  (insert "-----\n" msg "\n\n"
+                          (pp-to-string ',`(use-package ,name ,@orig-args))
+                          "\n  -->\n\n"
+                          (pp-to-string ',`(use-package ,name ,@args))
+                          "\n  ==>\n\n"
+                          (pp-to-string
+                           ',(let ((use-package-verbose 'errors)
+                                   (use-package-expand-minimally t))
+                               (macroexp-progn
+                                (use-package-process-keywords name args
+                                  (and (plist-get args :demand)
+                                       (list :demand t)))))))
+                  (emacs-lisp-mode)))
+              (ignore (display-warning 'use-package msg :error)))))))))
+
+;;;###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.
+
+: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',
+                 `: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.
+: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).
+:delight         Support for delight.el (if installed).
+:custom          Call `customize-set-variable' with each variable definition.
+:custom-face     Call `customize-set-faces' with each face definition.
+:ensure          Loads the package using package.el if necessary.
+:pin             Pin the package to an archive."
+  (declare (indent 1))
+  (unless (memq :disabled args)
+    (if (eq use-package-verbose 'errors)
+        (use-package-core name args)
+      (condition-case-unless-debug err
+          (use-package-core name args)
+        (error
+         (ignore
+          (let ((msg (format "Failed to parse package %s %s: %s"
+                             name args (error-message-string err))))
+            (display-warning 'use-package msg :error))))))))
+
+(put 'use-package 'lisp-indent-function 'defun)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Jump to declaration
+;;
+
+(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 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 'up-core)
+
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; End:
+
+;;; use-package.el ends here
diff --git a/up-delight.el b/up-delight.el
new file mode 100644 (file)
index 0000000..2a2138a
--- /dev/null
@@ -0,0 +1,87 @@
+;;; up-delight.el --- Support for the :delight keyword
+
+;; Copyright (C) 2012-2017 John Wiegley
+
+;; Author: John Wiegley <johnw@newartisans.com>
+;; Maintainer: John Wiegley <johnw@newartisans.com>
+;; Created: 17 Jun 2012
+;; Modified: 3 Dec 2017
+;; Version: 1.0
+;; Package-Requires: ((emacs "24.3") (use-package "2.4") (delight "1.5"))
+;; Keywords: dotemacs startup speed config package
+;; 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, 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 GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Provides support for the :delight keyword, which is made available by
+;; default by requiring `use-package'.
+
+;;; Code:
+
+(require 'up-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"))))
+
+(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)))))
+
+(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 'up-delight)
diff --git a/up-diminish.el b/up-diminish.el
new file mode 100644 (file)
index 0000000..f848531
--- /dev/null
@@ -0,0 +1,76 @@
+;;; up-diminish.el --- Support for the :diminish keyword
+
+;; Copyright (C) 2012-2017 John Wiegley
+
+;; Author: John Wiegley <johnw@newartisans.com>
+;; Maintainer: John Wiegley <johnw@newartisans.com>
+;; Created: 17 Jun 2012
+;; Modified: 3 Dec 2017
+;; Version: 1.0
+;; Package-Requires: ((emacs "24.3") (use-package "2.4") (diminish "0.45"))
+;; Keywords: dotemacs startup speed config package
+;; 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, 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 GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Provides support for the :diminish keyword, which is made available by
+;; default by requiring `use-package'.
+
+;;; Code:
+
+(require 'up-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")))))
+
+(defun use-package-normalize/:diminish (name keyword args)
+  (use-package-as-one (symbol-name keyword) args
+    (apply-partially #'use-package-normalize-diminish name) t))
+
+(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 'up-diminish)
diff --git a/up-ensure.el b/up-ensure.el
new file mode 100644 (file)
index 0000000..75b0ea1
--- /dev/null
@@ -0,0 +1,190 @@
+;;; up-ensure.el --- Support for the :ensure and :pin keywords
+
+;; Copyright (C) 2012-2017 John Wiegley
+
+;; Author: John Wiegley <johnw@newartisans.com>
+;; Maintainer: John Wiegley <johnw@newartisans.com>
+;; Created: 17 Jun 2012
+;; Modified: 3 Dec 2017
+;; Version: 1.0
+;; Package-Requires: ((emacs "24.3") (use-package "2.4"))
+;; Keywords: dotemacs startup speed config package
+;; 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, 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 GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Provides support for the :ensure and :pin keywords, which is made available
+;; by default by requiring `use-package'.
+
+;;; Code:
+
+(require 'up-core)
+
+(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)
+
+(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)
+
+(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 argument passed
+to `:ensure'; 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)
+
+;;;; :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)
+
+(defun use-package-normalize/:ensure (name keyword args)
+  (if (null args)
+      t
+    (use-package-only-one (symbol-name keyword) args
+      #'(lambda (label arg)
+          (if (symbolp arg)
+              arg
+            (use-package-error
+             (concat ":ensure wants an optional package name "
+                     "(an unquoted symbol name)")))))))
+
+(defun use-package-ensure-elpa (name ensure state &optional no-refresh)
+  (let ((package
+         (or (and (eq ensure t) (use-package-as-symbol name))
+             ensure)))
+    (when package
+      (require '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
+           (ignore
+            (display-warning 'use-package
+                             (format "Failed to install %s: %s"
+                                     name (error-message-string err))
+                             :error))))))))
+
+(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 use-package-always-ensure
+                       (lambda (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 'up-ensure)
diff --git a/up-tests.el b/up-tests.el
new file mode 100644 (file)
index 0000000..7f0dfe3
--- /dev/null
@@ -0,0 +1,1210 @@
+;;; use-package-tests.el --- Tests for use-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 2, 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 GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+\f
+;;; Commentary:
+
+;; 
+
+\f
+;;; Code:
+
+(require 'ert)
+(require 'use-package)
+
+(setq use-package-always-ensure nil
+      use-package-verbose 'errors
+      use-package-expand-minimally t
+      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 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")
+      (search-forward "(use-package")
+      (goto-char (match-beginning 0))
+      (let ((decl (read (current-buffer))))
+        (kill-sexp)
+        (let ((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)
+
+(eval-when-compile
+  (defun plist-delete (plist property)
+    "Delete PROPERTY from PLIST"
+    (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))
+
+  ;; `cl-flet' does not work for some of the mocking we do below, while `flet'
+  ;; always does.
+  (setplist 'flet (plist-delete (symbol-plist 'flet) 'byte-obsolete-info)))
+
+(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
+                (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
+                (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
+                (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 ()
+  (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)
+    (flet ((use-package-ensure-elpa
+            (name ensure state &optional no-refresh)
+            (when ensure
+              (setq tried-to-install name)))
+           (require (&rest ignore)))
+      (use-package foo :ensure t)
+      (should (eq tried-to-install 'foo)))))
+
+(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
+                (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
+                                 (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
+                                 (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))))))
+
+(ert-deftest use-package-test-normalize/:bind ()
+  (flet ((norm (&rest args)
+               (apply #'use-package-normalize-binder
+                      'foopkg :bind args)))
+    (let ((good-values '(:map map-sym
+                              ("str" . sym) ("str" . "str")
+                              ([vec] . sym) ([vec] . "str"))))
+      (should (equal (norm good-values) good-values)))
+    (should-error (norm '("foo")))
+    (should-error (norm '("foo" . 99)))
+    (should-error (norm '(99 . sym)))))
+
+(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))
+      (ignore
+       (bind-keys :package foo ("C-k" . key))))))
+
+(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))
+      (ignore
+       (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))
+   `(ignore
+     (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))
+   `(ignore
+     (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
+      (add-to-list 'interpreter-mode-alist '("interp" . foo))
+      (unless (fboundp 'foo)
+        (autoload #'foo "foo" nil t)))))
+
+(ert-deftest use-package-test/:interpreter-2 ()
+  (match-expansion
+   (use-package foo :interpreter ("interp" . fun))
+   `(progn
+      (add-to-list 'interpreter-mode-alist '("interp" . fun))
+      (unless (fboundp 'fun)
+        (autoload #'fun "foo" nil t)))))
+
+(ert-deftest use-package-test-normalize/:mode ()
+  (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
+      (add-to-list 'auto-mode-alist '("interp" . foo))
+      (unless (fboundp 'foo)
+        (autoload #'foo "foo" nil t)))))
+
+(ert-deftest use-package-test/:mode-2 ()
+  (match-expansion
+   (use-package foo :mode ("interp" . fun))
+   `(progn
+      (add-to-list 'auto-mode-alist '("interp" . fun))
+      (unless (fboundp 'fun)
+        (autoload #'fun "foo" nil t)))))
+
+(ert-deftest use-package-test/:magic-1 ()
+  (match-expansion
+   (use-package foo :magic "interp")
+   `(progn
+      (add-to-list 'magic-mode-alist '("interp" . foo))
+      (unless (fboundp 'foo)
+        (autoload #'foo "foo" nil t)))))
+
+(ert-deftest use-package-test/:magic-2 ()
+  (match-expansion
+   (use-package foo :magic ("interp" . fun))
+   `(progn
+      (add-to-list 'magic-mode-alist '("interp" . fun))
+      (unless (fboundp 'fun)
+        (autoload #'fun "foo" nil t)))))
+
+(ert-deftest use-package-test/:magic-fallback-1 ()
+  (match-expansion
+   (use-package foo :magic-fallback "interp")
+   `(progn
+      (add-to-list 'magic-fallback-mode-alist '("interp" . foo))
+      (unless (fboundp 'foo)
+        (autoload #'foo "foo" nil t)))))
+
+(ert-deftest use-package-test/:magic-fallback-2 ()
+  (match-expansion
+   (use-package foo :magic-fallback ("interp" . fun))
+   `(progn
+      (add-to-list 'magic-fallback-mode-alist '("interp" . fun))
+      (unless (fboundp 'fun)
+        (autoload #'fun "foo" nil t)))))
+
+(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
+                                 (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/: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
+                (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
+                (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
+                               (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
+                (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
+                                 (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
+                               (load "foo" nil t)))))))
+
+(ert-deftest use-package-test-normalize/:hook ()
+  (flet ((norm (&rest args)
+               (apply #'use-package-normalize/:hook
+                      'foopkg :hook args)))
+    (should-error (norm nil))
+    (should (equal (norm '(bar))
+                   '((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))))
+    (should (equal (norm '((bar baz) (quux bow)))
+                   '(((bar baz) . foopkg) ((quux bow) . foopkg))))
+    (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))
+    (should
+     (equal
+      (expand-minimally
+       (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
+                 (load "foo" nil t))))
+         (add-hook 'hook-hook #'fun)
+         (unless (fboundp 'fun)
+           (autoload #'fun "foo" nil t))
+         (eval-when-compile
+           (declare-function fun "foo"))
+         (unless (fboundp 'key)
+           (autoload #'key "foo" nil t))
+         (eval-when-compile
+           (declare-function key "foo"))
+         (ignore
+          (bind-keys :package foo ("C-a" . key))))))))
+
+(ert-deftest use-package-test-normalize/:custom ()
+  (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
+      (customize-set-variable 'foo bar "Customized with use-package foo")
+      (require 'foo nil nil))))
+
+(ert-deftest use-package-test/:custom-face-1 ()
+  (match-expansion
+   (use-package foo :custom-face (foo ((t (:background "#e4edfc")))))
+   `(progn
+      (custom-set-faces '(foo ((t (:background "#e4edfc")))))
+      (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
+                                 (load "foo" nil t))))
+        (init)
+        (require 'foo nil nil)))))
+
+(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
+                                 (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))
+   `(lexical-let ,_
+      (lexical-let ,_
+        (progn
+          (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))
+   `(lexical-let ,_
+      (lexical-let ,_
+        (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))
+   `(lexical-let ,_
+      (lexical-let ,_
+        (progn
+          (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)))
+   `(lexical-let ,_
+      (lexical-let ,_
+        (progn
+          (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)))
+   `(lexical-let ,_
+      (lexical-let ,_
+        (progn
+          (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)))
+   `(lexical-let ,_
+      (lexical-let ,_
+        (progn
+          (eval-after-load 'quux
+            '(eval-after-load 'bar
+               `(funcall ,_)))
+          (progn
+            (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
+                                 (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
+                                 (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
+                                 (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 "site-lisp/swiper"
+;;      :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 "/Users/johnw/.emacs.d/site-lisp/swiper"))
+;;       (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))
+;;            (ignore
+;;             (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
+                                 (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
+                                 (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)))))))
+
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; End:
+
+;;; use-package-tests.el ends here