4

In c-mode it's possible to show doxygen comments /** ... */ using font-lock-doc-face. See: docs for c-doc-comment-style.

How can this be done in c-ts-mode ?


I can find documentation pointing to treesit-font-lock-settings but this is mainly focusing on supporting major-modes from scratch, not customizing existing modes.


This patch on Emacs-30 implements the feature but I would like to be able to achieve this without having to patch Emacs, I'm still not sure how to properly implement this as an extension though.

diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index b3c48eb2c65..9e8fd18da66 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -541,13 +541,35 @@ c-ts-mode--for-each-tail-regexp "LIVE_BUFFER" "FRAME")) "A regexp matching all the variants of the FOR_EACH_* macro.") +(defun c-ts-mode--comment-docstring (node override start end &rest _args) + "Use documentation face for /** ... */ comments." + + (let* ((beg (treesit-node-start node)) + (end (treesit-node-end node)) + (prefix (buffer-substring-no-properties beg (+ beg 3)))) + (cond + ((string-equal "/**" prefix) + (treesit-fontify-with-override + beg end + 'font-lock-doc-face override start end)) + ((string-equal "//" (substring prefix 0 2)) + (treesit-fontify-with-override + beg end + 'font-lock-preprocessor-face override start end)) + (t + (treesit-fontify-with-override + beg end + 'font-lock-comment-face override start end))))) + (defun c-ts-mode--font-lock-settings (mode) "Tree-sitter font-lock settings. MODE is either `c' or `cpp'." (treesit-font-lock-rules :language mode :feature 'comment - `((comment) @font-lock-comment-face + `((comment) @c-ts-mode--comment-docstring (comment) @contextual) :language mode 
2
  • What is your actual question? It looks like you’ve written the code correctly (though you need to fix the docstring for your new c-ts-mode--comment-docstring function). Commented Aug 28, 2023 at 11:39
  • 1
    @db48x my question is how to use c-doc-comment-style in c-ts-mode, WITHOUT a custom patched version of emacs. Commented Aug 28, 2023 at 23:58

2 Answers 2

3

I believe that treesit-font-lock-settings is currently indeed the "whole story" for color customization. It's clunky and there isn't yet a lot of info online, but you don't need to resort to copying or advice. You can modify it after the fact.

Here's my init.el snippet customizing coloring, in this case for namespace references. I based it mainly on https://www.masteringemacs.org/article/lets-write-a-treesitter-major-mode.

;; c++-ts-mode-hook evidently runs *after* somethng snapshots ;; this. The extra features in the hook "take effect", but font lock ;; level changes don't. ;; (setq treesit-font-lock-level 2) (add-hook 'c++-ts-mode-hook (lambda() ;; c++-ts-mode fontifies C in C::Foo() as a plain type, ;; while c++-mode knows that it's a namespace and uses ;; (confusingly) font-lock-constant-face (confirm with ;; describe-face). ;; ;; car because treesit-font-lock-rules returns a ;; list. ;; (add-to-list 'treesit-font-lock-settings (car (treesit-font-lock-rules :language 'cpp :override t ;; The arbitrary "feature" name that ;; I've chosen for this rule. ;; :feature 'namespace ;; First elem is the syntax node type ;; to match, as seen in ;; treesit-explore-mode. Second is the ;; face to use for it. ;; '((namespace_identifier) @compilation-mode-line-run))) t) ;; You also have to mention the new "feature" in one of ;; the sublists of this thing defining "font lock ;; verbosity levels". Here I'm adding it to level 2 ;; (treesit-font-lock-level counts from 1). (push 'namespace (nth 1 treesit-font-lock-feature-list)))) 

I think that you could adapt this to register c-ts-mode--comment-docstring as a new feature, or to replace the query for the existing comment feature like you do in your example (the more performant option, IIUC).

For example, for the former approach, I think you'd replace (namespace_identifier) @compilation-mode-line-run with (comment) @c-ts-mode--comment-docstring. Note that the override flag would likely be important in this case, to make sure that the new rule supersedes the built-in coloring for comment nodes.

1
  • Very helpful answer - thank you. BTW, for some reason my uniquely named "feature" (set up like in the first half of that hook) works even without adding it to treesit-font-lock-feature-list. Commented Aug 25, 2024 at 7:49
1

If you just want to use this modification yourself, all you have to do is stick your new c-ts-mode--comment-docstring function and your modified c-ts-mode--font-lock-settings function into your init file (usually ~/.emacs.d/init.el).

When you load a C file and Emacs starts the c-ts-mode for you, your modified c-ts-mode--font-lock-settings function will be called instead of the original one that it replaced. Of course you could also use advice for that, but since you are replacing the whole return value there isn’t much point.

Naturally you should also send this patch off to the emacs-devel mailing list, if you haven’t already. I am sure the maintainers would be happy to see it, and then the next release of Emacs would have this change built in.

3
  • This means I need to maintain a copy of c-ts-mode--font-lock-settings in my init.el this is 163 lines on non-trivial elisp, with references to tree-sitter and c-ts-mode internals. Of course it can be done, but in that case I'd rather use a patched emacs. Commented Aug 30, 2023 at 3:09
  • Yep. You could add a :filter-return advice that modifies the return value of the font lock settings. Either way, make sure you send your patch to the mailing list. Commented Aug 30, 2023 at 11:36
  • There really should be an easier way for users to customize the tree-sitter rules. I've also been accumulating a number of patches in my init files. Having a treesit-font-lock-feature-list entry devoted to user mods that gets applied in all modes might be useful. Commented Oct 6, 2023 at 18:57

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.