emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] /srv/bzr/emacs/trunk r106729: Introduce a mechanism to wid


From: Alan Mackenzie
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r106729: Introduce a mechanism to widen the region used in context font locking.
Date: Sat, 24 Dec 2011 19:32:31 +0000
User-agent: Bazaar (2.3.1)

------------------------------------------------------------
revno: 106729
committer: Alan Mackenzie <address@hidden>
branch nick: trunk
timestamp: Sat 2011-12-24 19:32:31 +0000
message:
  Introduce a mechanism to widen the region used in context font locking.
  Use this to protect declarations from losing their contexts.
modified:
  lisp/ChangeLog
  lisp/progmodes/cc-langs.el
  lisp/progmodes/cc-mode.el
=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2011-12-24 19:16:53 +0000
+++ b/lisp/ChangeLog    2011-12-24 19:32:31 +0000
@@ -1,3 +1,26 @@
+2011-12-24  Alan Mackenzie  <address@hidden>
+
+       Introduce a mechanism to widen the region used in context font
+       locking.  Use this to protect declarations from losing their
+       contexts.
+
+       * progmodes/cc-langs.el (c-before-font-lock-functions): replace
+       c-set-fl-decl-start with c-change-set-fl-decl-start (Renaming).
+       (c-before-context-fontification-functions): new defvar, a list of
+       functions to be run just before context (etc.) font locking.
+
+       * progmodes/cc-mode.el (c-extend-font-lock-region-for-macros):
+       new, functionality extracted from
+       c-neutralize-syntax-in-and-mark-CPP.
+       (c-in-after-change-fontification): new variable.
+       (c-after-change): Set c-in-after-change-fontification.
+       (c-set-fl-decl-start): Rejig its interface, so it can be called
+       from both after-change and context fontifying.
+       (c-change-set-fl-decl-start, c-context-set-fl-decl-start): new
+       functions.
+       (c-standard-font-lock-fontify-region-function): new variable.
+       (c-font-lock-fontify-region): new function.
+
 2011-12-24  Juri Linkov  <address@hidden>
 
        * window.el (window--state-get-1): Set `FORCE' arg of `mark' to t.

