uben0/tree-sitter-typst

keys of dictionnary are highlighted differently if they are constant name

Closed this issue · 6 comments

I think this screenshot explain the problem well.

screenshot_02272024_09_42_18

uben0 commented

Yes, this is problematic. I am aware of this issue but I didn't know the right way to solve it. Let me explain:

There are two situations where we don't want identifiers to be classified as builtins,

  1. When used as dictionary keys (white: a)
  2. When used as member access b.white

In the second case, it is easy to prevent .white from being classified as builtin. But in the first case, it's trickier.

To be efficient and small, the parser is not aware of the difference between the array notation, the dictionary notation, the argument notation or the simple parenthesized expression. This means, when finding an identifier after (, we don't know yet if it will be used as a dictionary key (or named parameter) or if it is part of an expression.

The solution I found is to alias a builtin when directly used as dictionary key. The 244c53f commit should fix it. Test it and tell me if it works.

I insist on directly because the following is valid Typst code:

#("a" + "b": 1)
#let text = "e"
#let world = "f"
#(world + text: 1)
(ab: 1)
(ef: 1)
uben0 commented

I actually broke operator precedence by trying to fix this issue:

#(white + white: 0)

Is now incorrectly parsed as:

(source_file
  (group
    (add
      (builtin)
      (tagged
        field: (ident)
        (number)))))

Instead of:

(source_file
  (group
    (tagged
      field: (add
        (builtin)
        (builtin))
      (number))))

Moreover, it increases the size of the produced parser by ~5%.

I am thinking about not recognizing builtins at all. Because it is not necessarily useful nor meaningful, as the feedback it provides is not context aware, in opposition with the language server, that will indicate if a identifier is undefined.

I tried the latest main branch and I now have proper highlighting within the dictionary. But now, I have the same highlight color for white everywhere. Did you remove builtin highlight? If yes, I think this is a fine solution if you want to keep the parser small.

uben0 commented

Well, I made a commit to fix the issue but as it introduced a bug I just reverted it.

Now I made a last commit (3c3e5f8) that just removes the detection of builtins. After trying it, it feels more coherent, because as I said, differentiating builtins is more of a context sensitive task and doesn't bring much on syntax highlighting. For instance, when one defines a custom heading function, let say let section(...) = ..., using this as heading will be strange as it won't be highlighted the same:

#heading(...) // <- builtin style

#section(...) // <- regular style

Even the official Tyspt App doesn't distinguishes builtins:

image

Great! Do you plan to do a new release with this update?

uben0 commented

No, I'll wait for the next Typst release.