0
|
1 ;;; lazy-lock.el --- Lazy demand-driven fontification for fast Font Lock mode.
|
|
2
|
|
3 ;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
|
|
4
|
|
5 ;; Author: Simon Marshall <simon@gnu.ai.mit.edu>
|
|
6 ;; Keywords: faces files
|
|
7 ;; Version: 1.14
|
|
8
|
|
9 ;; LCD Archive Entry:
|
|
10 ;; lazy-lock|Simon Marshall|simon@gnu.ai.mit.edu|
|
|
11 ;; Lazy Font Lock mode (with fast demand-driven fontification).|
|
|
12 ;; 13-Oct-95|1.14|~/modes/lazy-lock.el.Z|
|
|
13
|
|
14 ;; The archive is archive.cis.ohio-state.edu in /pub/gnu/emacs/elisp-archive.
|
|
15
|
|
16 ;;; This file is part of GNU Emacs.
|
|
17
|
|
18 ;; GNU Emacs is free software; you can redistribute it and/or modify
|
|
19 ;; it under the terms of the GNU General Public License as published by
|
|
20 ;; the Free Software Foundation; either version 2, or (at your option)
|
|
21 ;; any later version.
|
|
22
|
|
23 ;; GNU Emacs is distributed in the hope that it will be useful,
|
|
24 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
25 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
26 ;; GNU General Public License for more details.
|
|
27
|
|
28 ;; You should have received a copy of the GNU General Public License
|
|
29 ;; along with GNU Emacs; see the file COPYING. If not, write to
|
|
30 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
31
|
|
32 ;;; Synched up with: Not in FSF. (This seems very strange to me.)
|
|
33
|
|
34 ;;; Commentary:
|
|
35
|
|
36 ;; Purpose:
|
|
37 ;;
|
|
38 ;; To make visiting buffers in `font-lock-mode' faster by making fontification
|
|
39 ;; be demand-driven and stealthy.
|
|
40 ;; Fontification only occurs when, and where, necessary.
|
|
41 ;;
|
|
42 ;; See caveats and feedback below. See also the defer-lock and fast-lock
|
|
43 ;; packages. (But don't use lazy-lock.el and fast-lock.el at the same time!)
|
|
44
|
|
45 ;; Installation:
|
|
46 ;;
|
|
47 ;; Put this file somewhere where Emacs can find it (i.e., in one of the paths
|
|
48 ;; in your `load-path'), `byte-compile-file' it, and put in your ~/.emacs:
|
|
49 ;;
|
|
50 ;; (autoload 'turn-on-lazy-lock "lazy-lock"
|
|
51 ;; "Unconditionally turn on Lazy Lock mode.")
|
|
52 ;;
|
|
53 ;; (add-hook 'font-lock-mode-hook 'turn-on-lazy-lock)
|
|
54 ;;
|
|
55 ;; Start up a new Emacs and use font-lock as usual (except that you can use the
|
|
56 ;; so-called "gaudier" fontification regexps on big files without frustration).
|
|
57 ;;
|
|
58 ;; In a buffer (which has `font-lock-mode' enabled) which is at least
|
|
59 ;; `lazy-lock-minimum-size' characters long, only the visible portion of the
|
|
60 ;; buffer will be fontified. Motion around the buffer will fontify those
|
|
61 ;; visible portions that were not previous fontified. If the variable
|
|
62 ;; `lazy-lock-hide-invisible' is non-nil, redisplay will be delayed until after
|
|
63 ;; fontification. Otherwise, text that has not yet been fontified is displayed
|
|
64 ;; in `lazy-lock-invisible-foreground'.
|
|
65 ;;
|
|
66 ;; If stealth fontification is enabled, fontification will occur in invisible
|
|
67 ;; parts of the buffer after `lazy-lock-stealth-time' seconds of idle time.
|
|
68
|
|
69 ;; Advanced Use:
|
|
70 ;;
|
|
71 ;; You can also do fancy things with `advice'. For example, to fontify when
|
|
72 ;; dragging the scroll-bar in Emacs, you could put in your ~/.emacs:
|
|
73 ;;
|
|
74 ;; (autoload 'lazy-lock-post-command-fontify-windows "lazy-lock")
|
|
75 ;;
|
|
76 ;; (defadvice scroll-bar-drag-1 (after fontify-window activate compile)
|
|
77 ;; (let ((lazy-lock-walk-windows nil) (lazy-lock-hide-invisible nil))
|
|
78 ;; (lazy-lock-post-command-fontify-windows)))
|
|
79 ;;
|
|
80 ;; Or to fontify when the Debugger pops up a source code window:
|
|
81 ;;
|
|
82 ;; (autoload 'lazy-lock-fontify-walk-windows "lazy-lock")
|
|
83 ;;
|
|
84 ;; (defadvice gud-display-line (after fontify-window activate compile)
|
|
85 ;; (let ((lazy-lock-walk-windows t) (lazy-lock-hide-invisible t))
|
|
86 ;; (lazy-lock-fontify-walk-windows)))
|
|
87 ;;
|
|
88 ;; Scott Byer <byer@mv.us.adobe.com> suggested this to fontify the visible part
|
|
89 ;; of an insertion only:
|
|
90 ;;
|
|
91 ;; (defvar lazy-lock-insert-commands
|
|
92 ;; '(yank yank-pop clipboard-yank hilit-yank hilit-yank-pop
|
|
93 ;; mail-yank-original mouse-yank-at-click mouse-yank-secondary
|
|
94 ;; yank-rectangle)
|
|
95 ;; "A list of insertion commands.")
|
|
96 ;;
|
|
97 ;; (defadvice font-lock-after-change-function (around fontify-insertion
|
|
98 ;; activate compile)
|
|
99 ;; (if (or (not (memq this-command lazy-lock-insert-commands))
|
|
100 ;; (and (pos-visible-in-window-p beg) (pos-visible-in-window-p end)))
|
|
101 ;; ad-do-it
|
|
102 ;; (let ((this-command 'ignore))
|
|
103 ;; (put-text-property beg end 'fontified nil)
|
|
104 ;; (lazy-lock-fontify-window))))
|
|
105 ;;
|
|
106 ;; Let me know if you use any other `advice' and I'll put it here. Thanks.
|
|
107 ;;
|
|
108 ;; These kinds of things with `advice' aren't done automatically because they
|
|
109 ;; cause large packages (advice.el plus bytecomp.el and friends) to be loaded.
|
|
110
|
|
111 ;; Caveats:
|
|
112 ;;
|
|
113 ;; Lazy Lock mode does not work efficiently with Outline mode. This is because
|
|
114 ;; when in Outline mode, although text may be hidden (not visible in the
|
|
115 ;; window), the text is visible to Emacs Lisp code (not surprisingly) and Lazy
|
|
116 ;; Lock fontifies it mercilessly. Hopefully this will be fixed one day.
|
|
117 ;;
|
|
118 ;; Lazy Lock mode does not fontify windows as they appear:
|
|
119 ;;
|
|
120 ;; 1. With `query-replace' or `ispell-*', as Lazy Lock only knows about point
|
|
121 ;; motion after the command exits.
|
|
122 ;;
|
|
123 ;; 2. When displayed by gud.el (the Grand Unified Debugger), as they are
|
|
124 ;; displayed via a process sentinel. See `Advanced Use' above.
|
|
125 ;;
|
|
126 ;; 3. In XEmacs 19.12, when the last command was invoked via a mouse event,
|
|
127 ;; because of a bug/feature in/of `sit-for'.
|
|
128 ;;
|
|
129 ;; 4. In other random situations that I don't know about (yet).
|
|
130 ;;
|
|
131 ;; If you have `lazy-lock-hide-invisible' you may notice that redisplay occurs
|
|
132 ;; before fontification regardlessly. This is due to other packages sitting on
|
|
133 ;; `post-command-hook' and provoking redisplay. If you use these packages, you
|
|
134 ;; can't use `lazy-lock-hide-invisible'.
|
|
135 ;;
|
|
136 ;; If you have `lazy-lock-hide-invisible' and use scrollbar scrolling using
|
|
137 ;; Emacs 19, hidden text will not be fontified as it becomes visible. It is
|
|
138 ;; expected that Emacs 19 will provide the necessary hooks in future, to solve
|
|
139 ;; this problem and the problem above.
|
|
140 ;;
|
|
141 ;; Unless otherwise stated, "Emacs 19.X" means versions up to and including X.
|
|
142 ;;
|
|
143 ;; In Emacs 19.25, one `window-start'/`window-end' bug means that if you open a
|
|
144 ;; file in another frame (such as via `find-tag-other-frame'), the whole buffer
|
|
145 ;; is fontified regardless. Upgrade!
|
|
146 ;;
|
|
147 ;; In Emacs 19.25, fontification by stealth is turned off because of a fatal
|
|
148 ;; bug in `previous-single-property-change'. Upgrade!
|
|
149 ;;
|
|
150 ;; In Emacs 19.28, if you see a message in the minibuffer of the form
|
|
151 ;; "Fontifying window... done. (Restarted in foo.c)"
|
|
152 ;; it means the Garbage Collector has marked some (subsequently used) text
|
|
153 ;; properties. Lazy Lock attempts to recover the situation by restarting in
|
|
154 ;; that buffer. Unfortunately, that buffer will be left in a writable and
|
|
155 ;; modified state. Also, other windows may not be fontified when this happens.
|
|
156 ;; To reduce the frequency of this bug occuring, increase in your ~/.emacs the
|
|
157 ;; value of `gc-cons-threshold' to, say, 1Meg, e.g.:
|
|
158 ;;
|
|
159 ;; (setq gc-cons-threshold (* 1024 1024))
|
|
160 ;;
|
|
161 ;; The solution is to upgrade! (With thanks to Kevin Broadey for help here.)
|
|
162 ;;
|
|
163 ;; For XEmacs 19.11 and Lucid Emacs 19.10 users, lazy-lock sort-of works.
|
|
164 ;; There are bugs in text property and point/window primatives. Upgrade!
|
|
165
|
|
166 ;; Feedback:
|
|
167 ;;
|
|
168 ;; Feedback is welcome.
|
|
169 ;; To submit a bug report (or make comments) please use the mechanism provided:
|
|
170 ;;
|
|
171 ;; M-x lazy-lock-submit-bug-report RET
|
|
172
|
|
173 ;; History:
|
|
174 ;;
|
|
175 ;; 0.01--1.00:
|
|
176 ;; - Changed name from fore-lock to lazy-lock. Shame though.
|
|
177 ;; - Dropped `advice'-wrapping completely. Ask me if you're interested in it.
|
|
178 ;; - Made `lazy-lock-mode' ignore `post-command-hook' and `buffer-file-name'.
|
|
179 ;; - Made `lazy-lock-fontify-window' check `lazy-lock-mode' and `this-command'.
|
|
180 ;; - Made `lazy-lock-fontify-window' redisplay via `sit-for'.
|
|
181 ;; - Added `lazy-lock-minimum-size' to control `lazy-lock-mode'.
|
|
182 ;; 1.00--1.01:
|
|
183 ;; - Added `lazy-lock-fontify-buffer'.
|
|
184 ;; - Made `lazy-lock-fontify-window' ignore `lazy-lock-mode'.
|
|
185 ;; - Made `lazy-lock-fontify-window' suspicious of `window-' favourites again.
|
|
186 ;; - Added `lazy-lock-delay-commands' (idea from William G. Dubuque).
|
|
187 ;; - Added `lazy-lock-ignore-commands' for completeness.
|
|
188 ;; - Added `lazy-lock-continuity-time' for normal input delay.
|
|
189 ;; 1.01--1.02:
|
|
190 ;; - Made `lazy-lock-fontify-window' cope with multiple unfontified regions.
|
|
191 ;; - Made `lazy-lock-mode' remove `fontified' properties if turned off.
|
|
192 ;; - Made `lazy-lock-fontify-window' fontify by lines.
|
|
193 ;; - Added `lazy-lock-cache-position' buffer local to detect visibility change.
|
|
194 ;; - Added `lazy-lock-post-command-hook' to do the waiting.
|
|
195 ;; - Made `lazy-lock-fontify-window' just do the fontification.
|
|
196 ;; - Made `lazy-lock-mode' append `lazy-lock-post-command-hook'.
|
|
197 ;; - Added `lazy-lock-walk-windows' to hack multi-window motion.
|
|
198 ;; - Made `lazy-lock-post-command-hook' `walk-windows' if variable is non-nil.
|
|
199 ;; - Removed `lazy-lock-ignore-commands' since insertion may change window.
|
|
200 ;; - Added `lazy-lock-fontify-stealthily' and `lazy-lock-stealth-time'.
|
|
201 ;; - Made `lazy-lock-post-command-hook' use them.
|
|
202 ;; 1.02--1.03:
|
|
203 ;; - Made `lazy-lock-fontify-stealthily' do `forward-line' not `previous-line'.
|
|
204 ;; - Made `lazy-lock-fontify-stealthily' `move-to-window-line' first.
|
|
205 ;; - Made `lazy-lock-fontify-stealthily' use `text-property-any' for region.
|
|
206 ;; - Made `lazy-lock-post-command-hook' loop on `lazy-lock-fontify-stealthily'.
|
|
207 ;; 1.03--1.04:
|
|
208 ;; - Made `lazy-lock-mode' reset `lazy-lock-cache-position'.
|
|
209 ;; - Made `lazy-lock-post-command-hook' `widen' for `if' `text-property-any'.
|
|
210 ;; - Made `lazy-lock-fontify-stealthily' return `text-property-any'.
|
|
211 ;; - Added `lazy-lock-percent-fontified' for a/be-musement.
|
|
212 ;; - Made `lazy-lock-post-command-hook' use it.
|
|
213 ;; - Made `lazy-lock-mode' use `make-local-hook' etc. if available.
|
|
214 ;; - Made `lazy-lock-mode' use `before-revert-hook' and `after-revert-hook'.
|
|
215 ;; - Made `lazy-lock-post-command-hook' protect `deactivate-mark'.
|
|
216 ;; - Adds `lazy-lock-post-command-hook' globally to `post-command-hook'.
|
|
217 ;; 1.04--1.05:
|
|
218 ;; - Made `lazy-lock-mode' test `make-local-hook' not `emacs-minor-version'.
|
|
219 ;; 1.05--1.06:
|
|
220 ;; - Added `lazy-lock-ignore-commands' for commands that leave no event but do.
|
|
221 ;; - Made `lazy-lock-post-command-hook' check `lazy-lock-ignore-commands'.
|
|
222 ;; 1.06--1.07:
|
|
223 ;; - Removed `before-revert-hook' and `after-revert-hook' use.
|
|
224 ;; 1.07--1.08:
|
|
225 ;; - Added `lazy-lock-submit-bug-report'.
|
|
226 ;; - Made `lazy-lock-post-command-hook' check `executing-macro'.
|
|
227 ;; - Made it sort-of/almost work for XEmacs (help from Jonas Jarnestrom).
|
|
228 ;; - XEmacs: Fix `text-property-not-all' (fix based on fast-lock.el 3.05 fix).
|
|
229 ;; - XEmacs: Set `font-lock-no-comments' and alias `frame-parameters'.
|
|
230 ;; - Made `byte-compile-warnings' omit `unresolved' on compilation.
|
|
231 ;; - Made `lazy-lock-post-command-hook' protect `buffer-undo-list'.
|
|
232 ;; - Moved `deactivate-mark' and `buffer-undo-list' protection to functions.
|
|
233 ;; - Added `lazy-lock-invisible-foreground' (idea from Boris Goldowsky).
|
|
234 ;; - XEmacs: Fix to use `text-property-not-all' t, not `text-property-any' nil.
|
|
235 ;; - Made `lazy-lock-percent-fontified' return `round' to an integer.
|
|
236 ;; - XEmacs: Fix `text-property-any' (fix and work around for a bug elsewhere).
|
|
237 ;; - XEmacs: Fix `lazy-lock-submit-bug-report' for reporter.el & vm-window.el.
|
|
238 ;; - XEmacs: Made `lazy-lock-fontify-window' loop `while' `<' not `/='.
|
|
239 ;; - Use `font-lock-after-change-function' to do the fontification.
|
|
240 ;; 1.08--1.09:
|
|
241 ;; - Made `lazy-lock-post-command-hook' protect with `condition-case'.
|
|
242 ;; - Made `lazy-lock-cache-start' to cache `window-start'.
|
|
243 ;; - Made `lazy-lock-fontify-window' check and cache `lazy-lock-cache-start'.
|
|
244 ;; - Renamed `lazy-lock-cache-position' to `lazy-lock-cache-end'.
|
|
245 ;; - XEmacs: Fix for `font-lock-after-change-function'.
|
|
246 ;; - Adds `lazy-lock-post-command-hook' globally to `window-setup-hook'.
|
|
247 ;; 1.09--1.10:
|
|
248 ;; - Made `buffer-file-name' be `let' to prevent supersession (Kevin Broadey).
|
|
249 ;; - Made `lazy-lock-submit-bug-report' `require' reporter (Ilya Zakharevich).
|
|
250 ;; - Made `lazy-lock-mode' and `turn-on-lazy-lock' succeed `autoload' cookies.
|
|
251 ;; - Added `lazy-lock-fontify-walk-windows' for walking window fontification.
|
|
252 ;; - Added `lazy-lock-fontify-walk-stealthily' for walking stealth.
|
|
253 ;; - Removed `move-to-window-line' from `lazy-lock-fontify-stealthily'.
|
|
254 ;; - Made `lazy-lock-percent-fontified' use `truncate' rather than `round'.
|
|
255 ;; - Added other `*-argument' to `lazy-lock-ignore-commands' (Kevin Broadey).
|
|
256 ;; - Made `lazy-lock-fontify-stealthily' not assume buffer is part `fontified'.
|
|
257 ;; - Emacs: Fix for `font-lock-fontify-region'.
|
|
258 ;; - Made `lazy-lock-post-command-hook' check for minibuffer (Kevin Broadey).
|
|
259 ;; - Added `lazy-lock-stealth-nice' for niceness during stealth fontification.
|
|
260 ;; - Added `lazy-lock-stealth-lines' for chunks of stealth fontification.
|
|
261 ;; 1.10--1.11: incorporated hack by Ben Wing from William Dubuque's fontifly.el
|
|
262 ;; - Made `lazy-lock-fontify-stealthily' see a non `fontified' preceding line.
|
|
263 ;; - XEmacs: Fix `text-property-any' and `text-property-not-all' (Ben Wing).
|
|
264 ;; - XEmacs: Fix `lazy-lock-continuity-time' (Ben Wing).
|
|
265 ;; - Added awful `lazy-lock-running-xemacs-p' (Ben Wing).
|
|
266 ;; - Made loading set `emacs-minor-version' if it's not bound.
|
|
267 ;; - Added `lazy-lock-hide-invisible' to control redisplay.
|
|
268 ;; - Made `lazy-lock-post-command-hook' use it in `sit-for' (Ben Wing).
|
|
269 ;; - Made `lazy-lock-fontify-window' move relative to `end-of-line' if non-nil.
|
|
270 ;; - Added `lazy-lock-fontify-region' so packages can ensure fontification.
|
|
271 ;; - Made `lazy-lock-fontify-walk-stealthily' do stealth widening.
|
|
272 ;; - Made `lazy-lock-fontify-stealthily' always do adjacent preceding regions.
|
|
273 ;; - Added `lazy-lock-after-fontify-buffer'.
|
|
274 ;; - XEmacs: Removed `font-lock-no-comments' incompatibility code.
|
|
275 ;; - Removed `lazy-lock-delay-time' and `lazy-lock-delay-commands'.
|
|
276 ;; - Removed `lazy-lock-post-command' and split the functionality.
|
|
277 ;; - Adds `lazy-lock-post-command-fontify-windows' on first.
|
|
278 ;; - Adds `lazy-lock-post-command-fontify-stealthily' on last.
|
|
279 ;; - Made `lazy-lock-mode' ensure both first and last on `post-command-hook'.
|
|
280 ;; - Made `lazy-lock-mode' ensure `font-lock-mode' is on.
|
|
281 ;; - Wrap `lazy-lock-post-command-fontify-stealthily' for errors (David Karr).
|
|
282 ;; - Added `calcDigit-key' to `lazy-lock-ignore-commands' (Bob Glickstein).
|
|
283 ;; - Wrap `lazy-lock-running-xemacs-p' with `eval-and-compile' (Erik Naggum).
|
|
284 ;; - XEmacs: Fix use of `previous-single-property-change' (Jim Thompson).
|
|
285 ;; - XEmacs: Fix `next-single-property-change' fix for 19.11 (Jim Thompson).
|
|
286 ;; - Added `lazy-lock-post-resize-fontify-windows' to fontify on resizing.
|
|
287 ;; - Adds globally to `window-size-change-functions'.
|
|
288 ;; - Added `lazy-lock-post-setup-fontify-windows' to fontify after start up.
|
|
289 ;; - Adds globally to `window-setup-hook'.
|
|
290 ;; - Made `lazy-lock-post-command-fontify-windows' check for `input-pending-p'.
|
|
291 ;; - Made `save-selected-window' to restore the `selected-window'.
|
|
292 ;; - Use `save-selected-window' rather than `save-window-excursion'.
|
|
293 ;; 1.11--1.12:
|
|
294 ;; - Made `lazy-lock-post-command-fontify-windows' do `set-buffer' first.
|
|
295 ;; - Made `lazy-lock-fontify-stealthily' respect narrowing before point.
|
|
296 ;; - Added `lazy-lock-post-setup-ediff-control-frame' for Ediff control frame.
|
|
297 ;; - Adds globally to `ediff-after-setup-control-frame-hooks'.
|
|
298 ;; - Wrap `save-selected-window' with `save-excursion' for `current-buffer'.
|
|
299 ;; 1.12--1.13:
|
|
300 ;; - XEmacs: Add `lazy-lock-after-fontify-buffer' to the Font Lock hook.
|
|
301 ;; - Made `buffer-file-truename' also wrapped for supersession (Rick Sladkey).
|
|
302 ;; - Made `font-lock-beginning-of-syntax-function' wrapped for fontification.
|
|
303 ;; - Added `lazy-lock-stealth-verbose' (after harassment from Ben Wing).
|
|
304 ;; - XEmacs: Made `font-lock-verbose' wrapped for stealth fontification.
|
|
305 ;; 1.13--1.14:
|
|
306 ;; - Wrap `lazy-lock-colour-invisible' for `set-face-foreground' (Jari Aalto).
|
|
307
|
|
308 (require 'font-lock)
|
|
309
|
|
310 (eval-when-compile
|
|
311 ;; Only `require' so `ediff-multiframe-setup-p' is expanded at compile time.
|
|
312 (condition-case nil (require 'ediff) (file-error))
|
|
313 ;; Well, shouldn't Lazy Lock be as lazy as possible?
|
|
314 ;(setq byte-compile-dynamic t byte-compile-dynamic-docstrings t)
|
|
315 ;; Shut Emacs' byte-compiler up (cf. stop me getting mail from users).
|
|
316 (setq byte-compile-warnings '(free-vars callargs redefine)))
|
|
317
|
|
318 (defun lazy-lock-submit-bug-report ()
|
|
319 "Submit via mail a bug report on lazy-lock.el."
|
|
320 (interactive)
|
|
321 (require 'reporter)
|
|
322 (let ((reporter-prompt-for-summary-p t))
|
|
323 (reporter-submit-bug-report "simon@gnu.ai.mit.edu" "lazy-lock 1.14"
|
|
324 '(lazy-lock-walk-windows lazy-lock-continuity-time
|
|
325 lazy-lock-stealth-time lazy-lock-stealth-nice
|
|
326 lazy-lock-stealth-lines lazy-lock-stealth-verbose
|
|
327 lazy-lock-hide-invisible lazy-lock-invisible-foreground
|
|
328 lazy-lock-minimum-size lazy-lock-ignore-commands)
|
|
329 nil nil
|
|
330 (concat "Hi Si.,
|
|
331
|
|
332 I want to report a bug. I've read the `Bugs' section of `Info' on Emacs, so I
|
|
333 know how to make a clear and unambiguous report. To reproduce the bug:
|
|
334
|
|
335 Start a fresh Emacs via `" invocation-name " -no-init-file -no-site-file'.
|
|
336 In the `*scratch*' buffer, evaluate:"))))
|
|
337
|
|
338 ;; Let's define `emacs-major-version', `emacs-minor-version', and
|
|
339 ;; `emacs-version>=' if no-one else has.
|
|
340
|
|
341 (if (not (boundp 'emacs-major-version))
|
|
342 (eval-and-compile
|
|
343 (defconst emacs-major-version
|
|
344 (progn (or (string-match "^[0-9]+" emacs-version)
|
|
345 (error "emacs-version unparsable"))
|
|
346 (string-to-int (match-string 0 emacs-version)))
|
|
347 "Major version number of this version of Emacs, as an integer.
|
|
348 Warning, this variable did not exist in Emacs versions earlier than:
|
|
349 FSF Emacs: 19.23
|
|
350 XEmacs: 19.10")))
|
|
351
|
|
352 (if (not (boundp 'emacs-minor-version))
|
|
353 (eval-and-compile
|
|
354 (defconst emacs-minor-version
|
|
355 (progn (or (string-match "^[0-9]+\\.\\([0-9]+\\)" emacs-version)
|
|
356 (error "emacs-version unparsable"))
|
|
357 (string-to-int (match-string 1 emacs-version)))
|
|
358 "Minor version number of this version of Emacs, as an integer.
|
|
359 Warning, this variable did not exist in Emacs versions earlier than:
|
|
360 FSF Emacs: 19.23
|
|
361 XEmacs: 19.10")))
|
|
362
|
|
363 (if (not (fboundp 'emacs-version>=))
|
|
364 (eval-and-compile
|
|
365 (defun emacs-version>= (major &optional minor)
|
|
366 "Return true if the Emacs version is >= to the given MAJOR and MINOR numbers.
|
|
367
|
|
368 The MAJOR version number argument is required, but the MINOR version number
|
|
369 argument is optional. If the minor version number is not specified (or is the
|
|
370 symbol `nil') then only the major version numbers are considered in the test."
|
|
371 (if (null minor)
|
|
372 (>= emacs-major-version major)
|
|
373 (or (> emacs-major-version major)
|
|
374 (and (= emacs-major-version major)
|
|
375 (>= emacs-minor-version minor))
|
|
376 )
|
|
377 ))))
|
|
378
|
|
379 ;; Yuck, but we make so much use of this variable it's probably worth it.
|
|
380 (eval-and-compile
|
|
381 (defconst lazy-lock-running-xemacs-p
|
|
382 (not (null (save-match-data (string-match "Lucid" emacs-version))))))
|
|
383
|
|
384 (defvar lazy-lock-cache-start nil) ; for window fontifiction
|
|
385 (defvar lazy-lock-cache-end nil) ; for window fontifiction
|
|
386 (defvar lazy-lock-cache-continue nil) ; for stealth fontifiction
|
|
387
|
|
388 ;;;###autoload
|
|
389 (defvar lazy-lock-mode nil) ; for modeline
|
|
390
|
|
391 ;; User Variables:
|
|
392
|
|
393 (defvar lazy-lock-minimum-size (* 25 1024)
|
|
394 "*If non-nil, the minimum size for buffers.
|
|
395 Only buffers more than this can have demand-driven fontification.
|
|
396 If nil, means size is irrelevant.")
|
|
397
|
|
398 (defvar lazy-lock-walk-windows t
|
|
399 "*If non-nil, fontify windows other than the selected window.
|
|
400 If `all-frames', fontify windows even on other frames.
|
|
401 A non-nil value slows down redisplay.")
|
|
402
|
|
403 ;; XEmacs 19.11 and below exercise a bug in the Xt event loop.
|
|
404 (defvar lazy-lock-continuity-time
|
|
405 (if (or (not lazy-lock-running-xemacs-p) (emacs-version>= 19 12))
|
|
406 0
|
|
407 (if (featurep 'lisp-float-type) 0.001 1))
|
|
408 "*Time in seconds to delay before normal window fontification.
|
|
409 Window fontification occurs if there is no input within this time.")
|
|
410
|
|
411 ;; `previous-single-property-change' at `point-min' up to Emacs 19.25 is fatal.
|
|
412 ;; `text-property-any', `text-property-not-all' and
|
|
413 ;; `next-single-property-change' up to XEmacs 19.11 are too broke.
|
|
414 (defvar lazy-lock-stealth-time
|
|
415 (if (emacs-version>= 19 (if lazy-lock-running-xemacs-p 12 26)) 30)
|
|
416 "*Time in seconds to delay before beginning stealth fontification.
|
|
417 Stealth fontification occurs if there is no input within this time.
|
|
418 If nil, means no fontification by stealth.")
|
|
419
|
|
420 (defvar lazy-lock-stealth-lines
|
|
421 (cond ((boundp 'font-lock-maximum-decoration)
|
|
422 (if font-lock-maximum-decoration 75 150))
|
|
423 ((boundp 'font-lock-use-maximal-decoration)
|
|
424 (if font-lock-use-maximal-decoration 50 100))
|
|
425 (t
|
|
426 50))
|
|
427 "*If non-nil, the maximum size of a chunk of stealth fontification.
|
|
428 Each iteration of stealth fontification can fontify this number of lines.
|
|
429 To speed up input response during stealth fontification, at the cost of stealth
|
|
430 taking longer to fontify, you could reduce the value of this variable.
|
|
431 If nil, means use `window-height' for the maximum chunk size.")
|
|
432
|
|
433 (defvar lazy-lock-stealth-nice (if (featurep 'lisp-float-type) 0.125 1)
|
|
434 "*Time in seconds to pause during chunks of stealth fontification.
|
|
435 To reduce machine load during stealth fontification, at the cost of stealth
|
|
436 taking longer to fontify, you could increase the value of this variable.")
|
|
437
|
|
438 (defvar lazy-lock-stealth-verbose font-lock-verbose
|
|
439 "*If non-nil, means stealth fontification should show status messages.")
|
|
440
|
|
441 (defvar lazy-lock-ignore-commands
|
|
442 (append
|
|
443 ;; Standard commands...
|
|
444 '(universal-argument digit-argument negative-argument
|
|
445 isearch-other-control-char isearch-other-meta-char)
|
|
446 ;; And some resulting from non-standard packages...
|
|
447 (if (fboundp 'calc) '(calcDigit-key)))
|
|
448 "A list of commands after which fontification should not occur.
|
|
449 To speed up typing response, at the cost of Lazy Lock not fontifying when
|
|
450 insertion causes scrolling, you could add `self-insert-command' to this list.")
|
|
451
|
|
452 (defvar lazy-lock-hide-invisible lazy-lock-running-xemacs-p
|
|
453 "*If non-nil, hide invisible text while it is fontified.
|
|
454 If non-nil, redisplay is delayed until after fontification occurs. If nil,
|
|
455 text is shown (in `lazy-lock-invisible-foreground') while it is fontified.
|
|
456 A non-nil value slows down redisplay and can slow down cursor motion.")
|
|
457
|
|
458 (defvar lazy-lock-invisible-foreground "gray50"
|
|
459 "The foreground colour to use to display invisible text.
|
|
460 If nil, the default foreground is used. If t, the default background is used.
|
|
461 If a string, it should be a colour to use (either its name or its RGB value).
|
|
462 Invisible text is momentarily seen (if `lazy-lock-hide-invisible' is nil) when
|
|
463 scrolling into unfontified regions.")
|
|
464
|
|
465 ;; User Functions:
|
|
466
|
|
467 ;;;###autoload
|
|
468 (defun lazy-lock-mode (&optional arg)
|
|
469 "Toggle Lazy Lock mode.
|
|
470 With arg, turn Lazy Lock mode on if and only if arg is positive and the buffer
|
|
471 is at least `lazy-lock-minimum-size' characters long.
|
|
472
|
|
473 When Lazy Lock mode is enabled, fontification is demand-driven and stealthy:
|
|
474
|
|
475 - Fontification occurs in visible parts of buffers when necessary.
|
|
476 Occurs if there is no input after pausing for `lazy-lock-continuity-time'.
|
|
477
|
|
478 - Fontification occurs in invisible parts when Emacs has been idle.
|
|
479 Occurs if there is no input after pausing for `lazy-lock-stealth-time'.
|
|
480
|
|
481 If `lazy-lock-hide-invisible' is non-nil, text is not displayed until it is
|
|
482 fontified, otherwise it is displayed in `lazy-lock-invisible-foreground'.
|
|
483
|
|
484 See also variables `lazy-lock-walk-windows' and `lazy-lock-ignore-commands' for
|
|
485 window (scroll) fontification, and `lazy-lock-stealth-lines',
|
|
486 `lazy-lock-stealth-nice' and `lazy-lock-stealth-verbose' for stealth
|
|
487 fontification.
|
|
488
|
|
489 Use \\[lazy-lock-submit-bug-report] to send bug reports or feedback."
|
|
490 (interactive "P")
|
|
491 (set (make-local-variable 'lazy-lock-mode)
|
|
492 (and (<= (or lazy-lock-minimum-size 0) (buffer-size))
|
|
493 (if arg (> (prefix-numeric-value arg) 0) (not lazy-lock-mode))))
|
|
494 (if (and lazy-lock-mode (not font-lock-mode))
|
|
495 ;; Turned on `lazy-lock-mode' rather than using `font-lock-mode-hook'.
|
|
496 (progn
|
|
497 (add-hook 'font-lock-mode-hook 'turn-on-lazy-lock)
|
|
498 (font-lock-mode 1))
|
|
499 (lazy-lock-fixup-hooks)
|
|
500 ;; Let's get down to business.
|
|
501 (if (not lazy-lock-mode)
|
|
502 (let ((modified (buffer-modified-p)) (inhibit-read-only t)
|
|
503 (buffer-undo-list t)
|
|
504 deactivate-mark buffer-file-name buffer-file-truename)
|
|
505 (remove-text-properties (point-min) (point-max) '(fontified nil))
|
|
506 (or modified (set-buffer-modified-p nil)))
|
|
507 (if (and (not lazy-lock-hide-invisible) lazy-lock-invisible-foreground)
|
|
508 (lazy-lock-colour-invisible))
|
|
509 (set (make-local-variable 'lazy-lock-cache-start) 0)
|
|
510 (set (make-local-variable 'lazy-lock-cache-end) 0)
|
|
511 (set (make-local-variable 'font-lock-fontified) t))))
|
|
512
|
|
513 ;;;###autoload
|
|
514 (defun turn-on-lazy-lock ()
|
|
515 "Unconditionally turn on Lazy Lock mode."
|
|
516 (lazy-lock-mode 1))
|
|
517
|
|
518 (if (not (emacs-version>= 19 (if lazy-lock-running-xemacs-p 12 29)))
|
|
519 ;; We don't need this in Emacs 19.29 or XEmacs 19.12.
|
|
520 (defun lazy-lock-fontify-buffer ()
|
|
521 "Fontify the current buffer where necessary."
|
|
522 (interactive)
|
|
523 (lazy-lock-fontify-region (point-min) (point-max))))
|
|
524
|
|
525 ;; API Functions:
|
|
526
|
|
527 (defun lazy-lock-fixup-hooks ()
|
|
528 ;; Make sure our hooks are correct.
|
|
529 (remove-hook 'pre-idle-hook 'lazy-lock-pre-idle-fontify-windows)
|
|
530 (remove-hook 'post-command-hook 'lazy-lock-post-command-fontify-stealthily)
|
|
531 ;; Make sure our hooks are at the end. Font-lock in XEmacs installs
|
|
532 ;; its own pre-idle-hook to implement deferral (#### something that
|
|
533 ;; should really be merged with this file; or more likely, lazy-lock
|
|
534 ;; in its entirety should be merged into font-lock).
|
|
535 (add-hook 'pre-idle-hook 'lazy-lock-pre-idle-fontify-windows t)
|
|
536 (add-hook 'post-command-hook 'lazy-lock-post-command-fontify-stealthily t)
|
|
537 ;; Fascistically remove font-lock's after-change-function and install
|
|
538 ;; our own. We know better than font-lock what to do. Otherwise,
|
|
539 ;; revert-buffer, insert-file, etc. cause full refontification of the
|
|
540 ;; entire changed area.
|
|
541 (if lazy-lock-mode
|
|
542 (progn
|
|
543 (remove-hook 'after-change-functions 'font-lock-after-change-function
|
|
544 t)
|
|
545 (make-local-hook 'after-change-functions)
|
|
546 (add-hook 'after-change-functions 'lazy-lock-after-change-function
|
|
547 nil t))
|
|
548 (remove-hook 'after-change-functions 'lazy-lock-after-change-function t)
|
|
549 (if font-lock-mode
|
|
550 (add-hook 'after-change-functions 'font-lock-after-change-function
|
|
551 nil t)))
|
|
552 )
|
|
553
|
|
554 ;; use put-nonduplicable-text-property to avoid unfriendly behavior
|
|
555 ;; when doing undo, etc. We really don't want syntax-highlighting text
|
|
556 ;; properties copied into strings or tracked by undo.
|
|
557 ;;
|
|
558 ;; #### If start-open and end-open really behaved like they are supposed to,
|
|
559 ;; we wouldn't really need this. I kind of fixed them up, but there's still
|
|
560 ;; a bug -- inserting text into the middle of a region of
|
|
561 ;; (start-open t end-open t) text should cause it not to inherit, but it
|
|
562 ;; does.
|
|
563
|
|
564 (if lazy-lock-running-xemacs-p
|
|
565 (defalias 'lazy-lock-put-text-property 'put-nonduplicable-text-property)
|
|
566 (defalias 'lazy-lock-put-text-property 'put-text-property))
|
|
567
|
|
568 (defun lazy-lock-fontify-region (start end &optional buffer)
|
|
569 "Fontify between START and END in BUFFER where necessary."
|
|
570 (save-excursion
|
|
571 (and buffer (set-buffer buffer))
|
|
572 (save-restriction
|
|
573 (narrow-to-region start end)
|
|
574 (let ((lazy-lock-stealth-lines (count-lines start end)))
|
|
575 (while (text-property-not-all start end 'fontified t)
|
|
576 (lazy-lock-fontify-stealthily))))))
|
|
577
|
|
578 (defun lazy-lock-after-fontify-buffer ()
|
|
579 ;; Mark the buffer as `fontified'.
|
|
580 (let ((modified (buffer-modified-p)) (inhibit-read-only t)
|
|
581 (buffer-undo-list t)
|
|
582 deactivate-mark buffer-file-name buffer-file-truename)
|
|
583 (lazy-lock-put-text-property (point-min) (point-max) 'fontified t)
|
|
584 (or modified (set-buffer-modified-p nil))))
|
|
585
|
|
586 ;; Just a cleaner-looking way of coping with Emacs' and XEmacs' `sit-for'.
|
|
587 (defmacro lazy-lock-sit-for (seconds &optional nodisp)
|
|
588 (if lazy-lock-running-xemacs-p
|
|
589 (` (sit-for (, seconds) (, nodisp)))
|
|
590 (` (sit-for (, seconds) 0 (, nodisp)))))
|
|
591
|
|
592 ;; Using `save-window-excursion' provokes `window-size-change-functions'.
|
|
593 ;; I prefer `save-walking-excursion', of course, because I have a warped mind.
|
|
594 (if (fboundp 'save-selected-window)
|
|
595 nil
|
|
596 (eval-and-compile
|
|
597 (defmacro save-selected-window (&rest body)
|
|
598 "Execute the BODY forms, restoring the selected window.
|
|
599 Does not restore the value of point in the selected window, or anything else."
|
|
600 (` (let ((original-window (selected-window)))
|
|
601 (unwind-protect
|
|
602 (progn (,@ body))
|
|
603 (select-window original-window))))))
|
|
604 (put 'save-selected-window 'lisp-indent-function 0))
|
|
605
|
|
606 ;; Functions for hooks:
|
|
607
|
|
608 ;; lazy-lock optimization:
|
|
609 ;;
|
|
610 ;; pre-idle-hook is called an awful lot -- pretty much every time the
|
|
611 ;; mouse moves or a timeout expires, for example. On Linux (sometimes),
|
|
612 ;; IRIX 5.x, and Solaris 2.something, it happens every 1/4 of a second
|
|
613 ;; due to the 1/4-second timers installed to compensate for various
|
|
614 ;; operating system deficiencies in the handling of SIGIO and SIGCHLD.
|
|
615 ;; (Those timers cause a cycle of the event loop. They don't necessarily
|
|
616 ;; have to, but rewriting to avoid this is fairly tricky and requires
|
|
617 ;; having significant amounts of code called from signal handlers, which
|
|
618 ;; (despite that fact that FSF Emacs reads its X input during a signal
|
|
619 ;; handler ?!), is almost always a bad idea -- it's extremely easy to
|
|
620 ;; introduce race conditions, which are very hard to track down.
|
|
621 ;;
|
|
622 ;; So to improve things, I added `frame-modified-tick'. This is an
|
|
623 ;; internal counter that gets ticked any time that any internal
|
|
624 ;; redisplay variable gets ticked. If `frame-modified-tick' is
|
|
625 ;; the same as the last time we checked, it means that redisplay will
|
|
626 ;; do absolutely nothing when encountering this frame, and thus we
|
|
627 ;; can skip out immediately. This happens when the 1/4-second timer
|
|
628 ;; fires while we're idle, or if we just move the mouse. (Moving
|
|
629 ;; around in a buffer changes `frame-modified-tick' because the
|
|
630 ;; internal redisplay variable "point_changed" gets ticked. We could
|
|
631 ;; easily improve things further by adding more tick counters, mirroring
|
|
632 ;; more closely the internal redisplay counters -- e.g. if we had
|
|
633 ;; another counter that didn't get ticked when point moved, we could
|
|
634 ;; tell if anything was going to happen by seeing if point is within
|
|
635 ;; window-start and window-end, since we know that redisplay will
|
|
636 ;; only do a window-scroll if it's not. (If window-start or window-end
|
|
637 ;; or window-buffer or anything else changed, windows_changed or
|
|
638 ;; some other variable will get ticked.))
|
|
639 ;;
|
|
640 ;; Also, it's wise to try and avoid things that cons. Avoiding
|
|
641 ;; `save-window-excursion', as we do, is definitely a major win
|
|
642 ;; because that's a heavy-duty function as regards consing and such.
|
|
643
|
|
644 (defvar lazy-lock-pre-idle-frame-modified-tick nil)
|
|
645 (defvar lazy-lock-pre-idle-selected-frame nil)
|
|
646
|
|
647 (defun lazy-lock-pre-idle-fontify-windows ()
|
|
648 ;; Do groovy things always unless we're in one of the ignored commands.
|
|
649 ;; The old version did the following five checks:
|
|
650 ;;
|
|
651 ;; (a) not in a macro,
|
|
652 ;; (b) no input pending,
|
|
653 ;; (c) got a real command (i.e. not an ignored command)
|
|
654 ;; (d) not in the minibuffer
|
|
655 ;; (e) no input after waiting for `lazy-lock-continuity-time'.
|
|
656 ;;
|
|
657 ;; (a), (b), and (e) are automatically taken care of by `pre-idle-hook'.
|
|
658 ;; I removed (d) because there doesn't seem to be any reason for it.
|
|
659 ;;
|
|
660 ;; Also, we do not have to `set-buffer' and in fact it would be
|
|
661 ;; incorrect to do so, since we may be being called from
|
|
662 ;; `accept-process-output' or whatever.
|
|
663 ;;
|
|
664 (if (memq this-command lazy-lock-ignore-commands)
|
|
665 (setq lazy-lock-cache-continue nil)
|
|
666 (setq lazy-lock-cache-continue t)
|
|
667 ;; #### we don't yet handle frame-modified-tick on multiple frames.
|
|
668 ;; handling this shouldn't be hard but I just haven't done it yet.
|
|
669 (if (or (eq 'all-frames lazy-lock-walk-windows)
|
|
670 (not (eq lazy-lock-pre-idle-selected-frame (selected-frame)))
|
|
671 (not (eq lazy-lock-pre-idle-frame-modified-tick
|
|
672 (frame-modified-tick (selected-frame)))))
|
|
673 (progn
|
|
674 ;; Do the visible parts of the buffer(s), i.e., the window(s).
|
|
675 (if (or (not lazy-lock-walk-windows)
|
|
676 (and (eq lazy-lock-walk-windows t) (one-window-p t)))
|
|
677 (if lazy-lock-mode (condition-case nil
|
|
678 (lazy-lock-fontify-window)))
|
|
679 (lazy-lock-fontify-walk-windows))
|
|
680 (setq lazy-lock-pre-idle-selected-frame (selected-frame))
|
|
681 (setq lazy-lock-pre-idle-frame-modified-tick
|
|
682 (frame-modified-tick (selected-frame)))))))
|
|
683
|
|
684 (defun lazy-lock-after-change-function (beg end old-len)
|
|
685 (and lazy-lock-mode
|
|
686 (if (= beg end)
|
|
687 (font-lock-after-change-function beg end old-len)
|
|
688 (lazy-lock-put-text-property beg end 'fontified nil))))
|
|
689
|
|
690 ;; DO NOT put this as a pre-idle hook! The sit-for messes up
|
|
691 ;; mouse dragging.
|
|
692 (defun lazy-lock-post-command-fontify-stealthily ()
|
|
693 ;; Do groovy things if (a-d) above, (e) not moving the mouse, and (f) no
|
|
694 ;; input after after waiting for `lazy-lock-stealth-time'.
|
|
695 (if (and lazy-lock-cache-continue lazy-lock-stealth-time)
|
|
696 (condition-case data
|
|
697 (if (lazy-lock-sit-for lazy-lock-stealth-time)
|
|
698 ;; Do the invisible parts of buffers.
|
|
699 (lazy-lock-fontify-walk-stealthily))
|
|
700 (error (message "Fontifying stealthily... %s" data)))))
|
|
701
|
|
702 ;; In XEmacs 19.14 with pre-idle-hook we do not have to call this.
|
|
703 (defun lazy-lock-post-resize-fontify-windows (frame)
|
|
704 ;; Fontify all windows in FRAME.
|
|
705 (let ((lazy-lock-walk-windows t) executing-kbd-macro this-command)
|
|
706 (save-excursion
|
|
707 (save-selected-window
|
|
708 (select-frame frame)
|
|
709 (lazy-lock-pre-idle-fontify-windows)))))
|
|
710
|
|
711 (defun lazy-lock-post-setup-emacs-fontify-windows ()
|
|
712 ;; Fontify all windows in all frames.
|
|
713 (let ((lazy-lock-walk-windows 'all-frames) executing-kbd-macro this-command)
|
|
714 (lazy-lock-pre-idle-fontify-windows)))
|
|
715
|
|
716 (defun lazy-lock-post-setup-ediff-control-frame ()
|
|
717 ;; Fontify all windows in all frames when using the Ediff control frame.
|
|
718 (make-local-variable 'lazy-lock-walk-windows)
|
|
719 (setq lazy-lock-walk-windows (if (ediff-multiframe-setup-p) 'all-frames t))
|
|
720 (lazy-lock-fixup-hooks))
|
|
721
|
|
722 ;; Functions for fontification:
|
|
723
|
|
724 (defun lazy-lock-fontify-window ()
|
|
725 ;; Fontify the visible part of the buffer where necessary.
|
|
726 (let ((ws (if lazy-lock-hide-invisible
|
|
727 (save-excursion
|
|
728 (end-of-line) (forward-line (- (window-height))) (point))
|
|
729 (min (max (window-start) (point-min)) (point-max))))
|
|
730 (we (if lazy-lock-hide-invisible
|
|
731 (save-excursion
|
|
732 (end-of-line) (forward-line (window-height)) (point))
|
|
733 (min (max (1- (window-end)) (point-min)) (point-max)))))
|
|
734 (if (or (/= ws lazy-lock-cache-start) (/= we lazy-lock-cache-end))
|
|
735 ;; Find where we haven't `fontified' before.
|
|
736 (let* ((start (or (text-property-not-all ws we 'fontified t) ws))
|
|
737 (end (or (text-property-any start we 'fontified t) we))
|
|
738 (modified (buffer-modified-p)) (inhibit-read-only t)
|
|
739 ;; We do the following to prevent: undo list addition; region
|
|
740 ;; highlight disappearance; supersession/locking checks.
|
|
741 (buffer-undo-list t)
|
|
742 deactivate-mark buffer-file-name buffer-file-truename
|
|
743 ;; Ensure Emacs 19.30 syntactic fontification is always correct.
|
|
744 font-lock-beginning-of-syntax-function
|
|
745 ;; Prevent XEmacs 19.13 during fontification from messages.
|
|
746 font-lock-verbose)
|
|
747 (while (< start end)
|
|
748 ;; Fontify and flag the region as `fontified'.
|
|
749 ;; XEmacs: need to bind `font-lock-always-fontify-immediately'
|
|
750 ;; or we'll mess up in the presence of deferred font-locking.
|
|
751 (let ((font-lock-always-fontify-immediately t))
|
|
752 (font-lock-after-change-function start end 0))
|
|
753 (lazy-lock-put-text-property start end 'fontified t)
|
|
754 ;; Find the next region.
|
|
755 (setq start (or (text-property-not-all ws we 'fontified t) ws)
|
|
756 end (or (text-property-any start we 'fontified t) we)))
|
|
757 (setq lazy-lock-cache-start ws lazy-lock-cache-end we)
|
|
758 (or modified (set-buffer-modified-p nil))))))
|
|
759
|
|
760 (defun lazy-lock-fontify-walk-windows ()
|
|
761 ;; Fontify windows in all required by walking through them.
|
|
762 (save-excursion
|
|
763 (save-selected-window
|
|
764 (condition-case nil
|
|
765 (walk-windows
|
|
766 (function (lambda (window)
|
|
767 (select-window window)
|
|
768 (if lazy-lock-mode (lazy-lock-fontify-window))))
|
|
769 'no-minibuf (eq lazy-lock-walk-windows 'all-frames))
|
|
770 (wrong-type-argument
|
|
771 ;; Looks like the Emacs 19.28 Garbage Collection bug has hit town.
|
|
772 ;; Completely remove all text properties and restart.
|
|
773 (set-text-properties (point-min) (point-max) nil)
|
|
774 (turn-on-lazy-lock)
|
|
775 (lazy-lock-fontify-window)
|
|
776 (message "Fontifying window... done. (Restarted in %s)"
|
|
777 (buffer-name)))))))
|
|
778
|
|
779 (defun lazy-lock-fontify-stealthily ()
|
|
780 ;; Fontify an invisible part of the buffer where necessary.
|
|
781 (save-excursion
|
|
782 ;; Move to the end in case the character to the left is not `fontified'.
|
|
783 (end-of-line)
|
|
784 ;; Find where the next and previous regions not `fontified' begin and end.
|
|
785 (let ((next (text-property-not-all (point) (point-max) 'fontified t))
|
|
786 (prev (let ((p (previous-single-property-change (point) 'fontified)))
|
|
787 (and p (> p (point-min)) p)))
|
|
788 (modified (buffer-modified-p)) (inhibit-read-only t) start end
|
|
789 ;; We do the following to prevent: undo list addition; region
|
|
790 ;; highlight disappearance; supersession/locking checks.
|
|
791 (buffer-undo-list t)
|
|
792 deactivate-mark buffer-file-name buffer-file-truename
|
|
793 ;; Ensure Emacs 19.30 syntactic fontification is always correct.
|
|
794 font-lock-beginning-of-syntax-function
|
|
795 ;; Prevent XEmacs 19.13 during fontification from spewing messages.
|
|
796 font-lock-verbose)
|
|
797 (cond ((and (null next) (null prev))
|
|
798 ;; Nothing has been `fontified' yet.
|
|
799 (beginning-of-line 1) (setq start (point))
|
|
800 (forward-line (or lazy-lock-stealth-lines (window-height)))
|
|
801 (setq end (point)))
|
|
802 ((or (null prev)
|
|
803 (and next (> (- (point) prev) (- next (point)))))
|
|
804 ;; The next region is the nearest not `fontified'.
|
|
805 (goto-char next) (beginning-of-line 1) (setq start (point))
|
|
806 (forward-line (or lazy-lock-stealth-lines (window-height)))
|
|
807 ;; Maybe the region is already partially `fontified'.
|
|
808 (setq end (or (text-property-any next (point) 'fontified t)
|
|
809 (point))))
|
|
810 (t
|
|
811 ;; The previous region is the nearest not `fontified'.
|
|
812 (goto-char prev) (forward-line 1) (setq end (point))
|
|
813 (forward-line (- (or lazy-lock-stealth-lines (window-height))))
|
|
814 ;; Maybe the region is already partially `fontified'.
|
|
815 (setq start
|
|
816 (or (previous-single-property-change prev 'fontified nil (point))
|
|
817 (point)))))
|
|
818 ;; Fontify and flag the region as `fontified'.
|
|
819 ;; XEmacs: need to bind `font-lock-always-fontify-immediately'
|
|
820 ;; or we'll mess up in the presence of deferred font-locking.
|
|
821 (let ((font-lock-always-fontify-immediately t))
|
|
822 (font-lock-after-change-function start end 0))
|
|
823 (lazy-lock-put-text-property start end 'fontified t)
|
|
824 (or modified (set-buffer-modified-p nil)))))
|
|
825
|
|
826 (defun lazy-lock-fontify-walk-stealthily ()
|
|
827 ;; Fontify regions in all required buffers while there is no input.
|
|
828 (let ((buffers (buffer-list)) (continue t) fontified message-log-max)
|
|
829 (save-excursion
|
|
830 (while (and buffers continue)
|
|
831 (set-buffer (car buffers))
|
|
832 (if (and lazy-lock-mode (lazy-lock-unfontified-p))
|
|
833 ;; Fontify regions in this buffer while there is no input.
|
|
834 (let ((bufname (buffer-name)))
|
|
835 (if (and lazy-lock-stealth-verbose (not fontified))
|
|
836 (message "Fontifying stealthily..."))
|
|
837 ;; We `save-restriction' and `widen' around everything as
|
|
838 ;; `lazy-lock-fontify-stealthily' doesn't and we `sit-for'.
|
|
839 (save-restriction (widen) (lazy-lock-fontify-stealthily))
|
|
840 (while (and (lazy-lock-unfontified-p)
|
|
841 (setq continue (lazy-lock-sit-for
|
|
842 lazy-lock-stealth-nice)))
|
|
843 (if lazy-lock-stealth-verbose
|
|
844 (message "Fontifying stealthily... %2d%% of %s"
|
|
845 (lazy-lock-percent-fontified) bufname))
|
|
846 (save-restriction (widen) (lazy-lock-fontify-stealthily)))
|
|
847 ;; Note that fontification occurred.
|
|
848 (setq fontified t)))
|
|
849 (setq buffers (cdr buffers))))
|
|
850 (if (and lazy-lock-stealth-verbose fontified)
|
|
851 (message "Fontifying stealthily... %s." (if continue "done" "quit")))))
|
|
852
|
|
853 (defun lazy-lock-unfontified-p ()
|
|
854 ;; Return non-nil if there is anywhere still to be `fontified'.
|
|
855 (save-restriction
|
|
856 (widen)
|
|
857 (text-property-not-all (point-min) (point-max) 'fontified t)))
|
|
858
|
|
859 (defun lazy-lock-percent-fontified ()
|
|
860 ;; Return the percentage (of characters) of the buffer that are `fontified'.
|
|
861 (save-restriction
|
|
862 (widen)
|
|
863 (let ((size 0) (start (point-min)) (max (point-max)) end)
|
|
864 (while (setq start (text-property-any start max 'fontified t))
|
|
865 (setq end (or (text-property-not-all start max 'fontified t) max)
|
|
866 size (+ size (- end start))
|
|
867 start end))
|
|
868 ;; Saying "99% done" is probably better than "100% done" when it isn't.
|
|
869 (truncate (/ (* size 100.0) (buffer-size))))))
|
|
870
|
|
871 (defun lazy-lock-colour-invisible ()
|
|
872 ;; Fontify the current buffer in `lazy-lock-invisible-face'.
|
|
873 (save-restriction
|
|
874 (widen)
|
|
875 (let ((face 'lazy-lock-invisible-face)
|
|
876 (fore (if (stringp lazy-lock-invisible-foreground)
|
|
877 lazy-lock-invisible-foreground
|
|
878 (cdr (assq 'background-color (frame-parameters)))))
|
|
879 (modified (buffer-modified-p)) (inhibit-read-only t)
|
|
880 (buffer-undo-list t)
|
|
881 deactivate-mark buffer-file-name buffer-file-truename)
|
|
882 (make-face face)
|
|
883 (if (not (equal (face-foreground face) fore))
|
|
884 (condition-case nil
|
|
885 (set-face-foreground face fore)
|
|
886 (error (message "Unable to use foreground \"%s\"" fore))))
|
|
887 (lazy-lock-put-text-property (point-min) (point-max) 'face face)
|
|
888 (lazy-lock-put-text-property (point-min) (point-max) 'fontified nil)
|
|
889 (or modified (set-buffer-modified-p nil)))))
|
|
890
|
|
891 ;; Functions for Emacs:
|
|
892
|
|
893 ;; This fix is for a number of bugs in the function in Emacs 19.28.
|
|
894 (if (and (not lazy-lock-running-xemacs-p)
|
|
895 (not (emacs-version>= 19 29)))
|
|
896 (defun font-lock-fontify-region (start end &optional loudly)
|
|
897 "Put proper face on each string and comment between START and END."
|
|
898 (save-excursion
|
|
899 (save-restriction
|
|
900 (widen)
|
|
901 (goto-char start)
|
|
902 (beginning-of-line)
|
|
903 (if loudly (message "Fontifying %s... (syntactically...)" (buffer-name)))
|
|
904 (let ((inhibit-read-only t) (buffer-undo-list t)
|
|
905 buffer-file-name buffer-file-truename
|
|
906 (modified (buffer-modified-p))
|
|
907 (old-syntax (syntax-table))
|
|
908 (synstart (if comment-start-skip
|
|
909 (concat "\\s\"\\|" comment-start-skip)
|
|
910 "\\s\""))
|
|
911 (comstart (if comment-start-skip
|
|
912 (concat "\\s<\\|" comment-start-skip)
|
|
913 "\\s<"))
|
|
914 (startline (point))
|
|
915 state prev prevstate)
|
|
916 (unwind-protect
|
|
917 (progn
|
|
918 (if font-lock-syntax-table
|
|
919 (set-syntax-table font-lock-syntax-table))
|
|
920 ;; Find the state at the line-beginning before START.
|
|
921 (if (eq startline font-lock-cache-position)
|
|
922 (setq state font-lock-cache-state)
|
|
923 ;; Find outermost containing sexp.
|
|
924 (beginning-of-defun)
|
|
925 ;; Find the state at STARTLINE.
|
|
926 (while (< (point) startline)
|
|
927 (setq state (parse-partial-sexp (point) startline 0)))
|
|
928 (setq font-lock-cache-state state
|
|
929 font-lock-cache-position (point)))
|
|
930 ;; Now find the state precisely at START.
|
|
931 (setq state (parse-partial-sexp (point) start nil nil state))
|
|
932 ;; If the region starts inside a string, show the extent of it.
|
|
933 (if (nth 3 state)
|
|
934 (let ((beg (point)))
|
|
935 (while (and (re-search-forward "\\s\"" end 'move)
|
|
936 (nth 3 (parse-partial-sexp beg (point) nil nil
|
|
937 state))))
|
|
938 (lazy-lock-put-text-property
|
|
939 beg (point) 'face font-lock-string-face)
|
|
940 (setq state (parse-partial-sexp beg (point)
|
|
941 nil nil state))))
|
|
942 ;; Likewise for a comment.
|
|
943 (if (or (nth 4 state) (nth 7 state))
|
|
944 (let ((beg (point)))
|
|
945 (save-restriction
|
|
946 (narrow-to-region (point-min) end)
|
|
947 (condition-case nil
|
|
948 (progn
|
|
949 (re-search-backward comstart (point-min) 'move)
|
|
950 (forward-comment 1)
|
|
951 ;; forward-comment skips all whitespace,
|
|
952 ;; so go back to the real end of the comment.
|
|
953 (skip-chars-backward " \t"))
|
|
954 (error (goto-char end))))
|
|
955 (lazy-lock-put-text-property beg (point) 'face
|
|
956 font-lock-comment-face)
|
|
957 (setq state (parse-partial-sexp beg (point)
|
|
958 nil nil state))))
|
|
959 ;; Find each interesting place between here and END.
|
|
960 (while (and (< (point) end)
|
|
961 (setq prev (point) prevstate state)
|
|
962 (re-search-forward synstart end t)
|
|
963 (progn
|
|
964 ;; Clear out the fonts of what we skip over.
|
|
965 (remove-text-properties prev (point) '(face nil))
|
|
966 ;; Verify the state at that place
|
|
967 ;; so we don't get fooled by \" or \;.
|
|
968 (setq state (parse-partial-sexp prev (point)
|
|
969 nil nil state))))
|
|
970 (let ((here (point)))
|
|
971 (if (or (nth 4 state) (nth 7 state))
|
|
972 ;; We found a real comment start.
|
|
973 (let ((beg (match-beginning 0)))
|
|
974 (goto-char beg)
|
|
975 (save-restriction
|
|
976 (narrow-to-region (point-min) end)
|
|
977 (condition-case nil
|
|
978 (progn
|
|
979 (forward-comment 1)
|
|
980 ;; forward-comment skips all whitespace,
|
|
981 ;; so go back to the real end of the comment.
|
|
982 (skip-chars-backward " \t"))
|
|
983 (error (goto-char end))))
|
|
984 (lazy-lock-put-text-property
|
|
985 beg (point) 'face font-lock-comment-face)
|
|
986 (setq state (parse-partial-sexp here (point)
|
|
987 nil nil state)))
|
|
988 (if (nth 3 state)
|
|
989 (let ((beg (match-beginning 0)))
|
|
990 (while (and (re-search-forward "\\s\"" end 'move)
|
|
991 (nth 3 (parse-partial-sexp
|
|
992 here (point) nil nil state))))
|
|
993 (lazy-lock-put-text-property
|
|
994 beg (point) 'face font-lock-string-face)
|
|
995 (setq state (parse-partial-sexp here (point)
|
|
996 nil nil state))))))
|
|
997 ;; Make sure PREV is non-nil after the loop
|
|
998 ;; only if it was set on the very last iteration.
|
|
999 (setq prev nil)))
|
|
1000 (set-syntax-table old-syntax)
|
|
1001 (and prev
|
|
1002 (remove-text-properties prev end '(face nil)))
|
|
1003 (and (buffer-modified-p)
|
|
1004 (not modified)
|
|
1005 (set-buffer-modified-p nil))))))))
|
|
1006
|
|
1007 ;; Functions for XEmacs:
|
|
1008
|
|
1009 ;; These fix bugs in `text-property-any' and `text-property-not-all'. They may
|
|
1010 ;; not work perfectly in 19.11 and below because `next-single-property-change'
|
|
1011 ;; is also broke and not easily fixable in Lisp.
|
|
1012 (if (and lazy-lock-running-xemacs-p
|
|
1013 (not (emacs-version>= 19 12)))
|
|
1014 (progn
|
|
1015 ;; Loop through property changes until found. This fix includes a work
|
|
1016 ;; around which prevents a bug in `window-start' causing a barf here.
|
|
1017 (defun text-property-any (start end prop value &optional buffer)
|
|
1018 "Check text from START to END to see if PROP is ever `eq' to VALUE.
|
|
1019 If so, return the position of the first character whose PROP is `eq'
|
|
1020 to VALUE. Otherwise return nil."
|
|
1021 (let ((start (min start end)) (end (max start end)))
|
|
1022 (while (and start (not (eq (get-text-property start prop buffer) value)))
|
|
1023 (setq start (next-single-property-change start prop buffer end)))
|
|
1024 start))
|
|
1025 ;; No need to loop here; if it's not at START it's at the next change.
|
|
1026 ;; However, `next-single-property-change' sometimes returns LIMIT, or
|
|
1027 ;; `point-max', if no change is found and sometimes returns nil.
|
|
1028 (defun text-property-not-all (start end prop value &optional buffer)
|
|
1029 "Check text from START to END to see if PROP is ever not `eq' to VALUE.
|
|
1030 If so, return the position of the first character whose PROP is not
|
|
1031 `eq' to VALUE. Otherwise, return nil."
|
|
1032 (if (not (eq value (get-text-property start prop buffer)))
|
|
1033 start
|
|
1034 (let ((next (next-single-property-change start prop buffer end))
|
|
1035 (end (or end (save-excursion (and buffer (set-buffer buffer))
|
|
1036 (point-max)))))
|
|
1037 (and next (< next end) next))))))
|
|
1038
|
|
1039 ;; XEmacs 19.11 function `font-lock-any-extents-p' looks for `text-prop' rather
|
|
1040 ;; than `face'. Since `font-lock-unfontify-region' only removes `face', and we
|
|
1041 ;; have non-font-lock properties hanging about, `text-prop' never gets removed.
|
|
1042 ;; Unfortunately `font-lock-any-extents-p' is inlined so we can't redefine it.
|
|
1043 (if (and lazy-lock-running-xemacs-p
|
|
1044 (not (emacs-version>= 19 12)))
|
|
1045 (add-hook 'font-lock-mode-hook
|
|
1046 (function (lambda ()
|
|
1047 (remove-hook 'after-change-functions 'font-lock-after-change-function)
|
|
1048 (add-hook 'after-change-functions
|
|
1049 (function (lambda (beg end old-len)
|
|
1050 (let ((a-c-beg beg) (a-c-end end))
|
|
1051 (save-excursion
|
|
1052 ;; First set `text-prop' to nil for `font-lock-any-extents-p'.
|
|
1053 (goto-char end) (forward-line 1) (setq end (point))
|
|
1054 (goto-char beg) (beginning-of-line) (setq beg (point))
|
|
1055 (lazy-lock-put-text-property beg end 'text-prop nil)
|
|
1056 ;; Then do the real `font-lock-after-change-function'.
|
|
1057 (font-lock-after-change-function a-c-beg a-c-end old-len)
|
|
1058 ;; Now set `fontified' to t to stop `lazy-lock-fontify-window'.
|
|
1059 (lazy-lock-put-text-property beg end 'fontified t))))))))))
|
|
1060
|
|
1061 (if (and lazy-lock-running-xemacs-p (emacs-version>= 19 12))
|
|
1062 ;; XEmacs 19.12 font-lock.el's `font-lock-fontify-buffer' runs a hook.
|
|
1063 (add-hook 'font-lock-after-fontify-buffer-hook
|
|
1064 'lazy-lock-after-fontify-buffer))
|
|
1065
|
|
1066 ;; Cope with the differences between Emacs and [LX]Emacs.
|
|
1067 (or (fboundp 'frame-parameters)
|
|
1068 (defalias 'frame-parameters 'screen-parameters))
|
|
1069
|
|
1070 ;; Install ourselves:
|
|
1071
|
|
1072 ;; We don't install ourselves on `font-lock-mode-hook' as other packages can be
|
|
1073 ;; used with font-lock.el, and lazy-lock.el should be dumpable without forcing
|
|
1074 ;; people to get lazy or making it difficult for people to use alternatives.
|
|
1075 ;; make sure we add after font-lock's own pre-idle-hook.
|
|
1076 (add-hook 'window-setup-hook 'lazy-lock-post-setup-emacs-fontify-windows)
|
|
1077 ;Not needed in XEmacs 19.14:
|
|
1078 ;(add-hook 'window-size-change-functions 'lazy-lock-post-resize-fontify-windows)
|
|
1079
|
|
1080 ;; Package-specific.
|
|
1081 (add-hook 'ediff-after-setup-control-frame-hooks
|
|
1082 'lazy-lock-post-setup-ediff-control-frame)
|
|
1083
|
|
1084 ;; Might as well uninstall too. Package-local symbols would be nice...
|
|
1085 (and (fboundp 'unintern) (unintern 'lazy-lock-running-xemacs-p))
|
|
1086 (and (fboundp 'unintern) (unintern 'lazy-lock-sit-for))
|
|
1087
|
|
1088 ;; Maybe save on the modeline?
|
|
1089 ;;(setcdr (assq 'font-lock-mode minor-mode-alist) '(" Lazy"))
|
|
1090
|
|
1091 ;(or (assq 'lazy-lock-mode minor-mode-alist)
|
|
1092 ; (setq minor-mode-alist (cons '(lazy-lock-mode " Lazy") minor-mode-alist)))
|
|
1093
|
|
1094 ;; XEmacs change: do it the right way. This works with modeline mousing.
|
|
1095 ;;;###autoload
|
|
1096 (add-minor-mode 'lazy-lock-mode " Lazy")
|
|
1097
|
|
1098 ;; Provide ourselves:
|
|
1099
|
|
1100 (provide 'lazy-lock)
|
|
1101
|
|
1102 ;;; lazy-lock.el ends here
|