emacs-devel
[Top][All Lists]
Advanced

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

RE: how to prevent font-lock from messing with a portion of text?


From: Drew Adams
Subject: RE: how to prevent font-lock from messing with a portion of text?
Date: Sun, 25 Mar 2007 18:48:09 -0700

> > I can't believe it would be hard for font-lock to check if text it
> > wants to work with has an ignore-me property.
>
> Nobody asks you to believe it would be hard.

To show what I meant, here's a naive implementation that seems to work.

1. In font-lock.el, use this everywhere that `put-text-property' is used
now:

(defun put-text-property-unless-ignore (start end property value &optional
object)
  "`put-text-property', but ignore text with property `font-lock-ignore'."
  (let ((here (min start end))
        (end1 (max start end)))
    (while (< here end1)
      (unless (get-text-property here 'font-lock-ignore object)
        (put-text-property here (1+ here) property value object))
      (setq here (1+ here)))))

2. In font-lock.el, use this definition of
`font-lock-default-unfontify-region':

(defun font-lock-default-unfontify-region (beg end)
  "Unfontify from BEG to END, unless text with property `font-lock-ignore'."
  (let ((here (min beg end))
        (end1 (max beg end)))
    (while (< here end1)
      (unless (get-text-property here 'font-lock-ignore)
        (remove-list-of-text-properties
         here (1+ here) (append font-lock-extra-managed-props
                                (if font-lock-syntactic-keywords
                                    '(syntax-table face font-lock-multiline)
                                  '(face font-lock-multiline)))))
      (setq here (1+ here)))))

That is enough to get the behavior I described: putting a `font-lock-ignore'
property on selected portions of text tells font-lock "hands off". Try it,
for instance, with highlighting from `facemenu-set-face' (`M-o o') - see end
of mail.

I'm not suggesting these definitions should be used as is. They should be
enough, however, to show what I meant. They should point out that the task
is not that difficult, at least in terms of functionality. Or perhaps they
will point out what I'm misunderstanding or missing - please let me know in
that case. So far, this works OK for me.

Caveats:

a. These are obviously naive implementations, advancing only a character at
a time. The functionality seems to be OK, but the performance could be
improved. Perhaps `text-property-any' (or `-not-all') or
`next-single-property-change' could be used to let
`put-text-property-unless-ignore' process larger stretches of text at a
time.

b. So far, I haven't actually seen fontification being noticeably slower,
but the modified version of `font-lock-default-unfontify-region' is
unacceptably slow, for sure, with a large buffer. It can't simply remove
properties from BEG to END in one fell swoop as the original version does.
To obtain acceptable performance here, it would perhaps be appropriate to
write another built-in (C) analogous to `remove-list-of-text-properties',
but which allows for a similar test.

c. This doesn't take care of any MATCHER functions that might be used in
font-lock specs. Unless coded explicitly to be sensitive to property
`font-lock-ignore', they would act as they do now. I think that's
acceptable, but users would need to be made aware of that.

d. There might be some boundary cases that would need to be tweaked. For
instance, I imagine that (put-text-property pos pos ...) puts the property
at position pos, but (put-text-property-unless-ignore pos pos ...) does
nothing. I don't know whether the current uses of `put-text-property' in
font-lock.el really need to treat the start=end case.

If an Emacs developer were to implement something like this in a performant
way and add it to Emacs, it would mean that facemenu and hilock highlighting
could be used in font-locked buffers, which I think many users would
appreciate. facemenu.el would also need a minor change to
`facemenu-add-face', to put property `font-lock-ignore' on the text it
highlights. hilock.el would similarly need tweaking.

If you want to try this to see what it's like (including performance
penalties), add this line to `facemenu-add-face':

                                ;; Specify the selected frame
                                ;; because nil would mean to use
                                ;; the new-frame default settings,
                                ;; and those are usually nil.
                                (selected-frame))))
++        (put-text-property part-start part-end 'font-lock-ignore t))
        (setq part-start part-end)))

Then load library library `font-lock+.el', which is essentially the code
shown at the top. Use `M-o o' to highlight portions of text, and then turn
font-locking off and on to see the effect and the performance.

Alternatively, you can try it using library `highlight.el' and library
`font-lock+.el'. Do (define-key ctl-x-map [(control ?y)] 'highlight), and
then use `C-x C-y' to highlight (and unhighlight) text. Oh, and you will
need to set `highlight-use-overlays-flag' to nil - the default value uses
overlays, which font lock of course doesn't interfere with.

The code is here:

http://www.emacswiki.org/cgi-bin/wiki/font-lock%2b.el

http://www.emacswiki.org/cgi-bin/wiki/highlight.el








reply via email to

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