From: Po Lu Date: Wed, 23 Mar 2022 08:48:49 +0000 (+0800) Subject: Restore old hl-line code X-Git-Tag: emacs-29.0.90~1931^2~964 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=a34afbf2aea2fdaf691f4bf250a18991b21301d7;p=emacs.git Restore old hl-line code * lisp/hl-line.el: Restore old code to remove obsoletions. (hl-line-overlay-priority): Make defcustom. --- diff --git a/lisp/hl-line.el b/lisp/hl-line.el index f1c2e1ebf23..20b3f4160fd 100644 --- a/lisp/hl-line.el +++ b/lisp/hl-line.el @@ -24,40 +24,58 @@ ;;; Commentary: -;; Proper scuttling of unsticky overlays relies on `post-command-hook` -;; being called on a buffer switch and the stationarity of -;; `hl-line--buffer` across switches. One could easily imagine -;; programatically defeating unsticky overlays by bypassing -;; `post-command-hook`. +;; Provides a local minor mode (toggled by M-x hl-line-mode) and +;; a global minor mode (toggled by M-x global-hl-line-mode) to +;; highlight, on a suitable terminal, the line on which point is. The +;; global mode highlights the current line in the selected window only +;; (except when the minibuffer window is selected). This was +;; implemented to satisfy a request for a feature of Lesser Editors. +;; The local mode is sticky: it highlights the line about the buffer's +;; point even if the buffer's window is not selected. Caveat: the +;; buffer's point might be different from the point of a non-selected +;; window. Set the variable `hl-line-sticky-flag' to nil to make the +;; local mode behave like the global mode. -;;; Code: +;; You probably don't really want to use the global mode; if the +;; cursor is difficult to spot, try changing its color, relying on +;; `blink-cursor-mode' or both. The hookery used might affect +;; response noticeably on a slow machine. The local mode may be +;; useful in non-editing buffers such as Gnus or PCL-CVS though. + +;; An overlay is used. In the non-sticky cases, this overlay is +;; active only on the selected window. A hook is added to +;; `post-command-hook' to activate the overlay and move it to the line +;; about point. + +;; You could make variable `global-hl-line-mode' buffer-local and set +;; it to nil to avoid highlighting specific buffers, when the global +;; mode is used. -(make-obsolete-variable 'hl-line-overlay 'hl-line--overlay "29.1") -(make-obsolete-variable 'global-hl-line-overlay nil "29.1") -(make-obsolete-variable 'global-hl-line-overlays nil "29.1") -(make-obsolete-variable 'global-hl-line-sticky-flag nil "29.1") -(make-obsolete-variable 'hl-line-overlay-buffer 'hl-line--buffer "29.1") -(make-obsolete-variable 'hl-line-range-function nil "29.1") +;; By default the whole line is highlighted. The range of highlighting +;; can be changed by defining an appropriate function as the +;; buffer-local value of `hl-line-range-function'. -(defvar-local hl-line--overlay nil - "The prevailing highlighting overlay per buffer.") +;;; Code: + +(defvar-local hl-line-overlay nil + "Overlay used by Hl-Line mode to highlight the current line.") -(defvar hl-line--buffer nil - "Used to track last buffer.") +(defvar-local global-hl-line-overlay nil + "Overlay used by Global-Hl-Line mode to highlight the current line.") -;; 1. define-minor-mode creates buffer-local hl-line--overlay -;; 2. overlay wiped by kill-all-local-variables -;; 3. post-command-hook dupes overlay -;; Solution: prevent step 2. -(put 'hl-line--overlay 'permanent-local t) +(defvar global-hl-line-overlays nil + "Overlays used by Global-Hl-Line mode in various buffers. +Global-Hl-Line keeps displaying one overlay in each buffer +when `global-hl-line-sticky-flag' is non-nil.") (defgroup hl-line nil "Highlight the current line." :version "21.1" :group 'convenience) -(defface hl-line '((t :inherit highlight :extend t)) - "Default face for highlighting the current line in hl-line-mode." +(defface hl-line + '((t :inherit highlight :extend t)) + "Default face for highlighting the current line in Hl-Line mode." :version "22.1" :group 'hl-line) @@ -69,77 +87,204 @@ (set symbol value) (dolist (buffer (buffer-list)) (with-current-buffer buffer - (when hl-line--overlay - (overlay-put hl-line--overlay 'face hl-line-face)))))) + (when (overlayp hl-line-overlay) + (overlay-put hl-line-overlay 'face hl-line-face)))) + (when (overlayp global-hl-line-overlay) + (overlay-put global-hl-line-overlay 'face hl-line-face)))) (defcustom hl-line-sticky-flag t - "Non-nil to preserve highlighting overlay when focus leaves window." + "Non-nil means the HL-Line mode highlight appears in all windows. +Otherwise Hl-Line mode will highlight only in the selected +window. Setting this variable takes effect the next time you use +the command `hl-line-mode' to turn Hl-Line mode on. + +This variable has no effect in Global Highlight Line mode. +For that, use `global-hl-line-sticky-flag'." :type 'boolean :version "22.1" - :group 'hl-line - :initialize #'custom-initialize-default - :set (lambda (symbol value) - (set-default symbol value) - (unless value - (let ((selected (window-buffer (selected-window)))) - (dolist (buffer (buffer-list)) - (unless (eq buffer selected) - (with-current-buffer buffer - (hl-line-unhighlight)))))))) + :group 'hl-line) + +(defcustom global-hl-line-sticky-flag nil + "Non-nil means the Global HL-Line mode highlight appears in all windows. +Otherwise Global Hl-Line mode will highlight only in the selected +window. Setting this variable takes effect the next time you use +the command `global-hl-line-mode' to turn Global Hl-Line mode on." + :type 'boolean + :version "24.1" + :group 'hl-line) + +(defvar hl-line-range-function nil + "If non-nil, function to call to return highlight range. +The function of no args should return a cons cell; its car value +is the beginning position of highlight and its cdr value is the +end position of highlight in the buffer. +It should return nil if there's no region to be highlighted. + +This variable is expected to be made buffer-local by modes.") + +(defvar hl-line-overlay-buffer nil + "Most recently visited buffer in which Hl-Line mode is enabled.") (defcustom hl-line-overlay-priority -50 "Priority used on the overlay used by hl-line." :type 'integer - :version "22.1" - :group 'hl-line) - -(defcustom hl-line-highlight-hook nil - "After hook for `hl-line-highlight'. -Currently used in calendar/todo-mode." - :type 'hook + :version "28.1" :group 'hl-line) ;;;###autoload (define-minor-mode hl-line-mode - "Toggle highlighting of the current line." + "Toggle highlighting of the current line (Hl-Line mode). + +Hl-Line mode is a buffer-local minor mode. If +`hl-line-sticky-flag' is non-nil, Hl-Line mode highlights the +line about the buffer's point in all windows. Caveat: the +buffer's point might be different from the point of a +non-selected window. Hl-Line mode uses the function +`hl-line-highlight' on `post-command-hook' in this case. + +When `hl-line-sticky-flag' is nil, Hl-Line mode highlights the +line about point in the selected window only." :group 'hl-line (if hl-line-mode (progn - (hl-line-highlight) + ;; In case `kill-all-local-variables' is called. (add-hook 'change-major-mode-hook #'hl-line-unhighlight nil t) + (hl-line-highlight) + (setq hl-line-overlay-buffer (current-buffer)) (add-hook 'post-command-hook #'hl-line-highlight nil t)) (remove-hook 'post-command-hook #'hl-line-highlight t) - (remove-hook 'change-major-mode-hook #'hl-line-unhighlight t) + (hl-line-unhighlight) + (remove-hook 'change-major-mode-hook #'hl-line-unhighlight t))) + +(defun hl-line-make-overlay () + (let ((ol (make-overlay (point) (point)))) + (overlay-put ol 'priority hl-line-overlay-priority) ;(bug#16192) + (overlay-put ol 'face hl-line-face) + ol)) + +(defun hl-line-highlight () + "Activate the Hl-Line overlay on the current line." + (if hl-line-mode ; Might be changed outside the mode function. + (progn + (unless (overlayp hl-line-overlay) + (setq hl-line-overlay (hl-line-make-overlay))) ; To be moved. + (overlay-put hl-line-overlay + 'window (unless hl-line-sticky-flag (selected-window))) + (hl-line-move hl-line-overlay) + (hl-line-maybe-unhighlight)) (hl-line-unhighlight))) (defun hl-line-unhighlight () - (when hl-line--overlay - (delete-overlay hl-line--overlay) - (setq hl-line--overlay nil))) + "Deactivate the Hl-Line overlay on the current line." + (when (overlayp hl-line-overlay) + (delete-overlay hl-line-overlay) + (setq hl-line-overlay nil))) -(defun hl-line-highlight () - (unless (minibufferp) - (unless hl-line--overlay - (setq hl-line--overlay - (let ((ol (make-overlay (point) (point)))) - (prog1 ol - (overlay-put ol 'priority hl-line-overlay-priority) - (overlay-put ol 'face hl-line-face))))) - (move-overlay hl-line--overlay - (line-beginning-position) - (line-beginning-position 2)) - (when (and (not (eq hl-line--buffer (current-buffer))) +(defun hl-line-maybe-unhighlight () + "Maybe deactivate the Hl-Line overlay on the current line. +Specifically, when `hl-line-sticky-flag' is nil deactivate all +such overlays in all buffers except the current one." + (let ((hlob hl-line-overlay-buffer) + (curbuf (current-buffer))) + (when (and (buffer-live-p hlob) (not hl-line-sticky-flag) - (buffer-live-p hl-line--buffer)) - (with-current-buffer hl-line--buffer + (not (eq curbuf hlob)) + (not (minibufferp))) + (with-current-buffer hlob (hl-line-unhighlight))) - (setq hl-line--buffer (current-buffer)) - (run-hooks 'hl-line-highlight-hook))) + (when (and (overlayp hl-line-overlay) + (eq (overlay-buffer hl-line-overlay) curbuf)) + (setq hl-line-overlay-buffer curbuf)))) + +;;;###autoload +(define-minor-mode global-hl-line-mode + "Toggle line highlighting in all buffers (Global Hl-Line mode). + +If `global-hl-line-sticky-flag' is non-nil, Global Hl-Line mode +highlights the line about the current buffer's point in all live +windows. + +Global-Hl-Line mode uses the function `global-hl-line-highlight' +on `post-command-hook'." + :global t + :group 'hl-line + (if global-hl-line-mode + (progn + ;; In case `kill-all-local-variables' is called. + (add-hook 'change-major-mode-hook #'global-hl-line-unhighlight) + (global-hl-line-highlight-all) + (add-hook 'post-command-hook #'global-hl-line-highlight)) + (global-hl-line-unhighlight-all) + (remove-hook 'post-command-hook #'global-hl-line-highlight) + (remove-hook 'change-major-mode-hook #'global-hl-line-unhighlight))) + +(defun global-hl-line-highlight () + "Highlight the current line in the current window." + (when global-hl-line-mode ; Might be changed outside the mode function. + (unless (window-minibuffer-p) + (unless (overlayp global-hl-line-overlay) + (setq global-hl-line-overlay (hl-line-make-overlay))) ; To be moved. + (unless (member global-hl-line-overlay global-hl-line-overlays) + (push global-hl-line-overlay global-hl-line-overlays)) + (overlay-put global-hl-line-overlay 'window + (unless global-hl-line-sticky-flag + (selected-window))) + (hl-line-move global-hl-line-overlay) + (global-hl-line-maybe-unhighlight)))) + +(defun global-hl-line-highlight-all () + "Highlight the current line in all live windows." + (walk-windows (lambda (w) + (with-current-buffer (window-buffer w) + (global-hl-line-highlight))) + nil t)) + +(defun global-hl-line-unhighlight () + "Deactivate the Global-Hl-Line overlay on the current line." + (when (overlayp global-hl-line-overlay) + (delete-overlay global-hl-line-overlay) + (setq global-hl-line-overlay nil))) -(defun hl-line-turn-on () - (unless (minibufferp) - (let (inhibit-quit) - (hl-line-mode 1)))) +(defun global-hl-line-maybe-unhighlight () + "Maybe deactivate the Global-Hl-Line overlay on the current line. +Specifically, when `global-hl-line-sticky-flag' is nil deactivate +all such overlays in all buffers except the current one." + (mapc (lambda (ov) + (let ((ovb (overlay-buffer ov))) + (when (and (not global-hl-line-sticky-flag) + (bufferp ovb) + (not (eq ovb (current-buffer))) + (not (minibufferp))) + (with-current-buffer ovb + (global-hl-line-unhighlight))))) + global-hl-line-overlays)) + +(defun global-hl-line-unhighlight-all () + "Deactivate all Global-Hl-Line overlays." + (mapc (lambda (ov) + (let ((ovb (overlay-buffer ov))) + (when (bufferp ovb) + (with-current-buffer ovb + (global-hl-line-unhighlight))))) + global-hl-line-overlays) + (setq global-hl-line-overlays nil)) + +(defun hl-line-move (overlay) + "Move the Hl-Line overlay. +If `hl-line-range-function' is non-nil, move the OVERLAY to the position +where the function returns. If `hl-line-range-function' is nil, fill +the line including the point by OVERLAY." + (let (tmp b e) + (if hl-line-range-function + (setq tmp (funcall hl-line-range-function) + b (car tmp) + e (cdr tmp)) + (setq tmp t + b (line-beginning-position) + e (line-beginning-position 2))) + (if tmp + (move-overlay overlay b e) + (move-overlay overlay 1 1)))) (defun hl-line-unload-function () "Unload the Hl-Line library." @@ -151,12 +296,6 @@ Currently used in calendar/todo-mode." ;; continue standard unloading nil) -;;;###autoload -(define-globalized-minor-mode global-hl-line-mode - hl-line-mode hl-line-turn-on - :group 'hl-line - :version "29.1") - (provide 'hl-line) ;;; hl-line.el ends here