(const :tag "Debug" debug))
:group 'use-package)
-(defcustom use-package-debug nil
- "Whether to display use-package expansions in a *use-package* buffer."
- :type 'boolean
- :group 'use-package)
-
(defcustom use-package-check-before-init nil
"If non-nil, check that package exists before executing its `:init' block.
The check is performed by looking for the module using `locate-library'."
'(:disabled
:pin
:ensure
- :if
- :when
- :unless
+ :if :when :unless
:requires
:load-path
- :defines
- :functions
- :preface
:no-require
+ :preface :defines :functions
+ :after
+ :custom
+ :custom-face
+ :init
:bind
:bind*
:bind-keymap
:mode
:magic
:magic-fallback
- :commands
:hook
+ ;; Any other keyword that also declares commands to be autoloaded (such as
+ ;; :bind) must appear before this keyword.
+ :commands
:defer
- :custom
- :custom-face
- :init
- :after
: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)
:group 'use-package)
(defcustom use-package-defaults
- '((:config '(t) t)
- (:ensure use-package-always-ensure use-package-always-ensure)
+ '((:config '(t) t) ; this '(t) has special meaning; see
+ ; the handler for :config
+ (: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
is a form that can be evaluated to determine whether or not to
assign a default value; if it evaluates to nil, then the default
value is not assigned even if the keyword is not present in the
-`use-package' form."
- :type '(repeat (list symbol sexp sexp)))
+`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)
+;;; jww (2017-12-02): This should be in the :set for the option.
(when use-package-enable-imenu-support
(eval-after-load 'lisp-mode
`(let ((sym-regexp (or (bound-and-true-p lisp-mode-symbol-regexp)
`(load ,name ,noerror)
`(require ',name nil ,noerror)))
-(defun use-package-expand (name label form)
- "FORM is a list of forms, so `((foo))' if only `foo' is being called."
- (declare (indent 1))
- (when form
- (if use-package-expand-minimally
- form
- (let ((err (make-symbol "err")))
- (list
- `(condition-case-unless-debug ,err
- ,(macroexp-progn form)
- (error
- (ignore
- (display-warning 'use-package
- (format "%s %s: %s"
- ,name ,label (error-message-string ,err))
- :error)))))))))
-
-(put 'use-package-expand 'lisp-indent-function 'defun)
-
(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)
- (use-package-expand name-string (format "%s" keyword) body)
+ body
(let ((keyword-name (substring (format "%s" keyword) 1)))
- `((when ,(macroexp-progn
- (use-package-expand name-string (format "pre-%s hook" keyword)
- `((run-hook-with-args-until-failure
- ',(intern (concat "use-package--" name-string
- "--pre-" keyword-name "-hook"))))))
- ,(macroexp-progn
- (use-package-expand name-string (format "%s" keyword) body))
- ,(macroexp-progn
- (use-package-expand name-string (format "post-%s hook" keyword)
- `((run-hooks
- ',(intern (concat "use-package--" name-string
- "--post-" keyword-name "-hook")))))))))))
+ `((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--require (name &optional no-require body)
- (use-package--with-elapsed-timer
- (format "Loading package %s" name)
- (if use-package-expand-minimally
- (use-package-concat
- (unless no-require
- (list (use-package-load-name name)))
- body)
- (if 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 (message (format "Cannot load %s" ',name)))
+ (ignore
+ (display-warning 'use-package
+ (format "Cannot load %s" ',name)
+ :error))
,@body))))))
(defun use-package--with-elapsed-timer (text body)
(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))
+
(defun use-package-split-list (pred xs)
(let ((ys (list nil)) (zs (list nil)) flip)
(dolist (x xs)
(defsubst use-package-concat (&rest elems)
"Delete all empty lists from ELEMS (nil or (list nil)), and append them."
- (apply #'nconc (delete nil (delete (list nil) elems))))
+ (apply #'append (delete nil (delete (list nil) elems))))
(defsubst use-package--non-nil-symbolp (sym)
(and sym (symbolp sym)))
(t
(error "Not recognized as regular expression: %s" re))))
-(defun use-package-normalize-plist (name input)
- "Given a pseudo-plist, normalize it to a regular plist."
- (unless (null input)
+(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
- ((eq keyword :disabled)
- (use-package-normalize-plist name tail))
- ((functionp normalizer)
- (funcall normalizer name keyword args))
- ((= (length args) 1)
- (car args))
- (t
- args))))
+ (arg (cond ((functionp normalizer)
+ (funcall normalizer name keyword args))
+ ((= (length args) 1)
+ (car args))
+ (t
+ args))))
(if (memq keyword use-package-keywords)
- (cons keyword
- (cons arg (use-package-normalize-plist name tail)))
+ (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)
(put 'use-package-process-keywords 'lisp-indent-function 'defun)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; :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)"))))))
+ #'(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)
(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)")))))))
+ #'(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
(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)
(let ((body (use-package-process-keywords name rest state)))
(if (null requires)
body
- `((when ,(if (listp requires)
+ `((when ,(if (> (length requires) 1)
`(not (member nil (mapcar #'featurep ',requires)))
- `(featurep ',requires))
+ `(featurep ',(car requires)))
,@body)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defalias 'use-package-normalize/:no-require 'use-package-normalize-predicate)
(defun use-package-handler/:no-require (name keyword arg rest state)
- ;; This keyword has no functional meaning.
- (use-package-process-keywords name rest
- (plist-put state :no-require t)))
+ (use-package-process-keywords name rest state))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
`((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*
(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))))
+ #'(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))))
(defalias 'use-package-normalize/:bind 'use-package-normalize-binder)
(defalias 'use-package-normalize/:bind* 'use-package-normalize-binder)
(use-package-concat
(use-package-process-keywords name
(use-package-sort-keywords
- (use-package-plist-maybe-put rest :defer t))
- (use-package-plist-append state :commands commands))
+ (use-package-plist-append rest :commands commands))
+ state)
`((ignore
(,(if bind-macro bind-macro 'bind-keys)
:package ,name ,@nargs))))))
',(cdr binding) ',(use-package-as-symbol name)
,override)))) arg)))
(use-package-concat
- (use-package-process-keywords name
- (use-package-sort-keywords
- (use-package-plist-maybe-put rest :defer t))
- state)
+ (use-package-process-keywords name rest state)
`((ignore ,@form)))))
(defun use-package-handler/:bind-keymap* (name keyword arg rest state)
"Handle keywords which add regexp/mode pairs to an alist."
(cl-destructuring-bind (nargs . commands)
(use-package--normalize-commands args)
- (let ((form
- (mapcar
- #'(lambda (thing)
- `(add-to-list
- ',alist
- ',(cons (use-package-normalize-regex (car thing))
- (cdr thing))))
- nargs)))
- (use-package-concat
- (use-package-process-keywords name
- (use-package-sort-keywords
- (use-package-plist-maybe-put rest :defer t))
- (use-package-plist-append state :commands commands))
- `((ignore ,@form))))))
+ (use-package-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)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;;; :commands
-;;
-
-(defalias 'use-package-normalize/:commands 'use-package-normalize-symlist)
-
-(defun use-package-handler/:commands (name keyword arg rest state)
- ;; The actual processing for commands is done in :defer
- (use-package-process-keywords name
- (use-package-sort-keywords
- (use-package-plist-maybe-put rest :defer t))
- (use-package-plist-append state :commands arg)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; :defines
+;;; :hook
;;
-(defalias 'use-package-normalize/:defines 'use-package-normalize-symlist)
+(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/:defines (name keyword arg rest state)
- (use-package-process-keywords name rest state))
+(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))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;;; :functions
+;;; :commands
;;
-(defalias 'use-package-normalize/:functions 'use-package-normalize-symlist)
+(defalias 'use-package-normalize/:commands 'use-package-normalize-symlist)
-(defun use-package-handler/:functions (name keyword arg rest state)
- (use-package-process-keywords name rest state))
+(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)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
(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
- (plist-put state :deferred t)))
- (name-string (use-package-as-string name)))
+ (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)))
- ;; Since we deferring load, establish any necessary autoloads, and also
- ;; keep the byte-compiler happy.
- (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 (plist-get state :commands)))
-
- body)))
-
+ (if (or (not arg) (null body))
+ body
+ (list (use-package--require-after-load
+ name (macroexp-progn body)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; :after
;;
-(defalias 'use-package-normalize/:after 'use-package-normalize-recursive-symlist)
+(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-require-after-load (features)
- "Return form for after any of FEATURES require NAME."
+(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)
- `(lambda (body)
- (list 'eval-after-load (list 'quote ',feat)
- (list 'quote body))))
- (`(,(or :or :any) . ,rest)
- `(lambda (body)
- (append (list 'progn)
- (mapcar (lambda (form)
- (funcall form body))
- (list ,@(use-package-require-after-load rest))))))
- (`(,(or :and :all) . ,rest)
- `(lambda (body)
- (let ((result body))
- (dolist (form (list ,@(use-package-require-after-load rest)))
- (setq result (funcall form result)))
- result)))
+ 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)
- (if rest
- (cons (use-package-require-after-load feat)
- (use-package-require-after-load rest))
- (list (use-package-require-after-load feat))))))
+ (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--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)))))))
(defun use-package-handler/:after (name keyword arg rest state)
- (let ((body (use-package-process-keywords name rest
- (plist-put state :deferred t)))
- (name-string (use-package-as-string name)))
- (if (and (consp arg)
- (not (memq (car arg) '(:or :any :and :all))))
- (setq arg (cons :all arg)))
- (use-package-concat
- (when arg
- (list (funcall
- (use-package-require-after-load arg)
- (macroexp-progn
- (use-package--require name)))))
- body)))
+ (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))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
(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
- (use-package-plist-delete state :deferred)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; :init
-;;
-
-(defalias 'use-package-normalize/:init 'use-package-normalize-forms)
-
-(defun use-package-handler/:init (name keyword arg rest state)
- (let ((body (use-package-process-keywords name rest state)))
- (use-package-concat
- ;; The user's initializations
- (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))
- 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))
- (config-body
- (if (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))))))
- (if (plist-get state :deferred)
- (unless (or (null config-body) (equal config-body '(t)))
- `((eval-after-load ,(if (symbolp name) `',name name)
- ',(macroexp-progn config-body))))
- (use-package--require name (plist-get state ':no-require)
- config-body))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; :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
- (use-package-process-keywords name
- (if commands
- (use-package-sort-keywords
- (use-package-plist-maybe-put rest :defer t))
- rest)
- (if commands
- (use-package-plist-append state :commands commands)
- state))
- (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 rest state))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
(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))))
+ #'(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."
- (let ((body (use-package-process-keywords name rest state)))
- (use-package-concat
- (mapcar (lambda (def)
+ (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)
- body)))
+ args)
+ (use-package-process-keywords name rest state)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
(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
+ ;; The user's initializations
+ (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)))
- (use-package-concat
- (mapcar (lambda (def)
- `(custom-set-faces (quote ,def)))
- args)
- body)))
+ (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))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; The main macro
;;
+(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--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 (not (eq use-package-verbose 'debug))
+ body
+ `(condition-case-unless-debug err
+ ,body
+ (error
+ (let ((msg (format "%s: %s" ',name (error-message-string err))))
+ (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 (concat msg " (see the *use-package* buffer)")
+ :error)))))))))
+
;;;###autoload
(defmacro use-package (name &rest args)
"Declare an Emacs package by specifying a group of configuration options.
:ensure Loads the package using package.el if necessary.
:pin Pin the package to an archive."
(declare (indent 1))
- (unless (member :disabled args)
- (let ((name-symbol (if (stringp name) (intern name) name))
- (orig-args args)
- (args (use-package-normalize-plist name args)))
- (dolist (spec use-package-defaults)
- (setq args (if (eval (nth 2 spec))
- (use-package-plist-maybe-put
- args (nth 0 spec) (eval (nth 1 spec)))
- args)))
-
- ;; When byte-compiling, pre-load the package so all its symbols are in
- ;; scope.
- (if (bound-and-true-p byte-compile-current-file)
- (setq args
- (use-package-plist-append
- args :preface
- (use-package-concat
- (mapcar #'(lambda (var) `(defvar ,var))
- (plist-get args :defines))
- (mapcar #'(lambda (fn) `(declare-function
- ,fn ,(use-package-as-string name)))
- (plist-get args :functions))
- `((eval-when-compile
- (with-demoted-errors
- ,(format "Cannot load %s: %%S" name)
- ,(if (eq use-package-verbose 'debug)
- `(message "Compiling package %s" ',name-symbol))
- ,(unless (plist-get args :no-require)
- `(load ,(if (stringp name)
- name
- (symbol-name name)) nil t)))))))))
-
- (let ((body
- `(progn
- ,@(use-package-process-keywords name
- (let ((args*
- (use-package-sort-keywords
- (if (and use-package-always-demand
- (not (memq :defer args)))
- (plist-put args :demand t)
- args))))
- ;; The :demand keyword should not override :after
- (if (and (plist-member args* :after)
- (plist-member args* :demand))
- (setq args* (use-package-plist-delete args* :demand)))
- (when (and use-package-always-ensure
- (plist-member args* :load-path)
- (not (plist-member orig-args :ensure)))
- (plist-put args* :ensure nil))
- (unless (plist-member args* :init)
- (plist-put args* :init nil))
- (unless (plist-member args* :config)
- (plist-put args* :config '(t)))
- args*)
- (and use-package-always-defer
- (list :deferred t))))))
- (when use-package-debug
- (display-buffer
- (save-current-buffer
- (with-current-buffer (get-buffer-create "*use-package*")
- (goto-char (point-max))
- (emacs-lisp-mode)
- (insert (pp-to-string body))
- (current-buffer)))))
- body))))
-
+ (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
+ (display-warning
+ 'use-package
+ (format "Failed to parse package %s %s: %s"
+ name args (error-message-string err))
+ :error)))))))
(put 'use-package 'lisp-indent-function 'defun)
(require 'use-package)
(setq use-package-always-ensure nil
- use-package-verbose nil
+ use-package-verbose 'errors
use-package-expand-minimally t
- max-lisp-eval-depth 8000)
-
-;; (let ((byte-compile-current-file nil)) (expand-minimally ()))
-(fset 'insert-expansion
- [?\C-\M- ?\M-w ?\M-: ?\M-p ?\C-e ?\C-b ?\C-b ?\C-\M-b ?\C-y ?\C-\M-k return ?\C-\M- ?\M-w C-return ?\C-z ?\C-n ?\C-f ?\C-y ?\C-\M-k])
+ max-lisp-eval-depth 8000
+ max-specpdl-size 8000)
(defmacro expand-minimally (form)
- `(let ((use-package-verbose nil)
+ `(let ((use-package-verbose 'errors)
(use-package-expand-minimally t))
- (macroexpand ',form)))
+ (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"
(ert-deftest use-package-test/:disabled ()
(match-expansion
(use-package foo :disabled t)
- `())
-
- (match-expansion
- ;; jww (2017-11-30): Should :disabled ignore its argument?
- (use-package foo :disabled nil)
`()))
(ert-deftest use-package-test/:preface ()
(ert-deftest use-package-test/:defer-install ()
(match-expansion
(use-package foo :defer-install t)
- `(progn
- (require 'foo nil nil))))
+ `(require 'foo nil nil)))
(ert-deftest use-package-test-normalize/:ensure ()
(flet ((norm (&rest args)
(match-expansion
(use-package foo :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/:if ()
(match-expansion
(use-package foo :if t)
- `(progn
- (when (symbol-value 't)
- (require 'foo nil nil))))
+ `(when t
+ (require 'foo nil nil)))
(match-expansion
(use-package foo :if (and t t))
- `(progn
- (when (and t t)
- (require 'foo nil nil))))
+ `(when (and t t)
+ (require 'foo nil nil)))
(match-expansion
(use-package foo :if nil)
- `(progn
- (when nil
- (require 'foo nil nil)))))
+ `(when nil
+ (require 'foo nil nil))))
(ert-deftest use-package-test/:when ()
(match-expansion
(use-package foo :when t)
- `(progn
- (when (symbol-value 't)
- (require 'foo nil nil))))
+ `(when t
+ (require 'foo nil nil)))
(match-expansion
(use-package foo :when (and t t))
- `(progn
- (when (and t t)
- (require 'foo nil nil))))
+ `(when (and t t)
+ (require 'foo nil nil)))
(match-expansion
(use-package foo :when nil)
- `(progn
- (when nil
- (require 'foo nil nil)))))
+ `(when nil
+ (require 'foo nil nil))))
(ert-deftest use-package-test/:unless ()
(match-expansion
(use-package foo :unless t)
- `(progn
- (unless (symbol-value 't)
- (require 'foo nil nil))))
+ `(when (not t)
+ (require 'foo nil nil)))
(match-expansion
(use-package foo :unless (and t t))
- `(progn
- (unless (and t t)
- (require 'foo nil nil))))
+ `(when (not (and t t))
+ (require 'foo nil nil)))
(match-expansion
(use-package foo :unless nil)
- `(progn
- (unless nil
- (require 'foo nil nil)))))
+ `(unless nil
+ (require 'foo nil nil))))
(ert-deftest use-package-test/:requires ()
(match-expansion
(use-package foo :requires bar)
- `(progn
- (when (not (member nil (mapcar #'featurep '(bar))))
+ `(when (featurep 'bar)
+ (require 'foo nil nil)))
+
+ (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))))
+ (match-expansion
+ (use-package foo :requires (bar quux))
+ `(when (not (member nil (mapcar #'featurep '(bar quux))))
+ (require 'foo nil nil)))
+
(let ((byte-compile-current-file t))
(match-expansion
(use-package foo :requires bar)
- `(progn
- (when (not (member nil (mapcar #'featurep '(bar))))
- (eval-and-compile
- (eval-when-compile
- (with-demoted-errors "Cannot load foo: %S" nil
- (load "foo" nil t))))
- (require 'foo nil nil))))))
+ `(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 ()
(match-expansion
(ert-deftest use-package-test/:no-require ()
(match-expansion
(use-package foo :no-require t)
- `(progn))
+ `nil)
(match-expansion
(use-package foo :no-require t :config (config))
(let ((byte-compile-current-file t))
(match-expansion
(use-package foo :no-require t)
- `(progn
- (eval-and-compile
- (eval-when-compile
- (with-demoted-errors "Cannot load foo: %S" nil nil)))))))
+ `(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)
(ert-deftest use-package-test/:bind-keymap ()
(match-expansion
(use-package foo :bind-keymap ("C-k" . key))
- `(progn
- (ignore
- (bind-key "C-k"
- #'(lambda ()
- (interactive)
- (use-package-autoload-keymap 'key 'foo nil)))))))
+ `(ignore
+ (bind-key "C-k"
+ #'(lambda nil
+ (interactive)
+ (use-package-autoload-keymap 'key 'foo nil))))))
(ert-deftest use-package-test/:bind-keymap* ()
(match-expansion
(use-package foo :bind-keymap* ("C-k" . key))
- `(progn
- (ignore
- (bind-key* "C-k"
- #'(lambda ()
- (interactive)
- (use-package-autoload-keymap 'key 'foo t)))))))
+ `(ignore
+ (bind-key* "C-k"
+ #'(lambda ()
+ (interactive)
+ (use-package-autoload-keymap 'key 'foo t))))))
(ert-deftest use-package-test/:interpreter ()
(match-expansion
(use-package foo :interpreter "interp")
`(progn
+ (add-to-list 'interpreter-mode-alist '("interp" . foo))
(unless (fboundp 'foo)
- (autoload #'foo "foo" nil t))
- (ignore
- (add-to-list 'interpreter-mode-alist
- '("interp" . foo)))))
+ (autoload #'foo "foo" nil t))))
(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))
- (ignore
- (add-to-list 'interpreter-mode-alist
- '("interp" . fun))))))
+ (autoload #'fun "foo" nil t)))))
(ert-deftest use-package-test-normalize/:mode ()
(flet ((norm (&rest args)
(match-expansion
(use-package foo :mode "interp")
`(progn
+ (add-to-list 'auto-mode-alist '("interp" . foo))
(unless (fboundp 'foo)
- (autoload #'foo "foo" nil t))
- (ignore
- (add-to-list 'auto-mode-alist
- '("interp" . foo)))))
+ (autoload #'foo "foo" nil t))))
(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))
- (ignore
- (add-to-list 'auto-mode-alist
- '("interp" . fun))))))
+ (autoload #'fun "foo" nil t)))))
(ert-deftest use-package-test/:magic ()
(match-expansion
(use-package foo :magic "interp")
`(progn
+ (add-to-list 'magic-mode-alist '("interp" . foo))
(unless (fboundp 'foo)
- (autoload #'foo "foo" nil t))
- (ignore
- (add-to-list 'magic-mode-alist
- '("interp" . foo)))))
+ (autoload #'foo "foo" nil t))))
(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))
- (ignore
- (add-to-list 'magic-mode-alist
- '("interp" . fun))))))
+ (autoload #'fun "foo" nil t)))))
(ert-deftest use-package-test/:magic-fallback ()
(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))
- (ignore
- (add-to-list 'magic-fallback-mode-alist
- '("interp" . foo)))))
+ (autoload #'foo "foo" nil t))))
(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))
- (ignore
- (add-to-list 'magic-fallback-mode-alist
- '("interp" . fun))))))
+ (autoload #'fun "foo" nil t)))))
(ert-deftest use-package-test/:commands ()
(match-expansion
(use-package foo :commands bar)
- `(progn
- (unless (fboundp 'bar)
- (autoload #'bar "foo" nil t))))
+ `(unless (fboundp 'bar)
+ (autoload #'bar "foo" nil t)))
(match-expansion
(use-package foo :commands (bar quux))
(ert-deftest use-package-test/:defines ()
(match-expansion
(use-package foo :defines bar)
- `(progn
- (require 'foo nil nil)))
+ `(require 'foo nil nil))
(let ((byte-compile-current-file t))
(match-expansion
(ert-deftest use-package-test/:functions ()
(match-expansion
(use-package foo :functions bar)
- `(progn
- (require 'foo nil nil)))
+ `(require 'foo nil nil))
(let ((byte-compile-current-file t))
(match-expansion
(match-expansion
(use-package foo :defer t :functions bar)
- `(progn))
+ `nil)
(let ((byte-compile-current-file t))
(match-expansion
(use-package foo :defer t :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-and-compile
+ (declare-function bar "foo")
+ (eval-when-compile
+ (with-demoted-errors "Cannot load foo: %S" nil
+ (load "foo" nil t))))))
(let ((byte-compile-current-file t))
(match-expansion
(ert-deftest use-package-test/:defer ()
(match-expansion
(use-package foo)
- `(progn
- (require 'foo nil nil)))
+ `(require 'foo nil nil))
(let ((byte-compile-current-file t))
(match-expansion
(match-expansion
(use-package foo :defer t)
- `(progn))
+ `nil)
(let ((byte-compile-current-file t))
(match-expansion
(use-package foo :defer t)
- `(progn
- (eval-and-compile
- (eval-when-compile
- (with-demoted-errors "Cannot load foo: %S" nil
- (load "foo" nil 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)
(ert-deftest use-package-test/:hook ()
(let ((byte-compile-current-file t))
(should
- (equal ; pcase crashes
+ (equal
(expand-minimally
(use-package foo
:bind (("C-a" . key))
'(progn
(eval-and-compile
(eval-when-compile
- (with-demoted-errors "Cannot load foo: %S" nil
- (load "foo" nil t))))
+ (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
(autoload #'key "foo" nil t))
(eval-when-compile
(declare-function key "foo"))
- (add-hook 'hook-hook #'fun)
(ignore
(bind-keys :package foo ("C-a" . key))))))))
(ert-deftest use-package-test/:after ()
(match-expansion
(use-package foo :after bar)
- `(progn
- (eval-after-load 'bar
- '(require 'foo nil nil))))
+ `(eval-after-load 'bar
+ '(require 'foo nil nil)))
(let ((byte-compile-current-file t))
(match-expansion
(match-expansion
(use-package foo :after (bar quux))
- `(progn
- (eval-after-load 'quux
- '(eval-after-load 'bar
- '(require 'foo nil nil)))))
+ `(eval-after-load 'quux
+ '(eval-after-load 'bar
+ '(require 'foo nil nil))))
(match-expansion
(use-package foo :after (:all bar quux))
- `(progn
- (eval-after-load 'quux
- '(eval-after-load 'bar
- '(require 'foo nil nil)))))
+ `(eval-after-load 'quux
+ '(eval-after-load 'bar
+ '(require 'foo nil nil))))
(match-expansion
(use-package foo :after (:any bar quux))
- `(progn
- (progn
- (eval-after-load 'bar
- '(require 'foo nil nil))
- (eval-after-load 'quux
- '(require 'foo nil nil)))))
+ `(lexical-let ,_
+ (lexical-let ,_
+ (progn
+ (eval-after-load 'bar
+ `(funcall ,_))
+ (eval-after-load 'quux
+ `(funcall ,_))))))
(match-expansion
(use-package foo :after (:all (:any bar quux) bow))
- `(progn
- (eval-after-load 'bow
- '(progn
- (eval-after-load 'bar
- '(require 'foo nil nil))
- (eval-after-load 'quux
- '(require 'foo nil nil))))))
+ `(lexical-let ,_
+ (lexical-let ,_
+ (eval-after-load 'bow
+ '(progn
+ (eval-after-load 'bar
+ `(funcall ,_))
+ (eval-after-load 'quux
+ `(funcall ,_)))))))
(match-expansion
(use-package foo :after (:any (:all bar quux) bow))
- `(progn
- (progn
- (eval-after-load 'quux
- '(eval-after-load 'bar
- '(require 'foo nil nil)))
- (eval-after-load 'bow
- '(require 'foo nil nil)))))
+ `(lexical-let ,_
+ (lexical-let ,_
+ (progn
+ (eval-after-load 'quux
+ '(eval-after-load 'bar
+ `(funcall ,_)))
+ (eval-after-load 'bow
+ `(funcall ,_))))))
(match-expansion
(use-package foo :after (:all (:any bar quux) (:any bow baz)))
- `(progn
- (progn
- (eval-after-load 'bow
- '(progn
- (eval-after-load 'bar
- '(require 'foo nil nil))
- (eval-after-load 'quux
- '(require 'foo nil nil))))
- (eval-after-load 'baz
- '(progn
- (eval-after-load 'bar
- '(require 'foo nil nil))
- (eval-after-load 'quux
- '(require 'foo nil nil)))))))
+ `(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 ,_))))))))
(match-expansion
(use-package foo :after (:any (:all bar quux) (:all bow baz)))
- `(progn
- (progn
- (eval-after-load 'quux
- '(eval-after-load 'bar
- '(require 'foo nil nil)))
- (eval-after-load 'baz
- '(eval-after-load 'bow
- '(require 'foo nil nil))))))
+ `(lexical-let ,_
+ (lexical-let ,_
+ (progn
+ (eval-after-load 'quux
+ '(eval-after-load 'bar
+ `(funcall ,_)))
+ (eval-after-load 'baz
+ '(eval-after-load 'bow
+ `(funcall ,_)))))))
(match-expansion
(use-package foo :after (:any (:all bar quux) (:any bow baz)))
- `(progn
- (progn
- (eval-after-load 'quux
- '(eval-after-load 'bar
- '(require 'foo nil nil)))
+ `(lexical-let ,_
+ (lexical-let ,_
(progn
- (eval-after-load 'bow
- '(require 'foo nil nil))
- (eval-after-load 'baz
- '(require 'foo nil nil)))))))
+ (eval-after-load 'quux
+ '(eval-after-load 'bar
+ `(funcall ,_)))
+ (progn
+ (eval-after-load 'bow
+ `(funcall ,use-package--next142993))
+ (eval-after-load 'baz
+ `(funcall ,_))))))))
(ert-deftest use-package-test/:demand ()
(match-expansion
(use-package foo :demand t)
- `(progn
- (require 'foo nil nil)))
+ `(require 'foo nil nil))
(let ((byte-compile-current-file t))
(match-expansion
;; #529 - :demand should not override an explicit use of :after
(match-expansion
(use-package foo :demand t :after bar)
- `(progn
- (eval-after-load 'bar
- '(require 'foo nil nil))))
+ `(eval-after-load 'bar
+ '(require 'foo nil nil)))
(let ((byte-compile-current-file t))
(match-expansion
(with-demoted-errors "Cannot load foo: %S" nil
(load "foo" nil t))))
(eval-after-load 'bar
- '(require 'foo nil nil))))))
+ '(require 'foo nil nil)))))
+
+ (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 ()
(match-expansion
(match-expansion
(use-package foo :defer t :config (config))
- `(progn
- (eval-after-load 'foo
- '(progn
- (config)
- t))))
+ `(eval-after-load 'foo
+ '(progn
+ (config)
+ t)))
(let ((byte-compile-current-file t))
(match-expansion