Mercurial > emacs
changeset 72251:0933613f837b
(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.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Thu, 03 Aug 2006 07:14:39 +0000 |
parents | 482bf4e8cc00 |
children | 54e1bf749744 |
files | etc/NEWS lisp/ChangeLog lisp/font-lock.el lispref/modes.texi |
diffstat | 4 files changed, 88 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- a/etc/NEWS Thu Aug 03 05:42:53 2006 +0000 +++ b/etc/NEWS Thu Aug 03 07:14:39 2006 +0000 @@ -5363,6 +5363,11 @@ 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: +++
--- a/lisp/ChangeLog Thu Aug 03 05:42:53 2006 +0000 +++ b/lisp/ChangeLog Thu Aug 03 07:14:39 2006 +0000 @@ -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.
--- a/lisp/font-lock.el Thu Aug 03 05:42:53 2006 +0000 +++ b/lisp/font-lock.el Thu Aug 03 07:14:39 2006 +0000 @@ -1040,6 +1040,53 @@ 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 @@ ;; 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 @@ ;; 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.
--- a/lispref/modes.texi Thu Aug 03 05:42:53 2006 +0000 +++ b/lispref/modes.texi Thu Aug 03 07:14:39 2006 +0000 @@ -3044,7 +3044,7 @@ 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 @@ 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: