# HG changeset patch # User Alan Mackenzie # Date 1175894515 0 # Node ID 469570420bff2970aad3c436aec8e2102241febd # Parent 2f0b1b082f4a09fde049d1c2c1d52da789475aa7 Fix fontification of labels, and other things with ":". * progmodes/cc-engine.el (c-forward-label): The function now returns 'goto-target, 'qt-2kwds-colon, 'qt-1kwd-colon, as well as the former t. * progmodes/cc-fonts.el (c-font-lock-declarations): Interpret the new return code from c-forward-label, fontifying tokens properly. Add some general comments throughout the file. diff -r 2f0b1b082f4a -r 469570420bff lisp/progmodes/cc-engine.el --- a/lisp/progmodes/cc-engine.el Fri Apr 06 21:07:56 2007 +0000 +++ b/lisp/progmodes/cc-engine.el Fri Apr 06 21:21:55 2007 +0000 @@ -5371,7 +5371,7 @@ ;; True if there's a prefix match outside the outermost ;; paren pair that surrounds the declarator. got-prefix-before-parens -y ;; True if there's a suffix match outside the outermost + ;; True if there's a suffix match outside the outermost ;; paren pair that surrounds the declarator. The value is ;; the position of the first suffix match. got-suffix-after-parens @@ -5877,19 +5877,23 @@ (defun c-forward-label (&optional assume-markup preceding-token-end limit) ;; Assuming that point is at the beginning of a token, check if it starts a - ;; label and if so move over it and return t, otherwise don't move and - ;; return nil. "Label" here means "most things with a colon". + ;; label and if so move over it and return non-nil (t in default situations, + ;; specific symbols (see below) for interesting situations), otherwise don't + ;; move and return nil. "Label" here means "most things with a colon". ;; ;; More precisely, a "label" is regarded as one of: - ;; (i) a goto target like "foo:"; - ;; (ii) A case label - either the entire construct "case FOO:" or just the - ;; bare "case", should the colon be missing; - ;; (iii) a keyword which needs a colon, like "default:" or "private:"; + ;; (i) a goto target like "foo:" - returns the symbol `goto-target'; + ;; (ii) A case label - either the entire construct "case FOO:", or just the + ;; bare "case", should the colon be missing. We return t; + ;; (iii) a keyword which needs a colon, like "default:" or "private:"; We + ;; return t; ;; (iv) One of QT's "extended" C++ variants of - ;; "private:"/"protected:"/"public:"/"more:" looking like "public slots:". + ;; "private:"/"protected:"/"public:"/"more:" looking like "public slots:". + ;; Returns the symbol `qt-2kwds-colon'. + ;; (v) QT's construct "signals:". Returns the symbol `qt-1kwd-colon'. ;; (v) One of the keywords matched by `c-opt-extra-label-key' (without any ;; colon). Currently (2006-03), this applies only to Objective C's - ;; keywords "@private", "@protected", and "@public". + ;; keywords "@private", "@protected", and "@public". Returns t. ;; ;; One of the things which will NOT be recognised as a label is a bit-field ;; element of a struct, something like "int foo:5". @@ -5918,8 +5922,10 @@ ;; This function might do hidden buffer changes. (let ((start (point)) + label-end qt-symbol-idx - macro-start) ; if we're in one. + macro-start ; if we're in one. + label-type) (cond ;; "case" or "default" (Doesn't apply to AWK). ((looking-at c-label-kwds-regexp) @@ -5932,25 +5938,26 @@ ;; Find the label end. (goto-char kwd-end) - (if (and (c-syntactic-re-search-forward - ;; Stop on chars that aren't allowed in expressions, - ;; and on operator chars that would be meaningless - ;; there. FIXME: This doesn't cope with ?: operators. - "[;{=,@]\\|\\(\\=\\|[^:]\\):\\([^:]\\|\\'\\)" - limit t t nil 1) - (match-beginning 2)) - - (progn - (goto-char (match-beginning 2)) ; just after the : - (c-put-c-type-property (1- (point)) 'c-decl-end) - t) - - ;; It's an unfinished label. We consider the keyword enough - ;; to recognize it as a label, so that it gets fontified. - ;; Leave the point at the end of it, but don't put any - ;; `c-decl-end' marker. - (goto-char kwd-end) - t))) + (setq label-type + (if (and (c-syntactic-re-search-forward + ;; Stop on chars that aren't allowed in expressions, + ;; and on operator chars that would be meaningless + ;; there. FIXME: This doesn't cope with ?: operators. + "[;{=,@]\\|\\(\\=\\|[^:]\\):\\([^:]\\|\\'\\)" + limit t t nil 1) + (match-beginning 2)) + + (progn ; there's a proper : + (goto-char (match-beginning 2)) ; just after the : + (c-put-c-type-property (1- (point)) 'c-decl-end) + t) + + ;; It's an unfinished label. We consider the keyword enough + ;; to recognize it as a label, so that it gets fontified. + ;; Leave the point at the end of it, but don't put any + ;; `c-decl-end' marker. + (goto-char kwd-end) + t)))) ;; @private, @protected, @public, in Objective C, or similar. ((and c-opt-extra-label-key @@ -5962,7 +5969,7 @@ (when c-record-type-identifiers (c-record-ref-id (cons (match-beginning 1) (point)))) (c-put-c-type-property (1- (point)) 'c-decl-end) - t) + (setq label-type t)) ;; All other cases of labels. ((and c-recognize-colon-labels ; nil for AWK and IDL, otherwise t. @@ -6038,26 +6045,49 @@ (c-forward-syntactic-ws) (c-forward-label nil pte start)))))))))) + ;; Point is still at the beginning of the possible label construct. + ;; ;; Check that the next nonsymbol token is ":", or that we're in one ;; of QT's "slots" declarations. Allow '(' for the sake of macro ;; arguments. FIXME: Should build this regexp from the language ;; constants. - (when (c-syntactic-re-search-forward - "[ \t[:?;{=*/%&|,<>!@+-]" limit t t) ; not at EOB - (backward-char) - (setq qt-symbol-idx - (and (c-major-mode-is 'c++-mode) - (string-match - "\\(p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|more\\)\\>" - (buffer-substring start (point))))) - (c-forward-syntactic-ws limit) - (when (or (looking-at ":\\([^:]\\|\\'\\)") ; A single colon. - (and qt-symbol-idx - (search-forward-regexp "\\=slots\\>" limit t) - (progn (c-forward-syntactic-ws limit) - (looking-at ":\\([^:]\\|\\'\\)")))) ; A single colon - (forward-char) ; to after the colon. - t))) + (cond + ;; public: protected: private: + ((and + (c-major-mode-is 'c++-mode) + (search-forward-regexp + "\\=p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\>[^_]" nil t) + (progn (backward-char) + (c-forward-syntactic-ws limit) + (looking-at ":\\([^:]\\|\\'\\)"))) ; A single colon. + (forward-char) + (setq label-type t)) + ;; QT double keyword like "protected slots:" or goto target. + ((progn (goto-char start) nil)) + ((when (c-syntactic-re-search-forward + "[ \t\n[:?;{=*/%&|,<>!@+-]" limit t t) ; not at EOB + (backward-char) + (setq label-end (point)) + (setq qt-symbol-idx + (and (c-major-mode-is 'c++-mode) + (string-match + "\\(p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|more\\)\\>" + (buffer-substring start (point))))) + (c-forward-syntactic-ws limit) + (cond + ((looking-at ":\\([^:]\\|\\'\\)") ; A single colon. + (forward-char) + (setq label-type + (if (string= "signals" ; Special QT macro + (buffer-substring-no-properties start label-end)) + 'qt-1kwd-colon + 'goto-target))) + ((and qt-symbol-idx + (search-forward-regexp "\\=slots\\>" limit t) + (progn (c-forward-syntactic-ws limit) + (looking-at ":\\([^:]\\|\\'\\)"))) ; A single colon + (forward-char) + (setq label-type 'qt-2kwds-colon))))))) (save-restriction (narrow-to-region start (point)) @@ -6068,6 +6098,7 @@ (while (progn (when (looking-at c-nonlabel-token-key) (goto-char start) + (setq label-type nil) (throw 'check-label nil)) (and (c-safe (c-forward-sexp) (c-forward-syntactic-ws) @@ -6087,12 +6118,12 @@ (c-put-c-type-property (1- (point-max)) 'c-decl-end) (goto-char (point-max)) - t))) + ))) (t ;; Not a label. - (goto-char start) - nil)))) + (goto-char start))) + label-type)) (defun c-forward-objc-directive () ;; Assuming the point is at the beginning of a token, try to move diff -r 2f0b1b082f4a -r 469570420bff lisp/progmodes/cc-fonts.el --- a/lisp/progmodes/cc-fonts.el Fri Apr 06 21:07:56 2007 +0000 +++ b/lisp/progmodes/cc-fonts.el Fri Apr 06 21:21:55 2007 +0000 @@ -704,8 +704,13 @@ )) (defun c-font-lock-complex-decl-prepare (limit) + ;; This function will be called from font-lock for a region bounded by POINT + ;; and LIMIT, as though it were to identify a keyword for + ;; font-lock-keyword-face. It always returns NIL to inhibit this and + ;; prevent a repeat invocation. See elisp/lispref page "Search-based + ;; Fontification". + ;; ;; Called before any of the matchers in `c-complex-decl-matchers'. - ;; Nil is always returned. ;; ;; This function does hidden buffer changes. @@ -742,10 +747,15 @@ nil) (defun c-font-lock-<>-arglists (limit) + ;; This function will be called from font-lock for a region bounded by POINT + ;; and LIMIT, as though it were to identify a keyword for + ;; font-lock-keyword-face. It always returns NIL to inhibit this and + ;; prevent a repeat invocation. See elisp/lispref page "Search-based + ;; Fontification". + ;; ;; Fontify types and references in names containing angle bracket ;; arglists from the point to LIMIT. Note that - ;; `c-font-lock-declarations' already has handled many of them. Nil - ;; is always returned. + ;; `c-font-lock-declarations' already has handled many of them. ;; ;; This function might do hidden buffer changes. @@ -971,9 +981,14 @@ font-lock-keyword-face)) (defun c-font-lock-declarations (limit) + ;; This function will be called from font-lock for a region bounded by POINT + ;; and LIMIT, as though it were to identify a keyword for + ;; font-lock-keyword-face. It always returns NIL to inhibit this and + ;; prevent a repeat invocation. See elisp/lispref page "Search-based + ;; Fontification". + ;; ;; Fontify all the declarations, casts and labels from the point to LIMIT. - ;; Assumes that strings and comments have been fontified already. Nil is - ;; always returned. + ;; Assumes that strings and comments have been fontified already. ;; ;; This function might do hidden buffer changes. @@ -1009,6 +1024,7 @@ ;; `c-forward-decl-or-cast-1' and `c-forward-label' for ;; later fontification. (c-record-type-identifiers t) + label-type c-record-ref-identifiers ;; Make `c-forward-type' calls mark up template arglists if ;; it finds any. That's necessary so that we later will @@ -1174,39 +1190,31 @@ (c-fontify-recorded-types-and-refs) nil)) - ;; It was a false alarm. + ;; It was a false alarm. Check if we're in a label (or other + ;; construct with `:' except bitfield) instead. (goto-char start-pos) - ;; The below code attempts to fontify the case constants in - ;; c-label-face-name, but it cannot catch every case [sic]. - ;; And do we want to fontify case constants anyway? - (c-forward-label t match-pos nil) -;;; (when (c-forward-label t match-pos nil) -;;; ;; Can't use `c-fontify-types-and-refs' here since we -;;; ;; should use the label face. -;;; (save-excursion -;;; (while c-record-ref-identifiers -;;; (let ((elem (car c-record-ref-identifiers)) -;;; c-record-type-identifiers) -;;; (goto-char (cdr elem)) -;;; ;; Find the end of any label. -;;; (while (and (re-search-forward "\\sw\\|:" nil t) -;;; (progn (backward-char 1) t) -;;; (or (re-search-forward -;;; "\\=0[Xx][0-9A-Fa-f]+\\|\\([0-9]+\\)" nil t) -;;; (c-forward-name))) -;;; (c-backward-syntactic-ws) -;;; (let ((end (point))) -;;; ;; Now find the start of the bit we regard as the label. -;;; (when (and (c-simple-skip-symbol-backward) -;;; (not (c-get-char-property (point) 'face))) -;;; (c-put-font-lock-face (point) end c-label-face-name)) -;;; (goto-char end)))) -;;; (setq c-record-ref-identifiers (cdr c-record-ref-identifiers)))) -;;; ;; `c-forward-label' probably has added a `c-decl-end' -;;; ;; marker, so return t to `c-find-decl-spots' to signal -;;; ;; that. -;;; t) - ))) + (when (setq label-type (c-forward-label t match-pos nil)) + ;; Can't use `c-fontify-types-and-refs' here since we + ;; use the label face at times. + (cond ((eq label-type 'goto-target) + (c-put-font-lock-face (caar c-record-ref-identifiers) + (cdar c-record-ref-identifiers) + c-label-face-name)) + ((eq label-type 'qt-1kwd-colon) + (c-put-font-lock-face (caar c-record-ref-identifiers) + (cdar c-record-ref-identifiers) + 'font-lock-keyword-face)) + ((eq label-type 'qt-2kwds-colon) + (mapc + (lambda (kwd) + (c-put-font-lock-face (car kwd) (cdr kwd) + 'font-lock-keyword-face)) + c-record-ref-identifiers))) + (setq c-record-ref-identifiers nil) + ;; `c-forward-label' has probably added a `c-decl-end' + ;; marker, so return t to `c-find-decl-spots' to signal + ;; that. + t)))) nil))) @@ -1285,6 +1293,14 @@ "Complex font lock matchers for types and declarations. Used on level 3 and higher." + ;; Note: This code in this form dumps a number of funtions into the + ;; resulting constant, `c-matchers-3'. At run time, font lock will call + ;; each of them as a "FUNCTION" (see Elisp page "Search-based + ;; Fontification"). The font lock region is delimited by POINT and the + ;; single parameter, LIMIT. Each of these functions returns NIL (thus + ;; inhibiting spurious font-lock-keyword-face highlighting and another + ;; call). + t `(;; Initialize some things before the search functions below. c-font-lock-complex-decl-prepare @@ -1397,6 +1413,8 @@ ;; Fontify the type in C++ "new" expressions. ,@(when (c-major-mode-is 'c++-mode) + ;; This pattern is a probably a "(MATCHER . ANCHORED-HIGHLIGHTER)" + ;; (see Elisp page "Search-based Fontification"). `(("\\" (c-font-lock-c++-new)))) ))