Mercurial > hg > xemacs-beta
comparison lisp/packages/lazy-lock.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | ac2d302a0011 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
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 |