diff --git a/bin/doom b/bin/doom index 9ddbc2b54..01c990e4b 100755 --- a/bin/doom +++ b/bin/doom @@ -85,5 +85,18 @@ ((let ((default-directory emacs-dir)) (setq argv nil noninteractive 'doom) - (doom-dispatch args))))) - + (condition-case e (doom-dispatch args) + ((debug error) + (message "--------------------------------------------------\n") + (message "There was an unexpected error:") + (message " %s (%s)" (get (car e) 'error-message) (car e)) + (dolist (item (cdr e)) + (message " %s" item)) + (unless debug-on-error + (message + (concat "\nRun the command again with the -d (or --debug) option to enable debug\n" + "mode and, hopefully, generate a stack trace. If you decide to file a bug\n" + "report, please include it!\n\n" + "Emacs outputs to standard error, so you'll need to redirect stderr to\n" + "stdout to pipe this to a file or clipboard!\n\n" + " e.g. doom -d install 2>&1 | clipboard-program"))))))))) diff --git a/core/core-lib.el b/core/core-lib.el index ba118a2cd..6f66cdafe 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -463,10 +463,22 @@ If NOERROR is non-nil, don't throw an error if the file doesn't exist." (setq path (or (DIR!) (error "Could not detect path to look for '%s' in" filename)))) - `(load ,(if path - `(expand-file-name ,filename ,path) - filename) - ,noerror ,(not doom-debug-mode))) + (let ((file (if path `(expand-file-name ,filename ,path) filename))) + `(condition-case e + (load ,file ,noerror ,(not doom-debug-mode)) + ((debug doom-error) (signal (car e) (cdr e))) + ((debug error) + (let* ((source (file-name-sans-extension ,file)) + (err (cond ((file-in-directory-p source doom-core-dir) + (cons 'doom-error doom-core-dir)) + ((file-in-directory-p source doom-private-dir) + (cons 'doom-private-error doom-private-dir)) + ((cons 'doom-module-error doom-emacs-dir))))) + (signal (car err) + (list (file-relative-name + (concat source ".el") + (cdr err)) + e))))))) (provide 'core-lib) ;;; core-lib.el ends here diff --git a/core/core-modules.el b/core/core-modules.el index a3d6035a4..8ba8de2aa 100644 --- a/core/core-modules.el +++ b/core/core-modules.el @@ -27,10 +27,6 @@ A warning will be put out if these deprecated modules are used.") ;; Bootstrap API ;; -;; Custom errors -(define-error 'doom-autoload-error "Error in your autoloads file(s)" 'doom-error) -(define-error 'doom-private-error "Error in your private config" 'doom-error) - (defun doom-initialize-modules (&optional force-p) "Loads the init.el in `doom-private-dir' and sets up hooks for a healthy session of Dooming. Will noop if used more than once, unless FORCE-P is @@ -43,8 +39,8 @@ non-nil." (condition-case e (load (expand-file-name "init" doom-private-dir) 'noerror 'nomessage) - ((debug error) - (signal 'doom-private-error (list 'init e))))))) + ((debug doom-error) (signal (car e) (cdr e))) + ((debug error) (signal 'doom-private-error (list "init.el" e))))))) ;; @@ -285,11 +281,7 @@ to least)." (let ((doom--stage 'config)) ,@(nreverse config-forms) (when doom-private-dir - (condition-case e - (load ,(expand-file-name "config" doom-private-dir) - t (not doom-debug-mode)) - ((debug error) - (signal 'doom-private-error (list 'config e)))))))))) + (load! "config" doom-private-dir))))))) (defvar doom-disabled-packages) (defmacro def-package! (name &rest plist) diff --git a/core/core-packages.el b/core/core-packages.el index ba858c613..e4693ea05 100644 --- a/core/core-packages.el +++ b/core/core-packages.el @@ -93,13 +93,11 @@ them." ;; the current session, but if you change an packages.el file in a module, ;; there's no non-trivial way to detect that, so we give you a way to ;; reload only doom-packages (by passing 'internal as FORCE-P). - ;; `doom-packages' (unless (eq force-p 'internal) ;; `package-alist' (when (or force-p (not (bound-and-true-p package-alist))) (setq load-path (cons doom-core-dir doom-site-load-path)) (doom-ensure-packages-initialized 'force)) - ;; `quelpa-cache' (when (or force-p (not (bound-and-true-p quelpa-cache))) ;; ensure un-byte-compiled version of quelpa is loaded @@ -108,22 +106,32 @@ them." (setq quelpa-initialized-p nil) (or (quelpa-setup-p) (error "Could not initialize quelpa")))) - + ;; `doom-packages' (when (or force-p (not doom-packages)) - (let ((doom-modules (doom-modules)) - (doom--stage 'packages) - (noninteractive t)) - (setq doom-packages nil) - (load (expand-file-name "packages.el" doom-core-dir) t t) - ;; We load the private packages file twice to ensure disabled - ;; packages are seen ASAP, and a second time to ensure privately - ;; overridden packages are properly overwritten. - (let ((private-packages (expand-file-name "packages.el" doom-private-dir))) - (load private-packages t t) - (cl-loop for key being the hash-keys of doom-modules - for path = (doom-module-path (car key) (cdr key) "packages.el") - do (let ((doom--current-module key)) (load path t t))) - (load private-packages t t))))))) + (cl-flet + ((_load + (lambda (file &optional noerror) + (condition-case e + (load file noerror t t) + ((debug error) + (signal 'doom-package-error + (list (or (doom-module-from-path file) + '(:private . packages)) + e))))))) + (let ((doom-modules (doom-modules)) + (doom--stage 'packages) + (noninteractive t)) + (setq doom-packages nil) + (_load (expand-file-name "packages.el" doom-core-dir)) + ;; We load the private packages file twice to ensure disabled + ;; packages are seen ASAP, and a second time to ensure privately + ;; overridden packages are properly overwritten. + (let ((private-packages (expand-file-name "packages.el" doom-private-dir))) + (_load private-packages t) + (cl-loop for key being the hash-keys of doom-modules + for path = (doom-module-path (car key) (cdr key) "packages.el") + do (let ((doom--current-module key)) (_load path t))) + (_load private-packages t)))))))) ;; @@ -191,35 +199,31 @@ Returns t if package is successfully registered, and nil if it was disabled elsewhere." (declare (indent defun)) (doom--assert-stage-p 'packages #'package!) - (condition-case e - (let* ((old-plist (cdr (assq name doom-packages))) - (pkg-recipe (or (plist-get plist :recipe) - (and old-plist (plist-get old-plist :recipe)))) - (pkg-pin (or (plist-get plist :pin) - (and old-plist (plist-get old-plist :pin)))) - (pkg-disable (or (plist-get plist :disable) - (and old-plist (plist-get old-plist :disable))))) - (when pkg-disable - (add-to-list 'doom-disabled-packages name nil #'eq)) - (when pkg-recipe - (when (= 0 (% (length pkg-recipe) 2)) - (setq plist (plist-put plist :recipe (cons name pkg-recipe)))) - (when pkg-pin - (setq plist (plist-put plist :pin nil)))) - (dolist (prop '(:ignore :freeze)) - (when-let* ((val (plist-get plist prop))) - (setq plist (plist-put plist prop (eval val))))) - (when (file-in-directory-p (or (bound-and-true-p byte-compile-current-file) - load-file-name) - doom-private-dir) - (setq plist (plist-put plist :private t))) - `(progn - ,(if pkg-pin `(map-put package-pinned-packages ',name ,pkg-pin)) - (map-put doom-packages ',name ',plist) - (not (memq ',name doom-disabled-packages)))) - ((debug error) - (signal 'doom-private-error - (list (list 'packages name) e))))) + (let* ((old-plist (cdr (assq name doom-packages))) + (pkg-recipe (or (plist-get plist :recipe) + (and old-plist (plist-get old-plist :recipe)))) + (pkg-pin (or (plist-get plist :pin) + (and old-plist (plist-get old-plist :pin)))) + (pkg-disable (or (plist-get plist :disable) + (and old-plist (plist-get old-plist :disable))))) + (when pkg-disable + (add-to-list 'doom-disabled-packages name nil #'eq)) + (when pkg-recipe + (when (= 0 (% (length pkg-recipe) 2)) + (setq plist (plist-put plist :recipe (cons name pkg-recipe)))) + (when pkg-pin + (setq plist (plist-put plist :pin nil)))) + (dolist (prop '(:ignore :freeze)) + (when-let* ((val (plist-get plist prop))) + (setq plist (plist-put plist prop (eval val))))) + (when (file-in-directory-p (or (bound-and-true-p byte-compile-current-file) + load-file-name) + doom-private-dir) + (setq plist (plist-put plist :private t))) + `(progn + ,(if pkg-pin `(map-put package-pinned-packages ',name ,pkg-pin)) + (map-put doom-packages ',name ',plist) + (not (memq ',name doom-disabled-packages))))) (defmacro packages! (&rest packages) "A convenience macro like `package!', but allows you to declare multiple diff --git a/core/core.el b/core/core.el index 3e9026600..d86fa22f1 100644 --- a/core/core.el +++ b/core/core.el @@ -119,8 +119,12 @@ else (except for `window-setup-hook').") ;; Custom error types ;; -(define-error 'doom-error "Doom Emacs error") +(define-error 'doom-error "Error in Doom Emacs core") (define-error 'doom-hook-error "Error in a Doom startup hook" 'doom-error) +(define-error 'doom-autoload-error "Error in an autoloads file" 'doom-error) +(define-error 'doom-module-error "Error in a Doom module" 'doom-error) +(define-error 'doom-private-error "Error in private config" 'doom-error) +(define-error 'doom-package-error "Error with packages" 'doom-error) ;;