These are category/syntax-table properties to give < and > paren syntax.
Also apply certain `c-type' text properties to the insides of <..> constructs
to ensure that identifiers contained by them get fontified. This patch fixes
bug #681.
* lisp/progmodes/cc-cmds.el (c-electric-lt-gt): Reformulate due to new
after-change action.
* lisp/progmodes/cc-engine.el (c-before-change-check-<>-operators): Expand
change region to include <s and >s which might not be already marked as
parens, rather than just when paren text properties are removed.
(c-restore-<>-properties): New after-change function, which applies text
properties marking < and > with paren syntax.
* lisp/progmodes/cc-fonts.el (c-font-lock-declarations): Ensure `c-type'
properties are applied to the interiors of <...> constructs, to ensure
fontification of identifiers there.
* lisp/progmodes/cc-langs.el (c-before-font-lock-functions): Add
c-restore-<>-properties to this list for C++ and Java.
* lisp/progmodes/cc-mode.el (c-common-init): When invoking
c-before-font-lock-functions, exclude c-restore-<>-properties from the
functions invoked.
(c-before-change): Initialize c-new-BEG/END here (rather than c-after-change)
to allow modification by before-change functions.
(c-after-change): Amend c-new-END here, rather than initializing it and
c-new-BEG.
(looking-at "<<"))
(>= (match-end 0) final-pos)))
- ;; It's a >. Either a C++ >> operator. ......
- (or (and (c-major-mode-is 'c++-mode)
+ ;; It's a >. Either a template/generic terminator ...
+ (or (c-get-char-property (1- final-pos) 'syntax-table)
+ ;; or a C++ >> operator.
+ (and (c-major-mode-is 'c++-mode)
(progn
(goto-char (1- final-pos))
(c-beginning-of-current-token)
(looking-at ">>"))
- (>= (match-end 0) final-pos))
- ;; ...., or search back for a < which isn't already marked as an
- ;; opening template delimiter.
- (save-restriction
- (widen)
- ;; Narrow to avoid `c-forward-<>-arglist' below searching past
- ;; our position.
- (narrow-to-region (point-min) final-pos)
- (goto-char final-pos)
- (while
- (and
- (progn
- (c-syntactic-skip-backward "^<;}" nil t)
- (eq (char-before) ?<))
- (progn
- (backward-char)
- (looking-at "\\s("))))
- (and (eq (char-after) ?<)
- (not (looking-at "\\s("))
- (progn (c-backward-syntactic-ws)
- (c-simple-skip-symbol-backward))
- (or (looking-at c-opt-<>-sexp-key)
- (not (looking-at c-keywords-regexp)))))))))
+ (>= (match-end 0) final-pos))))))
(goto-char final-pos)
(when found-delim
(when (and (eq (char-before) ?>)
(not executing-kbd-macro)
blink-paren-function)
- ;; Currently (2014-10-19), the syntax-table text properties on < and >
- ;; are only applied in code called during Emacs redisplay. We thus
- ;; explicitly cause a redisplay so that these properties have been
- ;; applied when `blink-paren-function' gets called.
- (sit-for 0)
+ ;; From now (2016-01-01), the syntax-table text properties on < and >
+ ;; are applied in an after-change function, not during redisplay. Hence
+ ;; we no longer need to call (sit-for 0) for blink paren to work.
(funcall blink-paren-function)))))
(defun c-electric-paren (arg)
(defun c-before-change-check-<>-operators (beg end)
;; Unmark certain pairs of "< .... >" which are currently marked as
- ;; template/generic delimiters. (This marking is via syntax-table
- ;; text properties).
+ ;; template/generic delimiters. (This marking is via syntax-table text
+ ;; properties), and expand the (c-new-BEG c-new-END) region to include all
+ ;; unmarked < and > operators within the certain bounds (see below).
;;
;; These pairs are those which are in the current "statement" (i.e.,
;; the region between the {, }, or ; before BEG and the one after
(save-excursion
(let ((beg-lit-limits (progn (goto-char beg) (c-literal-limits)))
(end-lit-limits (progn (goto-char end) (c-literal-limits)))
- new-beg new-end need-new-beg need-new-end)
- ;; Locate the barrier before the changed region
+ new-beg new-end beg-limit end-limit)
+ ;; Locate the earliest < after the barrier before the changed region,
+ ;; which isn't already marked as a paren.
(goto-char (if beg-lit-limits (car beg-lit-limits) beg))
- (c-syntactic-skip-backward "^;{}" (c-determine-limit 512))
- (setq new-beg (point))
+ (setq beg-limit (c-determine-limit 512))
;; Remove the syntax-table/category properties from each pertinent <...>
- ;; pair. Firsly, the ones with the < before beg and > after beg.
- (while
- (c-search-forward-char-property 'syntax-table c-<-as-paren-syntax beg)
- (if (c-clear-<-pair-props-if-match-after beg (1- (point)))
- (setq need-new-beg t)))
+ ;; pair. Firstly, the ones with the < before beg and > after beg....
+ (while (progn (c-syntactic-skip-backward "^;{}<" beg-limit)
+ (eq (char-before) ?<))
+ (c-backward-token-2)
+ (when (eq (char-after) ?<)
+ (c-clear-<-pair-props-if-match-after beg)))
+ (c-forward-syntactic-ws)
+ (setq new-beg (point))
- ;; Locate the barrier after END.
+ ;; ...Then the ones with < before end and > after end.
(goto-char (if end-lit-limits (cdr end-lit-limits) end))
- (c-syntactic-re-search-forward "[;{}]" (c-determine-+ve-limit 512) 'end)
+ (setq end-limit (c-determine-+ve-limit 512))
+ (while (and (c-syntactic-re-search-forward "[;{}>]" end-limit 'end)
+ (eq (char-before) ?>))
+ (c-end-of-current-token)
+ (when (eq (char-before) ?>)
+ (c-clear->-pair-props-if-match-before end (1- (point)))))
+ (c-backward-syntactic-ws)
(setq new-end (point))
- ;; Remove syntax-table properties from the remaining pertinent <...>
- ;; pairs, those with a > after end and < before end.
- (while (c-search-backward-char-property 'syntax-table c->-as-paren-syntax end)
- (if (c-clear->-pair-props-if-match-before end)
- (setq need-new-end t)))
-
;; Extend the fontification region, if needed.
- (when need-new-beg
- (goto-char new-beg)
- (c-forward-syntactic-ws)
- (and (< (point) c-new-BEG) (setq c-new-BEG (point))))
-
- (when need-new-end
- (and (> new-end c-new-END) (setq c-new-END new-end))))))
+ (and new-beg
+ (< new-beg c-new-BEG)
+ (setq c-new-BEG new-beg))
+ (and new-end
+ (> new-end c-new-END)
+ (setq c-new-END new-end)))))
(defun c-after-change-check-<>-operators (beg end)
;; This is called from `after-change-functions' when
(c-clear-<>-pair-props)
(forward-char)))))))
-
+(defun c-restore-<>-properties (_beg _end _old-len)
+ ;; This function is called as an after-change function. It restores the
+ ;; category/syntax-table properties on template/generic <..> pairs between
+ ;; c-new-BEG and c-new-END. It may do hidden buffer changes.
+ (c-save-buffer-state ((c-parse-and-markup-<>-arglists t)
+ c-restricted-<>-arglists lit-limits)
+ (goto-char c-new-BEG)
+ (if (setq lit-limits (c-literal-limits))
+ (goto-char (cdr lit-limits)))
+ (while (and (< (point) c-new-END)
+ (c-syntactic-re-search-forward "<" c-new-END 'bound))
+ (backward-char)
+ (save-excursion
+ (c-backward-token-2)
+ (setq c-restricted-<>-arglists
+ (and (not (looking-at c-opt-<>-sexp-key))
+ (progn (c-backward-syntactic-ws) ; to < or ,
+ (and (memq (char-before) '(?< ?,))
+ (not (eq (c-get-char-property (point) 'c-type)
+ 'c-decl-arg-start)))))))
+ (or (c-forward-<>-arglist nil)
+ (forward-char)))))
\f
;; Handling of small scale constructs like types and names.
;; Same as `max-type-decl-*', but used when we're before
;; `token-pos'.
(max-type-decl-end-before-token 0)
+ ;; End of <..> construct which has had c-<>-arg-sep c-type
+ ;; properties set within it.
+ (max-<>-end 0)
;; Set according to the context to direct the heuristics for
;; recognizing C++ templates.
c-restricted-<>-arglists
(setq decl-or-cast (c-forward-decl-or-cast-1
match-pos context last-cast-end))
+ ;; Ensure that c-<>-arg-sep c-type properties are in place on the
+ ;; commas separating the arguments inside template/generic <..>s.
+ (when (and (eq (char-before match-pos) ?<)
+ (> match-pos max-<>-end))
+ (save-excursion
+ (goto-char match-pos)
+ (c-backward-token-2)
+ (if (and
+ (eq (char-after) ?<)
+ (let ((c-restricted-<>-arglists
+ (save-excursion
+ (c-backward-token-2)
+ (and
+ (not (looking-at c-opt-<>-sexp-key))
+ (progn (c-backward-syntactic-ws)
+ (memq (char-before) '(?\( ?,)))
+ (not (eq (c-get-char-property (1- (point))
+ 'c-type)
+ 'c-decl-arg-start))))))
+ (c-forward-<>-arglist nil)))
+ (setq max-<>-end (point)))))
+
(cond
((eq decl-or-cast 'cast)
;; Save the position after the previous cast so we can feed
;; 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-change-expand-fl-region
- (c c++ objc) '(c-neutralize-syntax-in-and-mark-CPP
- c-change-expand-fl-region)
+ (c objc) '(c-neutralize-syntax-in-and-mark-CPP
+ c-change-expand-fl-region)
+ c++ '(c-neutralize-syntax-in-and-mark-CPP
+ c-restore-<>-properties
+ c-change-expand-fl-region)
+ java '(c-restore-<>-properties
+ c-change-expand-fl-region)
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)))
(font-lock-mode 1)))
;; 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-functions' BEG and END, and may be modified by functions in
+;; after-change function. They are initialized in c-before-change to
+;; before-change-functions' BEG and END. `c-new-END' is amended in
+;; c-after-change with after-change-functions' BEG, END, and OLD-LEN. These
+;; variables may be modified by any before/after-change function, in
+;; particular by functions in `c-get-state-before-change-functions' and
;; `c-before-font-lock-functions'.
(defvar c-new-BEG 0)
(make-variable-buffer-local 'c-new-BEG)
(funcall fn (point-min) (point-max)))
c-get-state-before-change-functions)
(mapc (lambda (fn)
- (funcall fn (point-min) (point-max)
- (- (point-max) (point-min))))
+ (if (not (eq fn 'c-restore-<>-properties))
+ (funcall fn (point-min) (point-max)
+ (- (point-max) (point-min)))))
c-before-font-lock-functions))))
(set (make-local-variable 'outline-regexp) "[^#\n\^M]")
c-just-done-before-change) ; guard against a spurious second
; invocation of before-change-functions.
(setq c-just-done-before-change t)
+ ;; (c-new-BEG c-new-END) will be the region to fontify.
+ (setq c-new-BEG beg c-new-END end)
(setq c-maybe-stale-found-type nil)
(save-restriction
(save-match-data
;; (c-new-BEG c-new-END) will be the region to fontify. It may become
;; larger than (beg end).
- (setq c-new-BEG beg c-new-END end)
+ ;; (setq c-new-BEG beg c-new-END end)
+ (setq c-new-END (- (+ c-new-END (- end beg)) old-len))
(unless (c-called-from-text-property-change-p)
(setq c-just-done-before-change nil)