[TMP] enable load_prefer_newer
[bpt/emacs.git] / lisp / hl-line.el
CommitLineData
2230a6e3 1;;; hl-line.el --- highlight the current line -*- lexical-binding:t -*-
798330fe 2
ba318903 3;; Copyright (C) 1998, 2000-2014 Free Software Foundation, Inc.
798330fe
DL
4
5;; Author: Dave Love <fx@gnu.org>
34dc21db 6;; Maintainer: emacs-devel@gnu.org
798330fe 7;; Created: 1998-09-13
39f8a48b 8;; Keywords: faces, frames, emulations
798330fe 9
643c911e
DL
10;; This file is part of GNU Emacs.
11
eb3fa2cf 12;; GNU Emacs is free software: you can redistribute it and/or modify
798330fe 13;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
798330fe 16
643c911e 17;; GNU Emacs is distributed in the hope that it will be useful,
798330fe
DL
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
eb3fa2cf 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
798330fe
DL
24
25;;; Commentary:
26
e5f06fce
EZ
27;; Provides a local minor mode (toggled by M-x hl-line-mode) and
28;; a global minor mode (toggled by M-x global-hl-line-mode) to
23db85ff
LK
29;; highlight, on a suitable terminal, the line on which point is. The
30;; global mode highlights the current line in the selected window only
31;; (except when the minibuffer window is selected). This was
32;; implemented to satisfy a request for a feature of Lesser Editors.
33;; The local mode is sticky: it highlights the line about the buffer's
34;; point even if the buffer's window is not selected. Caveat: the
35;; buffer's point might be different from the point of a non-selected
36;; window. Set the variable `hl-line-sticky-flag' to nil to make the
37;; local mode behave like the global mode.
38
39;; You probably don't really want to use the global mode; if the
6772c8e1 40;; cursor is difficult to spot, try changing its color, relying on
23db85ff
LK
41;; `blink-cursor-mode' or both. The hookery used might affect
42;; response noticeably on a slow machine. The local mode may be
43;; useful in non-editing buffers such as Gnus or PCL-CVS though.
44
45;; An overlay is used. In the non-sticky cases, this overlay is
46;; active only on the selected window. A hook is added to
47;; `post-command-hook' to activate the overlay and move it to the line
48;; about point. To get the non-sticky behavior, `hl-line-unhighlight'
49;; is added to `pre-command-hook' as well. This function deactivates
50;; the overlay unconditionally in case the command changes the
51;; selected window. (It does so rather than keeping track of changes
52;; in the selected window).
53
0052fe2a
LK
54;; You could make variable `global-hl-line-mode' buffer-local and set
55;; it to nil to avoid highlighting specific buffers, when the global
56;; mode is used.
57
a4c6ebf9 58;; By default the whole line is highlighted. The range of highlighting
bf247b6e 59;; can be changed by defining an appropriate function as the
9fd76d04
MY
60;; buffer-local value of `hl-line-range-function'.
61
798330fe
DL
62;;; Code:
63
2230a6e3 64(defvar-local hl-line-overlay nil
3775cb5c 65 "Overlay used by Hl-Line mode to highlight the current line.")
3775cb5c 66
daccca97 67(defvar-local global-hl-line-overlay nil
3775cb5c
CY
68 "Overlay used by Global-Hl-Line mode to highlight the current line.")
69
daccca97
BG
70(defvar global-hl-line-overlays nil
71 "Overlays used by Global-Hl-Line mode in various buffers.
72Global-Hl-Line keeps displaying one overlay in each buffer
73when `global-hl-line-sticky-flag' is non-nil.")
74
798330fe 75(defgroup hl-line nil
99f2fb1f 76 "Highlight the current line."
eee06d26 77 :version "21.1"
eba5b4dd 78 :group 'convenience)
798330fe 79
3775cb5c
CY
80(defface hl-line
81 '((t :inherit highlight))
82 "Default face for highlighting the current line in Hl-Line mode."
83 :version "22.1"
798330fe
DL
84 :group 'hl-line)
85
3775cb5c
CY
86(defcustom hl-line-face 'hl-line
87 "Face with which to highlight the current line in Hl-Line mode."
88 :type 'face
89 :group 'hl-line
90 :set (lambda (symbol value)
91 (set symbol value)
92 (dolist (buffer (buffer-list))
93 (with-current-buffer buffer
94 (when hl-line-overlay
95 (overlay-put hl-line-overlay 'face hl-line-face))))
96 (when global-hl-line-overlay
97 (overlay-put global-hl-line-overlay 'face hl-line-face))))
98
23db85ff 99(defcustom hl-line-sticky-flag t
88821ca0 100 "Non-nil means the HL-Line mode highlight appears in all windows.
23db85ff
LK
101Otherwise Hl-Line mode will highlight only in the selected
102window. Setting this variable takes effect the next time you use
88821ca0
CY
103the command `hl-line-mode' to turn Hl-Line mode on.
104
105This variable has no effect in Global Highlight Line mode.
106For that, use `global-hl-line-sticky-flag'."
23db85ff 107 :type 'boolean
bf247b6e 108 :version "22.1"
23db85ff
LK
109 :group 'hl-line)
110
88821ca0
CY
111(defcustom global-hl-line-sticky-flag nil
112 "Non-nil means the Global HL-Line mode highlight appears in all windows.
113Otherwise Global Hl-Line mode will highlight only in the selected
114window. Setting this variable takes effect the next time you use
115the command `global-hl-line-mode' to turn Global Hl-Line mode on."
116 :type 'boolean
117 :version "24.1"
118 :group 'hl-line)
119
9fd76d04
MY
120(defvar hl-line-range-function nil
121 "If non-nil, function to call to return highlight range.
122The function of no args should return a cons cell; its car value
bf247b6e 123is the beginning position of highlight and its cdr value is the
9fd76d04
MY
124end position of highlight in the buffer.
125It should return nil if there's no region to be highlighted.
126
127This variable is expected to be made buffer-local by modes.")
128
ceafc2fa 129;;;###autoload
3a850efa 130(define-minor-mode hl-line-mode
06e21633
CY
131 "Toggle highlighting of the current line (Hl-Line mode).
132With a prefix argument ARG, enable Hl-Line mode if ARG is
133positive, and disable it otherwise. If called from Lisp, enable
134the mode if ARG is omitted or nil.
23db85ff 135
06e21633
CY
136Hl-Line mode is a buffer-local minor mode. If
137`hl-line-sticky-flag' is non-nil, Hl-Line mode highlights the
23db85ff
LK
138line about the buffer's point in all windows. Caveat: the
139buffer's point might be different from the point of a
140non-selected window. Hl-Line mode uses the function
141`hl-line-highlight' on `post-command-hook' in this case.
142
143When `hl-line-sticky-flag' is nil, Hl-Line mode highlights the
144line about point in the selected window only. In this case, it
145uses the function `hl-line-unhighlight' on `pre-command-hook' in
146addition to `hl-line-highlight' on `post-command-hook'."
b862cd15 147 :group 'hl-line
3a850efa
DL
148 (if hl-line-mode
149 (progn
23db85ff
LK
150 ;; In case `kill-all-local-variables' is called.
151 (add-hook 'change-major-mode-hook #'hl-line-unhighlight nil t)
152 (if hl-line-sticky-flag
153 (remove-hook 'pre-command-hook #'hl-line-unhighlight t)
154 (add-hook 'pre-command-hook #'hl-line-unhighlight nil t))
155 (hl-line-highlight)
9df382fe 156 (add-hook 'post-command-hook #'hl-line-highlight nil t))
23db85ff 157 (remove-hook 'post-command-hook #'hl-line-highlight t)
3a850efa 158 (hl-line-unhighlight)
23db85ff
LK
159 (remove-hook 'change-major-mode-hook #'hl-line-unhighlight t)
160 (remove-hook 'pre-command-hook #'hl-line-unhighlight t)))
b184b2dd 161
2230a6e3
SM
162(defun hl-line-make-overlay ()
163 (let ((ol (make-overlay (point) (point))))
164 (overlay-put ol 'priority -50) ;(bug#16192)
165 (overlay-put ol 'face hl-line-face)
166 ol))
167
57e46f94 168(defun hl-line-highlight ()
a4c6ebf9 169 "Activate the Hl-Line overlay on the current line."
23db85ff
LK
170 (if hl-line-mode ; Might be changed outside the mode function.
171 (progn
172 (unless hl-line-overlay
2230a6e3 173 (setq hl-line-overlay (hl-line-make-overlay))) ; To be moved.
23db85ff
LK
174 (overlay-put hl-line-overlay
175 'window (unless hl-line-sticky-flag (selected-window)))
9fd76d04 176 (hl-line-move hl-line-overlay))
23db85ff 177 (hl-line-unhighlight)))
57e46f94
RS
178
179(defun hl-line-unhighlight ()
23db85ff 180 "Deactivate the Hl-Line overlay on the current line."
b1bad9f3
JB
181 (when hl-line-overlay
182 (delete-overlay hl-line-overlay)))
57e46f94 183
23db85ff
LK
184;;;###autoload
185(define-minor-mode global-hl-line-mode
06e21633
CY
186 "Toggle line highlighting in all buffers (Global Hl-Line mode).
187With a prefix argument ARG, enable Global Hl-Line mode if ARG is
188positive, and disable it otherwise. If called from Lisp, enable
189the mode if ARG is omitted or nil.
23db85ff 190
88821ca0
CY
191If `global-hl-line-sticky-flag' is non-nil, Global Hl-Line mode
192highlights the line about the current buffer's point in all
193windows.
194
23db85ff
LK
195Global-Hl-Line mode uses the functions `global-hl-line-unhighlight' and
196`global-hl-line-highlight' on `pre-command-hook' and `post-command-hook'."
197 :global t
198 :group 'hl-line
199 (if global-hl-line-mode
200 (progn
daccca97
BG
201 ;; In case `kill-all-local-variables' is called.
202 (add-hook 'change-major-mode-hook #'global-hl-line-unhighlight)
203 (if global-hl-line-sticky-flag
204 (remove-hook 'pre-command-hook #'global-hl-line-unhighlight)
205 (add-hook 'pre-command-hook #'global-hl-line-unhighlight))
206 (global-hl-line-highlight)
23db85ff 207 (add-hook 'post-command-hook #'global-hl-line-highlight))
daccca97 208 (global-hl-line-unhighlight-all)
23db85ff
LK
209 (remove-hook 'pre-command-hook #'global-hl-line-unhighlight)
210 (remove-hook 'post-command-hook #'global-hl-line-highlight)))
211
212(defun global-hl-line-highlight ()
503edac9 213 "Highlight the current line in the current window."
23db85ff 214 (when global-hl-line-mode ; Might be changed outside the mode function.
290d5b58 215 (unless (window-minibuffer-p)
23db85ff 216 (unless global-hl-line-overlay
2230a6e3 217 (setq global-hl-line-overlay (hl-line-make-overlay))) ; To be moved.
daccca97
BG
218 (unless (member global-hl-line-overlay global-hl-line-overlays)
219 (push global-hl-line-overlay global-hl-line-overlays))
88821ca0
CY
220 (overlay-put global-hl-line-overlay 'window
221 (unless global-hl-line-sticky-flag
222 (selected-window)))
9fd76d04 223 (hl-line-move global-hl-line-overlay))))
23db85ff
LK
224
225(defun global-hl-line-unhighlight ()
226 "Deactivate the Global-Hl-Line overlay on the current line."
b1bad9f3
JB
227 (when global-hl-line-overlay
228 (delete-overlay global-hl-line-overlay)))
23db85ff 229
daccca97
BG
230(defun global-hl-line-unhighlight-all ()
231 "Deactivate all Global-Hl-Line overlays."
232 (mapc (lambda (ov)
233 (let ((ovb (overlay-buffer ov)))
234 (when (bufferp ovb)
235 (with-current-buffer ovb
236 (global-hl-line-unhighlight)))))
237 global-hl-line-overlays)
238 (setq global-hl-line-overlays nil))
239
9fd76d04 240(defun hl-line-move (overlay)
a4c6ebf9 241 "Move the Hl-Line overlay.
9fd76d04 242If `hl-line-range-function' is non-nil, move the OVERLAY to the position
a4c6ebf9 243where the function returns. If `hl-line-range-function' is nil, fill
9fd76d04
MY
244the line including the point by OVERLAY."
245 (let (tmp b e)
246 (if hl-line-range-function
247 (setq tmp (funcall hl-line-range-function)
248 b (car tmp)
249 e (cdr tmp))
250 (setq tmp t
251 b (line-beginning-position)
252 e (line-beginning-position 2)))
253 (if tmp
254 (move-overlay overlay b e)
255 (move-overlay overlay 1 1))))
256
b1bad9f3
JB
257(defun hl-line-unload-function ()
258 "Unload the Hl-Line library."
259 (global-hl-line-mode -1)
260 (save-current-buffer
261 (dolist (buffer (buffer-list))
262 (set-buffer buffer)
263 (when hl-line-mode (hl-line-mode -1))))
264 ;; continue standard unloading
265 nil)
266
798330fe
DL
267(provide 'hl-line)
268
269;;; hl-line.el ends here