mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-03 08:30:09 +00:00
Introduce a mechanism to widen the region used in context font locking.
Use this to protect declarations from losing their contexts.
This commit is contained in:
parent
3ba1a2ad82
commit
be8b11bb32
@ -1,3 +1,26 @@
|
||||
2011-12-24 Alan Mackenzie <acm@muc.de>
|
||||
|
||||
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 <juri@jurta.org>
|
||||
|
||||
* window.el (window--state-get-1): Set `FORCE' arg of `mark' to t.
|
||||
|
@ -488,8 +488,9 @@ parameters \(point-min) and \(point-max).")
|
||||
(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 @@ The functions are called even when font locking is disabled.
|
||||
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
|
||||
|
@ -599,8 +599,8 @@ that requires a literal mode spec at compile time."
|
||||
|
||||
;; 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 @@ Note that the style variables are always made local to the buffer."
|
||||
; 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 that the style variables are always made local to the buffer."
|
||||
;; 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 @@ Note that the style variables are always made local to the buffer."
|
||||
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 @@ Note that the style variables are always made local to the buffer."
|
||||
;; 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.
|
||||
(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 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)
|
||||
;; 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)))
|
||||
|
||||
(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 (, [, <.
|
||||
|
||||
(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-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 @@ This does not load the font-lock package. Use after
|
||||
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))
|
||||
|
Loading…
Reference in New Issue
Block a user