diff options
| author | Richard M. Stallman | 1996-06-19 23:14:13 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1996-06-19 23:14:13 +0000 |
| commit | 2eb9703d6b4bd5688e2253bfe019e3ce0f2aeb12 (patch) | |
| tree | da8ff51b0539290dd4d4a6c61a3356f681bd73b1 | |
| parent | 5a6816daacc3e7c9becacec7588f91c418e08683 (diff) | |
| download | emacs-2eb9703d6b4bd5688e2253bfe019e3ce0f2aeb12.tar.gz emacs-2eb9703d6b4bd5688e2253bfe019e3ce0f2aeb12.zip | |
Initial revision
| -rw-r--r-- | lisp/lazy-lock.el | 829 |
1 files changed, 829 insertions, 0 deletions
diff --git a/lisp/lazy-lock.el b/lisp/lazy-lock.el new file mode 100644 index 00000000000..e93fd314d84 --- /dev/null +++ b/lisp/lazy-lock.el | |||
| @@ -0,0 +1,829 @@ | |||
| 1 | ;;; lazy-lock.el --- Lazy demand-driven fontification for fast Font Lock mode. | ||
| 2 | |||
| 3 | ;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Simon Marshall <simon@gnu.ai.mit.edu> | ||
| 6 | ;; Keywords: faces files | ||
| 7 | ;; Version: 2.05 | ||
| 8 | |||
| 9 | ;;; This file is part of GNU Emacs. | ||
| 10 | |||
| 11 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 12 | ;; it under the terms of the GNU General Public License as published by | ||
| 13 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 14 | ;; any later version. | ||
| 15 | |||
| 16 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | ;; GNU General Public License for more details. | ||
| 20 | |||
| 21 | ;; You should have received a copy of the GNU General Public License | ||
| 22 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 23 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 24 | ;; Boston, MA 02111-1307, USA. | ||
| 25 | |||
| 26 | ;;; Commentary: | ||
| 27 | |||
| 28 | ;; Purpose: | ||
| 29 | ;; | ||
| 30 | ;; To make visiting buffers in `font-lock-mode' faster by making fontification | ||
| 31 | ;; be demand-driven, deferred and stealthy. | ||
| 32 | ;; Fontification only occurs when, and where, necessary. | ||
| 33 | ;; | ||
| 34 | ;; See caveats and feedback below. | ||
| 35 | ;; See also the fast-lock package. (But don't use them at the same time!) | ||
| 36 | |||
| 37 | ;; Installation: | ||
| 38 | ;; | ||
| 39 | ;; Put in your ~/.emacs: | ||
| 40 | ;; | ||
| 41 | ;; (autoload 'turn-on-lazy-lock "lazy-lock" | ||
| 42 | ;; "Unconditionally turn on Lazy Lock mode.") | ||
| 43 | ;; | ||
| 44 | ;; (add-hook 'font-lock-mode-hook 'turn-on-lazy-lock) | ||
| 45 | ;; | ||
| 46 | ;; Start up a new Emacs and use font-lock as usual (except that you can use the | ||
| 47 | ;; so-called "gaudier" fontification regexps on big files without frustration). | ||
| 48 | ;; | ||
| 49 | ;; In a buffer (which has `font-lock-mode' enabled) which is at least | ||
| 50 | ;; `lazy-lock-minimum-size' characters long, buffer fontification will not | ||
| 51 | ;; occur and only the visible portion of the buffer will be fontified. Motion | ||
| 52 | ;; around the buffer will fontify those visible portions not previously | ||
| 53 | ;; fontified. If stealth fontification is enabled, buffer fontification will | ||
| 54 | ;; occur in invisible parts of the buffer after `lazy-lock-stealth-time' | ||
| 55 | ;; seconds of idle time. If on-the-fly fontification is deferred, on-the-fly | ||
| 56 | ;; fontification will occur after `lazy-lock-defer-time' seconds of idle time. | ||
| 57 | |||
| 58 | ;; User-visible differences with version 1: | ||
| 59 | ;; | ||
| 60 | ;; - Version 2 can defer on-the-fly fontification. Therefore you need not, and | ||
| 61 | ;; should not, use defer-lock.el with this version of lazy-lock.el. | ||
| 62 | ;; | ||
| 63 | ;; A number of variables have changed meaning: | ||
| 64 | ;; | ||
| 65 | ;; - A value of nil for the variable `lazy-lock-minimum-size' means never turn | ||
| 66 | ;; on demand-driven fontification. In version 1 this meant always turn on | ||
| 67 | ;; demand-driven fontification. If you really want demand-driven fontification | ||
| 68 | ;; regardless of buffer size, set this variable to 0. | ||
| 69 | ;; | ||
| 70 | ;; - The variable `lazy-lock-stealth-lines' cannot have a nil value. In | ||
| 71 | ;; version 1 this meant use `window-height' as the maximum number of lines to | ||
| 72 | ;; fontify as a stealth chunk. This makes no sense; stealth fontification is | ||
| 73 | ;; of a buffer, not a window. | ||
| 74 | |||
| 75 | ;; Implementation differences with version 1: | ||
| 76 | ;; | ||
| 77 | ;; - Version 1 of lazy-lock.el is a bit of a hack. Version 1 demand-driven | ||
| 78 | ;; fontification, the core feature of lazy-lock.el, is implemented by placing a | ||
| 79 | ;; function on `post-command-hook'. This function fontifies where necessary, | ||
| 80 | ;; i.e., where a window scroll has occurred. However, there are a number of | ||
| 81 | ;; problems with using `post-command-hook': | ||
| 82 | ;; | ||
| 83 | ;; (a) As the name suggests, `post-command-hook' is run after every command, | ||
| 84 | ;; i.e., frequently and regardless of whether scrolling has occurred. | ||
| 85 | ;; (b) Scrolling can occur during a command, when `post-command-hook' is not | ||
| 86 | ;; run, i.e., it is not necessarily run after scrolling has occurred. | ||
| 87 | ;; (c) When `post-command-hook' is run, there is nothing to suggest where | ||
| 88 | ;; scrolling might have occurred, i.e., which windows have scrolled. | ||
| 89 | ;; | ||
| 90 | ;; Thus lazy-lock.el's function is called almost as often as possible, usually | ||
| 91 | ;; when it need not be called, yet it is not always called when it is needed. | ||
| 92 | ;; Also, lazy-lock.el's function must check each window to see if a scroll has | ||
| 93 | ;; occurred there. Worse still, lazy-lock.el's function must fontify a region | ||
| 94 | ;; twice as large as necessary to make sure the window is completely fontified. | ||
| 95 | ;; Basically, `post-command-hook' is completely inappropriate for lazy-lock.el. | ||
| 96 | ;; | ||
| 97 | ;; Ideally, we want to attach lazy-lock.el's function to a hook that is run | ||
| 98 | ;; only when scrolling occurs, e.g., `window-start' has changed, and tells us | ||
| 99 | ;; as much information as we need, i.e., the window and its new buffer region. | ||
| 100 | ;; Richard Stallman implemented a `window-scroll-functions' for Emacs 19.30. | ||
| 101 | ;; Functions on it are run when `window-start' has changed, and are supplied | ||
| 102 | ;; with the window and the window's new `window-start' position. (It would be | ||
| 103 | ;; better if it also supplied the window's new `window-end' position, but that | ||
| 104 | ;; is calculated as part of the redisplay process, and the functions on | ||
| 105 | ;; `window-scroll-functions' are run before redisplay has finished.) Thus, the | ||
| 106 | ;; hook deals with the above problems (a), (b) and (c). | ||
| 107 | ;; | ||
| 108 | ;; If only life was that easy. Version 2 demand-driven fontification is mostly | ||
| 109 | ;; implemented by placing a function on `window-scroll-functions'. However, | ||
| 110 | ;; not all scrolling occurs when `window-start' has changed. A change in | ||
| 111 | ;; window size, e.g., via C-x 1, or a significant deletion, e.g., of a number | ||
| 112 | ;; of lines, causes `window-end' to change without changing `window-start'. | ||
| 113 | ;; Arguably, these events are not scrolling events, but fontification must | ||
| 114 | ;; occur for lazy-lock.el to work. Hooks `window-size-change-functions' and | ||
| 115 | ;; `redisplay-end-trigger-functions' were added for these circumstances. | ||
| 116 | ;; | ||
| 117 | ;; Ben Wing thinks these hooks are "horribly horribly kludgy", and implemented | ||
| 118 | ;; a `pre-idle-hook', a `mother-of-all-post-command-hooks', for XEmacs 19.14. | ||
| 119 | ;; He then hacked up a version 1 lazy-lock.el to use `pre-idle-hook' rather | ||
| 120 | ;; than `post-command-hook'. Whereas functions on `post-command-hook' are | ||
| 121 | ;; called almost as often as possible, functions on `pre-idle-hook' really are | ||
| 122 | ;; called as often as possible, even when the mouse moves and, on some systems, | ||
| 123 | ;; while XEmacs is idle. Thus, the hook deals with the above problem (b), but | ||
| 124 | ;; unfortunately it makes (a) worse and does not address (c) at all. | ||
| 125 | ;; | ||
| 126 | ;; I freely admit that `redisplay-end-trigger-functions' and, to a much lesser | ||
| 127 | ;; extent, `window-size-change-functions' are not pretty. However, I feel that | ||
| 128 | ;; a `window-scroll-functions' feature is cleaner than a `pre-idle-hook', and | ||
| 129 | ;; the result is faster and smaller, less intrusive and more targeted, code. | ||
| 130 | ;; Since `pre-idle-hook' is pretty much like `post-command-hook', there is no | ||
| 131 | ;; point in making this version of lazy-lock.el work with it. Anyway, that's | ||
| 132 | ;; Lit 30 of my humble opinion. | ||
| 133 | ;; | ||
| 134 | ;; - Version 1 stealth fontification is also implemented by placing a function | ||
| 135 | ;; on `post-command-hook'. This function waits for a given amount of time, | ||
| 136 | ;; and, if Emacs remains idle, fontifies where necessary. Again, there are a | ||
| 137 | ;; number of problems with using `post-command-hook': | ||
| 138 | ;; | ||
| 139 | ;; (a) Functions on `post-command-hook' are run sequentially, so this function | ||
| 140 | ;; can interfere with other functions on the hook, and vice versa. | ||
| 141 | ;; (b) This function waits for a given amount of time, so it can interfere with | ||
| 142 | ;; various features that are dealt with by Emacs after a command, e.g., | ||
| 143 | ;; region highlighting, asynchronous updating and keystroke echoing. | ||
| 144 | ;; (c) Fontification may be required during a command, when `post-command-hook' | ||
| 145 | ;; is not run. (Version 2 deferred fontification only.) | ||
| 146 | ;; | ||
| 147 | ;; Again, `post-command-hook' is completely inappropriate for lazy-lock.el. | ||
| 148 | ;; Richard Stallman and Morten Welinder implemented internal Timers and Idle | ||
| 149 | ;; Timers for Emacs 19.31. Functions can be run independently at given times | ||
| 150 | ;; or after given amounts of idle time. Thus, the feature deals with the above | ||
| 151 | ;; problems (a), (b) and (c). Version 2 deferral and stealth are implemented | ||
| 152 | ;; by functions on Idle Timers. (A function on XEmacs' `pre-idle-hook' is | ||
| 153 | ;; similar to an Emacs Idle Timer function with a fixed zero second timeout. | ||
| 154 | ;; Hey, maybe I could stop using `window-scroll-functions' for demand-driven | ||
| 155 | ;; fontification and use a zero second Emacs Idle Timer instead? Only joking!) | ||
| 156 | |||
| 157 | ;; Caveats: | ||
| 158 | ;; | ||
| 159 | ;; Lazy Lock mode does not work efficiently with Outline mode. This is because | ||
| 160 | ;; when in Outline mode, although text may be hidden (not visible in the | ||
| 161 | ;; window), the text is visible to Emacs Lisp code (not surprisingly) and Lazy | ||
| 162 | ;; Lock fontifies it mercilessly. Hopefully this will be fixed one day. | ||
| 163 | ;; | ||
| 164 | ;; Because buffer text is not necessarily fontified, other packages that expect | ||
| 165 | ;; buffer text to be fontified in Font Lock mode either might not work as | ||
| 166 | ;; expected, or might not display buffer text as expected. An example of the | ||
| 167 | ;; latter is `occur', which copies lines of buffer text into another buffer. | ||
| 168 | ;; | ||
| 169 | ;; In Emacs 19.30, Lazy Lock mode does not ensure that an existing buffer is | ||
| 170 | ;; fontified if it is made visible via a minibuffer-less command that replaces | ||
| 171 | ;; an existing window's buffer (e.g., via the Buffers menu). Upgrade! | ||
| 172 | ;; | ||
| 173 | ;; In Emacs 19.30, Lazy Lock mode does not work well with Transient Mark mode | ||
| 174 | ;; or modes based on Comint mode (e.g., Shell mode), and also interferes with | ||
| 175 | ;; the echoing of keystrokes in the minibuffer. This is because of the way | ||
| 176 | ;; deferral and stealth have to be implemented for Emacs 19.30. Upgrade! | ||
| 177 | ;; | ||
| 178 | ;; Currently XEmacs does not have the features to support lazy-lock.el. Maybe | ||
| 179 | ;; it will one day. | ||
| 180 | |||
| 181 | ;; Feedback: | ||
| 182 | ;; | ||
| 183 | ;; Feedback is welcome. | ||
| 184 | ;; To submit a bug report (or make comments) please use the mechanism provided: | ||
| 185 | ;; | ||
| 186 | ;; M-x lazy-lock-submit-bug-report RET | ||
| 187 | |||
| 188 | ;; History: | ||
| 189 | ;; | ||
| 190 | ;; 1.15--2.00: | ||
| 191 | ;; - Rewrite for Emacs 19.30 and the features rms added to support lazy-lock.el | ||
| 192 | ;; so that it could work correctly and efficiently. | ||
| 193 | ;; - Many thanks to those who reported bugs, fixed bugs, made suggestions or | ||
| 194 | ;; otherwise contributed in the version 1 cycle; Jari Aalto, Kevin Broadey, | ||
| 195 | ;; Ulrik Dickow, Bill Dubuque, Bob Glickstein, Boris Goldowsky, | ||
| 196 | ;; Jonas Jarnestrom, David Karr, Michael Kifer, Erik Naggum, Rick Sladkey, | ||
| 197 | ;; Jim Thompson, Ben Wing, Ilya Zakharevich, and Richard Stallman. | ||
| 198 | ;; 2.00--2.01: | ||
| 199 | ;; - Made `lazy-lock-fontify-after-command' always `sit-for' and so redisplay | ||
| 200 | ;; - Use `buffer-name' not `buffer-live-p' (Bill Dubuque hint) | ||
| 201 | ;; - Made `lazy-lock-install' do `add-to-list' not `setq' of `current-buffer' | ||
| 202 | ;; - Made `lazy-lock-fontify-after-install' loop over buffer list | ||
| 203 | ;; - Made `lazy-lock-arrange-before-change' to arrange `window-end' triggering | ||
| 204 | ;; - Made `lazy-lock-let-buffer-state' wrap both `befter-change-functions' | ||
| 205 | ;; - Made `lazy-lock-fontify-region' do `condition-case' (Hyman Rosen report) | ||
| 206 | ;; 2.01--2.02: | ||
| 207 | ;; - Use `buffer-live-p' as `buffer-name' can barf (Richard Stanton report) | ||
| 208 | ;; - Made `lazy-lock-install' set `font-lock-fontified' (Kevin Davidson report) | ||
| 209 | ;; - Made `lazy-lock-install' add hooks only if needed | ||
| 210 | ;; - Made `lazy-lock-unstall' add `font-lock-after-change-function' if needed | ||
| 211 | ;; 2.02--2.03: | ||
| 212 | ;; - Made `lazy-lock-fontify-region' do `condition-case' for `quit' too | ||
| 213 | ;; - Made `lazy-lock-mode' respect the value of `font-lock-inhibit-thing-lock' | ||
| 214 | ;; - Added `lazy-lock-after-unfontify-buffer' | ||
| 215 | ;; - Removed `lazy-lock-fontify-after-install' hack | ||
| 216 | ;; - Made `lazy-lock-fontify-after-scroll' not `set-buffer' to `window-buffer' | ||
| 217 | ;; - Made `lazy-lock-fontify-after-trigger' not `set-buffer' to `window-buffer' | ||
| 218 | ;; - Made `lazy-lock-fontify-after-idle' be interruptible (Scott Burson hint) | ||
| 219 | ;; 2.03--2.04: | ||
| 220 | ;; - Rewrite for Emacs 19.31 idle timers | ||
| 221 | ;; - Renamed `buffer-windows' to `get-buffer-window-list' | ||
| 222 | ;; - Removed `buffer-live-p' | ||
| 223 | ;; - Made `lazy-lock-defer-after-change' always save `current-buffer' | ||
| 224 | ;; - Made `lazy-lock-fontify-after-defer' just process buffers | ||
| 225 | ;; - Made `lazy-lock-install-hooks' add hooks correctly (Kevin Broadey report) | ||
| 226 | ;; - Made `lazy-lock-install' cope if `lazy-lock-defer-time' is a list | ||
| 227 | ;; 2.04--2.05: | ||
| 228 | ;; - Rewrite for Common Lisp macros | ||
| 229 | ;; - Added `do-while' macro | ||
| 230 | ;; - Renamed `lazy-lock-let-buffer-state' macro to `save-buffer-state' | ||
| 231 | ;; - Returned `lazy-lock-fontify-after-install' hack (Darren Hall hint) | ||
| 232 | ;; - Added `lazy-lock-defer-driven' functionality (Scott Byer hint) | ||
| 233 | ;; - Made `lazy-lock-mode' wrap `font-lock-support-mode' | ||
| 234 | |||
| 235 | (require 'font-lock) | ||
| 236 | |||
| 237 | ;; Make sure lazy-lock.el is supported. | ||
| 238 | (if (if (save-match-data (string-match "Lucid\\|XEmacs" (emacs-version))) | ||
| 239 | t | ||
| 240 | (and (= emacs-major-version 19) (< emacs-minor-version 30))) | ||
| 241 | (error "`lazy-lock' was written for Emacs 19.30 or later")) | ||
| 242 | |||
| 243 | ;; Flush out those lusers who didn't read all of the Commentary. | ||
| 244 | (if (or (memq 'turn-on-defer-lock font-lock-mode-hook) | ||
| 245 | (memq 'defer-lock-mode font-lock-mode-hook)) | ||
| 246 | (error "`lazy-lock' was written for use without `defer-lock'")) | ||
| 247 | |||
| 248 | (eval-when-compile | ||
| 249 | ;; | ||
| 250 | ;; We don't do this at the top-level as idle timers are not necessarily used. | ||
| 251 | (require 'timer) | ||
| 252 | ;; We don't do this at the top-level as we only use non-autoloaded macros. | ||
| 253 | (require 'cl) | ||
| 254 | ;; | ||
| 255 | ;; Well, shouldn't Lazy Lock mode be as lazy as possible? | ||
| 256 | (setq byte-compile-dynamic t byte-compile-dynamic-docstrings t) | ||
| 257 | ;; But, we make sure that the code is as zippy as can be. | ||
| 258 | (setq byte-optimize t) | ||
| 259 | ;; | ||
| 260 | ;; We use this to preserve or protect things when modifying text properties. | ||
| 261 | (defmacro save-buffer-state (varlist &rest body) | ||
| 262 | "Bind variables according to VARLIST and eval BODY restoring buffer state." | ||
| 263 | (` (let* ((,@ (append varlist | ||
| 264 | '((modified (buffer-modified-p)) | ||
| 265 | (inhibit-read-only t) (buffer-undo-list t) | ||
| 266 | before-change-functions after-change-functions | ||
| 267 | deactivate-mark buffer-file-name buffer-file-truename)))) | ||
| 268 | (,@ body) | ||
| 269 | (when (and (not modified) (buffer-modified-p)) | ||
| 270 | (set-buffer-modified-p nil))))) | ||
| 271 | (put 'save-buffer-state 'lisp-indent-function 1) | ||
| 272 | ;; | ||
| 273 | ;; We use this for clarity and speed. Naughty but nice. | ||
| 274 | (defmacro do-while (test &rest body) | ||
| 275 | "(do-while TEST BODY...): eval BODY... and repeat if TEST yields non-nil. | ||
| 276 | The order of execution is thus BODY, TEST, BODY, TEST and so on | ||
| 277 | until TEST returns nil." | ||
| 278 | (` (while (progn (,@ body) (, test))))) | ||
| 279 | (put 'do-while 'lisp-indent-function (get 'while 'lisp-indent-function))) | ||
| 280 | |||
| 281 | ;; User Variables: | ||
| 282 | |||
| 283 | (defvar lazy-lock-minimum-size (* 25 1024) | ||
| 284 | "*Minimum size of a buffer for demand-driven fontification. | ||
| 285 | On-demand fontification occurs if the buffer size is greater than this value. | ||
| 286 | If nil, means demand-driven fontification is never performed. | ||
| 287 | If a list, each element should be a cons pair of the form (MAJOR-MODE . SIZE), | ||
| 288 | where MAJOR-MODE is a symbol or t (meaning the default). For example: | ||
| 289 | ((c-mode . 25600) (c++-mode . 25600) (rmail-mode . 1048576)) | ||
| 290 | means that the minimum size is 25K for buffers in C or C++ modes, one megabyte | ||
| 291 | for buffers in Rmail mode, and size is irrelevant otherwise. | ||
| 292 | |||
| 293 | The value of this variable is used when Lazy Lock mode is turned on.") | ||
| 294 | |||
| 295 | (defvar lazy-lock-defer-driven nil | ||
| 296 | "*If non-nil, means fontification should be defer-driven. | ||
| 297 | If nil, means demand-driven fontification is performed. This means when the | ||
| 298 | window scrolls into unfontified areas of the buffer, those areas are | ||
| 299 | immediately fontified. Thus scrolling never presents unfontified areas. | ||
| 300 | However, since fontification occurs during scrolling, scrolling may be slow. | ||
| 301 | If t, means defer-driven fontification is performed. This means fontification | ||
| 302 | of those areas is deferred. Thus scrolling may present momentarily unfontified | ||
| 303 | areas. However, since fontification does not occur during scrolling, scrolling | ||
| 304 | will be faster than demand-driven fontification. | ||
| 305 | If non-nil and non-t, means buffer demand-driven fontification is performed | ||
| 306 | until the buffer is fontified, then buffer fontification becomes defer-driven. | ||
| 307 | Thus scrolling never presents unfontified areas until the buffer is fontified, | ||
| 308 | at which point subsequent scrolling may present future buffer insertions | ||
| 309 | momentarily unfontified. However, since fontification does not occur during | ||
| 310 | scrolling once the buffer is fontified, scrolling will become faster. | ||
| 311 | |||
| 312 | The value of this variable is used when Lazy Lock mode is turned on.") | ||
| 313 | |||
| 314 | (defvar lazy-lock-defer-time | ||
| 315 | (if (featurep 'lisp-float-type) (/ (float 1) (float 4)) 1) | ||
| 316 | "*Time in seconds to delay before beginning deferred fontification. | ||
| 317 | Deferred fontification occurs if there is no input within this time. | ||
| 318 | If nil, means fontification is never deferred. However, fontification occurs | ||
| 319 | on-the-fly or during scrolling, which may be slow. | ||
| 320 | If a list, it should be of the form (MAJOR-MODES . TIME), where MAJOR-MODES is | ||
| 321 | a list of `major-mode' symbols for which deferred fontification should occur. | ||
| 322 | The sense of the list is negated if it begins with `not'. For example: | ||
| 323 | ((c-mode c++-mode) . 0.25) | ||
| 324 | means that the deferral time is 0.25s for buffers in C or C++ modes, and | ||
| 325 | deferral does not occur otherwise. | ||
| 326 | |||
| 327 | The value of this variable is used when Lazy Lock mode is turned on.") | ||
| 328 | |||
| 329 | (defvar lazy-lock-stealth-time 30 | ||
| 330 | "*Time in seconds to delay before beginning stealth fontification. | ||
| 331 | Stealth fontification occurs if there is no input within this time. | ||
| 332 | If nil, means stealth fontification is never performed. | ||
| 333 | |||
| 334 | The value of this variable is used when Lazy Lock mode is turned on.") | ||
| 335 | |||
| 336 | (defvar lazy-lock-stealth-lines (if font-lock-maximum-decoration 100 200) | ||
| 337 | "*Maximum size of a chunk of stealth fontification. | ||
| 338 | Each iteration of stealth fontification can fontify this number of lines. | ||
| 339 | To speed up input response during stealth fontification, at the cost of stealth | ||
| 340 | taking longer to fontify, you could reduce the value of this variable.") | ||
| 341 | |||
| 342 | (defvar lazy-lock-stealth-nice | ||
| 343 | (if (featurep 'lisp-float-type) (/ (float 1) (float 8)) 1) | ||
| 344 | "*Time in seconds to pause between chunks of stealth fontification. | ||
| 345 | Each iteration of stealth fontification is separated by this amount of time. | ||
| 346 | To reduce machine load during stealth fontification, at the cost of stealth | ||
| 347 | taking longer to fontify, you could increase the value of this variable.") | ||
| 348 | |||
| 349 | (defvar lazy-lock-stealth-verbose font-lock-verbose | ||
| 350 | "*If non-nil, means stealth fontification should show status messages.") | ||
| 351 | |||
| 352 | (defvar lazy-lock-mode nil) | ||
| 353 | (defvar lazy-lock-buffers nil) ; for deferral | ||
| 354 | (defvar lazy-lock-timers (cons nil nil)) ; for deferral and stealth | ||
| 355 | |||
| 356 | ;; User Functions: | ||
| 357 | |||
| 358 | ;;;###autoload | ||
| 359 | (defun lazy-lock-mode (&optional arg) | ||
| 360 | "Toggle Lazy Lock mode. | ||
| 361 | With arg, turn Lazy Lock mode on if and only if arg is positive. Enable it | ||
| 362 | automatically in your `~/.emacs' by: | ||
| 363 | |||
| 364 | (setq font-lock-support-mode 'lazy-lock-mode) | ||
| 365 | |||
| 366 | When Lazy Lock mode is enabled, fontification can be lazy in a number of ways: | ||
| 367 | |||
| 368 | - Demand-driven buffer fontification if `lazy-lock-minimum-size' is non-nil. | ||
| 369 | This means initial fontification does not occur if the buffer is greater | ||
| 370 | than `lazy-lock-minimum-size' characters in length. Instead, fontification | ||
| 371 | occurs when necessary, such as when scrolling through the buffer would | ||
| 372 | otherwise reveal unfontified areas. This is useful if buffer fontification | ||
| 373 | is too slow for large buffers. | ||
| 374 | |||
| 375 | - Defer-driven buffer fontification if `lazy-lock-defer-driven' is non-nil. | ||
| 376 | This means all fontification is deferred, such as fontification that occurs | ||
| 377 | when scrolling through the buffer would otherwise reveal unfontified areas. | ||
| 378 | Instead, these areas are seen momentarily unfontified. This is useful if | ||
| 379 | demand-driven fontification is too slow to keep up with scrolling. | ||
| 380 | |||
| 381 | - Deferred on-the-fly fontification if `lazy-lock-defer-time' is non-nil. | ||
| 382 | This means on-the-fly fontification does not occur as you type. Instead, | ||
| 383 | fontification is deferred until after `lazy-lock-defer-time' seconds of | ||
| 384 | Emacs idle time, while Emacs remains idle. This is useful if on-the-fly | ||
| 385 | fontification is too slow to keep up with your typing. | ||
| 386 | |||
| 387 | - Stealthy buffer fontification if `lazy-lock-stealth-time' is non-nil. | ||
| 388 | This means remaining unfontified areas of buffers are fontified if Emacs has | ||
| 389 | been idle for `lazy-lock-stealth-time' seconds, while Emacs remains idle. | ||
| 390 | This is useful if any buffer has demand- or defer-driven fontification. | ||
| 391 | |||
| 392 | See also variables `lazy-lock-stealth-lines', `lazy-lock-stealth-nice' and | ||
| 393 | `lazy-lock-stealth-verbose' for stealth fontification. | ||
| 394 | |||
| 395 | Use \\[lazy-lock-submit-bug-report] to send bug reports or feedback." | ||
| 396 | (interactive "P") | ||
| 397 | (set (make-local-variable 'lazy-lock-mode) | ||
| 398 | (and (not (memq 'lazy-lock-mode font-lock-inhibit-thing-lock)) | ||
| 399 | (if arg (> (prefix-numeric-value arg) 0) (not lazy-lock-mode)))) | ||
| 400 | (cond ((and lazy-lock-mode (not font-lock-mode)) | ||
| 401 | ;; Turned on `lazy-lock-mode' rather than `font-lock-mode'. | ||
| 402 | (let ((font-lock-support-mode 'lazy-lock-mode)) | ||
| 403 | (font-lock-mode t))) | ||
| 404 | (lazy-lock-mode | ||
| 405 | ;; Turn ourselves on. | ||
| 406 | (lazy-lock-install)) | ||
| 407 | (t | ||
| 408 | ;; Turn ourselves off. | ||
| 409 | (lazy-lock-unstall)))) | ||
| 410 | |||
| 411 | (defun lazy-lock-submit-bug-report () | ||
| 412 | "Submit via mail a bug report on lazy-lock.el." | ||
| 413 | (interactive) | ||
| 414 | (let ((reporter-prompt-for-summary-p t)) | ||
| 415 | (reporter-submit-bug-report "simon@gnu.ai.mit.edu" "lazy-lock 2.05" | ||
| 416 | '(lazy-lock-minimum-size lazy-lock-defer-driven lazy-lock-defer-time | ||
| 417 | lazy-lock-stealth-time lazy-lock-stealth-nice lazy-lock-stealth-lines | ||
| 418 | lazy-lock-stealth-verbose) | ||
| 419 | nil nil | ||
| 420 | (concat "Hi Si., | ||
| 421 | |||
| 422 | I want to report a bug. I've read the `Bugs' section of `Info' on Emacs, so I | ||
| 423 | know how to make a clear and unambiguous report. To reproduce the bug: | ||
| 424 | |||
| 425 | Start a fresh Emacs via `" invocation-name " -no-init-file -no-site-file'. | ||
| 426 | In the `*scratch*' buffer, evaluate:")))) | ||
| 427 | |||
| 428 | ;;;###autoload | ||
| 429 | (defun turn-on-lazy-lock () | ||
| 430 | "Unconditionally turn on Lazy Lock mode." | ||
| 431 | (lazy-lock-mode t)) | ||
| 432 | |||
| 433 | (defun lazy-lock-install () | ||
| 434 | (let ((min-size (font-lock-value-in-major-mode lazy-lock-minimum-size))) | ||
| 435 | ;; | ||
| 436 | ;; Tell Font Lock whether Lazy Lock will do fontification. | ||
| 437 | (make-local-variable 'font-lock-fontified) | ||
| 438 | (setq font-lock-fontified (and min-size (>= (buffer-size) min-size))) | ||
| 439 | ;; | ||
| 440 | ;; Add the text properties and fontify. | ||
| 441 | (if (not font-lock-fontified) | ||
| 442 | (lazy-lock-after-fontify-buffer) | ||
| 443 | ;; Make sure we fontify in any existing windows showing the buffer. | ||
| 444 | (let ((windows (get-buffer-window-list (current-buffer) 'nomini t))) | ||
| 445 | (lazy-lock-after-unfontify-buffer) | ||
| 446 | (while windows | ||
| 447 | (lazy-lock-fontify-conservatively (car windows)) | ||
| 448 | (setq windows (cdr windows))))) | ||
| 449 | ;; | ||
| 450 | ;; Add the fontification hooks. | ||
| 451 | (lazy-lock-install-hooks | ||
| 452 | (or (numberp lazy-lock-defer-time) | ||
| 453 | (if (eq (car (car lazy-lock-defer-time)) 'not) | ||
| 454 | (not (memq major-mode (cdr (car lazy-lock-defer-time)))) | ||
| 455 | (memq major-mode (car lazy-lock-defer-time)))) | ||
| 456 | font-lock-fontified | ||
| 457 | (eq lazy-lock-defer-driven t)) | ||
| 458 | ;; | ||
| 459 | ;; Add the fontification timers. | ||
| 460 | (lazy-lock-install-timers | ||
| 461 | (or (cdr-safe lazy-lock-defer-time) lazy-lock-defer-time) | ||
| 462 | lazy-lock-stealth-time))) | ||
| 463 | |||
| 464 | (defun lazy-lock-install-hooks (deferring fontifying defer-driven) | ||
| 465 | ;; | ||
| 466 | ;; Add hook if lazy-lock.el is deferring or is fontifying on scrolling. | ||
| 467 | (when (or deferring fontifying) | ||
| 468 | (make-local-hook 'window-scroll-functions) | ||
| 469 | (add-hook 'window-scroll-functions (if (and deferring defer-driven) | ||
| 470 | 'lazy-lock-defer-after-scroll | ||
| 471 | 'lazy-lock-fontify-after-scroll) | ||
| 472 | nil t)) | ||
| 473 | ;; | ||
| 474 | ;; Add hook if lazy-lock.el is not deferring and is fontifying. | ||
| 475 | (when (and (not deferring) fontifying) | ||
| 476 | (make-local-hook 'before-change-functions) | ||
| 477 | (add-hook 'before-change-functions 'lazy-lock-arrange-before-change nil t)) | ||
| 478 | ;; | ||
| 479 | ;; Add hook if lazy-lock.el is deferring. | ||
| 480 | (when deferring | ||
| 481 | (remove-hook 'after-change-functions 'font-lock-after-change-function t) | ||
| 482 | (add-hook 'after-change-functions 'lazy-lock-defer-after-change nil t)) | ||
| 483 | ;; | ||
| 484 | ;; Add package-specific hooks. | ||
| 485 | (make-local-hook 'outline-view-change-hook) | ||
| 486 | (add-hook 'outline-view-change-hook 'lazy-lock-fontify-after-outline nil t)) | ||
| 487 | |||
| 488 | (defun lazy-lock-install-timers (dtime stime) | ||
| 489 | ;; Schedule or re-schedule the deferral and stealth timers. | ||
| 490 | ;; The layout of `lazy-lock-timers' is: | ||
| 491 | ;; ((DEFER-TIME . DEFER-TIMER) (STEALTH-TIME . STEALTH-TIMER) | ||
| 492 | ;; If an idle timeout has changed, cancel the existing idle timer (if there | ||
| 493 | ;; is one) and schedule a new one (if the new idle timeout is non-nil). | ||
| 494 | (unless (eq dtime (car (car lazy-lock-timers))) | ||
| 495 | (let ((defer (car lazy-lock-timers))) | ||
| 496 | (when (cdr defer) | ||
| 497 | (cancel-timer (cdr defer))) | ||
| 498 | (setcar lazy-lock-timers (cons dtime (and dtime | ||
| 499 | (run-with-idle-timer dtime t 'lazy-lock-fontify-after-defer)))))) | ||
| 500 | (unless (eq stime (car (cdr lazy-lock-timers))) | ||
| 501 | (let ((stealth (cdr lazy-lock-timers))) | ||
| 502 | (when (cdr stealth) | ||
| 503 | (cancel-timer (cdr stealth))) | ||
| 504 | (setcdr lazy-lock-timers (cons stime (and stime | ||
| 505 | (run-with-idle-timer stime t 'lazy-lock-fontify-after-idle))))))) | ||
| 506 | |||
| 507 | (defun lazy-lock-unstall () | ||
| 508 | ;; | ||
| 509 | ;; Remove the text properties. | ||
| 510 | (lazy-lock-after-unfontify-buffer) | ||
| 511 | ;; | ||
| 512 | ;; Remove the fontification hooks. | ||
| 513 | (remove-hook 'window-scroll-functions 'lazy-lock-fontify-after-scroll t) | ||
| 514 | (remove-hook 'window-scroll-functions 'lazy-lock-defer-after-scroll t) | ||
| 515 | (remove-hook 'before-change-functions 'lazy-lock-arrange-before-change t) | ||
| 516 | (remove-hook 'after-change-functions 'lazy-lock-defer-after-change t) | ||
| 517 | (remove-hook 'outline-view-change-hook 'lazy-lock-fontify-after-outline t) | ||
| 518 | ;; | ||
| 519 | ;; If Font Lock mode is still enabled, reinstall its hook. | ||
| 520 | (when font-lock-mode | ||
| 521 | (add-hook 'after-change-functions 'font-lock-after-change-function nil t))) | ||
| 522 | |||
| 523 | ;; Hook functions. | ||
| 524 | |||
| 525 | (defun lazy-lock-fontify-after-scroll (window window-start) | ||
| 526 | ;; Called from `window-scroll-functions'. | ||
| 527 | ;; Fontify WINDOW from WINDOW-START. We cannot use `window-end' so we work | ||
| 528 | ;; out what it would be via `vertical-motion'. | ||
| 529 | (save-excursion | ||
| 530 | (goto-char window-start) | ||
| 531 | (vertical-motion (window-height window) window) | ||
| 532 | (lazy-lock-fontify-region window-start (point))) | ||
| 533 | ;; A prior deletion that did not cause scrolling, followed by a scroll, would | ||
| 534 | ;; result in an unnecessary trigger after this if we did not cancel it now. | ||
| 535 | (set-window-redisplay-end-trigger window nil)) | ||
| 536 | |||
| 537 | (defun lazy-lock-fontify-after-trigger (window trigger-point) | ||
| 538 | ;; Called from `redisplay-end-trigger-functions'. | ||
| 539 | ;; Fontify WINDOW from TRIGGER-POINT. We cannot use `window-end' so we work | ||
| 540 | ;; out what it would be via `vertical-motion'. | ||
| 541 | ;; We could probably just use `lazy-lock-fontify-after-scroll' without loss: | ||
| 542 | ;; (lazy-lock-fontify-after-scroll window (window-start window)) | ||
| 543 | (save-excursion | ||
| 544 | (goto-char (window-start window)) | ||
| 545 | (vertical-motion (window-height window) window) | ||
| 546 | (lazy-lock-fontify-region trigger-point (point)))) | ||
| 547 | |||
| 548 | (defun lazy-lock-fontify-after-resize (frame) | ||
| 549 | ;; Called from `window-size-change-functions'. | ||
| 550 | ;; Fontify windows in FRAME. We cannot use `window-start' or `window-end' so | ||
| 551 | ;; we fontify conservatively. | ||
| 552 | (save-excursion | ||
| 553 | (save-selected-window | ||
| 554 | (select-frame frame) | ||
| 555 | (walk-windows (function (lambda (window) | ||
| 556 | (set-buffer (window-buffer window)) | ||
| 557 | (when lazy-lock-mode | ||
| 558 | (lazy-lock-fontify-conservatively window)) | ||
| 559 | (set-window-redisplay-end-trigger window nil))) | ||
| 560 | 'nomini frame)))) | ||
| 561 | |||
| 562 | (defun lazy-lock-arrange-before-change (beg end) | ||
| 563 | ;; Called from `before-change-functions'. | ||
| 564 | ;; Arrange that if text becomes visible it will be fontified (if a deletion | ||
| 565 | ;; is pending, text might become visible at the bottom). | ||
| 566 | (unless (eq beg end) | ||
| 567 | (let ((windows (get-buffer-window-list (current-buffer) 'nomini t)) window) | ||
| 568 | (while windows | ||
| 569 | (setq window (car windows)) | ||
| 570 | (unless (markerp (window-redisplay-end-trigger window)) | ||
| 571 | (set-window-redisplay-end-trigger window (make-marker))) | ||
| 572 | (set-marker (window-redisplay-end-trigger window) (window-end window)) | ||
| 573 | (setq windows (cdr windows)))))) | ||
| 574 | |||
| 575 | (defun lazy-lock-defer-after-scroll (window window-start) | ||
| 576 | ;; Called from `window-scroll-functions'. | ||
| 577 | ;; Defer fontification following the scroll. Save the current buffer so that | ||
| 578 | ;; we subsequently fontify in all windows showing the buffer. | ||
| 579 | (unless (memq (current-buffer) lazy-lock-buffers) | ||
| 580 | (push (current-buffer) lazy-lock-buffers))) | ||
| 581 | |||
| 582 | (defun lazy-lock-defer-after-change (beg end old-len) | ||
| 583 | ;; Called from `after-change-functions'. | ||
| 584 | ;; Defer fontification of the current line. Save the current buffer so that | ||
| 585 | ;; we subsequently fontify in all windows showing the buffer. | ||
| 586 | (save-buffer-state nil | ||
| 587 | (unless (memq (current-buffer) lazy-lock-buffers) | ||
| 588 | (push (current-buffer) lazy-lock-buffers)) | ||
| 589 | (remove-text-properties | ||
| 590 | (max (1- beg) (point-min)) (min (1+ end) (point-max)) '(lazy-lock nil)))) | ||
| 591 | |||
| 592 | (defun lazy-lock-fontify-after-defer () | ||
| 593 | ;; Called from `timer-idle-list'. | ||
| 594 | ;; Fontify all windows where deferral has occurred for its buffer. | ||
| 595 | (while (and lazy-lock-buffers (not (input-pending-p))) | ||
| 596 | (let ((windows (get-buffer-window-list (car lazy-lock-buffers) 'nomini t))) | ||
| 597 | (while windows | ||
| 598 | (lazy-lock-fontify-window (car windows)) | ||
| 599 | (setq windows (cdr windows))) | ||
| 600 | (setq lazy-lock-buffers (cdr lazy-lock-buffers)))) | ||
| 601 | ;; Add hook if fontification should be defer-driven from now on. | ||
| 602 | (unless (or (not lazy-lock-defer-driven) (eq lazy-lock-defer-driven t) | ||
| 603 | (memq 'lazy-lock-defer-after-scroll window-scroll-functions) | ||
| 604 | (input-pending-p) (lazy-lock-unfontified-p)) | ||
| 605 | (remove-hook 'window-scroll-functions 'lazy-lock-fontify-after-scroll t) | ||
| 606 | (add-hook 'window-scroll-functions 'lazy-lock-defer-after-scroll nil t))) | ||
| 607 | |||
| 608 | (defun lazy-lock-fontify-after-idle () | ||
| 609 | ;; Called from `timer-idle-list'. | ||
| 610 | ;; Fontify all buffers that need it, stealthily while idle. | ||
| 611 | (unless (or executing-kbd-macro (window-minibuffer-p (selected-window))) | ||
| 612 | ;; Loop over all buffers, fontify stealthily for each if necessary. | ||
| 613 | (let ((buffers (buffer-list)) (continue t) message message-log-max) | ||
| 614 | (save-excursion | ||
| 615 | (do-while (and buffers continue) | ||
| 616 | (set-buffer (car buffers)) | ||
| 617 | (if (not (and lazy-lock-mode (lazy-lock-unfontified-p))) | ||
| 618 | (setq continue (not (input-pending-p))) | ||
| 619 | ;; Fontify regions in this buffer while there is no input. | ||
| 620 | (do-while (and (lazy-lock-unfontified-p) | ||
| 621 | (setq continue (sit-for lazy-lock-stealth-nice))) | ||
| 622 | (when lazy-lock-stealth-verbose | ||
| 623 | (if message | ||
| 624 | (message "Fontifying stealthily... %2d%% of %s" | ||
| 625 | (lazy-lock-percent-fontified) (buffer-name)) | ||
| 626 | (message "Fontifying stealthily...") | ||
| 627 | (setq message t))) | ||
| 628 | (lazy-lock-fontify-chunk))) | ||
| 629 | (setq buffers (cdr buffers)))) | ||
| 630 | (when message | ||
| 631 | (message "Fontifying stealthily...%s" (if continue "done" "quit"))) | ||
| 632 | ))) | ||
| 633 | |||
| 634 | (defun lazy-lock-fontify-after-outline () | ||
| 635 | ;; Called from `outline-view-change-hook'. | ||
| 636 | ;; Fontify windows showing the current buffer, as its visibility has changed. | ||
| 637 | ;; This is a conspiracy hack between lazy-lock.el and noutline.el. | ||
| 638 | (let ((windows (get-buffer-window-list (current-buffer) 'nomini t))) | ||
| 639 | (while windows | ||
| 640 | (lazy-lock-fontify-conservatively (car windows)) | ||
| 641 | (setq windows (cdr windows))))) | ||
| 642 | |||
| 643 | (defun lazy-lock-after-fontify-buffer () | ||
| 644 | ;; Called from `font-lock-after-fontify-buffer'. | ||
| 645 | ;; Mark the current buffer as fontified. | ||
| 646 | ;; This is a conspiracy hack between lazy-lock.el and font-lock.el. | ||
| 647 | (save-buffer-state nil | ||
| 648 | (add-text-properties (point-min) (point-max) '(lazy-lock t)))) | ||
| 649 | |||
| 650 | (defun lazy-lock-after-unfontify-buffer () | ||
| 651 | ;; Called from `font-lock-after-unfontify-buffer'. | ||
| 652 | ;; Mark the current buffer as unfontified. | ||
| 653 | ;; This is a conspiracy hack between lazy-lock.el and font-lock.el. | ||
| 654 | (save-buffer-state nil | ||
| 655 | (remove-text-properties (point-min) (point-max) '(lazy-lock nil)))) | ||
| 656 | |||
| 657 | ;; Fontification functions. | ||
| 658 | |||
| 659 | ;; If packages want to ensure that some region of the buffer is fontified, they | ||
| 660 | ;; should use this function. For an example, see ps-print.el. | ||
| 661 | (defun lazy-lock-fontify-region (beg end) | ||
| 662 | ;; Fontify between BEG and END, where necessary, in the current buffer. | ||
| 663 | (when (setq beg (text-property-any beg end 'lazy-lock nil)) | ||
| 664 | (save-excursion | ||
| 665 | (save-match-data | ||
| 666 | (save-buffer-state | ||
| 667 | ;; Ensure syntactic fontification is always correct. | ||
| 668 | (font-lock-beginning-of-syntax-function next) | ||
| 669 | ;; Find successive unfontified regions between BEG and END. | ||
| 670 | (condition-case data | ||
| 671 | (do-while beg | ||
| 672 | (setq next (or (text-property-any beg end 'lazy-lock t) end)) | ||
| 673 | ;; Make sure the region end points are at beginning of line. | ||
| 674 | (goto-char beg) | ||
| 675 | (unless (bolp) | ||
| 676 | (beginning-of-line) | ||
| 677 | (setq beg (point))) | ||
| 678 | (goto-char next) | ||
| 679 | (unless (bolp) | ||
| 680 | (forward-line) | ||
| 681 | (setq next (point))) | ||
| 682 | ;; Fontify the region, then flag it as fontified. | ||
| 683 | (font-lock-fontify-region beg next) | ||
| 684 | (add-text-properties beg next '(lazy-lock t)) | ||
| 685 | (setq beg (text-property-any next end 'lazy-lock nil))) | ||
| 686 | ((error quit) (message "Fontifying region...%s" data)))))))) | ||
| 687 | |||
| 688 | (defun lazy-lock-fontify-chunk () | ||
| 689 | ;; Fontify the nearest chunk, for stealth, in the current buffer. | ||
| 690 | (save-excursion | ||
| 691 | (save-restriction | ||
| 692 | (widen) | ||
| 693 | ;; Move to end of line in case the character at point is not fontified. | ||
| 694 | (end-of-line) | ||
| 695 | ;; Find where the previous, and next, unfontified regions end, and begin. | ||
| 696 | (let ((prev (previous-single-property-change (point) 'lazy-lock)) | ||
| 697 | (next (text-property-any (point) (point-max) 'lazy-lock nil))) | ||
| 698 | ;; Fontify from the nearest unfontified position. | ||
| 699 | (if (or (null prev) (and next (< (- next (point)) (- (point) prev)))) | ||
| 700 | ;; The next, or neither, region is the nearest not fontified. | ||
| 701 | (lazy-lock-fontify-region | ||
| 702 | (progn (goto-char (or next (point-min))) | ||
| 703 | (beginning-of-line) | ||
| 704 | (point)) | ||
| 705 | (progn (goto-char (or next (point-min))) | ||
| 706 | (forward-line lazy-lock-stealth-lines) | ||
| 707 | (point))) | ||
| 708 | ;; The previous region is the nearest not fontified. | ||
| 709 | (lazy-lock-fontify-region | ||
| 710 | (progn (goto-char prev) | ||
| 711 | (forward-line (- lazy-lock-stealth-lines)) | ||
| 712 | (point)) | ||
| 713 | (progn (goto-char prev) | ||
| 714 | (forward-line) | ||
| 715 | (point)))))))) | ||
| 716 | |||
| 717 | (defun lazy-lock-fontify-window (window) | ||
| 718 | ;; Fontify in WINDOW between `window-start' and `window-end'. | ||
| 719 | ;; We can only do this when we can use `window-start' and `window-end'. | ||
| 720 | (save-excursion | ||
| 721 | (set-buffer (window-buffer window)) | ||
| 722 | (lazy-lock-fontify-region (window-start window) (window-end window)))) | ||
| 723 | |||
| 724 | (defun lazy-lock-fontify-conservatively (window) | ||
| 725 | ;; Fontify in WINDOW conservatively around point. | ||
| 726 | ;; Where we cannot use `window-start' and `window-end' we do `window-height' | ||
| 727 | ;; lines around point. That way we guarantee to have done enough. | ||
| 728 | (save-excursion | ||
| 729 | (set-buffer (window-buffer window)) | ||
| 730 | (lazy-lock-fontify-region | ||
| 731 | (save-excursion | ||
| 732 | (vertical-motion (- (window-height window)) window) (point)) | ||
| 733 | (save-excursion | ||
| 734 | (vertical-motion (window-height window) window) (point))))) | ||
| 735 | |||
| 736 | (defun lazy-lock-unfontified-p () | ||
| 737 | ;; Return non-nil if there is anywhere still to be fontified. | ||
| 738 | (save-restriction | ||
| 739 | (widen) | ||
| 740 | (text-property-any (point-min) (point-max) 'lazy-lock nil))) | ||
| 741 | |||
| 742 | (defun lazy-lock-percent-fontified () | ||
| 743 | ;; Return the percentage (of characters) of the buffer that are fontified. | ||
| 744 | (save-restriction | ||
| 745 | (widen) | ||
| 746 | (let ((beg (point-min)) (end (point-max)) (size 0) next) | ||
| 747 | ;; Find where the next fontified region begins. | ||
| 748 | (while (setq beg (text-property-any beg end 'lazy-lock t)) | ||
| 749 | (setq next (or (text-property-any beg end 'lazy-lock nil) end) | ||
| 750 | size (+ size (- next beg)) | ||
| 751 | beg next)) | ||
| 752 | (/ (* size 100) (buffer-size))))) | ||
| 753 | |||
| 754 | ;; Version dependent workarounds and fixes. | ||
| 755 | |||
| 756 | (when (if (save-match-data (string-match "Lucid\\|XEmacs" (emacs-version))) | ||
| 757 | nil | ||
| 758 | (and (= emacs-major-version 19) (= emacs-minor-version 30))) | ||
| 759 | ;; | ||
| 760 | ;; We use `post-command-idle-hook' for deferral and stealth. Oh Lordy. | ||
| 761 | (defun lazy-lock-install-timers (foo bar) | ||
| 762 | (add-hook 'post-command-idle-hook 'lazy-lock-fontify-post-command t) | ||
| 763 | (add-hook 'post-command-idle-hook 'lazy-lock-fontify-post-idle t) | ||
| 764 | (add-to-list 'lazy-lock-install (current-buffer)) | ||
| 765 | (add-hook 'post-command-hook 'lazy-lock-fontify-after-install)) | ||
| 766 | (defun lazy-lock-fontify-post-command () | ||
| 767 | (and lazy-lock-buffers (not executing-kbd-macro) | ||
| 768 | (progn | ||
| 769 | (and deactivate-mark (deactivate-mark)) | ||
| 770 | (sit-for | ||
| 771 | (or (cdr-safe lazy-lock-defer-time) lazy-lock-defer-time 0))) | ||
| 772 | (lazy-lock-fontify-after-defer))) | ||
| 773 | (defun lazy-lock-fontify-post-idle () | ||
| 774 | (and lazy-lock-stealth-time (not executing-kbd-macro) | ||
| 775 | (not (window-minibuffer-p (selected-window))) | ||
| 776 | (progn | ||
| 777 | (and deactivate-mark (deactivate-mark)) | ||
| 778 | (sit-for lazy-lock-stealth-time)) | ||
| 779 | (lazy-lock-fontify-after-idle))) | ||
| 780 | ;; | ||
| 781 | ;; Simulate running of `window-scroll-functions' in `set-window-buffer'. | ||
| 782 | (defvar lazy-lock-install nil) | ||
| 783 | (defun lazy-lock-fontify-after-install () | ||
| 784 | (remove-hook 'post-command-hook 'lazy-lock-fontify-after-install) | ||
| 785 | (while lazy-lock-install | ||
| 786 | (mapcar 'lazy-lock-fontify-conservatively | ||
| 787 | (get-buffer-window-list (pop lazy-lock-install) 'nomini t))))) | ||
| 788 | |||
| 789 | ;; Possibly absent. | ||
| 790 | |||
| 791 | (unless (boundp 'font-lock-inhibit-thing-lock) | ||
| 792 | ;; Font Lock mode uses this to direct Lazy and Fast Lock modes to stay off. | ||
| 793 | (defvar font-lock-inhibit-thing-lock nil | ||
| 794 | "List of Font Lock mode related modes that should not be turned on.")) | ||
| 795 | |||
| 796 | (unless (fboundp 'font-lock-value-in-major-mode) | ||
| 797 | (defun font-lock-value-in-major-mode (alist) | ||
| 798 | ;; Return value in ALIST for `major-mode'. | ||
| 799 | (if (consp alist) | ||
| 800 | (cdr (or (assq major-mode alist) (assq t alist))) | ||
| 801 | alist))) | ||
| 802 | |||
| 803 | (unless (fboundp 'get-buffer-window-list) | ||
| 804 | ;; We use this to get all windows showing a buffer we have to fontify. | ||
| 805 | (defun get-buffer-window-list (buffer &optional minibuf frame) | ||
| 806 | "Return windows currently displaying BUFFER, or nil if none." | ||
| 807 | (let ((buffer (if (bufferp buffer) buffer (get-buffer buffer))) windows) | ||
| 808 | (walk-windows (function (lambda (window) | ||
| 809 | (when (eq (window-buffer window) buffer) | ||
| 810 | (push window windows)))) | ||
| 811 | minibuf frame) | ||
| 812 | windows))) | ||
| 813 | |||
| 814 | ;; Install ourselves: | ||
| 815 | |||
| 816 | ;; We don't install ourselves on `font-lock-mode-hook' as other packages can be | ||
| 817 | ;; used with font-lock.el, and lazy-lock.el should be dumpable without forcing | ||
| 818 | ;; people to get lazy or making it difficult for people to use alternatives. | ||
| 819 | (add-hook 'window-size-change-functions 'lazy-lock-fontify-after-resize) | ||
| 820 | (add-hook 'redisplay-end-trigger-functions 'lazy-lock-fontify-after-trigger) | ||
| 821 | |||
| 822 | (unless (assq 'lazy-lock-mode minor-mode-alist) | ||
| 823 | (setq minor-mode-alist (append minor-mode-alist '((lazy-lock-mode nil))))) | ||
| 824 | |||
| 825 | ;; Provide ourselves: | ||
| 826 | |||
| 827 | (provide 'lazy-lock) | ||
| 828 | |||
| 829 | ;;; lazy-lock.el ends here | ||