From 1327c4e13d3c0f3ba0cf93c43ad82645365123df Mon Sep 17 00:00:00 2001 From: Gregory Heytings Date: Wed, 21 Apr 2021 14:52:01 +0000 Subject: [PATCH] New default bell. * lisp/simple.el (color-bell): New default bell, which briefly flashes the cursor and the echo area when an error occurs. (color-bell-echo-area-face, color-bell-cursor-face): New faces. (color-bell-ignored-errors, color-bell-duration): New user options. * src/eval.c (last-error-symbol, last-error-data): New variables. (signal_or_quit): Set the new variables. * lisp/face-remap.el (face-remap-remove-relative, buffer-face-mode-face, text-scale-mode-step): Autoload them. * etc/NEWS: Document the change. --- etc/NEWS | 10 +++++++ lisp/face-remap.el | 3 ++ lisp/simple.el | 69 ++++++++++++++++++++++++++++++++++++++++++++++ src/eval.c | 11 ++++++++ 4 files changed, 93 insertions(+) diff --git a/etc/NEWS b/etc/NEWS index e39aa7b437..4203e0b40d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -272,6 +272,16 @@ commands. The new keystrokes are 'C-x x g' ('revert-buffer'), ** Commands 'set-frame-width' and 'set-frame-height' can now get their input using the minibuffer. ++++ +** The default value of 'ring-bell-function' is now non-nil. +When an error occurs, Emacs will by default briefly flash the cursor +and the echo area. This effect can be customized with the user options +color-bell-duration, color-bell-cursor-face, color-bell-echo-area-face +and color-bell-ignored-errors. To restore the previous behavior, +add the following to your init file: + +(setq ring-bell-function nil) + * Editing Changes in Emacs 28.1 diff --git a/lisp/face-remap.el b/lisp/face-remap.el index 5914ee4a20..df4c59913c 100644 --- a/lisp/face-remap.el +++ b/lisp/face-remap.el @@ -142,6 +142,7 @@ face-remap-add-relative (force-mode-line-update)) (cons face specs))) +;;;###autoload (defun face-remap-remove-relative (cookie) "Remove a face remapping previously added by `face-remap-add-relative'. COOKIE should be the return value from that function." @@ -210,6 +211,7 @@ face-remap-set-base ;; ---------------------------------------------------------------- ;; text-scale-mode +;;;###autoload (defcustom text-scale-mode-step 1.2 "Scale factor used by `text-scale-mode'. Each positive or negative step scales the default face height by this amount." @@ -397,6 +399,7 @@ text-scale-adjust ;; ---------------------------------------------------------------- ;; buffer-face-mode +;;;###autoload (defcustom buffer-face-mode-face 'variable-pitch "The face specification used by `buffer-face-mode'. It may contain any value suitable for a `face' text property, diff --git a/lisp/simple.el b/lisp/simple.el index 999755a642..94984ba6d9 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -8511,7 +8511,76 @@ play-sound-file (plist-put sound :device device)) (push 'sound sound) (play-sound sound))) + +(defface color-bell-echo-area-face + `((((type tty)) (:inherit error :inverse-video t)) + (t (:inherit match))) + "Face used by `color-bell' to flash the echo area when an error happened." + :version "28.1") + +(defface color-bell-cursor-face + `((t (:inherit error))) + "Face used by `color-bell' to flash the cursor when an error happened. +The cursor is flashed with the foreground color of that face; it is not +flashed in terminals." + :version "28.1") + +(defcustom color-bell-ignored-errors nil + "List of errors symbols ignored by `color-bell'. +Error symbols that are present in this list are ignored by `color-bell', and +are displayed without flashing the cursor and echo area. +For example, the value '(quit beginning-of-buffer end-of-buffer) disables +`color-bell' on \\[keyboard-quit], and for beginning and end of buffer errors. +To find the symbol of an error, type \\[eval-expression] last-error-symbol \ +\\[newline] immediately +after the error happened, without using \\[indent-for-tab-command] for \ +completion." + :type 'list + :version "28.1") + +(defcustom color-bell-duration 0.25 + "Maximum duration of the `color-bell' flash. +The flash stops when input is available." + :type 'float + :version "28.1") + +(defvar color-bell--cursor-background nil) +(defvar color-bell--face-remapping nil) + +(defun color-bell () + (unless (memq last-error-symbol color-bell-ignored-errors) + (if (not (eq (face-attribute 'cursor :background) + color-bell--cursor-background)) + (setq color-bell--cursor-background + (face-attribute 'cursor :background))) + (set-face-attribute 'cursor nil :background + (face-attribute 'color-bell-cursor-face + :foreground nil t)) + (let* ((no-minibuffer (= (minibuffer-depth) 0)) + (inside-minibuffer (minibufferp (current-buffer))) + (buffer-name (if no-minibuffer + " *Echo Area 0*" + (format " *Minibuf-%d*" (minibuffer-depth)))) + (buffer (get-buffer buffer-name))) + (unless inside-minibuffer + (with-current-buffer buffer + (when color-bell--face-remapping + (face-remap-remove-relative color-bell--face-remapping)) + (setq-local color-bell--face-remapping + (face-remap-add-relative 'default + 'color-bell-echo-area-face)))) + (if no-minibuffer + (message (error-message-string (cons last-error-symbol nil)))) + (sit-for color-bell-duration) + (set-face-attribute 'cursor nil + :background color-bell--cursor-background) + (unless inside-minibuffer + (if (buffer-live-p buffer) + (with-current-buffer buffer + (face-remap-remove-relative color-bell--face-remapping) + (setq color-bell--face-remapping nil))))))) +(setq ring-bell-function #'color-bell) (defcustom read-mail-command 'rmail "Your preference for a mail reading package. diff --git a/src/eval.c b/src/eval.c index fd93f5b9e1..ea012eef77 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1716,6 +1716,9 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit) #endif #endif + Vlast_error_symbol = real_error_symbol; + Vlast_error_data = (NILP (error_symbol) ? Fcdr (data) : data); + /* This hook is used by edebug. */ if (! NILP (Vsignal_hook_function) && ! NILP (error_symbol) @@ -4321,6 +4324,14 @@ syms_of_eval (void) The Edebug package uses this to regain control. */); Vsignal_hook_function = Qnil; + DEFVAR_LISP ("last-error-symbol", Vlast_error_symbol, + doc: /* Symbol of the last error. */); + Vlast_error_symbol = Qnil; + + DEFVAR_LISP ("last-error-data", Vlast_error_data, + doc: /* Data of the last error. */); + Vlast_error_data = Qnil; + DEFVAR_LISP ("debug-on-signal", Vdebug_on_signal, doc: /* Non-nil means call the debugger regardless of condition handlers. Note that `debug-on-error', `debug-on-quit' and friends -- 2.30.2