Remove unnecessary require when compiling tcl.el
[bpt/emacs.git] / lisp / linum.el
CommitLineData
2fbc1934 1;;; linum.el --- display line numbers in the left margin -*- lexical-binding: t -*-
8e54981d 2
acaf905b 3;; Copyright (C) 2008-2012 Free Software Foundation, Inc.
8e54981d
JB
4
5;; Author: Markus Triska <markus.triska@gmx.at>
6;; Maintainer: FSF
7;; Keywords: convenience
aad4679e 8;; Version: 0.9x
8e54981d
JB
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software: you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
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
23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
24
25;;; Commentary:
26
27;; Display line numbers for the current buffer.
28;;
29;; Toggle display of line numbers with M-x linum-mode. To enable
30;; line numbering in all buffers, use M-x global-linum-mode.
31
32;;; Code:
33
34(defconst linum-version "0.9x")
35
36(defvar linum-overlays nil "Overlays used in this buffer.")
37(defvar linum-available nil "Overlays available for reuse.")
38(defvar linum-before-numbering-hook nil
39 "Functions run in each buffer before line numbering starts.")
40
41(mapc #'make-variable-buffer-local '(linum-overlays linum-available))
42
43(defgroup linum nil
44 "Show line numbers in the left margin."
45 :group 'convenience)
46
47;;;###autoload
48(defcustom linum-format 'dynamic
49 "Format used to display line numbers.
50Either a format string like \"%7d\", `dynamic' to adapt the width
51as needed, or a function that is called with a line number as its
52argument and should evaluate to a string to be shown on that line.
53See also `linum-before-numbering-hook'."
54 :group 'linum
55 :type 'sexp)
56
57(defface linum
58 '((t :inherit (shadow default)))
59 "Face for displaying line numbers in the display margin."
60 :group 'linum)
61
62(defcustom linum-eager t
63 "Whether line numbers should be updated after each command.
64The conservative setting `nil' might miss some buffer changes,
65and you have to scroll or press \\[recenter-top-bottom] to update the numbers."
66 :group 'linum
67 :type 'boolean)
68
69(defcustom linum-delay nil
70 "Delay updates to give Emacs a chance for other changes."
71 :group 'linum
72 :type 'boolean)
73
74;;;###autoload
75(define-minor-mode linum-mode
06e21633
CY
76 "Toggle display of line numbers in the left margin (Linum mode).
77With a prefix argument ARG, enable Linum mode if ARG is positive,
78and disable it otherwise. If called from Lisp, enable the mode
79if ARG is omitted or nil.
80
81Linum mode is a buffer-local minor mode."
8e54981d
JB
82 :lighter "" ; for desktop.el
83 (if linum-mode
84 (progn
85 (if linum-eager
86 (add-hook 'post-command-hook (if linum-delay
87 'linum-schedule
88 'linum-update-current) nil t)
89 (add-hook 'after-change-functions 'linum-after-change nil t))
90 (add-hook 'window-scroll-functions 'linum-after-scroll nil t)
b932657b
SM
91 ;; Using both window-size-change-functions and
92 ;; window-configuration-change-hook seems redundant. --Stef
93 ;; (add-hook 'window-size-change-functions 'linum-after-size nil t)
8e54981d
JB
94 (add-hook 'change-major-mode-hook 'linum-delete-overlays nil t)
95 (add-hook 'window-configuration-change-hook
b932657b
SM
96 ;; FIXME: If the buffer is shown in N windows, this
97 ;; will be called N times rather than once. We should use
98 ;; something like linum-update-window instead.
99 'linum-update-current nil t)
8e54981d
JB
100 (linum-update-current))
101 (remove-hook 'post-command-hook 'linum-update-current t)
102 (remove-hook 'post-command-hook 'linum-schedule t)
b932657b 103 ;; (remove-hook 'window-size-change-functions 'linum-after-size t)
8e54981d
JB
104 (remove-hook 'window-scroll-functions 'linum-after-scroll t)
105 (remove-hook 'after-change-functions 'linum-after-change t)
b932657b 106 (remove-hook 'window-configuration-change-hook 'linum-update-current t)
8e54981d
JB
107 (remove-hook 'change-major-mode-hook 'linum-delete-overlays t)
108 (linum-delete-overlays)))
109
110;;;###autoload
111(define-globalized-minor-mode global-linum-mode linum-mode linum-on)
112
113(defun linum-on ()
114 (unless (minibufferp)
115 (linum-mode 1)))
116
117(defun linum-delete-overlays ()
118 "Delete all overlays displaying line numbers for this buffer."
119 (mapc #'delete-overlay linum-overlays)
120 (setq linum-overlays nil)
121 (dolist (w (get-buffer-window-list (current-buffer) nil t))
245be23c 122 (set-window-margins w 0 (cdr (window-margins w)))))
8e54981d
JB
123
124(defun linum-update-current ()
125 "Update line numbers for the current buffer."
126 (linum-update (current-buffer)))
127
128(defun linum-update (buffer)
129 "Update line numbers for all windows displaying BUFFER."
130 (with-current-buffer buffer
131 (when linum-mode
132 (setq linum-available linum-overlays)
133 (setq linum-overlays nil)
134 (save-excursion
135 (mapc #'linum-update-window
136 (get-buffer-window-list buffer nil 'visible)))
137 (mapc #'delete-overlay linum-available)
138 (setq linum-available nil))))
139
140(defun linum-update-window (win)
141 "Update line numbers for the portion visible in window WIN."
142 (goto-char (window-start win))
143 (let ((line (line-number-at-pos))
144 (limit (window-end win t))
145 (fmt (cond ((stringp linum-format) linum-format)
146 ((eq linum-format 'dynamic)
147 (let ((w (length (number-to-string
148 (count-lines (point-min) (point-max))))))
149 (concat "%" (number-to-string w) "d")))))
150 (width 0))
151 (run-hooks 'linum-before-numbering-hook)
152 ;; Create an overlay (or reuse an existing one) for each
153 ;; line visible in this window, if necessary.
154 (while (and (not (eobp)) (<= (point) limit))
155 (let* ((str (if fmt
156 (propertize (format fmt line) 'face 'linum)
157 (funcall linum-format line)))
158 (visited (catch 'visited
159 (dolist (o (overlays-in (point) (point)))
0ca77a92
JB
160 (when (equal-including-properties
161 (overlay-get o 'linum-str) str)
8e54981d
JB
162 (unless (memq o linum-overlays)
163 (push o linum-overlays))
0ca77a92 164 (setq linum-available (delq o linum-available))
8e54981d
JB
165 (throw 'visited t))))))
166 (setq width (max width (length str)))
167 (unless visited
168 (let ((ov (if (null linum-available)
169 (make-overlay (point) (point))
170 (move-overlay (pop linum-available) (point) (point)))))
171 (push ov linum-overlays)
172 (overlay-put ov 'before-string
173 (propertize " " 'display `((margin left-margin) ,str)))
174 (overlay-put ov 'linum-str str))))
d204c46c
SM
175 ;; Text may contain those nasty intangible properties, but that
176 ;; shouldn't prevent us from counting those lines.
177 (let ((inhibit-point-motion-hooks t))
178 (forward-line))
8e54981d 179 (setq line (1+ line)))
245be23c 180 (set-window-margins win width (cdr (window-margins win)))))
8e54981d 181
2fbc1934 182(defun linum-after-change (beg end _len)
8e54981d
JB
183 ;; update overlays on deletions, and after newlines are inserted
184 (when (or (= beg end)
185 (= end (point-max))
186 (string-match-p "\n" (buffer-substring-no-properties beg end)))
187 (linum-update-current)))
188
2fbc1934 189(defun linum-after-scroll (win _start)
8e54981d
JB
190 (linum-update (window-buffer win)))
191
b932657b
SM
192;; (defun linum-after-size (frame)
193;; (linum-after-config))
8e54981d
JB
194
195(defun linum-schedule ()
196 ;; schedule an update; the delay gives Emacs a chance for display changes
197 (run-with-idle-timer 0 nil #'linum-update-current))
198
b932657b
SM
199;; (defun linum-after-config ()
200;; (walk-windows (lambda (w) (linum-update (window-buffer w))) nil 'visible))
8e54981d
JB
201
202(defun linum-unload-function ()
203 "Unload the Linum library."
204 (global-linum-mode -1)
205 ;; continue standard unloading
206 nil)
207
208(provide 'linum)
209
8e54981d 210;;; linum.el ends here