Mercurial > emacs
comparison lisp/jit-lock.el @ 41336:36e754afaf7a
(jit-lock-defer-time): New var.
(jit-lock-defer-timer, jit-lock-buffers): New vars.
(jit-lock-mode): Initialize them. Cancel the timers more carefully.
(jit-lock-function): Defer fontification if requested.
(jit-lock-stealth-chunk-start): Pay attention to the new non-nil value.
(jit-lock-stealth-fontify): Check the new `jit-lock-defer-multiline'
text property.
(jit-lock-deferred-fontify): New fun.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Wed, 21 Nov 2001 01:30:35 +0000 |
parents | b174db545cfd |
children | 828432e1e1d4 |
comparison
equal
deleted
inserted
replaced
41335:b300e8b6992e | 41336:36e754afaf7a |
---|---|
125 :type '(choice (const :tag "never" nil) | 125 :type '(choice (const :tag "never" nil) |
126 (const :tag "always" t) | 126 (const :tag "always" t) |
127 (other :tag "syntax-driven" syntax-driven)) | 127 (other :tag "syntax-driven" syntax-driven)) |
128 :group 'jit-lock) | 128 :group 'jit-lock) |
129 | 129 |
130 | 130 (defcustom jit-lock-defer-time nil ;; 0.5 |
131 "Idle time after which deferred fontification should take place. | |
132 If nil, fontification is not deferred." | |
133 :group 'jit-lock | |
134 :type '(choice (const :tag "never" nil) | |
135 (number :tag "seconds"))) | |
131 | 136 |
132 ;;; Variables that are not customizable. | 137 ;;; Variables that are not customizable. |
133 | 138 |
134 (defvar jit-lock-mode nil | 139 (defvar jit-lock-mode nil |
135 "Non-nil means Just-in-time Lock mode is active.") | 140 "Non-nil means Just-in-time Lock mode is active.") |
146 (make-variable-buffer-local 'jit-lock-first-unfontify-pos) | 151 (make-variable-buffer-local 'jit-lock-first-unfontify-pos) |
147 | 152 |
148 | 153 |
149 (defvar jit-lock-stealth-timer nil | 154 (defvar jit-lock-stealth-timer nil |
150 "Timer for stealth fontification in Just-in-time Lock mode.") | 155 "Timer for stealth fontification in Just-in-time Lock mode.") |
156 | |
157 (defvar jit-lock-defer-timer nil | |
158 "Timer for deferred fontification in Just-in-time Lock mode.") | |
159 | |
160 (defvar jit-lock-buffers nil | |
161 "List of buffers with pending deferred fontification.") | |
151 | 162 |
152 ;;; JIT lock mode | 163 ;;; JIT lock mode |
153 | 164 |
154 (defun jit-lock-mode (arg) | 165 (defun jit-lock-mode (arg) |
155 "Toggle Just-in-time Lock mode. | 166 "Toggle Just-in-time Lock mode. |
184 the variable `jit-lock-stealth-nice'." | 195 the variable `jit-lock-stealth-nice'." |
185 (setq jit-lock-mode arg) | 196 (setq jit-lock-mode arg) |
186 (cond (;; Turn Just-in-time Lock mode on. | 197 (cond (;; Turn Just-in-time Lock mode on. |
187 jit-lock-mode | 198 jit-lock-mode |
188 | 199 |
189 ;; Mark the buffer for refontification | 200 ;; Mark the buffer for refontification. |
190 (jit-lock-refontify) | 201 (jit-lock-refontify) |
191 | 202 |
192 ;; Install an idle timer for stealth fontification. | 203 ;; Install an idle timer for stealth fontification. |
193 (when (and jit-lock-stealth-time (null jit-lock-stealth-timer)) | 204 (when (and jit-lock-stealth-time (null jit-lock-stealth-timer)) |
194 (setq jit-lock-stealth-timer | 205 (setq jit-lock-stealth-timer |
195 (run-with-idle-timer jit-lock-stealth-time | 206 (run-with-idle-timer jit-lock-stealth-time t |
196 jit-lock-stealth-time | |
197 'jit-lock-stealth-fontify))) | 207 'jit-lock-stealth-fontify))) |
208 | |
209 ;; Init deferred fontification timer. | |
210 (when (and jit-lock-defer-time (null jit-lock-defer-timer)) | |
211 (setq jit-lock-defer-timer | |
212 (run-with-idle-timer jit-lock-defer-time t | |
213 'jit-lock-deferred-fontify))) | |
198 | 214 |
199 ;; Initialize deferred contextual fontification if requested. | 215 ;; Initialize deferred contextual fontification if requested. |
200 (when (eq jit-lock-defer-contextually t) | 216 (when (eq jit-lock-defer-contextually t) |
201 (setq jit-lock-first-unfontify-pos | 217 (setq jit-lock-first-unfontify-pos |
202 (or jit-lock-first-unfontify-pos (point-max)))) | 218 (or jit-lock-first-unfontify-pos (point-max)))) |
205 (add-hook 'after-change-functions 'jit-lock-after-change nil t) | 221 (add-hook 'after-change-functions 'jit-lock-after-change nil t) |
206 (add-hook 'fontification-functions 'jit-lock-function)) | 222 (add-hook 'fontification-functions 'jit-lock-function)) |
207 | 223 |
208 ;; Turn Just-in-time Lock mode off. | 224 ;; Turn Just-in-time Lock mode off. |
209 (t | 225 (t |
210 ;; Cancel our idle timer. | 226 ;; Cancel our idle timers. |
211 (when jit-lock-stealth-timer | 227 (when (and (or jit-lock-stealth-timer jit-lock-defer-timer) |
212 (cancel-timer jit-lock-stealth-timer) | 228 ;; Only if there's no other buffer using them. |
213 (setq jit-lock-stealth-timer nil)) | 229 (not (catch 'found |
230 (dolist (buf (buffer-list)) | |
231 (with-current-buffer buf | |
232 (when jit-lock-mode (throw 'found t))))))) | |
233 (when jit-lock-stealth-timer | |
234 (cancel-timer jit-lock-stealth-timer) | |
235 (setq jit-lock-stealth-timer nil)) | |
236 (when jit-lock-defer-timer | |
237 (cancel-timer jit-lock-defer-timer) | |
238 (setq jit-lock-defer-timer nil))) | |
214 | 239 |
215 ;; Remove hooks. | 240 ;; Remove hooks. |
216 (remove-hook 'after-change-functions 'jit-lock-after-change t) | 241 (remove-hook 'after-change-functions 'jit-lock-after-change t) |
217 (remove-hook 'fontification-functions 'jit-lock-function)))) | 242 (remove-hook 'fontification-functions 'jit-lock-function)))) |
218 | 243 |
240 (defun jit-lock-refontify (&optional beg end) | 265 (defun jit-lock-refontify (&optional beg end) |
241 "Force refontification of the region BEG..END (default whole buffer)." | 266 "Force refontification of the region BEG..END (default whole buffer)." |
242 (with-buffer-prepared-for-jit-lock | 267 (with-buffer-prepared-for-jit-lock |
243 (save-restriction | 268 (save-restriction |
244 (widen) | 269 (widen) |
245 (add-text-properties (or beg (point-min)) (or end (point-max)) | 270 (put-text-property (or beg (point-min)) (or end (point-max)) |
246 '(fontified nil))))) | 271 'fontified nil)))) |
247 | 272 |
248 ;;; On demand fontification. | 273 ;;; On demand fontification. |
249 | 274 |
250 (defun jit-lock-function (start) | 275 (defun jit-lock-function (start) |
251 "Fontify current buffer starting at position START. | 276 "Fontify current buffer starting at position START. |
252 This function is added to `fontification-functions' when `jit-lock-mode' | 277 This function is added to `fontification-functions' when `jit-lock-mode' |
253 is active." | 278 is active." |
254 (when jit-lock-mode | 279 (when jit-lock-mode |
255 (jit-lock-fontify-now start (+ start jit-lock-chunk-size)))) | 280 (if (null jit-lock-defer-time) |
256 | 281 ;; No deferral. |
282 (jit-lock-fontify-now start (+ start jit-lock-chunk-size)) | |
283 ;; Record the buffer for later fontification. | |
284 (unless (memq (current-buffer) jit-lock-buffers) | |
285 (push (current-buffer) jit-lock-buffers)) | |
286 ;; Mark the area as defer-fontified so that the redisplay engine | |
287 ;; is happy and so that the idle timer can find the places to fontify. | |
288 (with-buffer-prepared-for-jit-lock | |
289 (put-text-property start | |
290 (next-single-property-change | |
291 start 'fontified nil | |
292 (min (point-max) (+ start jit-lock-chunk-size))) | |
293 'fontified 'defer))))) | |
257 | 294 |
258 (defun jit-lock-fontify-now (&optional start end) | 295 (defun jit-lock-fontify-now (&optional start end) |
259 "Fontify current buffer from START to END. | 296 "Fontify current buffer from START to END. |
260 Defaults to the whole buffer. END can be out of bounds." | 297 Defaults to the whole buffer. END can be out of bounds." |
261 (with-buffer-prepared-for-jit-lock | 298 (with-buffer-prepared-for-jit-lock |
292 (goto-char start) (setq start (line-beginning-position)) | 329 (goto-char start) (setq start (line-beginning-position)) |
293 | 330 |
294 ;; Fontify the chunk, and mark it as fontified. | 331 ;; Fontify the chunk, and mark it as fontified. |
295 ;; We mark it first, to make sure that we don't indefinitely | 332 ;; We mark it first, to make sure that we don't indefinitely |
296 ;; re-execute this fontification if an error occurs. | 333 ;; re-execute this fontification if an error occurs. |
297 (add-text-properties start next '(fontified t)) | 334 (put-text-property start next 'fontified t) |
298 (run-hook-with-args 'jit-lock-functions start next) | 335 (run-hook-with-args 'jit-lock-functions start next) |
299 | 336 |
300 ;; Find the start of the next chunk, if any. | 337 ;; Find the start of the next chunk, if any. |
301 (setq start (text-property-any next end 'fontified nil))))))))) | 338 (setq start (text-property-any next end 'fontified nil))))))))) |
302 | 339 |
303 | 340 |
304 ;;; Stealth fontification. | 341 ;;; Stealth fontification. |
308 Value is nil if there is nothing more to fontify." | 345 Value is nil if there is nothing more to fontify." |
309 (if (zerop (buffer-size)) | 346 (if (zerop (buffer-size)) |
310 nil | 347 nil |
311 (save-restriction | 348 (save-restriction |
312 (widen) | 349 (widen) |
313 (let* ((next (text-property-any around (point-max) 'fontified nil)) | 350 (let* ((next (text-property-not-all around (point-max) 'fontified t)) |
314 (prev (previous-single-property-change around 'fontified)) | 351 (prev (previous-single-property-change around 'fontified)) |
315 (prop (get-text-property (max (point-min) (1- around)) | 352 (prop (get-text-property (max (point-min) (1- around)) |
316 'fontified)) | 353 'fontified)) |
317 (start (cond | 354 (start (cond |
318 ((null prev) | 355 ((null prev) |
319 ;; There is no property change between AROUND | 356 ;; There is no property change between AROUND |
320 ;; and the start of the buffer. If PROP is | 357 ;; and the start of the buffer. If PROP is |
321 ;; non-nil, everything in front of AROUND is | 358 ;; non-nil, everything in front of AROUND is |
322 ;; fontified, otherwise nothing is fontified. | 359 ;; fontified, otherwise nothing is fontified. |
323 (if prop | 360 (if (eq prop t) |
324 nil | 361 nil |
325 (max (point-min) | 362 (max (point-min) |
326 (- around (/ jit-lock-chunk-size 2))))) | 363 (- around (/ jit-lock-chunk-size 2))))) |
327 (prop | 364 ((eq prop t) |
328 ;; PREV is the start of a region of fontified | 365 ;; PREV is the start of a region of fontified |
329 ;; text containing AROUND. Start fontifying a | 366 ;; text containing AROUND. Start fontifying a |
330 ;; chunk size before the end of the unfontified | 367 ;; chunk size before the end of the unfontified |
331 ;; region in front of that. | 368 ;; region in front of that. |
332 (max (or (previous-single-property-change prev 'fontified) | 369 (max (or (previous-single-property-change prev 'fontified) |
347 | 384 |
348 (defun jit-lock-stealth-fontify () | 385 (defun jit-lock-stealth-fontify () |
349 "Fontify buffers stealthily. | 386 "Fontify buffers stealthily. |
350 This functions is called after Emacs has been idle for | 387 This functions is called after Emacs has been idle for |
351 `jit-lock-stealth-time' seconds." | 388 `jit-lock-stealth-time' seconds." |
389 ;; I used to check `inhibit-read-only' here, but I can't remember why. -stef | |
352 (unless (or executing-kbd-macro | 390 (unless (or executing-kbd-macro |
353 (window-minibuffer-p (selected-window))) | 391 (window-minibuffer-p (selected-window))) |
354 (let ((buffers (buffer-list)) | 392 (let ((buffers (buffer-list)) |
355 minibuffer-auto-raise | 393 minibuffer-auto-raise |
356 message-log-max) | 394 message-log-max) |
382 (when jit-lock-first-unfontify-pos | 420 (when jit-lock-first-unfontify-pos |
383 (save-restriction | 421 (save-restriction |
384 (widen) | 422 (widen) |
385 (when (and (>= jit-lock-first-unfontify-pos (point-min)) | 423 (when (and (>= jit-lock-first-unfontify-pos (point-min)) |
386 (< jit-lock-first-unfontify-pos (point-max))) | 424 (< jit-lock-first-unfontify-pos (point-max))) |
425 ;; If we're in text that matches a complex multi-line | |
426 ;; font-lock pattern, make sure the whole text will be | |
427 ;; redisplayed eventually. | |
428 (when (get-text-property jit-lock-first-unfontify-pos | |
429 'jit-lock-defer-multiline) | |
430 (setq jit-lock-first-unfontify-pos | |
431 (or (previous-single-property-change | |
432 jit-lock-first-unfontify-pos | |
433 'jit-lock-defer-multiline) | |
434 (point-min)))) | |
387 (with-buffer-prepared-for-jit-lock | 435 (with-buffer-prepared-for-jit-lock |
388 (put-text-property jit-lock-first-unfontify-pos | 436 (remove-text-properties |
389 (point-max) 'fontified nil)) | 437 jit-lock-first-unfontify-pos (point-max) |
438 '(fontified nil jit-lock-defer-multiline nil))) | |
390 (setq jit-lock-first-unfontify-pos (point-max))))) | 439 (setq jit-lock-first-unfontify-pos (point-max))))) |
391 | 440 |
392 ;; In the following code, the `sit-for' calls cause a | 441 ;; In the following code, the `sit-for' calls cause a |
393 ;; redisplay, so it's required that the | 442 ;; redisplay, so it's required that the |
394 ;; buffer-modified flag of a buffer that is displayed | 443 ;; buffer-modified flag of a buffer that is displayed |
395 ;; has the right value---otherwise the mode line of | 444 ;; has the right value---otherwise the mode line of |
396 ;; an unmodified buffer would show a `*'. | 445 ;; an unmodified buffer would show a `*'. |
397 (let (start | 446 (let (start |
398 (nice (or jit-lock-stealth-nice 0)) | 447 (nice (or jit-lock-stealth-nice 0)) |
399 (point (point))) | 448 (point (point-min))) |
400 (while (and (setq start | 449 (while (and (setq start |
401 (jit-lock-stealth-chunk-start point)) | 450 (jit-lock-stealth-chunk-start point)) |
402 (sit-for nice)) | 451 (sit-for nice)) |
403 | 452 |
453 ;; fontify a block. | |
454 (jit-lock-fontify-now start (+ start jit-lock-chunk-size)) | |
455 ;; If stealth jit-locking is done backwards, this leads to | |
456 ;; excessive O(n^2) refontification. -stef | |
457 ;; (when (>= jit-lock-first-unfontify-pos start) | |
458 ;; (setq jit-lock-first-unfontify-pos end)) | |
459 | |
404 ;; Wait a little if load is too high. | 460 ;; Wait a little if load is too high. |
405 (when (and jit-lock-stealth-load | 461 (when (and jit-lock-stealth-load |
406 (> (car (load-average)) jit-lock-stealth-load)) | 462 (> (car (load-average)) jit-lock-stealth-load)) |
407 (sit-for (or jit-lock-stealth-time 30))) | 463 (sit-for (or jit-lock-stealth-time 30))))))))))))) |
408 | |
409 ;; Unless there's input pending now, fontify. | |
410 (unless (input-pending-p) | |
411 (jit-lock-fontify-now | |
412 start (+ start jit-lock-chunk-size))))))))))))) | |
413 | 464 |
414 | 465 |
415 | 466 |
416 ;;; Deferred fontification. | 467 ;;; Deferred fontification. |
468 | |
469 (defun jit-lock-deferred-fontify () | |
470 "Fontify what was deferred." | |
471 (when jit-lock-buffers | |
472 ;; Mark the deferred regions back to `fontified = nil' | |
473 (dolist (buffer jit-lock-buffers) | |
474 (when (buffer-live-p buffer) | |
475 (with-current-buffer buffer | |
476 ;; (message "Jit-Defer %s" (buffer-name)) | |
477 (with-buffer-prepared-for-jit-lock | |
478 (let ((pos (point-min))) | |
479 (while | |
480 (progn | |
481 (when (eq (get-text-property pos 'fontified) 'defer) | |
482 (put-text-property | |
483 pos (setq pos (next-single-property-change | |
484 pos 'fontified nil (point-max))) | |
485 'fontified nil)) | |
486 (setq pos (next-single-property-change pos 'fontified))))))))) | |
487 (setq jit-lock-buffers nil) | |
488 ;; Force fontification of the visible parts. | |
489 (let ((jit-lock-defer-time nil)) | |
490 ;; (message "Jit-Defer Now") | |
491 (sit-for 0) | |
492 ;; (message "Jit-Defer Done") | |
493 ))) | |
494 | |
417 | 495 |
418 (defun jit-lock-after-change (start end old-len) | 496 (defun jit-lock-after-change (start end old-len) |
419 "Mark the rest of the buffer as not fontified after a change. | 497 "Mark the rest of the buffer as not fontified after a change. |
420 Installed on `after-change-functions'. | 498 Installed on `after-change-functions'. |
421 START and END are the start and end of the changed text. OLD-LEN | 499 START and END are the start and end of the changed text. OLD-LEN |
433 (goto-char start) | 511 (goto-char start) |
434 (setq start (line-beginning-position)) | 512 (setq start (line-beginning-position)) |
435 | 513 |
436 ;; If we're in text that matches a multi-line font-lock pattern, | 514 ;; If we're in text that matches a multi-line font-lock pattern, |
437 ;; make sure the whole text will be redisplayed. | 515 ;; make sure the whole text will be redisplayed. |
516 ;; I'm not sure this is ever necessary and/or sufficient. -stef | |
438 (when (get-text-property start 'font-lock-multiline) | 517 (when (get-text-property start 'font-lock-multiline) |
439 (setq start (or (previous-single-property-change | 518 (setq start (or (previous-single-property-change |
440 start 'font-lock-multiline) | 519 start 'font-lock-multiline) |
441 (point-min)))) | 520 (point-min)))) |
442 | 521 |