emacs-tree-sitter / elisp-tree-sitter

Emacs Lisp bindings for tree-sitter
https://emacs-tree-sitter.github.io
MIT License
816 stars 73 forks source link

Fine-grained differentiation of keywords #141

Open ianyepan opened 3 years ago

ianyepan commented 3 years ago

In emacs-tree-sitter, keywords like if/else/for/while/return (in C/C++/Java etc.) are all treated as tree-sitter-hl-face:keyword. However, in Neovim's tree-sitter support for instance, return is rendered differently to if/else/for/while. Implementation-wise, how hard would it be for emacs-tree-sitter to also differentiate these keywords with a more fine-grained control? As an Emacs-theme maker myself, this also gives me more faces to fine-tune my themes.

A couple of screenshots to illustrate my point. Please ignore the color differences, as those are minor implementation details. The main issue is the ability to differentiate different keywords

In Emacs:

image

In Neovim:

image

rirze commented 3 years ago

So looking through the C++ tree-sitter grammar, it certainly recognizes if statements directly, and it seems like specifying faces for certain elements would done as it is shown here. I used to specify custom faces for some Python keywords by modifying this file, but I'm not sure that is the best way to achieve custom themes.

woolsweater commented 3 years ago

This is fairly easy to customize; see Syntax Highlighting > Customization on the wiki. There are two steps.

First you need to change the highlight query attribute for the elements you're interested in. Maybe you would apply @keyword.control for return.

Then you need either a) a face tree-sitter-hl-face:keyword.control or b) a face with a different name and a mapping function to return it, advising emacs-tree-sitter, as shown in the wiki:

(add-function :before-while tree-sitter-hl-face-mapping-function
  (lambda (capture-name)
    (when (string= capture-name "keyword.control")
        'my-tree-sitter-face:keyword.control))))