1

Related to this question.

Here's my current font lock setup for python-mode:

(require 'org)
(defconst lpy-font-lock-keywords
  '(("^#\\(\\* .*\\)$" 1 'org-level-1 prepend)
    ("^#\\(\\*\\* .*\\)$" 1 'org-level-2 prepend)
    ("^#\\(\\*\\*\\* .*\\)$" 1 'org-level-3 prepend)
    ("^#\\(\\*\\*\\*\\* .*\\)$" 1 'org-level-4 prepend)
    ("^#\\(\\*\\*\\*\\*\\* .*\\)$" 1 'org-level-5 prepend)
    (lpy-outline-comment-highlight 1 'default prepend)
    ("`\\([^\n']+\\)'" 1 font-lock-constant-face prepend)))

(font-lock-add-keywords 'python-mode lpy-font-lock-keywords)
(defun lpy-outline-comment-highlight (limit)
  (when (re-search-forward "^#\\(?:[^*]\\|$\\)" limit t)
    (let* ((pt (point))
           (success (save-excursion
                      (and (re-search-backward "^#\\*" nil t)
                           (null (re-search-forward "^[^#]" pt t))))))
      (when success
        (set-match-data (list (line-beginning-position) (line-end-position)
                              (point) (line-end-position)))
        (end-of-line)
        t))))

The code appears to do what I want (have comment bodies, but not starters, in default face for comments that belong to outlines), but only for small buffers, or places that I modify.

For larger buffers (larger than one screen), font-lock will be lazy and not apply the required faces. However, if I modify the text around that region, it will be highlighted correctly.

font-lock-lazy

In the image above, font-lock is being lazy in the "Multi-dimensional indexing outline". So I moved a point there and entered a space - the highlight became correct.

How do I force font-lock to highlight every line on the screen?

2
  • You have you looked at the (elisp)Font Lock Multiline node of the manual?
    – Stefan
    Mar 4, 2016 at 18:30
  • Yes, but these rules look single-line to me.
    – abo-abo
    Mar 5, 2016 at 11:41

2 Answers 2

3

[ Indeed, your rules are "single line", so it's not among the problems described in (elisp)Font Lock Multiline. It really doesn't have anything to do with "laziness". ]

The problem is quite simple: in your lpy-outline-comment-highlight function, if you find a match but you decide that success nil, then you return nil, which will tell font-lock to stop looking any further.

IOW you need to replace your when with a loop.

Solution:

(defun lpy-outline-comment-highlight (limit)
  (catch 'done
    (while (re-search-forward "^#\\(?:[^*\n]\\)" limit t)
      (let* ((pt (point))
             (success (save-excursion
                        (and (re-search-backward "^#\\*" nil t)
                             (null (re-search-forward "^[^#]" pt t))))))
        (when success
          (set-match-data (list (line-beginning-position) (line-end-position)
                                (point) (line-end-position)))
          (end-of-line)
          (throw 'done t))))))
2

You can use font-lock-extend-region-functions. It contains a list of functions that extend the region that is rehighlighted. You can add your own function to it that extends the region to include the full comment, forcing your keywords to be applied correctly.

4
  • I don't get why I should use something else. My impression was that font-lock should be calling lpy-outline-comment-highlight over and over until the whole screen is processed.
    – abo-abo
    Mar 4, 2016 at 12:18
  • Well, it doesn't. If decides upon a region that it think is appropriate and highlights it. If that region start in the middle of one of your special comments, your function won't work. Connecting it to the screen isn't what you want either -- if the screen start in the middle of your comment, it still doesn't work. (If you like, I can send you an unreleased tool that visualizes the refontification area. I've been using it in similar situations.) Mar 4, 2016 at 12:35
  • Please do. I didn't manage to find much practical information on complex font-lock. The info pages give no examples, and examples on the wiki are trivial ones.
    – abo-abo
    Mar 4, 2016 at 12:48
  • @abo-abo, I just sent you an email. The best source for font-lock information is other packages, and the the variable documentation of the font-lock variables. It's very condensed, but typically contains the correct formation. What it needed is a cookbook of which tools are available and how you should pick the right one. Mar 4, 2016 at 15:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.