:defines
:functions
:preface
+ :catch
:after
:custom
:custom-face
'(;; this '(t) has special meaning; see `use-package-handler/:config'
(:config '(t) t)
(:init nil t)
+ (:catch t (lambda (args)
+ (not use-package-expand-minimally)))
(:defer use-package-always-defer
(lambda (args)
(and use-package-always-defer
(font-lock-add-keywords 'emacs-lisp-mode use-package-font-lock-keywords)
-(defvar use-package--hush-function)
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Utility functions
`((eval-and-compile ,@arg)))
body)))
+;;;; :catch
+
+(defvar use-package--form)
+(defvar use-package--hush-function #'(lambda (keyword body) body))
+
+(defsubst use-package-hush (context keyword body)
+ `((condition-case-unless-debug err
+ ,(macroexp-progn body)
+ (error (funcall ,context ,keyword err)))))
+
+(defun use-package-normalize/:catch (name keyword args)
+ (if (null args)
+ t
+ (use-package-only-one (symbol-name keyword) args
+ use-package--hush-function)))
+
+(defun use-package-handler/:catch (name keyword arg rest state)
+ (let* ((context (gensym "use-package--warning")))
+ (cond
+ ((not arg)
+ (use-package-process-keywords name rest state))
+ ((eq arg t)
+ `((let ((,context
+ #'(lambda (keyword err)
+ (let ((msg (format "%s/%s: %s" ',name keyword
+ (error-message-string err))))
+ ,(when (eq use-package-verbose 'debug)
+ `(progn
+ (with-current-buffer
+ (get-buffer-create "*use-package*")
+ (goto-char (point-max))
+ (insert "-----\n" msg ,use-package--form)
+ (emacs-lisp-mode))
+ (setq msg
+ (concat msg
+ " (see the *use-package* buffer)"))))
+ (ignore (display-warning 'use-package msg :error))))))
+ ,@(let ((use-package--hush-function
+ (apply-partially #'use-package-hush context)))
+ (funcall use-package--hush-function keyword
+ (use-package-process-keywords name rest state))))))
+ ((functionp arg)
+ `((let ((,context ,arg))
+ ,@(let ((use-package--hush-function
+ (apply-partially #'use-package-hush context)))
+ (funcall use-package--hush-function keyword
+ (use-package-process-keywords name rest state))))))
+ (t
+ (use-package-error "The :catch keyword expects 't' or a function")))))
+
;;;; :bind, :bind*
(defalias 'use-package-normalize/:bind 'use-package-normalize-binder)
(use-package-hook-injector (use-package-as-string name)
:init arg)))
(when init-body
- (funcall use-package--hush-function
+ (funcall use-package--hush-function :init
(if use-package-check-before-init
`((when (locate-library ,(use-package-as-string name))
,@init-body))
body
(use-package-with-elapsed-timer
(format "Configuring package %s" name-symbol)
- (funcall use-package--hush-function
+ (funcall use-package--hush-function :config
(use-package-concat
(use-package-hook-injector
(symbol-name name-symbol) :config arg)
;;; The main macro
;;
-(defsubst use-package-hush (context body)
- `((condition-case-unless-debug err
- ,(macroexp-progn body)
- (error (funcall ,context err)))))
-
(defun use-package-core (name args)
- (let* ((context (gensym "use-package--warning"))
- (args* (use-package-normalize-keywords name args))
- (use-package--hush-function #'identity))
- (if use-package-expand-minimally
- (use-package-process-keywords name args*
- (and (plist-get args* :demand)
- (list :demand t)))
- `((let
- ((,context
- #'(lambda (err)
- (let ((msg (format "%s: %s" ',name (error-message-string err))))
- ,(when (eq use-package-verbose 'debug)
- `(progn
- (with-current-buffer (get-buffer-create "*use-package*")
- (goto-char (point-max))
- (insert
- "-----\n" msg
- ,(concat
- "\n\n"
- (pp-to-string `(use-package ,name ,@args))
- "\n -->\n\n"
- (pp-to-string `(use-package ,name ,@args*))
- "\n ==>\n\n"
- (pp-to-string
- (macroexp-progn
- (let ((use-package-verbose 'errors)
- (use-package-expand-minimally t))
- (use-package-process-keywords name args*
- (and (plist-get args* :demand)
- (list :demand t))))))))
- (emacs-lisp-mode))
- (setq msg (concat msg " (see the *use-package* buffer)"))))
- (ignore (display-warning 'use-package msg :error))))))
- ,(let ((use-package--hush-function
- (apply-partially #'use-package-hush context)))
- (macroexp-progn
- (funcall use-package--hush-function
- (use-package-process-keywords name args*
- (and (plist-get args* :demand)
- (list :demand t)))))))))))
+ (let* ((args* (use-package-normalize-keywords name args))
+ (use-package--form
+ (concat "\n\n"
+ (pp-to-string `(use-package ,name ,@args))
+ "\n -->\n\n"
+ (pp-to-string `(use-package ,name ,@args*))
+ "\n ==>\n\n"
+ (pp-to-string
+ (macroexp-progn
+ (let ((use-package-verbose 'errors)
+ (use-package-expand-minimally t))
+ (use-package-process-keywords name args*
+ (and (plist-get args* :demand)
+ (list :demand t)))))))))
+ (use-package-process-keywords name args*
+ (and (plist-get args* :demand)
+ (list :demand t)))))
;;;###autoload
(defmacro use-package (name &rest args)
(init)
(require 'foo nil nil)))))
+(ert-deftest use-package-test/:catch-1 ()
+ (match-expansion
+ (use-package foo :catch t)
+ `(let
+ ((,_ #'(lambda (keyword err)
+ (let ((msg (format "%s/%s: %s" 'foo keyword
+ (error-message-string err))))
+ nil
+ (ignore (display-warning 'use-package msg :error))))))
+ (condition-case-unless-debug err
+ (require 'foo nil nil)
+ (error
+ (funcall ,_ :catch err))))))
+
+(ert-deftest use-package-test/:catch-2 ()
+ (match-expansion
+ (use-package foo :catch nil)
+ `(require 'foo nil nil)))
+
+(ert-deftest use-package-test/:catch-3 ()
+ (match-expansion
+ (use-package foo :catch (lambda (keyword error)))
+ `(let
+ ((,_ (lambda (keyword error))))
+ (condition-case-unless-debug err
+ (require 'foo nil nil)
+ (error
+ (funcall ,_ :catch err))))))
+
(ert-deftest use-package-test/:after-1 ()
(match-expansion
(use-package foo :after bar)