]> git.eshelyaron.com Git - emacs.git/commitdiff
(font-lock-beg, font-lock-end, font-lock-extend-region-functions): New vars.
authorStefan Monnier <monnier@iro.umontreal.ca>
Thu, 3 Aug 2006 07:14:39 +0000 (07:14 +0000)
committerStefan Monnier <monnier@iro.umontreal.ca>
Thu, 3 Aug 2006 07:14:39 +0000 (07:14 +0000)
(font-lock-extend-region-multiline)
(font-lock-extend-region-wholelines): New functions.
(font-lock-default-fontify-region): Use them.
(font-lock-extend-jit-lock-region-after-change): Only round up
if font-lock-default-fontify-region will do it as well.

etc/NEWS
lisp/ChangeLog
lisp/font-lock.el
lispref/modes.texi

index 52fcc1eea2ae60f65d3bab30a7268a21708bf08a..3f986846f17e2017286927d927214a7b68bd38ca 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -5363,6 +5363,11 @@ text to being a piece of code, so you'd put a `jit-lock-defer-multiline'
 property over the second half of the command to force (deferred)
 refontification of `bar' whenever the `e' is added/removed.
 
+*** `font-lock-extend-region-functions' makes it possible to alter the way
+the fontification region is chosen.  This can be used to prevent rounding
+up to whole lines, or to extend the region to include all related lines
+of multiline constructs so that such constructs get properly recognized.
+
 ** Major mode mechanism changes:
 
 +++
index dd1b63ba4ee50bb35b2eac50494e323c0c4b0177..6329e0e699d404fb6ed387a7c82726b61c947fc6 100644 (file)
@@ -1,5 +1,13 @@
 2006-08-03  Stefan Monnier  <monnier@iro.umontreal.ca>
 
+       * font-lock.el (font-lock-beg, font-lock-end)
+       (font-lock-extend-region-functions): New vars.
+       (font-lock-extend-region-multiline)
+       (font-lock-extend-region-wholelines): New functions.
+       (font-lock-default-fontify-region): Use them.
+       (font-lock-extend-jit-lock-region-after-change): Only round up
+       if font-lock-default-fontify-region will do it as well.
+
        * font-lock.el (font-lock-extend-after-change-region-function):
        Rename from font-lock-extend-region-function.
        (font-lock-extend-region): Remove by inlining at call sites.
index a7cc1a0902248445ecaf8052349b33b5a4fb9f23..0cad924f2011eacdaac60077991131447f3eb48d 100644 (file)
@@ -1040,6 +1040,53 @@ The region it returns may start or end in the middle of a line.")
 Useful for things like RMAIL and Info where the whole buffer is not
 a very meaningful entity to highlight.")
 
+
+(defvar font-lock-beg) (defvar font-lock-end)
+(defvar font-lock-extend-region-functions
+  '(font-lock-extend-region-wholelines
+    font-lock-extend-region-multiline)
+  "Special hook run just before proceeding to fontify a region.
+This is used to allow major modes to help font-lock find safe buffer positions
+as beginning and end of the fontified region.  Its most common use is to solve
+the problem of /identification/ of multiline elements by providing a function
+that tries to find such elements and move the boundaries such that they do
+not fall in the middle of one.
+Each function is called with no argument; it is expected to adjust the
+dynamically bound variables `font-lock-beg' and `font-lock-end'; and return
+non-nil iff it did make such an adjustment.
+These functions are run in turn repeatedly until they all return nil.
+Put first the functions more likely to cause a change and cheaper to compute.")
+;; Mark it as a special hook which doesn't use any global setting
+;; (i.e. doesn't obey the element t in the buffer-local value).
+(make-variable-buffer-local 'font-lock-extend-region-functions)
+
+(defun font-lock-extend-region-multiline ()
+  "Move fontification boundaries away from any `font-lock-multiline' property."
+  (let ((changed nil))
+    (when (and (> font-lock-beg (point-min))
+               (get-text-property (1- font-lock-beg) 'font-lock-multiline))
+      (setq changed t)
+      (setq font-lock-beg (or (previous-single-property-change
+                               font-lock-beg 'font-lock-multiline)
+                              (point-min))))
+    ;; 
+    (when (get-text-property font-lock-end 'font-lock-multiline)
+      (setq changed t)
+      (setq font-lock-end (or (text-property-any font-lock-end (point-max)
+                                                 'font-lock-multiline nil)
+                              (point-max))))
+    changed))
+  
+  
+(defun font-lock-extend-region-wholelines ()
+  "Move fontification boundaries to beginning of lines."
+  (let ((changed nil))
+    (goto-char font-lock-beg)
+    (unless (bobp) (setq changed t font-lock-beg (line-beginning-position)))
+    (goto-char font-lock-end)
+    (unless (bobp) (setq changed t font-lock-end (line-beginning-position 2)))
+    changed))
+
 (defun font-lock-default-fontify-region (beg end loudly)
   (save-buffer-state
       ((parse-sexp-lookup-properties
@@ -1051,24 +1098,21 @@ a very meaningful entity to highlight.")
          ;; Use the fontification syntax table, if any.
          (when font-lock-syntax-table
            (set-syntax-table font-lock-syntax-table))
-          (goto-char beg)
-         (setq beg (line-beginning-position))
-         ;; check to see if we should expand the beg/end area for
-         ;; proper multiline matches
-         (when (and (> beg (point-min))
-                    (get-text-property (1- beg) 'font-lock-multiline))
-           ;; We are just after or in a multiline match.
-           (setq beg (or (previous-single-property-change
-                          beg 'font-lock-multiline)
-                         (point-min)))
-           (goto-char beg)
-           (setq beg (line-beginning-position)))
-          (setq end (or (text-property-any end (point-max)
-                                           'font-lock-multiline nil)
-                        (point-max)))
-         (goto-char end)
-         ;; Round up to a whole line.
-          (unless (bolp) (setq end (line-beginning-position 2)))
+          ;; Extend the region to fontify so that it starts and ends at
+          ;; safe places.
+          (let ((funs font-lock-extend-region-functions)
+                (font-lock-beg beg)
+                (font-lock-end end))
+            (while funs
+              (setq funs (if (or (not (funcall (car funs)))
+                                 (eq funs font-lock-extend-region-functions))
+                             (cdr funs)
+                           ;; If there's been a change, we should go through
+                           ;; the list again since this new position may
+                           ;; warrant a different answer from one of the fun
+                           ;; we've already seen.
+                           font-lock-extend-region-functions)))
+            (setq beg font-lock-beg end font-lock-end))
          ;; Now do the fontification.
          (font-lock-unfontify-region beg end)
          (when font-lock-syntactic-keywords
@@ -1144,12 +1188,14 @@ what properties to clear before refontifying a region.")
       ;; Finally, pre-enlarge the region to a whole number of lines, to try
       ;; and predict what font-lock-default-fontify-region will do, so as to
       ;; avoid double-redisplay.
-      (goto-char beg)
-      (forward-line 0)
-      (setq jit-lock-start (min jit-lock-start (point)))
-      (goto-char end)
-      (forward-line 1)
-      (setq jit-lock-end (max jit-lock-end (point))))))
+      (when (memq 'font-lock-extend-region-wholelines
+                  font-lock-extend-region-functions)
+        (goto-char beg)
+        (forward-line 0)
+        (setq jit-lock-start (min jit-lock-start (point)))
+        (goto-char end)
+        (forward-line 1)
+        (setq jit-lock-end (max jit-lock-end (point)))))))
 
 (defun font-lock-fontify-block (&optional arg)
   "Fontify some lines the way `font-lock-fontify-buffer' would.
index 7ca8764a0a8ff0bf023ecd1debabc5918ca1b315..38227633c6b53598da80eca5dc28ee19a000c5e2 100644 (file)
@@ -3044,7 +3044,7 @@ closely related, and often getting one of them to work will appear to
 make the other also work.  However, for reliable results you must
 attend explicitly to both aspects.
 
-  There are two ways to ensure correct identification of multiline
+  There are three ways to ensure correct identification of multiline
 constructs:
 
 @itemize
@@ -3055,6 +3055,10 @@ property on the construct when it is added to the buffer.
 Use @code{font-lock-fontify-region-function} hook to extend the scan
 so that the scanned text never starts or ends in the middle of a
 multiline construct.
+@item
+Add a function to @code{font-lock-extend-region-functions} that does
+the \emph{identification} and extends the scan so that the scanned
+text never starts or ends in the middle of a multiline construct.
 @end itemize
 
   There are three ways to do rehighlighting of multiline constructs: