From 88cee3d4c7d168c3372ea28e7d3fb20726841ab2 Mon Sep 17 00:00:00 2001 From: Vincenzo Pupillo Date: Mon, 1 Jul 2024 12:34:01 +0200 Subject: [PATCH] Fontify doxygen support to 'c-ts-mode', 'c++-ts-mode' and 'java-ts-mode' Add doxygen support to 'c-ts-mode', 'c++-ts-mode' and 'java-ts-mode' using tree-sitter-doxygen from github.com/tree-sitter-grammars. * lisp/progmodes/c-ts-common.el (c-ts-mode-doxygen-comment-font-lock-settings): Add font locking rules for doxygen comment. * lisp/progmodes/c-ts-mode.el (c-ts-mode--feature-list): Add 'document' feature. (c-ts-mode--doxygen-comment-regex): New regular expression for doxygen comments. (c-ts-mode, c++-ts-mode): Add support for doxygen parser. * lisp/progmodes/java-ts-mode.el (java-ts-mode): Add support for doxygen parser. (Bug#71874) (cherry picked from commit c77a9b934bc1120c7726d271bbd4ada178cf8c2d) --- lisp/progmodes/c-ts-common.el | 22 +++++ lisp/progmodes/c-ts-mode.el | 126 +++++++++++++++++--------- lisp/progmodes/java-ts-mode.el | 159 ++++++++++++++++++--------------- 3 files changed, 193 insertions(+), 114 deletions(-) diff --git a/lisp/progmodes/c-ts-common.el b/lisp/progmodes/c-ts-common.el index 3882a697c48..a1f257ee09a 100644 --- a/lisp/progmodes/c-ts-common.el +++ b/lisp/progmodes/c-ts-common.el @@ -348,6 +348,28 @@ and /* */ comments. SOFT works the same as in (delete-region (line-beginning-position) (point)) (insert whitespaces))))) +;; Font locking using doxygen parser +(defvar c-ts-mode-doxygen-comment-font-lock-settings + (treesit-font-lock-rules + :language 'doxygen + :feature 'document + :override t + '((document) @font-lock-doc-face) + + :language 'doxygen + :override t + :feature 'keyword + '((tag_name) @font-lock-constant-face + (storageclass) @font-lock-constant-face) + + :language 'doxygen + :override t + :feature 'definition + '((tag (identifier) @font-lock-variable-name-face) + (function (identifier) @font-lock-function-name-face) + (function_link) @font-lock-function-name-face)) + "Tree-sitter font lock rules for doxygen like comment styles.") + ;;; Statement indent (defvar c-ts-common-indent-offset nil diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 6325fc20e6e..e989f44f588 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -63,6 +63,9 @@ ;; will set up Emacs to use the C/C++ modes defined here for other ;; files, provided that you have the corresponding parser grammar ;; libraries installed. +;; +;; If the tree-sitter doxygen grammar is available, then the comment +;; blocks will be highlighted according to this grammar. ;;; Code: @@ -539,7 +542,7 @@ NODE should be a labeled_statement. PARENT is its parent." ;;; Font-lock (defvar c-ts-mode--feature-list - '(( comment definition) + '(( comment document definition) ( keyword preprocessor string type) ( assignment constant escape-sequence label literal) ( bracket delimiter error function operator property variable)) @@ -591,6 +594,10 @@ MODE is either `c' or `cpp'." "LIVE_BUFFER" "FRAME")) "A regexp matching all the variants of the FOR_EACH_* macro.") +(defvar c-ts-mode--doxygen-comment-regex + (rx (| "/**" "/*!" "//!" "///")) + "A regexp that matches all doxygen comment styles.") + (defun c-ts-mode--font-lock-settings (mode) "Tree-sitter font-lock settings. MODE is either `c' or `cpp'." @@ -1317,30 +1324,47 @@ in your init files." (when c-ts-mode-emacs-sources-support (treesit-parser-create 'c nil nil 'for-each)) - (treesit-parser-create 'c) - ;; Comments. - (setq-local comment-start "/* ") - (setq-local comment-end " */") - ;; Indent. - (setq-local treesit-simple-indent-rules - (c-ts-mode--get-indent-style 'c)) - ;; Font-lock. - (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'c)) - ;; Navigation. - (setq-local treesit-defun-tactic 'top-level) - (treesit-major-mode-setup) - - ;; Emacs source support: handle DEFUN and FOR_EACH_* gracefully. - (when c-ts-mode-emacs-sources-support - (setq-local add-log-current-defun-function - #'c-ts-mode--emacs-current-defun-name) - - (setq-local treesit-range-settings - (treesit-range-rules 'c-ts-mode--emacs-set-ranges)) - - (setq-local treesit-language-at-point-function - (lambda (_pos) 'c)) - (treesit-font-lock-recompute-features '(emacs-devel))))) + (let ((primary-parser (treesit-parser-create 'c))) + ;; Comments. + (setq-local comment-start "/* ") + (setq-local comment-end " */") + ;; Indent. + (setq-local treesit-simple-indent-rules + (c-ts-mode--get-indent-style 'c)) + ;; Font-lock. + (setq-local treesit-font-lock-settings + (c-ts-mode--font-lock-settings 'c)) + ;; Navigation. + (setq-local treesit-defun-tactic 'top-level) + (treesit-major-mode-setup) + + ;; Emacs source support: handle DEFUN and FOR_EACH_* gracefully. + (when c-ts-mode-emacs-sources-support + (setq-local add-log-current-defun-function + #'c-ts-mode--emacs-current-defun-name) + + (setq-local treesit-range-settings + (treesit-range-rules 'c-ts-mode--emacs-set-ranges)) + + (setq-local treesit-language-at-point-function + (lambda (_pos) 'c)) + (treesit-font-lock-recompute-features '(emacs-devel))) + + ;; Inject doxygen parser for comment. + (when (treesit-ready-p 'doxygen) + (setq-local treesit-primary-parser primary-parser) + (setq-local treesit-font-lock-settings + (append + treesit-font-lock-settings + c-ts-mode-doxygen-comment-font-lock-settings)) + (setq-local treesit-range-settings + (treesit-range-rules + :embed 'doxygen + :host 'c + :local t + `(((comment) @cap + (:match + ,c-ts-mode--doxygen-comment-regex @cap))))))))) (derived-mode-add-parents 'c-ts-mode '(c-mode)) @@ -1368,24 +1392,40 @@ recommended to enable `electric-pair-mode' with this mode." :after-hook (c-ts-mode-set-modeline) (when (treesit-ready-p 'cpp) - - (treesit-parser-create 'cpp) - - ;; Syntax. - (setq-local syntax-propertize-function - #'c-ts-mode--syntax-propertize) - - ;; Indent. - (setq-local treesit-simple-indent-rules - (c-ts-mode--get-indent-style 'cpp)) - - ;; Font-lock. - (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'cpp)) - (treesit-major-mode-setup) - - (when c-ts-mode-emacs-sources-support - (setq-local add-log-current-defun-function - #'c-ts-mode--emacs-current-defun-name)))) + (let ((primary-parser (treesit-parser-create 'cpp))) + + ;; Syntax. + (setq-local syntax-propertize-function + #'c-ts-mode--syntax-propertize) + + ;; Indent. + (setq-local treesit-simple-indent-rules + (c-ts-mode--get-indent-style 'cpp)) + + ;; Font-lock. + (setq-local treesit-font-lock-settings + (c-ts-mode--font-lock-settings 'cpp)) + (treesit-major-mode-setup) + + (when c-ts-mode-emacs-sources-support + (setq-local add-log-current-defun-function + #'c-ts-mode--emacs-current-defun-name)) + + ;; Inject doxygen parser for comment. + (when (treesit-ready-p 'doxygen) + (setq-local treesit-primary-parser primary-parser) + (setq-local treesit-font-lock-settings + (append + treesit-font-lock-settings + c-ts-mode-doxygen-comment-font-lock-settings)) + (setq-local treesit-range-settings + (treesit-range-rules + :embed 'doxygen + :host 'cpp + :local t + `(((comment) @cap + (:match + ,c-ts-mode--doxygen-comment-regex @cap))))))))) (derived-mode-add-parents 'c++-ts-mode '(c++-mode)) diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el index 4ceb211ade1..68ead567632 100644 --- a/lisp/progmodes/java-ts-mode.el +++ b/lisp/progmodes/java-ts-mode.el @@ -24,6 +24,8 @@ ;;; Commentary: ;; +;; If the tree-sitter doxygen grammar is available, then the comment +;; blocks will be highlighted according to this grammar. ;;; Code: @@ -312,7 +314,7 @@ Return nil if there is no name or if NODE is not a defun node." (defvar java-ts-mode--feature-list - '(( comment definition ) + '(( comment document definition ) ( constant keyword string type) ( annotation expression literal) ( bracket delimiter operator))) @@ -326,76 +328,91 @@ Return nil if there is no name or if NODE is not a defun node." (unless (treesit-ready-p 'java) (error "Tree-sitter for Java isn't available")) - (treesit-parser-create 'java) - - ;; Comments. - (c-ts-common-comment-setup) - - ;; Indent. - (setq-local c-ts-common-indent-type-regexp-alist - `((block . ,(rx (or "class_body" - "array_initializer" - "constructor_body" - "annotation_type_body" - "interface_body" - "lambda_expression" - "enum_body" - "switch_block" - "record_declaration_body" - "block"))) - (close-bracket . "}") - (if . "if_statement") - (else . ("if_statement" . "alternative")) - (for . "for_statement") - (while . "while_statement") - (do . "do_statement"))) - (setq-local c-ts-common-indent-offset 'java-ts-mode-indent-offset) - (setq-local treesit-simple-indent-rules java-ts-mode--indent-rules) - - ;; Electric - (setq-local electric-indent-chars - (append "{}():;," electric-indent-chars)) - - ;; Navigation. - (setq-local treesit-defun-type-regexp - (regexp-opt '("method_declaration" - "class_declaration" - "record_declaration" - "interface_declaration" - "enum_declaration" - "import_declaration" - "package_declaration" - "module_declaration" - "constructor_declaration"))) - (setq-local treesit-defun-name-function #'java-ts-mode--defun-name) - - (setq-local treesit-thing-settings - `((java - (sexp ,(rx (or "annotation" - "parenthesized_expression" - "argument_list" - "identifier" - "modifiers" - "block" - "body" - "literal" - "access" - "reference" - "_type" - "true" - "false"))) - (sentence ,(rx (or "statement" - "local_variable_declaration" - "field_declaration" - "module_declaration" - "package_declaration" - "import_declaration"))) - (text ,(regexp-opt '("line_comment" - "block_comment" - "text_block")))))) - - ;; Font-lock. - (setq-local treesit-font-lock-settings java-ts-mode--font-lock-settings) + (let ((primary-parser (treesit-parser-create 'java))) + + ;; Comments. + (c-ts-common-comment-setup) + + ;; Indent. + (setq-local c-ts-common-indent-type-regexp-alist + `((block . ,(rx (or "class_body" + "array_initializer" + "constructor_body" + "annotation_type_body" + "interface_body" + "lambda_expression" + "enum_body" + "switch_block" + "record_declaration_body" + "block"))) + (close-bracket . "}") + (if . "if_statement") + (else . ("if_statement" . "alternative")) + (for . "for_statement") + (while . "while_statement") + (do . "do_statement"))) + (setq-local c-ts-common-indent-offset 'java-ts-mode-indent-offset) + (setq-local treesit-simple-indent-rules java-ts-mode--indent-rules) + + ;; Electric + (setq-local electric-indent-chars + (append "{}():;," electric-indent-chars)) + + ;; Navigation. + (setq-local treesit-defun-type-regexp + (regexp-opt '("method_declaration" + "class_declaration" + "record_declaration" + "interface_declaration" + "enum_declaration" + "import_declaration" + "package_declaration" + "module_declaration" + "constructor_declaration"))) + (setq-local treesit-defun-name-function #'java-ts-mode--defun-name) + + (setq-local treesit-thing-settings + `((java + (sexp ,(rx (or "annotation" + "parenthesized_expression" + "argument_list" + "identifier" + "modifiers" + "block" + "body" + "literal" + "access" + "reference" + "_type" + "true" + "false"))) + (sentence ,(rx (or "statement" + "local_variable_declaration" + "field_declaration" + "module_declaration" + "package_declaration" + "import_declaration"))) + (text ,(regexp-opt '("line_comment" + "block_comment" + "text_block")))))) + + ;; Font-lock. + (setq-local treesit-font-lock-settings + java-ts-mode--font-lock-settings) + + ;; Inject doxygen parser for comment. + (when (treesit-ready-p 'doxygen) + (setq-local treesit-primary-parser primary-parser) + (setq-local treesit-font-lock-settings + (append treesit-font-lock-settings + c-ts-mode-doxygen-comment-font-lock-settings)) + (setq-local treesit-range-settings + (treesit-range-rules + :embed 'doxygen + :host 'java + :local t + `(((block_comment) @cap (:match "/\\*\\*" @cap))))))) + (setq-local treesit-font-lock-feature-list java-ts-mode--feature-list) ;; Imenu. -- 2.39.2