X-Git-Url: https://code.delx.au/gnu-emacs-elpa/blobdiff_plain/eeac41976bc7b1aa5e732fb476d24ab4c2890712..e3ab5c3b4a3cf5c6e099534d6c1db5672511f67b:/beacon.el diff --git a/beacon.el b/beacon.el index 800c95858..ffdbcbc3b 100644 --- a/beacon.el +++ b/beacon.el @@ -5,7 +5,7 @@ ;; Author: Artur Malabarba ;; URL: https://github.com/Malabarba/beacon ;; Keywords: convenience -;; Version: 0.1.1 +;; Version: 0.3 ;; Package-Requires: ((seq "1.9")) ;; This program is free software; you can redistribute it and/or modify @@ -72,6 +72,13 @@ movement distance (in lines) that triggers a beacon blink." "Should the beacon blink when the window changes?" :type 'boolean) +(defcustom beacon-blink-when-focused nil + "Should the beacon blink when Emacs gains focus? +Note that, due to a limitation of `focus-in-hook', this might +trigger false positives on some systems." + :type 'boolean + :package-version '(beacon . "0.2")) + (defcustom beacon-blink-duration 0.3 "Time, in seconds, that the blink should last." :type 'number) @@ -96,6 +103,13 @@ If it is a string, it is a color name or specification, e.g. \"#666600\"." :type '(choice number color)) +(defface beacon-fallback-background + '((((class color) (background light)) (:background "black")) + (((class color) (background dark)) (:background "white"))) + "Fallback beacon background color. +Used in cases where the color can't be determined by Emacs. +Only the background of this face is used.") + (defvar beacon-dont-blink-predicates nil "A list of predicates that prevent the beacon blink. These predicate functions are called in order, with no @@ -110,7 +124,7 @@ For instance, if you want to disable beacon on buffers where (add-hook 'beacon-dont-blink-predicates #'window-minibuffer-p) -(defcustom beacon-dont-blink-major-modes '(magit-status-mode) +(defcustom beacon-dont-blink-major-modes '(magit-status-mode magit-popup-mode) "A list of major-modes where the beacon won't blink. Whenever the current buffer satisfies `derived-mode-p' for one of the major-modes on this list, the beacon will not @@ -124,6 +138,21 @@ predictable ways, when the blink would be more distracting than helpful.." :type '(repeat symbol)) + +;;; Internal variables +(defvar beacon--window-scrolled nil) +(defvar beacon--previous-place nil) +(defvar beacon--previous-mark-head nil) +(defvar beacon--previous-window nil) +(defvar beacon--previous-window-start 0) + +(defun beacon--record-vars () + (unless (window-minibuffer-p) + (setq beacon--previous-mark-head (car mark-ring)) + (setq beacon--previous-place (point-marker)) + (setq beacon--previous-window (selected-window)) + (setq beacon--previous-window-start (window-start)))) + ;;; Overlays (defvar beacon--ovs nil) @@ -199,7 +228,10 @@ Only returns `beacon-size' elements." (defun beacon--color-range () "Return a list of background colors for the beacon." - (let* ((bg (color-values (face-attribute 'default :background))) + (let* ((default-bg (face-attribute 'default :background)) + (bg (color-values (if (string-match "\\`unspecified-" default-bg) + (face-attribute 'beacon-fallback-background :background) + default-bg))) (fg (cond ((stringp beacon-color) (color-values beacon-color)) ((< (color-distance "black" bg) @@ -247,6 +279,9 @@ Only returns `beacon-size' elements." "Blink the beacon at the position of the cursor." (interactive) (beacon--vanish) + ;; Record vars here in case something is blinking outside the + ;; command loop. + (beacon--record-vars) (unless (or (not beacon-mode) (run-hook-with-args-until-success 'beacon-dont-blink-predicates) (seq-find #'derived-mode-p beacon-dont-blink-major-modes) @@ -259,11 +294,6 @@ Only returns `beacon-size' elements." ;;; Movement detection -(defvar beacon--window-scrolled nil) -(defvar beacon--previous-place nil) -(defvar beacon--previous-mark-head nil) -(defvar beacon--previous-window nil) - (defun beacon--movement-> (delta) "Return non-nil if latest point movement is > DELTA. If DELTA is nil, return nil." @@ -301,7 +331,7 @@ If DELTA is nil, return nil." (beacon--vanish)) ;; Blink for switching windows. ((and beacon-blink-when-window-changes - (not (eq beacon--previous-window (selected-window)))) + (not (eq beacon--previous-window (selected-window)))) (beacon-blink)) ;; Blink for scrolling. ((and beacon-blink-when-window-scrolls @@ -314,13 +344,9 @@ If DELTA is nil, return nil." ;; Even if we don't blink, vanish any previous beacon. (t (beacon--vanish))) (beacon--maybe-push-mark) - (setq beacon--window-scrolled nil) - (unless (window-minibuffer-p) - (setq beacon--previous-mark-head (car mark-ring)) - (setq beacon--previous-place (point-marker)) - (setq beacon--previous-window (selected-window)))) + (setq beacon--window-scrolled nil)) -(defun beacon--window-scroll-function (win _start-pos) +(defun beacon--window-scroll-function (win start-pos) "Blink the beacon or record that window has been scrolled. If invoked during the command loop, record the current window so that it may be blinked on post-command. This is because the @@ -329,18 +355,25 @@ scrolled window might not be active, but we only know that at If invoked outside the command loop, `post-command-hook' would be unreliable, so just blink immediately." - (if this-command - (setq beacon--window-scrolled win) - (setq beacon--window-scrolled nil) + (unless (and (equal beacon--previous-window-start start-pos) + (equal beacon--previous-window win)) + (if this-command + (setq beacon--window-scrolled win) + (setq beacon--window-scrolled nil) + (beacon-blink)))) + +(defun beacon--blink-on-focus () + "Blink if `beacon-blink-when-focused' is non-nil" + (when beacon-blink-when-focused (beacon-blink))) ;;; Minor-mode (defcustom beacon-lighter (cond - ((char-displayable-p ?💡) " 💡") - ((char-displayable-p ?Λ) " Λ") - (t " *")) + ;; ((char-displayable-p ?💡) " 💡") + ;; ((char-displayable-p ?Λ) " Λ") + (t " (*)")) "Lighter string used on the mode-line." :type 'string) @@ -351,12 +384,14 @@ unreliable, so just blink immediately." (if beacon-mode (progn (add-hook 'window-scroll-functions #'beacon--window-scroll-function) - (add-hook 'focus-in-hook #'beacon-blink) + (add-hook 'focus-in-hook #'beacon--blink-on-focus) (add-hook 'post-command-hook #'beacon--post-command) + (add-hook 'pre-command-hook #'beacon--record-vars) (add-hook 'pre-command-hook #'beacon--vanish)) - (remove-hook 'focus-in-hook #'beacon-blink) + (remove-hook 'focus-in-hook #'beacon--blink-on-focus) (remove-hook 'window-scroll-functions #'beacon--window-scroll-function) (remove-hook 'post-command-hook #'beacon--post-command) + (remove-hook 'pre-command-hook #'beacon--record-vars) (remove-hook 'pre-command-hook #'beacon--vanish))) (provide 'beacon)