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?

abo-abo
  • 13,943
  • 1
  • 29
  • 43

2 Answers2

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))))))
abo-abo
  • 13,943
  • 1
  • 29
  • 43
Stefan
  • 26,154
  • 3
  • 46
  • 84
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.

Lindydancer
  • 6,095
  • 1
  • 13
  • 25
  • 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 04 '16 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.) – Lindydancer Mar 04 '16 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 04 '16 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. – Lindydancer Mar 04 '16 at 15:21