[Top][All Lists]

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

Re: Conditionalized font-locking?

From: Stephen Berman
Subject: Re: Conditionalized font-locking?
Date: Thu, 10 May 2012 17:22:06 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.1.50 (gnu/linux)

On 7 May 2012 17:15:34 +0200 "Stephen Berman" <address@hidden> wrote:

> On Mon, 07 May 2012 11:05:27 -0400 Stefan Monnier <address@hidden> wrote:
>>> (defun srb-number-matcher (lim)
>>>   "Search for odd numbers within LIM for font-locking."
>>>   (re-search-forward "\\<\\([0-9]+\\)\\>" lim t)
>>>   (let ((num (match-string-no-properties 1)))
>>>     (when (eq (logand (string-to-number num) 1) 1) num)))
>> If the re-search-forward fails, this function will mis-behave.
> D'oh!

Unfortunately, I'm still not getting what I want.  It's not unlikely I'm
again overlooking something obvious (though I've looked long and hard,
and tried lots of variations), so if you or someone else can point it
out, I'd be grateful.

Again, what I want is to fontify date-time strings with a special face
if the date in the string is earlier than the current date; moreover,
the time string is optional.  The following code (which is close to what
I'm actually using but with a simpler regexp and filtering condition)
seems to work at first:

--8<---------------cut here---------------start------------->8---
(defvar srb-font-lock-keywords
   '(srb-date-time-matcher (1 font-lock-warning-face t t))
   '(srb-date-time-matcher (2 font-lock-warning-face t t))))

(defun srb-date-time-matcher (lim)
  "Search for date-time strings within LIM for font-locking."
  (when (re-search-forward (concat "^\\(?1:[0-9][0-9][0-9][0-9]-"
                                   " \\(?2:[0-9]?[0-9]:[0-9][0-9]\\)?")
                           lim t)
    (let* ((date (match-string-no-properties 1))
           (time (match-string-no-properties 2))
           ;; days-between needs a non-empty time string.
           (date-time (concat date " " (or time "00:00"))))
      (when (< (days-between date-time (current-time-string)) 0)
        (concat date " " time)))))

(define-derived-mode srb-mode nil "SRB" ()
  "Mode for testing font-locking."
  (set (make-local-variable 'font-lock-defaults)
       '(srb-font-lock-keywords t)))
--8<---------------cut here---------------end--------------->8---

However, if the buffer contains a string that matches the regexp but
fails the second when-condition, then not only is it -- correctly -- not
fontified but subsequent matching dates that pass the when-condition are
also -- incorrectly -- not fontified.  Here's a test file showing the

--8<---------------cut here---------------start------------->8---
2012-04-01 10:00 
2013-05-01 10:00 
2012-03-10 10:00 
2012-04-01 10:00 
2012-03-10 10:00 
2012-04-01 10:00 
2012-03-10 10:00 

Local Variables:
mode: srb
--8<---------------cut here---------------end--------------->8---

When I evaluate the code above and then visit this file, I see only the
first two dates in font-lock-warning-face.  However, if I modify the
buffer at one of the dates after the 2013 date that fails the
when-condition, e.g. by typing a space, then that date becomes fontified
(and maybe the following one too, this seems to vary).

(With my actual code and data, some but not all dates after a correctly
non-fontified date are correctly fontified, though I've found no pattern
to explain this; but I hope a solution to the above case will also take
care of this wrinkle.)

I suspect the problem has to do with this (info (elisp)Search-based

     Fontification will call FUNCTION repeatedly with the same limit,
     and with point where the previous invocation left it, until
     FUNCTION fails.  On failure, FUNCTION need not reset point in any
     particular way.

I tried resetting point on failure, but that either didn't have an
effect or it resulted in all dates being fontified.

So how can I get all and only dates that satisfy the when-condition

Steve Berman

reply via email to

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