[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

small bug in font-lock code fixed

From: David Moffat
Subject: small bug in font-lock code fixed
Date: Sun, 19 Jun 2005 22:19:09 +0100
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux)


(Got this @ddress from the FAQ section:
58.3 Checklist for Bug Reports
hope it's right one, as I'm running CVS version of emacs
version 22.0.50)

In the file:


in the CVS version (number above) that I got about a month or two back,
there is a bug in the code that makes font-locking barf on
a LaTeX file, e.g., where a line is commented out.

So in the lines in some LaTeX file:


the first line (with foo) will be highlighted correctly,
but the second line (with bar) will throw an error,
and the third line (with bland) will not be highlighted.

This is because font-latex.el in "auctex" library
has functions like "font-latex-match-font-outside-braces"
which decide to nullify matches for regexps that happen
to occur in the scope of a comment.
In case you don't have it (auctex not being FSF),
I've appended one of this family of functions below, at end...

Then the function here (from font-lock.el) aborts because
it assumes the match is not a null.
This is the fixed function, with explanation below:
(defun font-lock-fontify-keywords-region (start end &optional loudly)
  "Fontify according to `font-lock-keywords' between START and END.
START should be at the beginning of a line.
LOUDLY, if non-nil, allows progress-meter bar."
  (unless (eq (car font-lock-keywords) t)
    (setq font-lock-keywords
          (font-lock-compile-keywords font-lock-keywords t)))
  (let ((case-fold-search font-lock-keywords-case-fold-search)
        (keywords (cddr font-lock-keywords))
        (bufname (buffer-name)) (count 0)
        keyword matcher highlights)
    ;; Fontify each item in `font-lock-keywords' from `start' to `end'.
    (while keywords
      (if loudly (message "Fontifying %s... (regexps..%s)" bufname
                          (make-string (incf count) ?.)))
      ;; Find an occurrence of `matcher' from `start' to `end'.
      (setq keyword (car keywords) matcher (car keyword))
      (goto-char start)
      (while (and (< (point) end)
                  (if (stringp matcher)
                      (re-search-forward matcher end t)
                    (funcall matcher end)))
        (when (and font-lock-multiline
                   (match-beginning 0)  ; MdQ -- my fix to stop barfing on nil
                   ;; when lines in LaTeX buffers are commented out
                   ;; as in e.g. a line with ... % \textbf{a}
                   (>= (point)
                       (save-excursion (goto-char (match-beginning 0))
                                       (forward-line 1) (point))))
          ;; this is a multiline regexp match
          ;; (setq font-lock-multiline t)
          (put-text-property (if (= (point)
                                      (goto-char (match-beginning 0))
                                      (forward-line 1) (point)))
                                 (1- (point))
                               (match-beginning 0))
                             'font-lock-multiline t))
        ;; Apply each highlight to this instance of `matcher', which may be
        ;; specific highlights or more keywords anchored to `matcher'.
        (setq highlights (cdr keyword))
        (while highlights
          (if (numberp (car (car highlights)))
              (font-lock-apply-highlight (car highlights))
            (let ((pos (point)))
              (font-lock-fontify-anchored-keywords (car highlights) end)
              ;; Ensure forward progress.
              (if (< (point) pos) (goto-char pos))))
          (setq highlights (cdr highlights))))
      (setq keywords (cdr keywords)))))

OK, so the fix is the lines:
                   (match-beginning 0)  ; MdQ -- my fix to stop barfing on nil
                   ;; when lines in LaTeX buffers are commented out
                   ;; as in e.g. a line with ... % \textbf{a}
which have been inserted.
This line means that there is an additional check to prevent
font-lock properties being added to text if the match has
been nullified for whatever reason by other code.

You may not feel this is an FSF bug, since it results from an
interaction with auctex-code.
But if any other code should decide to nullify a regexp match
in the same way, such as for source that has been commented out,
then the same problem will arise.
All I've done really, is to introduce a single sanity check.

OK, that's it.
Do with it what you wish.
Here below is the auctex code you can look at if it helps.



~/Dave/lib/emacs/auctex/font-latex.el extract (there are several functions
like this one below... see the comment in it after the line
with the call to function: "font-latex-commented-outp") :
(defun font-latex-match-font-outside-braces (limit)
  "Search for font-changing command like \textbf{fubar} before LIMIT.  
Sets `match-data' so that:
 subexpression 0 is the keyword, 
 subexpression 1 is the content to fontify in italic.
 subexpression 2 is the content to fontify in bold.
 subexpression 3 is the content to fontify in type-face.
Returns nil if no font-changing command is found."
  (font-latex-check-cache 'font-latex-match-font-cache 'font limit)
  (when (re-search-forward
           (concat "\\\\" "\\("
                   "\\(emph\\)\\|"                            ;;; 2 - italic
                               "\\(it\\|sl\\)\\|"             ;;; 5 - italic
                               "\\(md\\|rm\\|sf\\|tt\\)\\|" ;;; 6 - type
                               "\\(bf\\|sc\\|up\\)"           ;;; 7 - bold
                   "\\(boldsymbol\\|pmb\\)"                   ;;; 8 - bold
                   "\\)" "{"))
         limit t)
      ;; Return a nul match such that we skip over this pattern.
      ;; (Would be better to skip over internally to this function)
      ;; Using `prepend' won't help here, because the problem is that
      ;; scan-sexp *fails* to find a commented-out matching bracket!
      (store-match-data (list nil nil))
      (let ((kbeg (match-beginning 0)) (kend (match-end 1)) 
            (beg  (1- (match-end 0)))   ;Include openning bracket
            end itbeg itend bfbeg bfend ttbeg ttend
            (parse-sexp-ignore-comments t) ; scan-sexps ignores comments
        (goto-char kend)
          ;; Restrict to LIMIT.
          (narrow-to-region (point-min) limit)
          (if (font-latex-find-matching-close ?\{ ?\})
              (setq end (point))
            (setq cache-reset t)
            (setq end (point-max))
            (goto-char end)))
        (cond ((or (match-beginning 2) (match-beginning 5))
               (setq itbeg beg  itend end))
              ((match-beginning 6)
               (setq ttbeg beg  ttend end))
               (setq bfbeg beg  bfend end)))
         (list kbeg kend itbeg itend bfbeg bfend ttbeg ttend))
        ;; Start the subsequent search immediately after this keyword.
          (goto-char kend)
        (when (and font-latex-do-multi-line cache-reset)
          (goto-char limit)             ;Avoid infinite loops?
           kbeg kend limit 'font 
           (list kbeg kend itbeg itend bfbeg bfend ttbeg ttend)))

Glasgow Caledonian University (SCAMS)
Cowcaddens Road                           room:  M628
GLASGOW                                  email:  address@hidden
G4 0BA                                     tel:  +44 141 331 3937

reply via email to

[Prev in Thread] Current Thread [Next in Thread]