# HG changeset patch # User Richard M. Stallman # Date 1146364535 0 # Node ID 608b16c5630431434777ff47473c03f9c7c2496d # Parent 45b7cad845ee8436fcc8c72aca9ec82a0b24fd79 (Multiline Font Lock): Renamed from Multi line Font Lock Elements. Much clarification. (Font Lock Multiline, Region to Fontify): Much clarification. diff -r 45b7cad845ee -r 608b16c56304 lispref/modes.texi --- a/lispref/modes.texi Sun Apr 30 01:36:19 2006 +0000 +++ b/lispref/modes.texi Sun Apr 30 02:35:35 2006 +0000 @@ -2345,8 +2345,8 @@ * Syntactic Font Lock:: Fontification based on syntax tables. * Setting Syntax Properties:: Defining character syntax based on context using the Font Lock mechanism. -* Multi line Font Lock Elements:: How to coerce Font Lock into properly - highlighting multiline elements. +* Multiline Font Lock:: How to coerce Font Lock into properly + highlighting multiline constructs. @end menu @node Font Lock Basics @@ -2625,7 +2625,7 @@ @strong{Warning:} Do not design an element of @code{font-lock-keywords} to match text which spans lines; this does not work reliably. -For details, see @xref{Multi line Font Lock Elements}. +For details, see @xref{Multiline Font Lock}. You can use @var{case-fold} in @code{font-lock-defaults} to specify the value of @code{font-lock-keywords-case-fold-search} which says @@ -2944,8 +2944,8 @@ This can be used to highlighting different kinds of strings or comments differently. It is also sometimes abused together with -@code{font-lock-syntactic-keywords} to highlight elements that span -multiple lines, but this is too obscure to document in this manual. +@code{font-lock-syntactic-keywords} to highlight constructs that span +multiple lines, but this is too esoteric to document here. Specify this variable using @var{other-vars} in @code{font-lock-defaults}. @@ -3015,64 +3015,60 @@ @code{font-lock-defaults}. @end defvar -@node Multi line Font Lock Elements -@subsection Multi line Font Lock Elements -@cindex multi line font lock - -Normally, Font Lock elements specified via @code{font-lock-keywords} -should not match across multiple lines. If they do, Font Lock may -fail to highlight them properly. This is fundamentally due to the -fact that Font Lock does not always look at the whole buffer at -a time, for obvious performance reasons, and instead only looks -at a small chunk at a time. In order for the highlight to be correct, -a chunk should not straddle an element matched by -@code{font-lock-keywords}. The default heuristic used for this is to -start and end chunks at the beginning resp. end of a line. - -In order for Font Lock to properly highlight elements that span -multiple lines, the package author has to ensure two things: correct -@emph{discovery} and correct @emph{re}highlighting. The first ensures -that Font Lock finds all multiline elements. The second ensures that -Font Lock will correctly re-highlight all the relevant text when -a multiline element is changed, e.g. causing some of the text that was -previously part of a multiline element to not be part of it any more. -The two aspects are closely related and often getting one of the two -to work will appear to make the other also work. But both aspects -have to be taken care of for the multiline elements to be -reliably highlighted. - -Correct @emph{re}highlighting of multiline elements can be done in the -following ways: +@node Multiline Font Lock +@subsection Multiline Font Lock Constructs +@cindex multiline font lock + + Normally, elements of @code{font-lock-keywords} should not match +across multiple lines; that doesn't work reliably, because Font Lock +usually scans just part of the buffer, and it can miss a multi-line +construct that crosses the line boundary where the scan starts. (The +scan normally starts at the beginning of a line.) + + Making elements that match multiline constructs work properly has +two aspects: correct @emph{identification} and correct +@emph{rehighlighting}. The first means that Font Lock finds all +multiline constructs. The second means that Font Lock will correctly +rehighlight all the relevant text when a multiline construct is +changed---for example, if some of the text that was previously part of +a multiline construct ceases to be part of it. The two aspects are +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 +constructs: + @itemize @item -Apply the @code{font-lock-multiline} property to the element. -This will ensure that the whole element will always be immediately -rehighlighted if any part of it is changed. This can sometimes be -done automatically by setting the @code{font-lock-multiline} variable. +Place a @code{font-lock-multiline} or @code{jit-lock-defer-multiline} +property on the construct when it is added to the buffer. @item -Rely on @code{jit-lock-contextually}. This will only rehighlight the -part of the element that follows the actual change, and will do it -after a short delay. This only works if the highlighting of the -various parts of your multiline element never depends on text in -subsequent lines. Since @code{jit-lock-contextually} is activated by -default, this can be an attractive solution. -@item -Apply the @code{jit-lock-defer-multiline} property to the element. -This works only if @code{jit-lock-contextually} is used and allows it -to also work when highlighting does depend on subsequent lines. -@item +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. @end itemize -Discovery of new multiline elements can be done in the following ways: + There are three ways to do rehighlighting of multiline constructs: + @itemize @item -Manually placing a @code{font-lock-multiline} or -@code{jit-lock-defer-multiline} property on the element when it is -added to the buffer. +Place a @code{font-lock-multiline} property on the construct. This +will rehighlight the whole construct if any part of it is changed. In +some cases you can do this automatically by setting the +@code{font-lock-multiline} variable. @item -Using the @code{font-lock-fontify-region-function} hook to extend the -highlighted chunks so that they never start or end in the middle of -multiline element. +Use @code{jit-lock-contextually}. This will only rehighlight the part +of the construct that follows the actual change, and will do it after +a short delay. This only works if the highlighting of the various +parts of your multiline construct never depends on text in subsequent +lines. Since @code{jit-lock-contextually} is activated by default, +this can be an attractive solution. +@item +Place a @code{jit-lock-defer-multiline} property on the construct. +This works only if @code{jit-lock-contextually} is used, but it can +handle the case where highlighting depends on subsequent lines. +@item @end itemize @menu @@ -3084,80 +3080,75 @@ @node Font Lock Multiline @subsubsection Font Lock Multiline -In order to make it possible to properly @emph{re}highlight elements that -span multiple lines, Font Lock obeys a special text property -@code{font-lock-multiline} which if non-@code{nil} indicates that this -piece of text was highlighted as part of a multiline construct. -So when Font Lock is asked to rehighlight a region, it first verifies -the two boundaries and extends them as needed so they do not fall in -the middle of a piece of text marked with the -@code{font-lock-multiline} property. Immediately after that, it also -erases all @code{font-lock-multiline} properties from the region it is -about to highlight, so it is the responsability of the highlighting -specification (mostly @code{font-lock-keywords}) to make sure that -this property is re-added where needed so as to inform the next round -of Font Locking of the presence of a multiline construct. - -It is important to understand that the @code{font-lock-multiline} -property should preferably only be used on Font Lock elements of -moderate size: every time that text is modified within a multiline -element (or nearby), the whole multiline element will be completely -re-highlighted, so if its size is large, the time to font-lock may -render editing painfully slow. + One way to ensure reliable rehighlighting of multiline Font Lock +constructs is to put on the text property @code{font-lock-multiline}. +It should be present and non-@code{nil} for text that is part of a +multiline construct. + + When Font Lock is about to highlight a range of text, it first +extends the boundaries of the range as necessary so that they do not +fall within text marked with the @code{font-lock-multiline} property. +Then it removes any @code{font-lock-multiline} properties from the +range, and highlights it. The highlighting specification (mostly +@code{font-lock-keywords}) must reinstall this property each time, +whenever it is appropriate. + + @strong{Warning:} don't use the @code{font-lock-multiline} property +on large ranges of text, because that will make rehighlighting slow. @defvar font-lock-multiline If the @code{font-lock-multiline} variable is set to @code{t}, Font -Lock will try to automatically add the @code{font-lock-multiline} -property on the keywords that span several lines. This is no silver -bullet however since it slows down Font Lock somewhat, and may miss -some cases or make the property larger or smaller than necessary, -especially for keywords whose @var{MATCHER} is a function, in which -case the function needs to make sure that the submatch 0 covers the -whole relevant multiline entity even if only a small subpart will -be highlighted. It is often just as easy to add the -@code{font-lock-multiline} property by hand. +Lock will try to add the @code{font-lock-multiline} property +automatically on multiline constructs. This is not a universal +solution, however, since it slows down Font Lock somewhat. It can +miss some multiline constructs, or make the property larger or smaller +than necessary. + +For elements whose @var{matcher} is a function, the function should +ensure that submatch 0 covers the whole relevant multiline construct, +even if only a small subpart will be highlighted. It is often just as +easy to add the @code{font-lock-multiline} property by hand. @end defvar -As mentioned, this property is mostly intended to ensure proper -@emph{re}fontification. It does not magically discover new -multiline elements. To discover new multiline elements, all that is -required is that font-lock operate on large enough chunks at a time. -This will happen by accident on many cases, which may give the -impression that multiline elements magically work. If you set the -@code{font-lock-multiline} variable, this impression will be even -stronger since the highlighting of those found elements will be -properly preserved from then on. But for such multiline elements to -be found reliably, you will need to either manually put the -@code{font-lock-multiline} property from some appropriate piece of -code run before Font Lock, or hook into -@code{font-lock-fontify-region-function} to manually extend the chunks -of text that Font Lock highlights so they never start or stop in the -middle of a multiline element. + The @code{font-lock-multiline} property is meant to ensure proper +refontification; it does not automatically identify new multiline +constructs. Identifying the requires that Font-Lock operate on large +enough chunks at a time. This will happen by accident on many cases, +which may give the impression that multiline constructs magically work. +If you set the @code{font-lock-multiline} variable non-@code{nil}, +this impression will be even stronger, since the highlighting of those +constructs which are found will be properly updated from then on. +But that does not work reliably. + + To find multiline constructs reliably, you must either manually +place the @code{font-lock-multiline} property on the text before +Font-Lock looks at it, or use +@code{font-lock-fontify-region-function}. @node Region to Fontify @subsubsection Region to Fontify after a Buffer Change - When a buffer is changed, the region that Font Lock refontifies is by -default the smallest sequence of whole lines that spans the change. + When a buffer is changed, the region that Font Lock refontifies is +by default the smallest sequence of whole lines that spans the change. While this works well most of the time, sometimes it doesn't---for -example, when a buffer change has changed the syntactic meaning of text -on an earlier line. - -You can enlarge (or even reduce) the region to fontify by setting @c either of -the following variables: +example, when a change alters the syntactic meaning of text on an +earlier line. + + You can enlarge (or even reduce) the region to fontify by setting +one the following variables: @defvar font-lock-extend-region-function -This buffer-local variable is either @code{nil} or is a function that -determines the region to fontify, which Emacs then calls after each -buffer change. +This buffer-local variable is either @code{nil} or a function for +Font-Lock to call to determine the region to scan and fontify. The function is given three parameters, the standard @var{beg}, -@var{end}, and @var{old-len} from after-change-functions (@pxref{Change -Hooks}). It should return either a cons of the beginning and end buffer -positions (in that order) of the region to fontify, or @code{nil} (which -directs the caller to fontify the default region). This function needs -to preserve point, the match-data, and the current restriction. -The region it returns may start or end in the middle of a line. +@var{end}, and @var{old-len} from after-change-functions +(@pxref{Change Hooks}). It should return either a cons of the +beginning and end buffer positions (in that order) of the region to +fontify, or @code{nil} (which means choose the region in the standard +way). This function needs to preserve point, the match-data, and the +current restriction. The region it returns may start or end in the +middle of a line. Since this function is called after every buffer change, it should be reasonably fast.