diff options
| author | Simon Marshall | 1995-06-01 09:26:48 +0000 |
|---|---|---|
| committer | Simon Marshall | 1995-06-01 09:26:48 +0000 |
| commit | 19f7908595ac9c2f7510a966dbd52940b086efe5 (patch) | |
| tree | 4431370cdc9c047c05845970f5fbfd762967a00d | |
| parent | 52436656c356cfb835364aa958193dd47b9336b1 (diff) | |
| download | emacs-19f7908595ac9c2f7510a966dbd52940b086efe5.tar.gz emacs-19f7908595ac9c2f7510a966dbd52940b086efe5.zip | |
New version 3.06 from author.
| -rw-r--r-- | lisp/fast-lock.el | 630 |
1 files changed, 361 insertions, 269 deletions
diff --git a/lisp/fast-lock.el b/lisp/fast-lock.el index 285c95ae979..c6c268bbfb5 100644 --- a/lisp/fast-lock.el +++ b/lisp/fast-lock.el | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | ;;; fast-lock.el --- Automagic text properties saving for fast font-lock-mode. | 1 | ;;; fast-lock.el --- Automagic text properties caching for fast Font Lock mode. |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 1994 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1994, 1995 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Author: Simon Marshall <Simon.Marshall@mail.esrin.esa.it> | 5 | ;; Author: Simon Marshall <simon@gnu.ai.mit.edu> |
| 6 | ;; Keywords: faces files | 6 | ;; Keywords: faces files |
| 7 | ;; Version: 3.05 | 7 | ;; Version: 3.06 |
| 8 | 8 | ||
| 9 | ;;; This file is part of GNU Emacs. | 9 | ;;; This file is part of GNU Emacs. |
| 10 | 10 | ||
| @@ -27,23 +27,14 @@ | |||
| 27 | ;; Purpose: | 27 | ;; Purpose: |
| 28 | ;; | 28 | ;; |
| 29 | ;; To make visiting a file in `font-lock-mode' faster by restoring its face | 29 | ;; To make visiting a file in `font-lock-mode' faster by restoring its face |
| 30 | ;; text properties from automatically saved associated font lock cache files. | 30 | ;; text properties from automatically saved associated Font Lock cache files. |
| 31 | ;; | 31 | ;; |
| 32 | ;; See also the face-lock package. | 32 | ;; See caveats and feedback below. |
| 33 | ;; 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!) |
| 34 | 34 | ||
| 35 | ;; Note that: | ||
| 36 | ;; | ||
| 37 | ;; - A cache will be saved when visiting a compressed file using crypt++, but | ||
| 38 | ;; not be read. This is a "feature"/"consequence"/"bug" of crypt++. | ||
| 39 | |||
| 40 | ;; Installation: | 35 | ;; Installation: |
| 41 | ;; | 36 | ;; |
| 42 | ;; Put this file somewhere where Emacs can find it (i.e., in one of the paths | 37 | ;; Put in your ~/.emacs: |
| 43 | ;; in your `load-path'), `byte-compile-file' it, and put in your ~/.emacs: | ||
| 44 | ;; | ||
| 45 | ;; (autoload 'turn-on-fast-lock "fast-lock" | ||
| 46 | ;; "Unconditionally turn on Fast Lock mode.") | ||
| 47 | ;; | 38 | ;; |
| 48 | ;; (add-hook 'font-lock-mode-hook 'turn-on-fast-lock) | 39 | ;; (add-hook 'font-lock-mode-hook 'turn-on-fast-lock) |
| 49 | ;; | 40 | ;; |
| @@ -51,31 +42,23 @@ | |||
| 51 | ;; so-called "gaudier" fontification regexps on big files without frustration). | 42 | ;; so-called "gaudier" fontification regexps on big files without frustration). |
| 52 | ;; | 43 | ;; |
| 53 | ;; When you visit a file (which has `font-lock-mode' enabled) that has a | 44 | ;; When you visit a file (which has `font-lock-mode' enabled) that has a |
| 54 | ;; corresponding font lock cache file associated with it, the font lock cache | 45 | ;; corresponding Font Lock cache file associated with it, the Font Lock cache |
| 55 | ;; will be loaded from that file instead of being generated by font-lock code. | 46 | ;; will be loaded from that file instead of being generated by Font Lock code. |
| 47 | |||
| 48 | ;; Caveats: | ||
| 56 | ;; | 49 | ;; |
| 57 | ;; Font lock caches will be saved: | 50 | ;; A cache will be saved when visiting a compressed file using crypt++, but not |
| 58 | ;; - For all buffers with Fast Lock mode enabled when you exit from Emacs. | 51 | ;; be read. This is a "feature"/"consequence"/"bug" of crypt++. |
| 59 | ;; - For a buffer with Fast Lock mode enabled when you kill the buffer. | ||
| 60 | ;; To provide control over how such cache files are written automagically, see | ||
| 61 | ;; variable `fast-lock-cache-directories'. To provide control over which such | ||
| 62 | ;; cache files are written, see variables `fast-lock-save-others' and | ||
| 63 | ;; `fast-lock-save-size'. Only cache files which were generated using the same | ||
| 64 | ;; `font-lock-keywords' as you are using will be used. | ||
| 65 | ;; | 52 | ;; |
| 66 | ;; As an illustration of the time saving, a 115k file of Emacs C code took 95 | 53 | ;; Version control packages are likely to stamp all over file modification |
| 67 | ;; seconds to fontify using Emacs 19.25 on a Sun SparcStation 2 LX (using | 54 | ;; times. Therefore the act of checking out may invalidate a cache. |
| 68 | ;; `c-font-lock-keywords-2'). The font lock cache file takes around 2 seconds | ||
| 69 | ;; to load (with around 4 seconds to generate and save). Bite it. Believe it. | ||
| 70 | ;; (For Lucid Emacs 19.10, the figures on a similar machine, file, and regexps, | ||
| 71 | ;; are 70, around 4, and around 4, seconds, respectively; for Emacs 19.28 the | ||
| 72 | ;; fontification takes around 26 seconds.) | ||
| 73 | 55 | ||
| 74 | ;; Feedback: | 56 | ;; Feedback: |
| 75 | ;; | 57 | ;; |
| 76 | ;; Please send me bug reports, bug fixes, and extensions, so that I can | 58 | ;; Feedback is welcome. |
| 77 | ;; merge them into the master source. | 59 | ;; To submit a bug report (or make comments) please use the mechanism provided: |
| 78 | ;; - Simon Marshall (Simon.Marshall@mail.esrin.esa.it) | 60 | ;; |
| 61 | ;; M-x fast-lock-submit-bug-report RET | ||
| 79 | 62 | ||
| 80 | (require 'font-lock) | 63 | (require 'font-lock) |
| 81 | 64 | ||
| @@ -83,16 +66,37 @@ | |||
| 83 | ;; Shut Emacs' byte-compiler up (cf. stop me getting mail from users). | 66 | ;; Shut Emacs' byte-compiler up (cf. stop me getting mail from users). |
| 84 | (setq byte-compile-warnings '(free-vars callargs redefine))) | 67 | (setq byte-compile-warnings '(free-vars callargs redefine))) |
| 85 | 68 | ||
| 86 | ;; User variables: | 69 | (defun fast-lock-submit-bug-report () |
| 70 | "Submit via mail a bug report on fast-lock.el." | ||
| 71 | (interactive) | ||
| 72 | (let ((reporter-prompt-for-summary-p t)) | ||
| 73 | (reporter-submit-bug-report "simon@gnu.ai.mit.edu" "fast-lock 3.06" | ||
| 74 | '(fast-lock-cache-directories fast-lock-minimum-size | ||
| 75 | fast-lock-save-others fast-lock-save-events fast-lock-save-faces) | ||
| 76 | nil nil | ||
| 77 | (concat "Hi Si., | ||
| 78 | |||
| 79 | I want to report a bug. I've read the `Bugs' section of `Info' on Emacs, so I | ||
| 80 | know how to make a clear and unambiguous report. To reproduce the bug: | ||
| 81 | |||
| 82 | Start a fresh Emacs via `" invocation-name " -no-init-file -no-site-file'. | ||
| 83 | In the `*scratch*' buffer, evaluate:")))) | ||
| 84 | |||
| 85 | ;;;###autoload | ||
| 86 | (defvar fast-lock-mode nil) ; for modeline | ||
| 87 | (defvar fast-lock-cache-timestamp nil) ; for saving/reading | ||
| 88 | (defvar fast-lock-cache-filename nil) ; for deleting | ||
| 89 | |||
| 90 | ;; User Variables: | ||
| 87 | 91 | ||
| 88 | (defvar fast-lock-cache-directories '("." "~/.emacs-flc") | 92 | (defvar fast-lock-cache-directories '("." "~/.emacs-flc") |
| 89 | ; - `internal', keep each file's font lock cache file in the same file. | 93 | ; - `internal', keep each file's Font Lock cache file in the same file. |
| 90 | ; - `external', keep each file's font lock cache file in the same directory. | 94 | ; - `external', keep each file's Font Lock cache file in the same directory. |
| 91 | "Directories in which font lock cache files are saved and read. | 95 | "Directories in which Font Lock cache files are saved and read. |
| 92 | Each item should be either DIR or a cons pair of the form (REGEXP . DIR) where | 96 | Each item should be either DIR or a cons pair of the form (REGEXP . DIR) where |
| 93 | DIR is a directory name (relative or absolute) and REGEXP is a regexp. | 97 | DIR is a directory name (relative or absolute) and REGEXP is a regexp. |
| 94 | 98 | ||
| 95 | An attempt will be made to save or read font lock cache files using these items | 99 | An attempt will be made to save or read Font Lock cache files using these items |
| 96 | until one succeeds (i.e., until a readable or writable one is found). If an | 100 | until one succeeds (i.e., until a readable or writable one is found). If an |
| 97 | item contains REGEXP, DIR is used only if the buffer file name matches REGEXP. | 101 | item contains REGEXP, DIR is used only if the buffer file name matches REGEXP. |
| 98 | For example: | 102 | For example: |
| @@ -101,174 +105,219 @@ For example: | |||
| 101 | \"~/.emacs-flc\") | 105 | \"~/.emacs-flc\") |
| 102 | 106 | ||
| 103 | would cause a file's current directory to be used if the file is under your | 107 | would cause a file's current directory to be used if the file is under your |
| 104 | home directory hierarchy, and the absolute directory otherwise.") | 108 | home directory hierarchy, or otherwise the absolute directory `~/.emacs-flc'.") |
| 105 | 109 | ||
| 106 | (defvar fast-lock-save-size (* 10 1024) | 110 | (defvar fast-lock-minimum-size (* 25 1024) |
| 107 | "If non-nil, the minimum size for buffer files. | 111 | "If non-nil, the minimum size for buffers. |
| 108 | Only buffer files at least this size can have associated font lock cache files | 112 | Only buffers more than this can have associated Font Lock cache files saved. |
| 109 | saved. If nil, means size is irrelevant.") | 113 | If nil, means size is irrelevant.") |
| 110 | 114 | ||
| 111 | (defvar fast-lock-save-others t | 115 | (defvar fast-lock-save-events '(kill-buffer kill-emacs) |
| 112 | "If non-nil, save font lock cache files irrespective of file owner. | 116 | "A list of events under which caches will be saved. |
| 113 | If nil, means only buffer files owned by you have a font lock cache saved.") | 117 | Valid events are `save-buffer', `kill-buffer' and `kill-emacs'. |
| 118 | If concurrent editing sessions use the same associated cache file for a file's | ||
| 119 | buffer, then you should add `save-buffer' to this list.") | ||
| 114 | 120 | ||
| 115 | (defvar fast-lock-mode nil) ; for modeline | 121 | (defvar fast-lock-save-others t |
| 116 | (defvar fast-lock-cache-timestamp nil) ; for saving/reading | 122 | "If non-nil, save Font Lock cache files irrespective of file owner. |
| 117 | (make-variable-buffer-local 'fast-lock-cache-timestamp) | 123 | If nil, means only buffer files known to be owned by you can have associated |
| 124 | Font Lock cache files saved. Ownership may be unknown for networked files.") | ||
| 125 | |||
| 126 | (defvar fast-lock-save-faces | ||
| 127 | ;; Since XEmacs uses extents for everything, we have to pick the right ones. | ||
| 128 | ;; In XEmacs 19.12 we can't identify which text properties are font-lock's. | ||
| 129 | (if (save-match-data (string-match "XEmacs" (emacs-version))) | ||
| 130 | '(font-lock-string-face font-lock-doc-string-face font-lock-type-face | ||
| 131 | font-lock-function-name-face font-lock-comment-face | ||
| 132 | font-lock-keyword-face) | ||
| 133 | ;; For Emacs 19.29 I don't think this is generally necessary. | ||
| 134 | ;(mapcar 'eval (mapcar 'car font-lock-face-attributes)) | ||
| 135 | ) | ||
| 136 | "A list of faces that will be saved in a Font Lock cache file. | ||
| 137 | If nil, means information for all faces will be saved.") | ||
| 118 | 138 | ||
| 119 | ;; Functions: | 139 | ;; User Functions: |
| 120 | 140 | ||
| 141 | ;;;###autoload | ||
| 121 | (defun fast-lock-mode (&optional arg) | 142 | (defun fast-lock-mode (&optional arg) |
| 122 | "Toggle Fast Lock mode. | 143 | "Toggle Fast Lock mode. |
| 123 | With arg, turn Fast Lock mode on if and only if arg is positive and the buffer | 144 | With arg, turn Fast Lock mode on if and only if arg is positive and the buffer |
| 124 | is associated with a file. | 145 | is associated with a file. Enable it automatically in your `~/.emacs' by: |
| 146 | |||
| 147 | (add-hook 'font-lock-mode-hook 'turn-on-fast-lock) | ||
| 125 | 148 | ||
| 126 | If Fast Lock mode is enabled, and the current buffer does not contain any text | 149 | If Fast Lock mode is enabled, and the current buffer does not contain any text |
| 127 | properties, any associated font lock cache is used (by `fast-lock-read-cache') | 150 | properties, any associated Font Lock cache is used if its timestamp matches the |
| 128 | if the same `font-lock-keywords' were used for the cache as you are using. | 151 | buffer's file, and its `font-lock-keywords' match those that you are using. |
| 152 | |||
| 153 | Font Lock caches may be saved: | ||
| 154 | - When you save the file's buffer. | ||
| 155 | - When you kill an unmodified file's buffer. | ||
| 156 | - When you exit Emacs, for all unmodified or saved buffers. | ||
| 157 | Depending on the value of `fast-lock-save-events'. | ||
| 158 | See also the commands `fast-lock-read-cache' and `fast-lock-save-cache'. | ||
| 129 | 159 | ||
| 130 | Font lock caches will be saved: | 160 | Use \\[font-lock-fontify-buffer] to fontify the buffer if the cache is bad. |
| 131 | - For all buffers with Fast Lock mode enabled when you exit from Emacs. | ||
| 132 | - For a buffer with Fast Lock mode enabled when you kill the buffer. | ||
| 133 | Saving is done by `fast-lock-save-cache' and `fast-lock-save-caches'. | ||
| 134 | 161 | ||
| 135 | Various methods of control are provided for the font lock cache. In general, | 162 | Various methods of control are provided for the Font Lock cache. In general, |
| 136 | see variable `fast-lock-cache-directories' and function `fast-lock-cache-name'. | 163 | see variable `fast-lock-cache-directories' and function `fast-lock-cache-name'. |
| 137 | For saving, see variables `fast-lock-save-others' and `fast-lock-save-size'." | 164 | For saving, see variables `fast-lock-minimum-size', `fast-lock-save-events', |
| 165 | `fast-lock-save-others' and `fast-lock-save-faces'. | ||
| 166 | |||
| 167 | Use \\[fast-lock-submit-bug-report] to send bug reports or feedback." | ||
| 138 | (interactive "P") | 168 | (interactive "P") |
| 139 | (set (make-local-variable 'fast-lock-mode) | 169 | (set (make-local-variable 'fast-lock-mode) |
| 140 | (and (buffer-file-name) | 170 | (and (buffer-file-name) |
| 141 | (if arg (> (prefix-numeric-value arg) 0) (not fast-lock-mode)))) | 171 | (if arg (> (prefix-numeric-value arg) 0) (not fast-lock-mode)))) |
| 142 | (if (and fast-lock-mode (not font-lock-fontified)) | 172 | (if (and fast-lock-mode (not font-lock-mode)) |
| 143 | (fast-lock-read-cache))) | 173 | ;; Turned on `fast-lock-mode' rather than using `font-lock-mode-hook'. |
| 174 | (progn | ||
| 175 | (add-hook 'font-lock-mode-hook 'turn-on-fast-lock) | ||
| 176 | (font-lock-mode 1)) | ||
| 177 | ;; Let's get down to business. | ||
| 178 | (set (make-local-variable 'fast-lock-cache-timestamp) nil) | ||
| 179 | (set (make-local-variable 'fast-lock-cache-filename) nil) | ||
| 180 | (if (and fast-lock-mode (not font-lock-fontified)) | ||
| 181 | (fast-lock-read-cache)))) | ||
| 144 | 182 | ||
| 145 | (defun fast-lock-read-cache () | 183 | (defun fast-lock-read-cache () |
| 146 | "Read the font lock cache for the current buffer. | 184 | "Read the Font Lock cache for the current buffer. |
| 147 | Returns t if the font lock cache file is read. | ||
| 148 | 185 | ||
| 149 | The following criteria must be met for a font lock cache file to be read: | 186 | The following criteria must be met for a Font Lock cache file to be read: |
| 150 | - Fast Lock mode must be turned on in the buffer. | 187 | - Fast Lock mode must be turned on in the buffer. |
| 188 | - The buffer must not be modified. | ||
| 151 | - The buffer's `font-lock-keywords' must match the cache's. | 189 | - The buffer's `font-lock-keywords' must match the cache's. |
| 152 | - The buffer file's timestamp must match the cache's. | 190 | - The buffer file's timestamp must match the cache's. |
| 153 | - Criteria imposed by `fast-lock-cache-directories'. | 191 | - Criteria imposed by `fast-lock-cache-directories'. |
| 154 | 192 | ||
| 155 | See also `fast-lock-save-cache' and `fast-lock-cache-name'." | 193 | See `fast-lock-mode'." |
| 156 | (interactive) | 194 | (interactive) |
| 157 | (let ((directories fast-lock-cache-directories) directory | 195 | (let ((directories fast-lock-cache-directories) |
| 158 | (modified (buffer-modified-p)) | 196 | (modified (buffer-modified-p)) (inhibit-read-only t) |
| 159 | (fontified font-lock-fontified)) | 197 | (fontified font-lock-fontified)) |
| 198 | (setq fast-lock-cache-filename nil) | ||
| 160 | (set (make-local-variable 'font-lock-fontified) nil) | 199 | (set (make-local-variable 'font-lock-fontified) nil) |
| 161 | ;; Keep trying directories until fontification is turned off. | 200 | ;; Keep trying directories until fontification is turned off. |
| 162 | (while (and directories (not font-lock-fontified)) | 201 | (while (and directories (not font-lock-fontified)) |
| 163 | (setq directory (fast-lock-cache-directory (car directories) nil) | 202 | (let* ((directory (fast-lock-cache-directory (car directories) nil)) |
| 164 | directories (cdr directories)) | 203 | (file (and directory (fast-lock-cache-name directory)))) |
| 165 | (if directory | 204 | (condition-case nil |
| 166 | (condition-case nil | 205 | (and file (file-readable-p file) (load file t t t)) |
| 167 | (load (fast-lock-cache-name directory) t t t) | 206 | (error nil) (quit nil)) |
| 168 | (error nil) (quit nil)))) | 207 | (setq directories (cdr directories)))) |
| 169 | (set-buffer-modified-p modified) | 208 | (set-buffer-modified-p modified) |
| 170 | (or font-lock-fontified (setq font-lock-fontified fontified)))) | 209 | (or font-lock-fontified (setq font-lock-fontified fontified)))) |
| 171 | 210 | ||
| 172 | (defun fast-lock-save-cache (&optional buffer) | 211 | (defun fast-lock-save-cache (&optional buffer) |
| 173 | "Save the font lock cache of BUFFER or the current buffer. | 212 | "Save the Font Lock cache of BUFFER or the current buffer. |
| 174 | Returns t if the font lock cache file is saved. | ||
| 175 | 213 | ||
| 176 | The following criteria must be met for a font lock cache file to be saved: | 214 | The following criteria must be met for a Font Lock cache file to be saved: |
| 177 | - Fast Lock mode must be turned on in the buffer. | 215 | - Fast Lock mode must be turned on in the buffer. |
| 178 | - The buffer must be at least `fast-lock-save-size' bytes long. | 216 | - The event must be one of `fast-lock-save-events'. |
| 217 | - The buffer must be at least `fast-lock-minimum-size' bytes long. | ||
| 179 | - The buffer file must be owned by you, or `fast-lock-save-others' must be t. | 218 | - The buffer file must be owned by you, or `fast-lock-save-others' must be t. |
| 180 | - The buffer must contain at least one `face' text property. | 219 | - The buffer must contain at least one `face' text property. |
| 181 | - The buffer file's timestamp must be different than its associated text | 220 | - The buffer must not be modified. |
| 182 | properties file's timestamp. | 221 | - The buffer file's timestamp must be the same as the file's on disk. |
| 222 | - The on disk file's timestamp must be different than the buffer's cache. | ||
| 183 | - Criteria imposed by `fast-lock-cache-directories'. | 223 | - Criteria imposed by `fast-lock-cache-directories'. |
| 184 | 224 | ||
| 185 | See also `fast-lock-save-caches', `fast-lock-read-cache' and `fast-lock-mode'." | 225 | See `fast-lock-mode'." |
| 186 | (interactive) | 226 | (interactive) |
| 187 | (let* ((bufile (buffer-file-name buffer)) | 227 | (save-excursion |
| 188 | (buatts (and bufile (file-attributes bufile))) | 228 | (and buffer (set-buffer buffer)) |
| 189 | (bufile-timestamp (nth 5 buatts)) | 229 | (let ((file-timestamp (visited-file-modtime)) (saved nil)) |
| 190 | (bufuid (nth 2 buatts)) (saved nil)) | ||
| 191 | (save-excursion | ||
| 192 | (and buffer (set-buffer buffer)) | ||
| 193 | (if (and fast-lock-mode | 230 | (if (and fast-lock-mode |
| 194 | ;; Only save if the timestamp of the file has changed. | 231 | ;; |
| 195 | (not (equal fast-lock-cache-timestamp bufile-timestamp)) | 232 | ;; "Only save if the buffer matches the file, the file has |
| 196 | ;; User's restrictions? | 233 | ;; changed, and it was changed by the current emacs session." |
| 197 | (or fast-lock-save-others (eq (user-uid) bufuid)) | 234 | ;; |
| 198 | (<= (or fast-lock-save-size 0) (buffer-size)) | 235 | ;; Only save if the buffer is not modified, |
| 199 | ;; Only save if there are properties to save. | 236 | ;; (i.e., so we don't save for something not on disk) |
| 237 | (not (buffer-modified-p)) | ||
| 238 | ;; and the file's timestamp is the same as the buffer's, | ||
| 239 | ;; (i.e., someone else hasn't written the file in the meantime) | ||
| 240 | (verify-visited-file-modtime (current-buffer)) | ||
| 241 | ;; and the file's timestamp is different from the cache's. | ||
| 242 | ;; (i.e., a save has occurred since the cache was read) | ||
| 243 | (not (equal fast-lock-cache-timestamp file-timestamp)) | ||
| 244 | ;; | ||
| 245 | ;; Only save if user's restrictions are satisfied. | ||
| 246 | (or (not fast-lock-minimum-size) | ||
| 247 | (<= fast-lock-minimum-size (buffer-size))) | ||
| 248 | (or fast-lock-save-others | ||
| 249 | (eq (user-uid) (nth 2 (file-attributes buffer-file-name)))) | ||
| 250 | ;; | ||
| 251 | ;; Only save if there are `face' properties to save. | ||
| 200 | (text-property-not-all (point-min) (point-max) 'face nil)) | 252 | (text-property-not-all (point-min) (point-max) 'face nil)) |
| 201 | (let ((directories fast-lock-cache-directories) directory) | 253 | ;; Try each directory until we manage to save or the user quits. |
| 202 | (while (and directories (not saved)) | 254 | (let ((directories fast-lock-cache-directories)) |
| 203 | (setq directory (fast-lock-cache-directory (car directories) t) | 255 | (while (and directories (memq saved '(nil error))) |
| 204 | directories (cdr directories)) | 256 | (let* ((dir (fast-lock-cache-directory (car directories) t)) |
| 205 | (if directory | 257 | (file (and dir (fast-lock-cache-name dir)))) |
| 206 | (setq saved (fast-lock-save-cache-data | 258 | (if (and file (file-writable-p file)) |
| 207 | directory bufile-timestamp)))))) | 259 | (setq saved (fast-lock-save-cache-1 file file-timestamp))) |
| 208 | ;; Set the buffer's timestamp if saved. | 260 | (setq directories (cdr directories))))))))) |
| 209 | (and saved (setq fast-lock-cache-timestamp bufile-timestamp))) | 261 | |
| 210 | saved)) | 262 | ;;;###autoload |
| 211 | |||
| 212 | (defun fast-lock-save-cache-data (directory timestamp) | ||
| 213 | ;; Save the file with the timestamp, if we can, in the given directory, as: | ||
| 214 | ;; (fast-lock-cache-data Version=2 TIMESTAMP font-lock-keywords PROPERTIES). | ||
| 215 | (let ((buname (buffer-name)) | ||
| 216 | (tpfile (fast-lock-cache-name directory)) | ||
| 217 | (saved nil)) | ||
| 218 | (if (file-writable-p tpfile) | ||
| 219 | (let ((tpbuf (generate-new-buffer " *fast-lock*"))) | ||
| 220 | (message "Saving %s font lock cache..." buname) | ||
| 221 | (unwind-protect | ||
| 222 | (save-excursion | ||
| 223 | (print (list 'fast-lock-cache-data 2 | ||
| 224 | (list 'quote timestamp) | ||
| 225 | (list 'quote font-lock-keywords) | ||
| 226 | (list 'quote (fast-lock-get-face-properties))) | ||
| 227 | tpbuf) | ||
| 228 | (set-buffer tpbuf) | ||
| 229 | (write-region (point-min) (point-max) tpfile nil 'quietly) | ||
| 230 | (setq saved t)) | ||
| 231 | (kill-buffer tpbuf)) | ||
| 232 | (message "Saving %s font lock cache... done." buname))) | ||
| 233 | saved)) | ||
| 234 | |||
| 235 | ;; Miscellaneous functions: | ||
| 236 | |||
| 237 | (defun turn-on-fast-lock () | 263 | (defun turn-on-fast-lock () |
| 238 | "Unconditionally turn on Fast Lock mode." | 264 | "Unconditionally turn on Fast Lock mode." |
| 239 | (fast-lock-mode 1)) | 265 | (fast-lock-mode 1)) |
| 266 | |||
| 267 | ;;; API Functions: | ||
| 268 | |||
| 269 | (defun fast-lock-after-fontify-buffer () | ||
| 270 | ;; Delete the Font Lock cache file used to restore fontification, if any. | ||
| 271 | (if fast-lock-cache-filename | ||
| 272 | (if (file-writable-p fast-lock-cache-filename) | ||
| 273 | (delete-file fast-lock-cache-filename) | ||
| 274 | (message "File %s font lock cache cannot be deleted" (buffer-name)))) | ||
| 275 | ;; Flag so that a cache will be saved later even if the file is never saved. | ||
| 276 | (setq fast-lock-cache-timestamp nil)) | ||
| 277 | |||
| 278 | ;; Miscellaneous Functions: | ||
| 279 | |||
| 280 | (defun fast-lock-after-save-hook () | ||
| 281 | ;; Do `fast-lock-save-cache' if `save-buffer' is on `fast-lock-save-events'. | ||
| 282 | (if (memq 'save-buffer fast-lock-save-events) | ||
| 283 | (fast-lock-save-cache))) | ||
| 284 | |||
| 285 | (defun fast-lock-kill-buffer-hook () | ||
| 286 | ;; Do `fast-lock-save-cache' if `kill-buffer' is on `fast-lock-save-events'. | ||
| 287 | (if (memq 'kill-buffer fast-lock-save-events) | ||
| 288 | (fast-lock-save-cache))) | ||
| 240 | 289 | ||
| 241 | (defun fast-lock-save-caches () | 290 | (defun fast-lock-kill-emacs-hook () |
| 242 | "Save the font lock caches of all buffers. | 291 | ;; Do `fast-lock-save-cache's if `kill-emacs' is on `fast-lock-save-events'. |
| 243 | Returns list of cache save success of buffers in `buffer-list'. | 292 | (if (memq 'kill-emacs fast-lock-save-events) |
| 244 | See `fast-lock-save-cache' for details of save criteria." | 293 | (mapcar 'fast-lock-save-cache (buffer-list)))) |
| 245 | (mapcar 'fast-lock-save-cache (buffer-list))) | ||
| 246 | 294 | ||
| 247 | (defun fast-lock-cache-directory (directory create) | 295 | (defun fast-lock-cache-directory (directory create) |
| 248 | "Return usable directory based on DIRECTORY. | 296 | "Return usable directory based on DIRECTORY. |
| 249 | Returns nil if the directory does not exist, or, if CREATE non-nil, cannot be | 297 | Returns nil if the directory does not exist, or, if CREATE non-nil, cannot be |
| 250 | created. DIRECTORY may be a string or a cons pair of the form (REGEXP . DIR). | 298 | created. DIRECTORY may be a string or a cons pair of the form (REGEXP . DIR). |
| 251 | See `fast-lock-cache-directories'." | 299 | See `fast-lock-cache-directories'." |
| 252 | (let ((dir (cond ((not buffer-file-name) | 300 | (let ((dir |
| 253 | nil) | 301 | (cond ((not buffer-file-name) |
| 254 | ((stringp directory) | 302 | ;; Should never be nil, but `crypt++' screws it up. |
| 255 | directory) | 303 | nil) |
| 256 | (t | 304 | ((stringp directory) |
| 257 | (let ((bufile (expand-file-name | 305 | ;; Just a directory. |
| 258 | (abbreviate-file-name | 306 | directory) |
| 259 | (file-truename buffer-file-name)))) | 307 | (t |
| 260 | (case-fold-search nil)) | 308 | ;; A directory iff the file name matches the regexp. |
| 261 | (if (string-match (car directory) bufile) | 309 | (let ((bufile (expand-file-name buffer-file-truename)) |
| 262 | (cdr directory))))))) | 310 | (case-fold-search nil)) |
| 311 | (if (save-match-data (string-match (car directory) bufile)) | ||
| 312 | (cdr directory))))))) | ||
| 263 | (cond ((not dir) | 313 | (cond ((not dir) |
| 264 | nil) | 314 | nil) |
| 265 | ((not create) | 315 | ((file-accessible-directory-p dir) |
| 266 | (and (file-accessible-directory-p dir) dir)) | 316 | dir) |
| 267 | (t | 317 | (create |
| 268 | (if (file-accessible-directory-p dir) | 318 | (condition-case nil |
| 269 | dir | 319 | (progn (make-directory dir t) dir) |
| 270 | (condition-case nil (make-directory dir t) (error nil)) | 320 | (error nil)))))) |
| 271 | (and (file-accessible-directory-p dir) dir)))))) | ||
| 272 | 321 | ||
| 273 | (defun fast-lock-cache-name (directory) | 322 | (defun fast-lock-cache-name (directory) |
| 274 | "Return full cache path name using caching DIRECTORY. | 323 | "Return full cache path name using caching DIRECTORY. |
| @@ -280,8 +329,7 @@ characters, and appended with `.flc'. | |||
| 280 | See `fast-lock-mode'." | 329 | See `fast-lock-mode'." |
| 281 | (if (string-equal directory ".") | 330 | (if (string-equal directory ".") |
| 282 | (concat buffer-file-name ".flc") | 331 | (concat buffer-file-name ".flc") |
| 283 | (let* ((bufile (expand-file-name | 332 | (let* ((bufile (expand-file-name buffer-file-truename)) |
| 284 | (abbreviate-file-name (file-truename buffer-file-name)))) | ||
| 285 | (chars-alist | 333 | (chars-alist |
| 286 | (if (eq system-type 'emx) | 334 | (if (eq system-type 'emx) |
| 287 | '((?/ . (?#)) (?# . (?# ?#)) (?: . (?\;)) (?\; . (?\; ?\;))) | 335 | '((?/ . (?#)) (?# . (?# ?#)) (?: . (?\;)) (?\; . (?\; ?\;))) |
| @@ -293,149 +341,193 @@ See `fast-lock-mode'." | |||
| 293 | (mapconcat 'char-to-string (apply 'append (mapcar mapchars bufile)) "") | 341 | (mapconcat 'char-to-string (apply 'append (mapcar mapchars bufile)) "") |
| 294 | ".flc")))) | 342 | ".flc")))) |
| 295 | 343 | ||
| 296 | ;; Font lock cache processing functions: | 344 | ;; Font Lock Cache Processing Functions: |
| 345 | |||
| 346 | (defun fast-lock-save-cache-1 (file timestamp) | ||
| 347 | ;; Save the FILE with the TIMESTAMP as: | ||
| 348 | ;; (fast-lock-cache-data Version=2 TIMESTAMP font-lock-keywords PROPERTIES). | ||
| 349 | ;; Returns non-nil if a save was attempted to a writable cache file. | ||
| 350 | (let ((tpbuf (generate-new-buffer " *fast-lock*")) | ||
| 351 | (buname (buffer-name)) (saved t)) | ||
| 352 | (message "Saving %s font lock cache..." buname) | ||
| 353 | (condition-case nil | ||
| 354 | (save-excursion | ||
| 355 | (print (list 'fast-lock-cache-data 2 | ||
| 356 | (list 'quote timestamp) | ||
| 357 | (list 'quote font-lock-keywords) | ||
| 358 | (list 'quote (fast-lock-get-face-properties))) | ||
| 359 | tpbuf) | ||
| 360 | (set-buffer tpbuf) | ||
| 361 | (write-region (point-min) (point-max) file nil 'quietly) | ||
| 362 | (setq fast-lock-cache-timestamp timestamp | ||
| 363 | fast-lock-cache-filename file)) | ||
| 364 | (error (setq saved 'error)) (quit (setq saved 'quit))) | ||
| 365 | (kill-buffer tpbuf) | ||
| 366 | (message "Saving %s font lock cache... %s." buname | ||
| 367 | (cond ((eq saved 'error) "failed") | ||
| 368 | ((eq saved 'quit) "aborted") | ||
| 369 | (t "done"))) | ||
| 370 | ;; We return non-nil regardless of whether a failure occurred. | ||
| 371 | saved)) | ||
| 297 | 372 | ||
| 298 | (defun fast-lock-cache-data (version timestamp keywords properties | 373 | (defun fast-lock-cache-data (version timestamp keywords properties |
| 299 | &rest ignored) | 374 | &rest ignored) |
| 300 | ;; Use the font lock cache PROPERTIES if we're using cache VERSION format 2, | 375 | ;; Change from (HIGH LOW) for back compatibility. Remove for version 3! |
| 376 | (if (consp (cdr-safe timestamp)) (setcdr timestamp (nth 1 timestamp))) | ||
| 377 | ;; Compile KEYWORDS and `font-lock-keywords' in case one is and one isn't. | ||
| 378 | (let ((current font-lock-keywords)) | ||
| 379 | (setq keywords (font-lock-compile-keywords keywords) | ||
| 380 | font-lock-keywords (font-lock-compile-keywords current))) | ||
| 381 | ;; Use the Font Lock cache PROPERTIES if we're using cache VERSION format 2, | ||
| 301 | ;; the current buffer's file timestamp matches the TIMESTAMP, and the current | 382 | ;; the current buffer's file timestamp matches the TIMESTAMP, and the current |
| 302 | ;; buffer's font-lock-keywords are the same as KEYWORDS. | 383 | ;; buffer's font-lock-keywords are the same as KEYWORDS. |
| 303 | (let ((buf-timestamp (nth 5 (file-attributes buffer-file-name))) | 384 | (let ((buf-timestamp (visited-file-modtime)) |
| 304 | (buname (buffer-name)) (inhibit-read-only t) (loaded t)) | 385 | (buname (buffer-name)) (loaded t)) |
| 305 | (if (or (/= version 2) | 386 | (if (or (/= version 2) |
| 387 | (buffer-modified-p) | ||
| 306 | (not (equal timestamp buf-timestamp)) | 388 | (not (equal timestamp buf-timestamp)) |
| 307 | (not (equal keywords font-lock-keywords))) | 389 | (not (equal keywords font-lock-keywords))) |
| 308 | (setq loaded nil) | 390 | (setq loaded nil) |
| 309 | (message "Loading %s font lock cache..." buname) | 391 | (message "Loading %s font lock cache..." buname) |
| 310 | (condition-case nil | 392 | (condition-case nil |
| 311 | (fast-lock-set-face-properties properties) | 393 | (fast-lock-set-face-properties properties) |
| 312 | (error (setq loaded nil)) (quit (setq loaded nil))) | 394 | (error (setq loaded 'error)) (quit (setq loaded 'quit))) |
| 313 | (message "Loading %s font lock cache... done." buname)) | 395 | (message "Loading %s font lock cache... %s." buname |
| 396 | (cond ((eq loaded 'error) "failed") | ||
| 397 | ((eq loaded 'quit) "aborted") | ||
| 398 | (t "done")))) | ||
| 314 | ;; If we used the text properties, stop fontification and keep timestamp. | 399 | ;; If we used the text properties, stop fontification and keep timestamp. |
| 315 | (setq font-lock-fontified loaded | 400 | ;; Kludge warning: `file' comes from sole caller `fast-lock-read-cache'. |
| 316 | fast-lock-cache-timestamp (and loaded timestamp)))) | 401 | (setq font-lock-fontified (eq loaded t) |
| 317 | 402 | fast-lock-cache-timestamp (and (eq loaded t) timestamp) | |
| 318 | (defun fast-lock-get-face-properties (&optional buffer) | 403 | fast-lock-cache-filename (and (eq loaded t) file)))) |
| 319 | "Return a list of all `face' text properties in BUFFER. | 404 | |
| 405 | ;; Text Properties Processing Functions: | ||
| 406 | |||
| 407 | ;; This is faster, but fails if adjacent characters have different `face' text | ||
| 408 | ;; properties. Maybe that's why I dropped it in the first place? | ||
| 409 | ;(defun fast-lock-get-face-properties () | ||
| 410 | ; "Return a list of all `face' text properties in the current buffer. | ||
| 411 | ;Each element of the list is of the form (VALUE START1 END1 START2 END2 ...) | ||
| 412 | ;where VALUE is a `face' property value and STARTx and ENDx are positions." | ||
| 413 | ; (save-restriction | ||
| 414 | ; (widen) | ||
| 415 | ; (let ((start (text-property-not-all (point-min) (point-max) 'face nil)) | ||
| 416 | ; (limit (point-max)) end properties value cell) | ||
| 417 | ; (while start | ||
| 418 | ; (setq end (next-single-property-change start 'face nil limit) | ||
| 419 | ; value (get-text-property start 'face)) | ||
| 420 | ; ;; Make, or add to existing, list of regions with same `face'. | ||
| 421 | ; (if (setq cell (assq value properties)) | ||
| 422 | ; (setcdr cell (cons start (cons end (cdr cell)))) | ||
| 423 | ; (setq properties (cons (list value start end) properties))) | ||
| 424 | ; (setq start (next-single-property-change end 'face))) | ||
| 425 | ; properties))) | ||
| 426 | |||
| 427 | (defun fast-lock-get-face-properties () | ||
| 428 | "Return a list of all `face' text properties in the current buffer. | ||
| 320 | Each element of the list is of the form (VALUE START1 END1 START2 END2 ...) | 429 | Each element of the list is of the form (VALUE START1 END1 START2 END2 ...) |
| 321 | where VALUE is a `face' property value and STARTx and ENDx are positions." | 430 | where VALUE is a `face' property value and STARTx and ENDx are positions. |
| 322 | (save-excursion | 431 | Only those `face' VALUEs in `fast-lock-save-faces' are returned." |
| 323 | (and buffer (set-buffer buffer)) | 432 | (save-restriction |
| 324 | (save-restriction | 433 | (widen) |
| 325 | (widen) | 434 | (let ((faces (or fast-lock-save-faces (face-list))) (limit (point-max)) |
| 326 | (let ((start (text-property-not-all (point-min) (point-max) 'face nil)) | 435 | properties regions face start end) |
| 327 | (limit (point-max)) end properties value cell) | 436 | (while faces |
| 328 | (while start | 437 | (setq face (car faces) faces (cdr faces) regions () end (point-min)) |
| 329 | (setq end (next-single-property-change start 'face nil limit) | 438 | ;; Make a list of start/end regions with `face' property face. |
| 330 | value (get-text-property start 'face)) | 439 | (while (setq start (text-property-any end limit 'face face)) |
| 331 | ;; Make or add to existing list of regions with same `face' property. | 440 | (setq end (or (text-property-not-all start limit 'face face) limit) |
| 332 | (if (setq cell (assq value properties)) | 441 | regions (cons start (cons end regions)))) |
| 333 | (setcdr cell (cons start (cons end (cdr cell)))) | 442 | ;; Add `face' face's regions, if any, to properties. |
| 334 | (setq properties (cons (list value start end) properties))) | 443 | (if regions (setq properties (cons (cons face regions) properties)))) |
| 335 | (setq start (next-single-property-change end 'face))) | 444 | properties))) |
| 336 | properties)))) | 445 | |
| 337 | 446 | (defun fast-lock-set-face-properties (properties) | |
| 338 | (defun fast-lock-set-face-properties (properties &optional buffer) | 447 | "Set all `face' text properties to PROPERTIES in the current buffer. |
| 339 | "Set all `face' text properties to PROPERTIES in BUFFER. | 448 | Any existing `face' text properties are removed first. Leaves buffer modified. |
| 340 | Any existing `face' text properties are removed first. Leaves BUFFER modified. | ||
| 341 | See `fast-lock-get-face-properties' for the format of PROPERTIES." | 449 | See `fast-lock-get-face-properties' for the format of PROPERTIES." |
| 342 | (save-excursion | 450 | (save-restriction |
| 343 | (and buffer (set-buffer buffer)) | 451 | (widen) |
| 344 | (save-restriction | 452 | (font-lock-unfontify-region (point-min) (point-max)) |
| 345 | (widen) | 453 | (while properties |
| 346 | (font-lock-unfontify-region (point-min) (point-max)) | 454 | (let ((plist (list 'face (car (car properties)))) |
| 347 | (while properties | 455 | (regions (cdr (car properties)))) |
| 348 | (let ((plist (list 'face (car (car properties)))) | 456 | ;; Set the `face' property for each start/end region. |
| 349 | (regions (cdr (car properties)))) | 457 | (while regions |
| 350 | ;; Set the `face' property for each start/end region. | 458 | (set-text-properties (nth 0 regions) (nth 1 regions) plist) |
| 351 | (while regions | 459 | (setq regions (nthcdr 2 regions))) |
| 352 | (set-text-properties (nth 0 regions) (nth 1 regions) plist buffer) | 460 | (setq properties (cdr properties)))))) |
| 353 | (setq regions (nthcdr 2 regions))) | ||
| 354 | (setq properties (cdr properties))))))) | ||
| 355 | 461 | ||
| 356 | ;; Functions for Lucid: | 462 | ;; Functions for XEmacs: |
| 357 | 463 | ||
| 358 | (or (fboundp 'face-list) | 464 | (if (save-match-data (string-match "XEmacs" (emacs-version))) |
| 359 | (defalias 'face-list 'list-faces)) | 465 | ;; It would be better to use XEmacs 19.12's `map-extents' over extents with |
| 360 | 466 | ;; `font-lock' property, but `face' properties are on different extents. | |
| 361 | (if (save-match-data (string-match "Lucid" (emacs-version))) | 467 | (defun fast-lock-get-face-properties () |
| 362 | ;; This is about a bazillion times faster at generating the cache in Lucid. | 468 | "Return a list of all `face' text properties in the current buffer. |
| 363 | (defun fast-lock-get-face-properties (&optional buffer) | ||
| 364 | "Return a list of all `face' text properties in BUFFER. | ||
| 365 | Each element of the list is of the form (VALUE START1 END1 START2 END2 ...) | 469 | Each element of the list is of the form (VALUE START1 END1 START2 END2 ...) |
| 366 | where VALUE is a `face' property value and STARTx and ENDx are positions." | 470 | where VALUE is a `face' property value and STARTx and ENDx are positions. |
| 367 | (save-excursion | 471 | Only those `face' VALUEs in `fast-lock-save-faces' are returned." |
| 368 | (and buffer (set-buffer buffer)) | 472 | (save-restriction |
| 369 | (save-restriction | 473 | (widen) |
| 370 | (widen) | 474 | (let ((properties ()) cell) |
| 371 | (let ((properties ())) | 475 | (map-extents |
| 372 | (map-extents | 476 | (function |
| 373 | (function (lambda (extent ignore) | 477 | (lambda (extent ignore) |
| 374 | (let* ((face (extent-face extent)) | 478 | (let ((value (extent-face extent))) |
| 375 | (start (extent-start-position extent)) | 479 | ;; We're only interested if it's one of `fast-lock-save-faces'. |
| 376 | (end (extent-end-position extent)) | 480 | (if (and value (or (null fast-lock-save-faces) |
| 377 | (facedata (assoc face properties))) | 481 | (memq value fast-lock-save-faces))) |
| 378 | (if facedata | 482 | (let ((start (extent-start-position extent)) |
| 379 | ;; Prepend the new start and end points onto the list. | 483 | (end (extent-end-position extent))) |
| 380 | (setcdr facedata (cons start (cons end (cdr facedata)))) | 484 | ;; Make or add to existing list of regions with the same |
| 381 | (setq properties (cons (list face start end) properties))) | 485 | ;; `face' property value. |
| 486 | (if (setq cell (assq value properties)) | ||
| 487 | (setcdr cell (cons start (cons end (cdr cell)))) | ||
| 488 | (setq properties (cons (list value start end) | ||
| 489 | properties))))) | ||
| 382 | ;; Return nil to keep `map-extents' going. | 490 | ;; Return nil to keep `map-extents' going. |
| 383 | nil)))) | 491 | nil)))) |
| 384 | properties))))) | 492 | properties)))) |
| 385 | 493 | ||
| 386 | (if (save-match-data (string-match "Lucid" (emacs-version))) | 494 | (if (save-match-data (string-match "XEmacs" (emacs-version))) |
| 387 | ;; This is faster at using the cache in Lucid. | 495 | ;; Make extents just like XEmacs's font-lock.el does. |
| 388 | (defun fast-lock-set-face-properties (properties &optional buffer) | 496 | (defun fast-lock-set-face-properties (properties) |
| 389 | "Set all `face' text properties to PROPERTIES in BUFFER. | 497 | "Set all `face' text properties to PROPERTIES in the current buffer. |
| 390 | Any existing `face' text properties are removed first. Leaves BUFFER modified. | 498 | Any existing `face' text properties are removed first. |
| 391 | See `fast-lock-get-face-properties' for the format of PROPERTIES." | 499 | See `fast-lock-get-face-properties' for the format of PROPERTIES." |
| 392 | (save-excursion | 500 | (save-restriction |
| 393 | (and buffer (set-buffer buffer)) | 501 | (widen) |
| 394 | (save-restriction | 502 | (font-lock-unfontify-region (point-min) (point-max)) |
| 395 | (widen) | 503 | (while properties |
| 396 | (font-lock-unfontify-region (point-min) (point-max)) | 504 | (let ((face (car (car properties))) |
| 397 | (while properties | 505 | (regions (cdr (car properties)))) |
| 398 | (let ((property (car (car properties))) | 506 | ;; Set the `face' property, etc., for each start/end region. |
| 399 | (regions (cdr (car properties))) extent) | 507 | (while regions |
| 400 | ;; Set the `face' property for each start/end region. | 508 | (font-lock-set-face (nth 0 regions) (nth 1 regions) face) |
| 401 | (while regions | 509 | (setq regions (nthcdr 2 regions))) |
| 402 | (setq extent (make-extent (nth 0 regions) (nth 1 regions)) | 510 | (setq properties (cdr properties))))))) |
| 403 | regions (nthcdr 2 regions)) | 511 | |
| 404 | (set-extent-face extent property) | 512 | (or (fboundp 'font-lock-compile-keywords) |
| 405 | (set-extent-property extent 'text-prop 'face)) | 513 | (defalias 'font-lock-compile-keywords 'identity)) |
| 406 | (setq properties (cdr properties)))))))) | ||
| 407 | |||
| 408 | (if (and (boundp 'emacs-minor-version) (< emacs-minor-version 12)) | ||
| 409 | ;; Must be [LX]Emacs; fix the 19.11 (at least) `text-property-not-all' bug. | ||
| 410 | (defun text-property-not-all (start end prop value &optional buffer) | ||
| 411 | "Check text from START to END to see if PROP is ever not `eq' to VALUE. | ||
| 412 | If so, return the position of the first character whose PROP is not | ||
| 413 | `eq' to VALUE. Otherwise, return nil." | ||
| 414 | (let ((maxend start)) | ||
| 415 | (map-extents | ||
| 416 | (function | ||
| 417 | (lambda (e ignore) | ||
| 418 | ;;### no, actually, this is harder. We need to collect all props | ||
| 419 | ;; for a given character, and then determine whether no extent | ||
| 420 | ;; contributes the given value. Doing this without consing lots | ||
| 421 | ;; of lists is the tricky part. | ||
| 422 | (if (not (eq value (extent-property e prop))) | ||
| 423 | (max start maxend) | ||
| 424 | (setq maxend (extent-end-position e)) | ||
| 425 | nil))) | ||
| 426 | nil start end buffer)))) | ||
| 427 | 514 | ||
| 428 | ;; Install ourselves: | 515 | ;; Install ourselves: |
| 429 | 516 | ||
| 517 | ;; We don't install ourselves on `font-lock-mode-hook' as packages with similar | ||
| 518 | ;; functionality exist, and fast-lock.el should be dumpable. | ||
| 519 | (add-hook 'after-save-hook 'fast-lock-after-save-hook) | ||
| 520 | (add-hook 'kill-buffer-hook 'fast-lock-kill-buffer-hook) | ||
| 521 | (add-hook 'kill-emacs-hook 'fast-lock-kill-emacs-hook) | ||
| 522 | |||
| 523 | ;; Maybe save on the modeline? | ||
| 524 | ;;(setcdr (assq 'font-lock-mode minor-mode-alist) '(" Fast")) | ||
| 525 | |||
| 430 | (or (assq 'fast-lock-mode minor-mode-alist) | 526 | (or (assq 'fast-lock-mode minor-mode-alist) |
| 431 | (setq minor-mode-alist (cons '(fast-lock-mode " Fast") minor-mode-alist))) | 527 | (setq minor-mode-alist (cons '(fast-lock-mode " Fast") minor-mode-alist))) |
| 432 | 528 | ||
| 433 | (add-hook 'kill-buffer-hook 'fast-lock-save-cache) | ||
| 434 | (add-hook 'kill-emacs-hook 'fast-lock-save-caches) | ||
| 435 | |||
| 436 | ;; Provide ourselves: | 529 | ;; Provide ourselves: |
| 437 | 530 | ||
| 438 | (provide 'fast-lock) | 531 | (provide 'fast-lock) |
| 439 | 532 | ||
| 440 | ;;; fast-lock.el ends here | 533 | ;;; fast-lock.el ends here |
| 441 | |||