emacs-devel
[Top][All Lists]
Advanced

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

Re: address@hidden: C++-mode: Syntax highlighting: wrong color for funct


From: Alan Mackenzie
Subject: Re: address@hidden: C++-mode: Syntax highlighting: wrong color for function identifier depending on the kind of whitespace that follows]
Date: Wed, 9 Mar 2005 21:18:40 +0000 (GMT)

address@hidden has been added]

[The discussion is about a font-locking problem reported in CC Mode:  The
user types the start of a C function, but puts a NL in the middle:

void function
                        (int x);

The second line gets incorrectly fontified, because in its
after-change-functions, font-lock considers only that line in and of
itself.]

Hi, Richard!

On Wed, 9 Mar 2005, Richard Stallman wrote:

>    Why not use the mechanism from AWK Mode, which was designed to
>    refont the opening quote of a (multi-line) string when the closing
>    quote gets typed?  This device advises the four critical font-lock
>    functions (e.g.  `font-lock-after-change-function').

>The technique may be a good one, but advising other parts of Emacs is a
>bug!

Hmmm.  The advice facility exists within Emacs, and it is difficult to
see what it could be used on, aside from another part of Emacs.  After
all, one does not need to advise one's own code, having full control over
the source.

But I take the point.  Advising font-lock is suboptimal, since it ties
AWK Mode to the precise internal implementation of font-lock.  Should
font-lock's internals change, AWK Mode will break.  Also, this use of
advice is ugly, and that's reason enough in itself to change it.  But
what we change it to must be _less_ ugly.

However:  I did complain about this shortcoming of font-lock on
gnu.emacs.bug way back, on Friday 10th May 2002 (Subject: Font-lock:
Major mode should be able to specify region to fontify.  Message-Id:
<address@hidden>), and that post of mine contained a patch to add
the facility to font-lock.  Nobody apart from Kim Storm (who objected
(quite reasonably) to the prolix function names I'd used) responded to
the post at the time, and nothing happened.  That's when I decided that
advising font-lock was the least bad way of solving the problem. 

>Let's look for a way to fix this to avoid using advice.  One idea is to
>have a hook that these functions run which can extend the region to be
>fontified.

By "these functions", I take it you mean
"font-lock-after-change-function" etc., rather than the AWK Mode
functions?  I believe it is a rather common need for Major modes to
calculate the region to fontify.  If so, let me start the ball rolling by
reposting my patch from 2002.  I can't guarantee it'll still work (or
even that it worked properly in 2002), but if you agree with the approach
in principle, I am prepared to rework the patch for a modern CVS version,
and amend the appropriate elisp.texi file.


"The context-diff is based on the source files from Emacs 21.1."

;;;;;; Changelog entry
2002-05-10  Alan Mackenzie  <address@hidden>

        The following set of changes allows a major mode dynamically to
        specify the region to fontify after a buffer change. (fast-lock.el
        doesn't need changing.)
        * font-lock.el
        New abnormal hook before-font-lock-after-change-function,
        New function font-lock-run-before-after-change-hook.
        Changed font-lock-after-change-function.
        * jit-lock.el
        Changed jit-lock-after-change
        * lazy-lock.el
        Changed lazy-lock-defer-line-after-change and
        lazy-lock-defer-rest-after-change.
;;;;;; End of Changelog entry

;;;;;; Patch
diff -c -x ChangeLog -x Makefile -x README 
/usr/src/packages/BUILD/emacs-21.1/lisp/font-lock.el NEW/font-lock.el
*** /usr/src/packages/BUILD/emacs-21.1/lisp/font-lock.el        Wed Sep  5 
13:36:29 2001
--- NEW/font-lock.el    Fri May 10 19:24:25 2002
***************
*** 1260,1270 ****
                                '(face nil syntax-table nil font-lock-multiline 
nil)
                              '(face nil font-lock-multiline nil)))))
  
  ;; Called when any modification is made to buffer text.
  (defun font-lock-after-change-function (beg end old-len)
!   (let ((inhibit-point-motion-hooks t))
      (save-excursion
        (save-match-data
        ;; Rescan between start of lines enclosing the region.
        (font-lock-fontify-region
         (progn (goto-char beg) (beginning-of-line) (point))
--- 1260,1309 ----
                                '(face nil syntax-table nil font-lock-multiline 
nil)
                              '(face nil font-lock-multiline nil)))))
  
+ (defvar before-font-lock-after-change-function nil
+   "If set to a function, this can specify the region to fontify after a 
change.
+ 
+ This variable is a buffer-local abnormal hook whose value, if set, should be a
+ single function.  The function gets called from the active font-lock
+ after-change function, and is intended to allow a major mode to calculate for
+ itself the region to be fontified after a buffer change.
+ 
+ The function is given three parameters, the standard BEG, END and OLD-LEN from
+ after-change-functions.  It should return either a cons of the beginning and 
end
+ buffer-positions \(in that order\) of the region to fontify, or nil (in which
+ case the default region will be used).")
+ (make-variable-buffer-local 'before-font-lock-after-change-function)
+ 
+ (defun font-lock-run-before-after-change-hook (beg end old-len)
+   "Run the hook function, if any, in before-font-lock-after-change-function,
+ returning its value (a cons of beg and end), if it's valid, else nil.
+ 
+ BEG END and OLD-LEN are the three parameters supplied by
+ after-change-functions."
+   (cond ((null before-font-lock-after-change-function) nil)
+         ((not (functionp before-font-lock-after-change-function))
+          (message "before-font-lock-after-change-function's value is not a \
+ function in buffer %S"
+                   (buffer-name))
+          nil)
+         (t (let ((region (funcall before-font-lock-after-change-function beg 
end old-len)))
+              (cond ((null region) nil)
+                    ((or (not (consp region))
+                         (not (wholenump (car region))) (not (wholenump (cdr 
region)))
+                         (not (<= (car region) (cdr region))))
+                     (message "before-font-lock-after-change-function returned 
%S.  \
+ This isn't a cons \(beg.end\), with beg and end numbers, and beg <= end")
+                     nil)
+                    (t region))))))
+ 
  ;; Called when any modification is made to buffer text.
  (defun font-lock-after-change-function (beg end old-len)
!   (let ((inhibit-point-motion-hooks t) region)
      (save-excursion
        (save-match-data
+         ;; Does the major mode have its own ideas about the region to fontify?
+         (setq region (font-lock-run-before-after-change-hook beg end old-len))
+         (if region (setq beg (car region)  end (cdr region)))
        ;; Rescan between start of lines enclosing the region.
        (font-lock-fontify-region
         (progn (goto-char beg) (beginning-of-line) (point))
diff -c -x ChangeLog -x Makefile -x README 
/usr/src/packages/BUILD/emacs-21.1/lisp/jit-lock.el NEW/jit-lock.el
*** /usr/src/packages/BUILD/emacs-21.1/lisp/jit-lock.el Mon Jul 16 12:22:58 2001
--- NEW/jit-lock.el     Fri May 10 18:59:36 2002
***************
*** 426,431 ****
--- 426,434 ----
    (when jit-lock-mode
      (save-excursion
        (with-buffer-prepared-for-jit-lock
+        ;; Does the major mode have its own ideas about the region to fontify?
+        (let ((region (font-lock-run-before-after-change-hook start end 
old-len)))
+          (if region (setq start (car region)  end (cdr region))))
         ;; It's important that the `fontified' property be set from the
         ;; beginning of the line, else font-lock will properly change the
         ;; text's face, but the display will have been done already and will
diff -c -x ChangeLog -x Makefile -x README 
/usr/src/packages/BUILD/emacs-21.1/lisp/lazy-lock.el NEW/lazy-lock.el
*** /usr/src/packages/BUILD/emacs-21.1/lisp/lazy-lock.el        Thu Aug 16 
14:25:15 2001
--- NEW/lazy-lock.el    Fri May 10 19:00:47 2002
***************
*** 771,776 ****
--- 771,779 ----
    (save-buffer-state nil
      (unless (memq (current-buffer) lazy-lock-buffers)
        (push (current-buffer) lazy-lock-buffers))
+     ;; Does the major mode have its own ideas about what to fontify?
+     (let ((region (font-lock-run-before-after-change-hook beg end old-len)))
+       (if region (setq beg (car region)  end (cdr region))))
      (remove-text-properties (max (1- beg) (point-min))
                            (min (1+ end) (point-max))
                            '(lazy-lock nil))))
***************
*** 784,789 ****
--- 787,795 ----
        (push (current-buffer) lazy-lock-buffers))
      (save-restriction
        (widen)
+       ;; Does the major mode have its own ideas about what to fontify?
+       (let ((region (font-lock-run-before-after-change-hook beg end old-len)))
+         (if region (setq beg (car region)  end (cdr region))))
        (remove-text-properties (max (1- beg) (point-min))
                              (point-max)
                              '(lazy-lock nil)))))
;;;;;; end of patch.

-- 
Alan Mackenzie (Munich, Germany)






reply via email to

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