=== modified file 'lisp/progmodes/cc-langs.el'
--- a/lisp/progmodes/cc-langs.el        2011-12-23 11:48:54 +0000
+++ b/lisp/progmodes/cc-langs.el        2011-12-24 19:32:31 +0000
@@ -488,8 +488,9 @@
 (c-lang-defconst c-before-font-lock-functions
   ;; For documentation see the following c-lang-defvar of the same name.
   ;; The value here may be a list of functions or a single function.
-  t 'c-set-fl-decl-start
-  (c c++ objc) '(c-neutralize-syntax-in-and-mark-CPP c-set-fl-decl-start)
+  t 'c-change-set-fl-decl-start
+  (c c++ objc) '(c-neutralize-syntax-in-and-mark-CPP
+                c-change-set-fl-decl-start)
   awk 'c-awk-extend-and-syntax-tablify-region)
 (c-lang-defvar c-before-font-lock-functions
               (let ((fs (c-lang-const c-before-font-lock-functions)))
@@ -514,6 +515,27 @@
 When the mode is initialized, these functions are called with
 parameters \(point-min), \(point-max) and <buffer size>.")
 
+(c-lang-defconst c-before-context-fontification-functions
+  awk nil
+  t 'c-context-set-fl-decl-start)
+  ;; For documentation see the following c-lang-defvar of the same name.
+  ;; The value here may be a list of functions or a single function.
+(c-lang-defvar c-before-context-fontification-functions
+  (let ((fs (c-lang-const c-before-context-fontification-functions)))
+    (if (listp fs)
+       fs
+      (list fs)))
+  "If non-nil, a list of functions called just before context (or
+other non-change) fontification is done.  Typically they will
+extend the region.
+
+These functions will be run in the order given.  Each of them
+takes 2 parameters, the BEG and END of the region to be
+fontified.  Point is undefined on both entry and exit.  On entry,
+the buffer will have been widened and match-data will have been
+saved; the return value is a cons of the adjusted
+region, (NEW-BEG . NEW-END).")
+
 
 ;;; Syntactic analysis ("virtual semicolons") for line-oriented languages 
(AWK).
 (c-lang-defconst c-at-vsemi-p-fn

=== modified file 'lisp/progmodes/cc-mode.el'
--- a/lisp/progmodes/cc-mode.el 2011-12-23 11:48:54 +0000
+++ b/lisp/progmodes/cc-mode.el 2011-12-24 19:32:31 +0000
@@ -599,8 +599,8 @@
 
 ;; Buffer local variables defining the region to be fontified by a font lock
 ;; after-change function.  They are set in c-after-change to
-;; after-change-function's BEG and END, and may be modified by a
-;; `c-before-font-lock-function'.
+;; after-change-functions' BEG and END, and may be modified by functions in
+;; `c-before-font-lock-functions'.
 (defvar c-new-BEG 0)
 (make-variable-buffer-local 'c-new-BEG)
 (defvar c-new-END 0)
@@ -830,6 +830,35 @@
                                 ; with a c-cpp-delimiter category property
   (setq c-old-EOM (point)))
 
+(defun c-extend-font-lock-region-for-macros (begg endd &optional old-len)
+  ;; Extend the region (BEGG ENDD) to cover all (possibly changed)
+  ;; preprocessor macros; return the cons (new-BEG . new-END).  OLD-LEN should
+  ;; be either the old length parameter when called from an
+  ;; after-change-function, or nil otherwise.  This defun uses the variables
+  ;; c-old-BOM, c-new-BOM.
+  ;;
+  ;; Point is undefined on both entry and exit to this function.  The buffer
+  ;; will have been widened on entry.
+  (let (limits new-beg new-end)
+    (goto-char c-old-BOM)        ; already set to old start of macro or begg.
+    (setq new-beg
+         (min begg
+              (if (setq limits (c-state-literal-at (point)))
+                  (cdr limits)     ; go forward out of any string or comment.
+                (point))))
+
+    (goto-char endd)
+    (if (setq limits (c-state-literal-at (point)))
+       (goto-char (car limits)))  ; go backward out of any string or comment.
+    (if (c-beginning-of-macro)
+       (c-end-of-macro))
+    (setq new-end (max endd
+                      (if old-len
+                          (+ (- c-old-EOM old-len) (- endd begg))
+                        c-old-EOM)
+                      (point)))
+    (cons new-beg new-end)))
+
 (defun c-neutralize-CPP-line (beg end)
   ;; BEG and END bound a region, typically a preprocessor line.  Put a
   ;; "punctuation" syntax-table property on syntactically obtrusive
@@ -886,26 +915,14 @@
   ;; Note: SPEED _MATTERS_ IN THIS FUNCTION!!!
   ;;
   ;; This function might make hidden buffer changes.
-  (c-save-buffer-state (limits)
+  (c-save-buffer-state (new-bounds)
     ;; First determine the region, (c-new-BEG c-new-END), which will get font
     ;; locked.  It might need "neutralizing".  This region may not start
     ;; inside a string, comment, or macro.
-    (goto-char c-old-BOM)        ; already set to old start of macro or begg.
-    (setq c-new-BEG
-         (min c-new-BEG
-              (if (setq limits (c-state-literal-at (point)))
-                  (cdr limits)     ; go forward out of any string or comment.
-                (point))))
-
-    (goto-char endd)
-    (if (setq limits (c-state-literal-at (point)))
-       (goto-char (car limits)))  ; go backward out of any string or comment.
-    (if (c-beginning-of-macro)
-       (c-end-of-macro))
-    (setq c-new-END (max c-new-END
-                        (+ (- c-old-EOM old-len) (- endd begg))
-                        (point)))
-
+    (setq new-bounds (c-extend-font-lock-region-for-macros
+                     c-new-BEG c-new-END old-len))
+    (setq c-new-BEG (car new-bounds)
+         c-new-END (cdr new-bounds))
     ;; Clear all old relevant properties.
     (c-clear-char-property-with-value c-new-BEG c-new-END 'syntax-table '(1))
     (c-clear-char-property-with-value c-new-BEG c-new-END 'category 
'c-cpp-delimiter)
@@ -1015,6 +1032,11 @@
                  c-get-state-before-change-functions))
        ))))
 
+(defvar c-in-after-change-fontification nil)
+(make-variable-buffer-local 'c-in-after-change-fontification)
+;; A flag to prevent region expanding stuff being done twice for after-change
+;; fontification.
+
 (defun c-after-change (beg end old-len)
   ;; Function put on `after-change-functions' to adjust various caches
   ;; etc.  Prefer speed to finesse here, since there will be an order
@@ -1066,63 +1088,113 @@
        ;; larger than (beg end).
        (setq c-new-BEG beg
              c-new-END end)
+       (setq c-in-after-change-fontification t)
        (save-excursion
          (mapc (lambda (fn)
                  (funcall fn beg end old-len))
                c-before-font-lock-functions))))))
 
-(defun c-set-fl-decl-start (beg end old-len)
-  ;; If the beginning of line containing c-new-BEG is in the middle of a
-  ;; "local" declaration (i.e. one which does not start outside of braces
-  ;; enclosing this pos, such as a struct), set c-new-BEG to (at most) the
-  ;; beginning of that declaration.  Note that declarations, in this sense,
-  ;; can be nested.  c-new-BEG will be used later by c-font-lock-declarations.
-  ;;
-  ;; This function is an element of c-before-font-lock-functions, being called
-  ;; (indirectly) from an after-change function.  The after-change-functions'
-  ;; parameters BEG, OLD and OLD-LEN are ignored here.
-  (when font-lock-mode
-    (goto-char (c-point 'bol c-new-BEG))
-    (let ((lit-limits (c-literal-limits))
-          bod-lim bo-decl)
-
-      (when lit-limits                 ; Comment or string.
-       (goto-char (car lit-limits)))
-      (setq bod-lim (max (- (point) 500) (point-min)))
-
-      (while
-         ;; Go to a less nested declaration each time round this loop.
-         (and
-          (eq (car (c-beginning-of-decl-1 bod-lim)) 'same)
-          (progn (setq bo-decl (point))
-                 ;; Are we looking at a keyword such as "template" or
-                 ;; "typedef" which can decorate a type, or the type itself?
-                 (when (or (looking-at c-prefix-spec-kwds-re)
-                           (c-forward-type t))
-                   ;; We've found another candidate position.
-                   (setq c-new-BEG (min c-new-BEG bo-decl))
-                   (goto-char bo-decl))
-                 t)
-          ;; Try and go out a level to search again.
-          (progn
-            (c-backward-syntactic-ws bod-lim)
-            (or (memq (char-before) '(?\( ?\[))
-                (and (eq (char-before) ?\<)
-                     (eq (c-get-char-property
-                          (1- (point)) 'syntax-table)
-                         c-<-as-paren-syntax))))
-          (not (bobp)))
-       (backward-char)))))             ; back over (, [, <.
-
+(defun c-set-fl-decl-start (pos)
+  ;; If the beginning of the line containing POS is in the middle of a "local"
+  ;; declaration (i.e. one which does not start outside of braces enclosing
+  ;; POS, such as a struct), return the beginning of that declaration.
+  ;; Otherwise return POS.  Note that declarations, in this sense, can be
+  ;; nested.
+  ;;
+  ;; This function is called indirectly from font locking stuff - either from
+  ;; c-after-change (to prepare for after-change font-lockng) or from font
+  ;; lock context (etc.) fontification.
+  (let ((lit-limits (c-literal-limits))
+       (new-pos pos)
+       bod-lim bo-decl)
+    (goto-char (c-point 'bol new-pos))
+    (when lit-limits                   ; Comment or string.
+      (goto-char (car lit-limits)))
+    (setq bod-lim (max (- (point) 500) (point-min)))
+
+    (while
+       ;; Go to a less nested declaration each time round this loop.
+       (and
+        (eq (car (c-beginning-of-decl-1 bod-lim)) 'same)
+        (progn (setq bo-decl (point))
+               ;; Are we looking at a keyword such as "template" or
+               ;; "typedef" which can decorate a type, or the type itself?
+               (when (or (looking-at c-prefix-spec-kwds-re)
+                         (c-forward-type t))
+                 ;; We've found another candidate position.
+                 (setq new-pos (min new-pos bo-decl))
+                 (goto-char bo-decl))
+               t)
+        ;; Try and go out a level to search again.
+        (progn
+          (c-backward-syntactic-ws bod-lim)
+          (or (memq (char-before) '(?\( ?\[))
+              (and (eq (char-before) ?\<)
+                   (eq (c-get-char-property
+                        (1- (point)) 'syntax-table)
+                       c-<-as-paren-syntax))))
+        (not (bobp)))
+      (backward-char))
+    new-pos))                          ; back over (, [, <.
+
+(defun c-change-set-fl-decl-start (beg end old-len)
+  ;; Set c-new-BEG to the beginning of a "local" declaration if it('s BOL) is
+  ;; inside one.  This is called from an after-change-function, but the
+  ;; parameters BEG END and OLD-LEN are ignored.  See `c-set-fl-decl-start'
+  ;; for the detailed functionality.
+  (if font-lock-mode
+      (setq c-new-BEG (c-set-fl-decl-start c-new-BEG))))
+
+(defun c-context-set-fl-decl-start (beg end)
+  ;; Return a cons (NEW-BEG . END), where NEW-BEG is the beginning of a
+  ;; "local" declaration (BOL at) NEW is inside or BEG.  See
+  ;; `c-set-fl-decl-start' for the detailed functionality.
+  (cons (c-set-fl-decl-start beg) end))
+
+(defvar c-standard-font-lock-fontify-region-function nil
+  "Standard value of `font-lock-fontify-region-function'")
+
+(defun c-font-lock-fontify-region (beg end &optional verbose)
+  ;; Effectively advice around `font-lock-fontify-region' which extends the
+  ;; region (BEG END), for example, to avoid context fontification chopping
+  ;; off the start of the context.  Do not do anything if it's already been
+  ;; done (i.e. from and after-change fontification.  An example (C++) where
+  ;; this used to happen is this:
+  ;;
+  ;;     template <typename T>
+  ;;
+  ;;
+  ;;     void myfunc(T* p) {}
+  ;; 
+  ;; Type a space in the first blank line, and the fontification of the next
+  ;; line was fouled up by context fontification.
+  (let ((new-beg beg) (new-end end) new-region)
+    (if c-in-after-change-fontification
+       (setq c-in-after-change-fontification nil)
+      (save-restriction
+       (widen)
+       (save-excursion
+         (mapc (lambda (fn)
+                 (setq new-region (funcall fn new-beg new-end))
+                 (setq new-beg (car new-region)  new-end (cdr new-region)))
+               c-before-context-fontification-functions))))
+    (funcall c-standard-font-lock-fontify-region-function
+            new-beg new-end verbose)))
+  
 (defun c-after-font-lock-init ()
-  ;; Put on `font-lock-mode-hook'.
+  ;; Put on `font-lock-mode-hook'.  This function ensures our after-change
+  ;; function will get excuted before the font-lock one.  Amongst other
+  ;; things.
   (remove-hook 'after-change-functions 'c-after-change t)
-  (add-hook 'after-change-functions 'c-after-change nil t))
+  (add-hook 'after-change-functions 'c-after-change nil t)
+  (setq c-standard-font-lock-fontify-region-function
+       (default-value 'font-lock-fontify-region-function)))
 
 (defun c-font-lock-init ()
   "Set up the font-lock variables for using the font-lock support in CC Mode.
 This does not load the font-lock package.  Use after
-`c-basic-common-init' and after cc-fonts has been loaded."
+`c-basic-common-init' and after cc-fonts has been loaded.
+This function is called from `c-common-init', once per mode initialization."
 
   (set (make-local-variable 'font-lock-defaults)
        `(,(if (c-major-mode-is 'awk-mode)
@@ -1136,6 +1208,10 @@
          c-beginning-of-syntax
          (font-lock-mark-block-function
           . c-mark-function)))
+
+  (make-local-variable 'font-lock-fontify-region-function)
+  (setq font-lock-fontify-region-function 'c-font-lock-fontify-region)
+
   (if (featurep 'xemacs)
       (make-local-hook 'font-lock-mode-hook))
   (add-hook 'font-lock-mode-hook 'c-after-font-lock-init nil t))


reply via email to

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