chris -- please try the attached patch and let me know [a] if it speeds things
up, and [b] if you see any problems.
Chris Holt wrote:
Ben Wing writes:
> ok i understand what's going on. i need to rewrite the font-lock
> after-change functions to use text properties instead of extents, and add
> some additional trickiness for deletes. as it is, you're getting 7900
> extents in the buffer generated by 7900 text-insertion operations, and
> each insertion operation needs to adjust the endpoint of all following
> extents ... you get the N^2 idea.
>
Just like Newton's apple: It fell right on my head. :-)
> i'll fix this within a couple of days and send a patch.
>
Sweet. Thanks.
> thanks once again for the investigative work, chris.
>
Most welcome, but I must admit that I'm one of those that needs font-lock to
work. I don't use the menubar, speedbar, buffers-tab, or gutter, but I *do*
worship at the altar of font-lock... and dynamic completion. Best things for
programming since the invention of the compiler.
Chris
--
ben
I'm sometimes slow in getting around to reading my mail, so if you
want to reach me faster, call 520-661-6661.
See
http://www.666.com/ben/chronic-pain/ for the hell I've been
through.
Index: font-lock.el
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/lisp/font-lock.el,v
retrieving revision 1.7.2.23
diff -u -r1.7.2.23 font-lock.el
--- font-lock.el 2000/08/06 09:26:48 1.7.2.23
+++ font-lock.el 2001/02/03 07:28:43
@@ -1130,12 +1130,14 @@
next redisplay cycle, avoiding excessive fontification when many
buffer modifications are performed or a buffer is reverted.")
-(defvar font-lock-pending-extent-table (make-hash-table :weakness 'key))
+;; list of buffers in which there is a pending change.
+(defvar font-lock-pending-buffer-table (make-hash-table :weakness 'key))
+;; table used to keep track of ranges needing fontification.
(defvar font-lock-range-table (make-range-table))
(defun font-lock-pre-idle-hook ()
(condition-case font-lock-error
- (if (> (hash-table-count font-lock-pending-extent-table) 0)
+ (if (> (hash-table-count font-lock-pending-buffer-table) 0)
(font-lock-fontify-pending-extents))
(error (warn "Error caught in `font-lock-pre-idle-hook': %s"
font-lock-error))))
@@ -1147,12 +1149,15 @@
(defun font-lock-after-change-function (beg end old-len)
(when font-lock-mode
- (let ((ex (make-extent beg end)))
- (set-extent-property ex 'detachable nil)
- (set-extent-property ex 'end-open nil)
- (let ((exs (gethash (current-buffer) font-lock-pending-extent-table)))
- (push ex exs)
- (puthash (current-buffer) exs font-lock-pending-extent-table)))
+ ;; treat deletions as if the following character (or previous, if
+ ;; there is no following) were inserted. this is a bit of a hack
+ ;; but allows us to use text properties for everything.
+ (if (= beg end)
+ (cond ((/= end (point-max)) (setq end (1+ end)))
+ ((/= beg (point-min)) (setq beg (1- beg)))
+ (t nil)))
+ (put-text-property beg end 'font-lock-pending t)
+ (puthash (current-buffer) t font-lock-pending-buffer-table)
(if font-lock-always-fontify-immediately
(font-lock-fontify-pending-extents))))
@@ -1162,39 +1167,43 @@
;; only one buffer and one contiguous region!
(save-match-data
(maphash
- #'(lambda (buffer exs)
+ #'(lambda (buffer dummy)
;; remove first, to avoid infinite reprocessing if error
- (remhash buffer font-lock-pending-extent-table)
+ (remhash buffer font-lock-pending-buffer-table)
(when (buffer-live-p buffer)
(clear-range-table font-lock-range-table)
(with-current-buffer buffer
(save-excursion
(save-restriction
- ;; if we don't widen, then the C code will fail to
- ;; realize that we're inside a comment.
+ ;; if we don't widen, then the C code in
+ ;; syntactically-sectionize will fail to realize that
+ ;; we're inside a comment.
(widen)
(let ((zmacs-region-stays
zmacs-region-stays)) ; protect from change!
- (mapc
- #'(lambda (ex)
- ;; paranoia.
- (when (and (extent-live-p ex)
- (not (extent-detached-p ex)))
- ;; first expand the ranges to full lines, because
- ;; that is what will be fontified; then use a
- ;; range table to merge the ranges.
- (let* ((beg (extent-start-position ex))
- (end (extent-end-position ex))
- (beg (progn (goto-char beg)
- (beginning-of-line)
- (point)))
- (end (progn (goto-char end)
- (forward-line 1)
- (point))))
- (detach-extent ex)
- (put-range-table beg end t
- font-lock-range-table))))
- exs)
+ (map-extents
+ #'(lambda (ex dummy-maparg)
+ ;; first expand the ranges to full lines,
+ ;; because that is what will be fontified;
+ ;; then use a range table to merge the
+ ;; ranges. (we could also do this simply using
+ ;; text properties. the range table code was
+ ;; here from a previous version of this code
+ ;; and works just as well.)
+ (let* ((beg (extent-start-position ex))
+ (end (extent-end-position ex))
+ (beg (progn (goto-char beg)
+ (beginning-of-line)
+ (point)))
+ (end (progn (goto-char end)
+ (forward-line 1)
+ (point))))
+ (put-range-table beg end t
+ font-lock-range-table)))
+ nil nil nil nil nil 'font-lock-pending t)
+ ;; clear all pending extents first in case of error below.
+ (put-text-property (point-min) (point-max)
+ 'font-lock-pending nil)
(map-range-table
#'(lambda (beg end val)
;; Maybe flush the internal cache used by
@@ -1216,14 +1225,14 @@
;; (font-lock-fontify-region beg end)))
(font-lock-fontify-region beg end))
font-lock-range-table)))))))
- font-lock-pending-extent-table)))
+ font-lock-pending-buffer-table)))
;; Syntactic fontification functions.
-;; Note: Here is the FSF version. Our version is much faster because
-;; of the C support we provide. This may be useful for reference,
-;; however, and perhaps there is something useful here that should
-;; be merged into our version.
+;; Note: Here is the FSF version. (#### which FSF version?) Our
+;; version is much faster because of the C support we provide. This
+;; may be useful for reference, however, and perhaps there is
+;; something useful here that should be merged into our version.
;;
;(defun font-lock-fontify-syntactically-region (start end &optional loudly)
; "Put proper face on each string and comment between START and END.