comparison lisp/packages/fast-lock.el @ 24:4103f0995bd7 r19-15b95

Import from CVS: tag r19-15b95
author cvs
date Mon, 13 Aug 2007 08:51:03 +0200
parents 8fc7fe29b841
children 131b0175ea99
comparison
equal deleted inserted replaced
23:0edd3412f124 24:4103f0995bd7
1 ;;; fast-lock.el --- Automagic text properties caching for fast Font Lock mode. 1 ;;; fast-lock.el --- Automagic text properties caching for fast Font Lock mode.
2 2
3 ;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. 3 ;; Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
4 4
5 ;; Author: Simon Marshall <simon@gnu.ai.mit.edu> 5 ;; Author: Simon Marshall <simon@gnu.ai.mit.edu>
6 ;; Keywords: faces files 6 ;; Keywords: faces files
7 ;; Version: 3.10.02 7 ;; Version: 3.11.01
8 8
9 ;;; This file is part of GNU Emacs. 9 ;;; This file is part of GNU Emacs.
10 10
11 ;; GNU Emacs is free software; you can redistribute it and/or modify 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 12 ;; it under the terms of the GNU General Public License as published by
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, 23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA. 24 ;; Boston, MA 02111-1307, USA.
25 25
26 ;;; Commentary: 26 ;;; Commentary:
27 27
28 ;; Purpose: 28 ;; Lazy Lock mode is a Font Lock support mode.
29 ;; 29 ;; It makes visiting a file in Font Lock mode faster by restoring its face text
30 ;; To make visiting a file in `font-lock-mode' faster by restoring its face 30 ;; properties from automatically saved associated Font Lock cache files.
31 ;; text properties from automatically saved associated Font Lock cache files.
32 ;; 31 ;;
33 ;; See caveats and feedback below. 32 ;; See caveats and feedback below.
34 ;; See also the lazy-lock package. (But don't use the two at the same time!) 33 ;; See also the lazy-lock package. (But don't use the two at the same time!)
35 34
36 ;; Installation: 35 ;; Installation:
51 ;; A cache will be saved when visiting a compressed file using crypt++, but not 50 ;; A cache will be saved when visiting a compressed file using crypt++, but not
52 ;; be read. This is a "feature"/"consequence"/"bug" of crypt++. 51 ;; be read. This is a "feature"/"consequence"/"bug" of crypt++.
53 ;; 52 ;;
54 ;; Version control packages are likely to stamp all over file modification 53 ;; Version control packages are likely to stamp all over file modification
55 ;; times. Therefore the act of checking out may invalidate a cache. 54 ;; times. Therefore the act of checking out may invalidate a cache.
56 ;;;;;^L 55
57 ;; History: 56 ;; History:
58 ;; 57 ;;
59 ;; 0.02--1.00: 58 ;; 0.02--1.00:
60 ;; - Changed name from turbo-prop to fast-lock. Automagic for font-lock only 59 ;; - Changed name from turbo-prop to fast-lock. Automagic for font-lock only
61 ;; - Made `fast-lock-mode' a minor mode, like G. Dinesh Dutt's fss-mode 60 ;; - Made `fast-lock-mode' a minor mode, like G. Dinesh Dutt's fss-mode
158 ;; - Made `fast-lock-mode' wrap `font-lock-support-mode' 157 ;; - Made `fast-lock-mode' wrap `font-lock-support-mode'
159 ;; 3.10--3.11: 158 ;; 3.10--3.11:
160 ;; - Made `fast-lock-get-face-properties' cope with face lists 159 ;; - Made `fast-lock-get-face-properties' cope with face lists
161 ;; - Added `fast-lock-verbose' 160 ;; - Added `fast-lock-verbose'
162 ;; - XEmacs: Add `font-lock-value-in-major-mode' if necessary 161 ;; - XEmacs: Add `font-lock-value-in-major-mode' if necessary
163 ;;;;;^L 162 ;; - Removed `fast-lock-submit-bug-report' and bade farewell
163 ;; 3.10--3.11:
164
165 ;;; Code:
166
164 (require 'font-lock) 167 (require 'font-lock)
165 168
166 ;; Make sure fast-lock.el is supported. 169 ;; Make sure fast-lock.el is supported.
167 (if (and (eq system-type 'ms-dos) (not (msdos-long-file-names))) 170 (if (and (eq system-type 'ms-dos) (not (msdos-long-file-names)))
168 (error "`fast-lock' was written for long file name systems")) 171 (error "`fast-lock' was written for long file name systems"))
190 (set-buffer-modified-p nil))))) 193 (set-buffer-modified-p nil)))))
191 (put 'save-buffer-state 'lisp-indent-function 1) 194 (put 'save-buffer-state 'lisp-indent-function 1)
192 ;; 195 ;;
193 ;; We use this to verify that a face should be saved. 196 ;; We use this to verify that a face should be saved.
194 (defmacro fast-lock-save-facep (face) 197 (defmacro fast-lock-save-facep (face)
195 "Return non-nil if FACE matches `fast-lock-save-faces'." 198 "Return non-nil if FACE is one of `fast-lock-save-faces'."
196 (` (or (null fast-lock-save-faces) 199 (` (or (null fast-lock-save-faces)
197 (if (symbolp (, face)) 200 (if (symbolp (, face))
198 (memq (, face) fast-lock-save-faces) 201 (memq (, face) fast-lock-save-faces)
199 (let ((list (, face)) found) 202 (let ((faces (, face)))
200 (while list 203 (while (unless (memq (car faces) fast-lock-save-faces)
201 (if (memq (car list) fast-lock-save-faces) 204 (setq faces (cdr faces))))
202 (setq list nil found t) 205 faces))))))
203 (setq list (cdr list)))) 206
204 found)))))) 207 ;(defun fast-lock-submit-bug-report ()
205 208 ; "Submit via mail a bug report on fast-lock.el."
206 (defun fast-lock-submit-bug-report () 209 ; (interactive)
207 "Submit via mail a bug report on fast-lock.el." 210 ; (let ((reporter-prompt-for-summary-p t))
208 (interactive) 211 ; (reporter-submit-bug-report "simon@gnu.ai.mit.edu" "fast-lock 3.11.01"
209 (let ((reporter-prompt-for-summary-p t)) 212 ; '(fast-lock-cache-directories fast-lock-minimum-size
210 (reporter-submit-bug-report "simon@gnu.ai.mit.edu" "fast-lock 3.10.02" 213 ; fast-lock-save-others fast-lock-save-events fast-lock-save-faces
211 '(fast-lock-cache-directories fast-lock-minimum-size 214 ; fast-lock-verbose)
212 fast-lock-save-others fast-lock-save-events fast-lock-save-faces 215 ; nil nil
213 fast-lock-verbose) 216 ; (concat "Hi Si.,
214 nil nil 217 ;
215 (concat "Hi Si., 218 ;I want to report a bug. I've read the `Bugs' section of `Info' on Emacs, so I
216 219 ;know how to make a clear and unambiguous report. To reproduce the bug:
217 I want to report a bug. I've read the `Bugs' section of `Info' on Emacs, so I 220 ;
218 know how to make a clear and unambiguous report. To reproduce the bug: 221 ;Start a fresh editor via `" invocation-name " -no-init-file -no-site-file'.
219 222 ;In the `*scratch*' buffer, evaluate:"))))
220 Start a fresh editor via `" invocation-name " -no-init-file -no-site-file'. 223
221 In the `*scratch*' buffer, evaluate:")))) 224 (defvar fast-lock-mode nil) ; Whether we are turned on.
222 225 (defvar fast-lock-cache-timestamp nil) ; For saving/reading.
223 ;;;###autoload 226 (defvar fast-lock-cache-filename nil) ; For deleting.
224 (defvar fast-lock-mode nil) 227
225 (defvar fast-lock-cache-timestamp nil) ; for saving/reading
226 (defvar fast-lock-cache-filename nil) ; for deleting
227 ;;;;;^L
228 ;; User Variables: 228 ;; User Variables:
229 229
230 (defvar fast-lock-cache-directories '("." "~/.emacs-flc") 230 (defvar fast-lock-cache-directories '("." "~/.emacs-flc")
231 ; - `internal', keep each file's Font Lock cache file in the same file. 231 ; - `internal', keep each file's Font Lock cache file in the same file.
232 ; - `external', keep each file's Font Lock cache file in the same directory. 232 ; - `external', keep each file's Font Lock cache file in the same directory.
276 If nil, means information for all faces will be saved.") 276 If nil, means information for all faces will be saved.")
277 277
278 (defvar fast-lock-verbose font-lock-verbose 278 (defvar fast-lock-verbose font-lock-verbose
279 "*If non-nil, means show status messages for cache processing. 279 "*If non-nil, means show status messages for cache processing.
280 If a number, only buffers greater than this size have processing messages.") 280 If a number, only buffers greater than this size have processing messages.")
281 ;;;;;^L 281
282 ;; User Functions: 282 ;; User Functions:
283 283
284 ;;;###autoload 284 ;;;###autoload
285 (defun fast-lock-mode (&optional arg) 285 (defun fast-lock-mode (&optional arg)
286 "Toggle Fast Lock mode. 286 "Toggle Fast Lock mode.
292 If Fast Lock mode is enabled, and the current buffer does not contain any text 292 If Fast Lock mode is enabled, and the current buffer does not contain any text
293 properties, any associated Font Lock cache is used if its timestamp matches the 293 properties, any associated Font Lock cache is used if its timestamp matches the
294 buffer's file, and its `font-lock-keywords' match those that you are using. 294 buffer's file, and its `font-lock-keywords' match those that you are using.
295 295
296 Font Lock caches may be saved: 296 Font Lock caches may be saved:
297 - When you save the file's buffer. 297 - When you save the file's buffer.
298 - When you kill an unmodified file's buffer. 298 - When you kill an unmodified file's buffer.
299 - When you exit Emacs, for all unmodified or saved buffers. 299 - When you exit Emacs, for all unmodified or saved buffers.
300 Depending on the value of `fast-lock-save-events'. 300 Depending on the value of `fast-lock-save-events'.
301 See also the commands `fast-lock-read-cache' and `fast-lock-save-cache'. 301 See also the commands `fast-lock-read-cache' and `fast-lock-save-cache'.
302 302
303 Use \\[font-lock-fontify-buffer] to fontify the buffer if the cache is bad. 303 Use \\[font-lock-fontify-buffer] to fontify the buffer if the cache is bad.
304 304
325 325
326 (defun fast-lock-read-cache () 326 (defun fast-lock-read-cache ()
327 "Read the Font Lock cache for the current buffer. 327 "Read the Font Lock cache for the current buffer.
328 328
329 The following criteria must be met for a Font Lock cache file to be read: 329 The following criteria must be met for a Font Lock cache file to be read:
330 - Fast Lock mode must be turned on in the buffer. 330 - Fast Lock mode must be turned on in the buffer.
331 - The buffer must not be modified. 331 - The buffer must not be modified.
332 - The buffer's `font-lock-keywords' must match the cache's. 332 - The buffer's `font-lock-keywords' must match the cache's.
333 - The buffer file's timestamp must match the cache's. 333 - The buffer file's timestamp must match the cache's.
334 - Criteria imposed by `fast-lock-cache-directories'. 334 - Criteria imposed by `fast-lock-cache-directories'.
335 335
336 See `fast-lock-mode'." 336 See `fast-lock-mode'."
337 (interactive) 337 (interactive)
338 (let ((directories fast-lock-cache-directories) 338 (let ((directories fast-lock-cache-directories)
339 (modified (buffer-modified-p)) (inhibit-read-only t) 339 (modified (buffer-modified-p)) (inhibit-read-only t)
358 358
359 (defun fast-lock-save-cache (&optional buffer) 359 (defun fast-lock-save-cache (&optional buffer)
360 "Save the Font Lock cache of BUFFER or the current buffer. 360 "Save the Font Lock cache of BUFFER or the current buffer.
361 361
362 The following criteria must be met for a Font Lock cache file to be saved: 362 The following criteria must be met for a Font Lock cache file to be saved:
363 - Fast Lock mode must be turned on in the buffer. 363 - Fast Lock mode must be turned on in the buffer.
364 - The event must be one of `fast-lock-save-events'. 364 - The event must be one of `fast-lock-save-events'.
365 - The buffer must be at least `fast-lock-minimum-size' bytes long. 365 - The buffer must be at least `fast-lock-minimum-size' bytes long.
366 - The buffer file must be owned by you, or `fast-lock-save-others' must be t. 366 - The buffer file must be owned by you, or `fast-lock-save-others' must be t.
367 - The buffer must contain at least one `face' text property. 367 - The buffer must contain at least one `face' text property.
368 - The buffer must not be modified. 368 - The buffer must not be modified.
369 - The buffer file's timestamp must be the same as the file's on disk. 369 - The buffer file's timestamp must be the same as the file's on disk.
370 - The on disk file's timestamp must be different than the buffer's cache. 370 - The on disk file's timestamp must be different than the buffer's cache.
371 - Criteria imposed by `fast-lock-cache-directories'. 371 - Criteria imposed by `fast-lock-cache-directories'.
372 372
373 See `fast-lock-mode'." 373 See `fast-lock-mode'."
374 (interactive) 374 (interactive)
375 (save-excursion 375 (save-excursion
376 (when buffer 376 (when buffer
411 411
412 ;;;###autoload 412 ;;;###autoload
413 (defun turn-on-fast-lock () 413 (defun turn-on-fast-lock ()
414 "Unconditionally turn on Fast Lock mode." 414 "Unconditionally turn on Fast Lock mode."
415 (fast-lock-mode t)) 415 (fast-lock-mode t))
416 ;;;;;^L 416
417 ;;; API Functions: 417 ;;; API Functions:
418 418
419 (defun fast-lock-after-fontify-buffer () 419 (defun fast-lock-after-fontify-buffer ()
420 ;; Delete the Font Lock cache file used to restore fontification, if any. 420 ;; Delete the Font Lock cache file used to restore fontification, if any.
421 (when fast-lock-cache-filename 421 (when fast-lock-cache-filename
425 ;; Flag so that a cache will be saved later even if the file is never saved. 425 ;; Flag so that a cache will be saved later even if the file is never saved.
426 (setq fast-lock-cache-timestamp nil)) 426 (setq fast-lock-cache-timestamp nil))
427 427
428 (defalias 'fast-lock-after-unfontify-buffer 428 (defalias 'fast-lock-after-unfontify-buffer
429 'ignore) 429 'ignore)
430 ;;;;;^L 430
431 ;; Miscellaneous Functions: 431 ;; Miscellaneous Functions:
432 432
433 (defun fast-lock-save-cache-after-save-file () 433 (defun fast-lock-save-cache-after-save-file ()
434 ;; Do `fast-lock-save-cache' if `save-buffer' is on `fast-lock-save-events'. 434 ;; Do `fast-lock-save-cache' if `save-buffer' is on `fast-lock-save-events'.
435 (when (memq 'save-buffer fast-lock-save-events) 435 (when (memq 'save-buffer fast-lock-save-events)
504 (function (lambda (c) (or (cdr (assq c chars-alist)) (list c)))))) 504 (function (lambda (c) (or (cdr (assq c chars-alist)) (list c))))))
505 (concat 505 (concat
506 (file-name-as-directory (expand-file-name directory)) 506 (file-name-as-directory (expand-file-name directory))
507 (mapconcat 'char-to-string (apply 'append (mapcar mapchars bufile)) "") 507 (mapconcat 'char-to-string (apply 'append (mapcar mapchars bufile)) "")
508 ".flc")))) 508 ".flc"))))
509 ;;;;;^L 509
510 ;; Font Lock Cache Processing Functions: 510 ;; Font Lock Cache Processing Functions:
511 511
512 (defun fast-lock-save-cache-1 (file timestamp) 512 (defun fast-lock-save-cache-1 (file timestamp)
513 ;; Save the FILE with the TIMESTAMP as: 513 ;; Save the FILE with the TIMESTAMP as:
514 ;; (fast-lock-cache-data Version=2 TIMESTAMP font-lock-keywords PROPERTIES). 514 ;; (fast-lock-cache-data Version=2 TIMESTAMP font-lock-keywords PROPERTIES).
569 (cond ((eq loaded 'error) "failed") 569 (cond ((eq loaded 'error) "failed")
570 ((eq loaded 'quit) "aborted") 570 ((eq loaded 'quit) "aborted")
571 (t "done"))))) 571 (t "done")))))
572 (setq font-lock-fontified (eq loaded t) 572 (setq font-lock-fontified (eq loaded t)
573 fast-lock-cache-timestamp (and (eq loaded t) timestamp)))) 573 fast-lock-cache-timestamp (and (eq loaded t) timestamp))))
574 ;;;;;^L 574
575 ;; Text Properties Processing Functions: 575 ;; Text Properties Processing Functions:
576 576
577 ;; This is faster, but fails if adjacent characters have different `face' text 577 ;; This is fast, but fails if adjacent characters have different `face' text
578 ;; properties. Maybe that's why I dropped it in the first place? 578 ;; properties. Maybe that's why I dropped it in the first place?
579 ;(defun fast-lock-get-face-properties () 579 ;(defun fast-lock-get-face-properties ()
580 ; "Return a list of all `face' text properties in the current buffer. 580 ; "Return a list of all `face' text properties in the current buffer.
581 ;Each element of the list is of the form (VALUE START1 END1 START2 END2 ...) 581 ;Each element of the list is of the form (VALUE START1 END1 START2 END2 ...)
582 ;where VALUE is a `face' property value and STARTx and ENDx are positions." 582 ;where VALUE is a `face' property value and STARTx and ENDx are positions."
592 ; (setcdr cell (cons start (cons end (cdr cell)))) 592 ; (setcdr cell (cons start (cons end (cdr cell))))
593 ; (setq properties (cons (list value start end) properties))) 593 ; (setq properties (cons (list value start end) properties)))
594 ; (setq start (next-single-property-change end 'face))) 594 ; (setq start (next-single-property-change end 'face)))
595 ; properties))) 595 ; properties)))
596 596
597 ;; This copes if adjacent characters have different `face' text properties, but 597 ;; This is slow, but copes if adjacent characters have different `face' text
598 ;; fails if they are lists. 598 ;; properties, but fails if they are lists.
599 ;(defun fast-lock-get-face-properties () 599 ;(defun fast-lock-get-face-properties ()
600 ; "Return a list of all `face' text properties in the current buffer. 600 ; "Return a list of all `face' text properties in the current buffer.
601 ;Each element of the list is of the form (VALUE START1 END1 START2 END2 ...) 601 ;Each element of the list is of the form (VALUE START1 END1 START2 END2 ...)
602 ;where VALUE is a `face' property value and STARTx and ENDx are positions. 602 ;where VALUE is a `face' property value and STARTx and ENDx are positions.
603 ;Only those `face' VALUEs in `fast-lock-save-faces' are returned." 603 ;Only those `face' VALUEs in `fast-lock-save-faces' are returned."
621 Each element of the list is of the form (VALUE START1 END1 START2 END2 ...) 621 Each element of the list is of the form (VALUE START1 END1 START2 END2 ...)
622 where VALUE is a `face' property value and STARTx and ENDx are positions." 622 where VALUE is a `face' property value and STARTx and ENDx are positions."
623 (save-restriction 623 (save-restriction
624 (widen) 624 (widen)
625 (let ((start (text-property-not-all (point-min) (point-max) 'face nil)) 625 (let ((start (text-property-not-all (point-min) (point-max) 'face nil))
626 (limit (point-max)) end properties value cell) 626 end properties value cell)
627 (while start 627 (while start
628 (setq end (next-single-property-change start 'face nil limit) 628 (setq end (next-single-property-change start 'face nil (point-max))
629 value (get-text-property start 'face)) 629 value (get-text-property start 'face))
630 ;; Make, or add to existing, list of regions with same `face'. 630 ;; Make, or add to existing, list of regions with same `face'.
631 (cond ((setq cell (assoc value properties)) 631 (cond ((setq cell (assoc value properties))
632 (setcdr cell (cons start (cons end (cdr cell))))) 632 (setcdr cell (cons start (cons end (cdr cell)))))
633 ((fast-lock-save-facep value) 633 ((fast-lock-save-facep value)
634 (push (list value start end) properties))) 634 (push (list value start end) properties)))
635 (setq start (if (get-text-property end 'face) 635 (setq start (text-property-not-all end (point-max) 'face nil)))
636 end
637 (next-single-property-change end 'face))))
638 properties))) 636 properties)))
639 637
640 (defun fast-lock-set-face-properties (properties) 638 (defun fast-lock-set-face-properties (properties)
641 "Set all `face' text properties to PROPERTIES in the current buffer. 639 "Set all `face' text properties to PROPERTIES in the current buffer.
642 Any existing `face' text properties are removed first. 640 Any existing `face' text properties are removed first.
651 properties (cdr properties)) 649 properties (cdr properties))
652 ;; Set the `face' property for each start/end region. 650 ;; Set the `face' property for each start/end region.
653 (while regions 651 (while regions
654 (set-text-properties (nth 0 regions) (nth 1 regions) plist) 652 (set-text-properties (nth 0 regions) (nth 1 regions) plist)
655 (setq regions (nthcdr 2 regions))))))) 653 (setq regions (nthcdr 2 regions)))))))
656 ;;;;;^L 654
657 ;; Functions for XEmacs: 655 ;; Functions for XEmacs:
658 656
659 (when (save-match-data (string-match "XEmacs" (emacs-version))) 657 (when (save-match-data (string-match "XEmacs" (emacs-version)))
660 ;; 658 ;;
661 ;; It would be better to use XEmacs' `map-extents' over extents with a 659 ;; It would be better to use XEmacs' `map-extents' over extents with a
716 (cdr (or (assq major-mode alist) (assq t alist))) 714 (cdr (or (assq major-mode alist) (assq t alist)))
717 alist))) 715 alist)))
718 716
719 (unless (fboundp 'font-lock-compile-keywords) 717 (unless (fboundp 'font-lock-compile-keywords)
720 (defalias 'font-lock-compile-keywords 'identity)) 718 (defalias 'font-lock-compile-keywords 'identity))
721 ;;;;;^L 719
722 ;; Install ourselves: 720 ;; Install ourselves:
723 721
724 (add-hook 'after-save-hook 'fast-lock-save-cache-after-save-file) 722 (add-hook 'after-save-hook 'fast-lock-save-cache-after-save-file)
725 (add-hook 'kill-buffer-hook 'fast-lock-save-cache-before-kill-buffer) 723 (add-hook 'kill-buffer-hook 'fast-lock-save-cache-before-kill-buffer)
726 (add-hook 'kill-emacs-hook 'fast-lock-save-caches-before-kill-emacs) 724 (add-hook 'kill-emacs-hook 'fast-lock-save-caches-before-kill-emacs)
727 725
728 ;;;###autoload 726 ;;;###autoload
729 (if (fboundp 'add-minor-mode) (add-minor-mode 'fast-lock-mode nil)) 727 (when (fboundp 'add-minor-mode)
728 (defvar fast-lock-mode nil)
729 (add-minor-mode 'fast-lock-mode nil))
730 ;;;###dont-autoload 730 ;;;###dont-autoload
731 (unless (assq 'fast-lock-mode minor-mode-alist) 731 (unless (assq 'fast-lock-mode minor-mode-alist)
732 (setq minor-mode-alist (append minor-mode-alist '((fast-lock-mode nil))))) 732 (setq minor-mode-alist (append minor-mode-alist '((fast-lock-mode nil)))))
733 733
734 ;; Provide ourselves: 734 ;; Provide ourselves: