"+=" "*=" "/=" "%=" "|=" "&=" "^=" ">>=" "<<=" "--" "++")
"C/C++ operators for tree-sitter font-locking.")
+(defvar c-ts-mode--for-each-tail-regexp
+ (rx "FOR_EACH_" (or "TAIL" "TAIL_SAFE" "ALIST_VALUE"
+ "LIVE_BUFFER" "FRAME"))
+ "A regexp matching all the variants of the FOR_EACH_* macro.")
+
(defun c-ts-mode--font-lock-settings (mode)
"Tree-sitter font-lock settings.
MODE is either `c' or `cpp'."
:language mode
:feature 'emacs-devel
:override t
- '(((call_expression
+ `(((call_expression
(call_expression function: (identifier) @fn)
@c-ts-mode--fontify-DEFUN)
- (:match "^DEFUN$" @fn)))))
+ (:match "^DEFUN$" @fn))
+
+ ((function_definition type: (_) @for-each-tail)
+ @c-ts-mode--fontify-for-each-tail
+ (:match ,c-ts-mode--for-each-tail-regexp @for-each-tail)))))
;;; Font-lock helpers
(treesit-node-start arg) (treesit-node-end arg)
'default override start end))))))
+(defun c-ts-mode--fontify-for-each-tail (node override start end &rest _)
+ "Fontify FOR_EACH_TAIL variants in Emacs sources.
+For NODE, OVERRIDE, START, and END, see
+`treesit-font-lock-rules'. The captured NODE is a
+function_definition node."
+ (let ((for-each-tail (treesit-node-child-by-field-name node "type"))
+ (args (treesit-node-child-by-field-name node "declarator")))
+ (treesit-fontify-with-override
+ (treesit-node-start for-each-tail) (treesit-node-end for-each-tail)
+ 'default override start end)
+ (treesit-fontify-with-override
+ (1+ (treesit-node-start args)) (1- (treesit-node-end args))
+ 'default override start end)))
+
(defun c-ts-mode--fontify-error (node override start end &rest _)
"Fontify the error nodes.
For NODE, OVERRIDE, START, and END, see
;; skips those FOR_EACH_*'s. Note that we only ignore FOR_EACH_*'s
;; with a unbracketed body. Those with a bracketed body parse more
;; or less fine.
-
-(defvar c-ts-mode--for-each-tail-regexp
- (rx "FOR_EACH_" (or "TAIL" "TAIL_SAFE" "ALIST_VALUE"
- "LIVE_BUFFER" "FRAME"))
- "A regexp matching all the variants of the FOR_EACH_* macro.")
+;;
+;; In the meantime, we have a special fontification rule for
+;; FOR_EACH_* macros with a bracketed body that removes any applied
+;; fontification (which are wrong anyway), to keep them consistent
+;; with the skipped FOR_EACH_* macros (which have no fontification).
+;; The rule is in 'emacs-devel' feature.
(defun c-ts-mode--for-each-tail-body-matcher (_n _p bol &rest _)
"A matcher that matches the first line after a FOR_EACH_* macro.
(treesit-range-rules 'c-ts-mode--emacs-set-ranges))
(setq-local treesit-language-at-point-function
- (lambda (_pos) 'c)))))
+ (lambda (_pos) 'c))
+ (treesit-font-lock-recompute-features '(emacs-devel)))))
;;;###autoload
(define-derived-mode c++-ts-mode c-ts-base-mode "C++"