Skip to content

Commit

Permalink
Ensure early startup warnings are visible at the end. (Bug#20792)
Browse files Browse the repository at this point in the history
* lisp/emacs-lisp/warnings.el (display-warning):
If startup isn't complete, delay the warning.

* lisp/startup.el (normal-top-level, command-line):
Let display-warning automatically handle the needed delays.
Run delayed-warnings-hook.
  • Loading branch information
rgmorris committed Jun 13, 2015
1 parent 147c391 commit 1fabab6
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 99 deletions.
166 changes: 85 additions & 81 deletions lisp/emacs-lisp/warnings.el
Expand Up @@ -224,87 +224,91 @@ See the `warnings' custom group for user customization features.
See also `warning-series', `warning-prefix-function' and
`warning-fill-prefix' for additional programming features."
(unless level
(setq level :warning))
(unless buffer-name
(setq buffer-name "*Warnings*"))
(if (assq level warning-level-aliases)
(setq level (cdr (assq level warning-level-aliases))))
(or (< (warning-numeric-level level)
(warning-numeric-level warning-minimum-log-level))
(warning-suppress-p type warning-suppress-log-types)
(let* ((typename (if (consp type) (car type) type))
(old (get-buffer buffer-name))
(buffer (or old (get-buffer-create buffer-name)))
(level-info (assq level warning-levels))
start end)
(with-current-buffer buffer
;; If we created the buffer, disable undo.
(unless old
(special-mode)
(setq buffer-read-only t)
(setq buffer-undo-list t))
(goto-char (point-max))
(when (and warning-series (symbolp warning-series))
(setq warning-series
(prog1 (point-marker)
(unless (eq warning-series t)
(funcall warning-series)))))
(let ((inhibit-read-only t))
(unless (bolp)
(newline))
(setq start (point))
(if warning-prefix-function
(setq level-info (funcall warning-prefix-function
level level-info)))
(insert (format (nth 1 level-info)
(format warning-type-format typename))
message)
(newline)
(when (and warning-fill-prefix (not (string-match "\n" message)))
(let ((fill-prefix warning-fill-prefix)
(fill-column 78))
(fill-region start (point))))
(setq end (point)))
(when (and (markerp warning-series)
(eq (marker-buffer warning-series) buffer))
(goto-char warning-series)))
(if (nth 2 level-info)
(funcall (nth 2 level-info)))
(cond (noninteractive
;; Noninteractively, take the text we inserted
;; in the warnings buffer and print it.
;; Do this unconditionally, since there is no way
;; to view logged messages unless we output them.
(with-current-buffer buffer
(save-excursion
;; Don't include the final newline in the arg
;; to `message', because it adds a newline.
(goto-char end)
(if (bolp)
(forward-char -1))
(message "%s" (buffer-substring start (point))))))
((and (daemonp) (null after-init-time))
;; Warnings assigned during daemon initialization go into
;; the messages buffer.
(message "%s"
(with-current-buffer buffer
(save-excursion
(goto-char end)
(if (bolp)
(forward-char -1))
(buffer-substring start (point))))))
(t
;; Interactively, decide whether the warning merits
;; immediate display.
(or (< (warning-numeric-level level)
(warning-numeric-level warning-minimum-level))
(warning-suppress-p type warning-suppress-types)
(let ((window (display-buffer buffer)))
(when (and (markerp warning-series)
(eq (marker-buffer warning-series) buffer))
(set-window-start window warning-series))
(sit-for 0))))))))
(if (not (or after-init-time noninteractive (daemonp)))
;; Ensure warnings that happen early in the startup sequence
;; are visible when startup completes (bug#20792).
(delay-warning type message level buffer-name)
(unless level
(setq level :warning))
(unless buffer-name
(setq buffer-name "*Warnings*"))
(if (assq level warning-level-aliases)
(setq level (cdr (assq level warning-level-aliases))))
(or (< (warning-numeric-level level)
(warning-numeric-level warning-minimum-log-level))
(warning-suppress-p type warning-suppress-log-types)
(let* ((typename (if (consp type) (car type) type))
(old (get-buffer buffer-name))
(buffer (or old (get-buffer-create buffer-name)))
(level-info (assq level warning-levels))
start end)
(with-current-buffer buffer
;; If we created the buffer, disable undo.
(unless old
(special-mode)
(setq buffer-read-only t)
(setq buffer-undo-list t))
(goto-char (point-max))
(when (and warning-series (symbolp warning-series))
(setq warning-series
(prog1 (point-marker)
(unless (eq warning-series t)
(funcall warning-series)))))
(let ((inhibit-read-only t))
(unless (bolp)
(newline))
(setq start (point))
(if warning-prefix-function
(setq level-info (funcall warning-prefix-function
level level-info)))
(insert (format (nth 1 level-info)
(format warning-type-format typename))
message)
(newline)
(when (and warning-fill-prefix (not (string-match "\n" message)))
(let ((fill-prefix warning-fill-prefix)
(fill-column 78))
(fill-region start (point))))
(setq end (point)))
(when (and (markerp warning-series)
(eq (marker-buffer warning-series) buffer))
(goto-char warning-series)))
(if (nth 2 level-info)
(funcall (nth 2 level-info)))
(cond (noninteractive
;; Noninteractively, take the text we inserted
;; in the warnings buffer and print it.
;; Do this unconditionally, since there is no way
;; to view logged messages unless we output them.
(with-current-buffer buffer
(save-excursion
;; Don't include the final newline in the arg
;; to `message', because it adds a newline.
(goto-char end)
(if (bolp)
(forward-char -1))
(message "%s" (buffer-substring start (point))))))
((and (daemonp) (null after-init-time))
;; Warnings assigned during daemon initialization go into
;; the messages buffer.
(message "%s"
(with-current-buffer buffer
(save-excursion
(goto-char end)
(if (bolp)
(forward-char -1))
(buffer-substring start (point))))))
(t
;; Interactively, decide whether the warning merits
;; immediate display.
(or (< (warning-numeric-level level)
(warning-numeric-level warning-minimum-level))
(warning-suppress-p type warning-suppress-types)
(let ((window (display-buffer buffer)))
(when (and (markerp warning-series)
(eq (marker-buffer warning-series) buffer))
(set-window-start window warning-series))
(sit-for 0)))))))))

;; Use \\<special-mode-map> so that help-enable-auto-load can do its thing.
;; Any keymap that is defined will do.
Expand Down
32 changes: 14 additions & 18 deletions lisp/startup.el
Expand Up @@ -612,7 +612,7 @@ It is the default value of the variable `top-level'."
charset-map-path))))
(if default-directory
(setq default-directory (abbreviate-file-name default-directory))
(delay-warning 'initialization "Error setting default-directory"))
(display-warning 'initialization "Error setting default-directory"))
(let ((old-face-font-rescale-alist face-font-rescale-alist))
(unwind-protect
(command-line)
Expand Down Expand Up @@ -1167,25 +1167,18 @@ please check its value")
(funcall inner)
(setq init-file-had-error nil))
(error
;; Postpone displaying the warning until all hooks
;; in `after-init-hook' like `desktop-read' will finalize
;; possible changes in the window configuration.
(add-hook
'after-init-hook
(lambda ()
(display-warning
'initialization
(format "An error occurred while loading `%s':\n\n%s%s%s\n\n\
(display-warning
'initialization
(format "An error occurred while loading `%s':\n\n%s%s%s\n\n\
To ensure normal operation, you should investigate and remove the
cause of the error in your initialization file. Start Emacs with
the `--debug-init' option to view a complete error backtrace."
user-init-file
(get (car error) 'error-message)
(if (cdr error) ": " "")
(mapconcat (lambda (s) (prin1-to-string s t))
(cdr error) ", "))
:warning))
t)
user-init-file
(get (car error) 'error-message)
(if (cdr error) ": " "")
(mapconcat (lambda (s) (prin1-to-string s t))
(cdr error) ", "))
:warning)
(setq init-file-had-error t))))

(if (and deactivate-mark transient-mark-mode)
Expand Down Expand Up @@ -1268,7 +1261,10 @@ the `--debug-init' option to view a complete error backtrace."
(package-initialize))

(setq after-init-time (current-time))
(run-hooks 'after-init-hook)
;; Display any accumulated warnings after all functions in
;; `after-init-hook' like `desktop-read' have finalized possible
;; changes in the window configuration.
(run-hooks 'after-init-hook 'delayed-warnings-hook)

;; If *scratch* exists and init file didn't change its mode, initialize it.
(if (get-buffer "*scratch*")
Expand Down

0 comments on commit 1fabab6

Please sign in to comment.