Subject: bug#67061: [PATCH] Improve syntax highlighting for python-ts-mode

From: Denis Zubarev <[email-masked]>
Date: Sun, 17 Dec 2023 04:56:16 +0300

> Do we want to have a common face which would inherit from

> font-lock-variable-name-face and would be used solely for

> function/methods parameters and nothing else? I don't object, but I

> don't quite see the point either.

The point is to make it easy for users to customize faces of features

independently from each other.

It is not only about variables/parameters.

For example, if I want to change a face for decorators, I have to change

font-lock-type-face, which will change also all type faces.

I like approach from the helix editor. They introduce many captures with

different levels of specificity, for example @variable for (identifier),

@variable.parameter for function parameters, @variable.builtin for

self|cls etc. I guess by default the default face defined for a @variable

is used. But one can customize variable.parameter to their liking without touching any

other variables.

> Then I suppose we should clarify whether Denis wants a face that only

> matches function parameters, or implicit variable declarations as well.

> Or maybe instead a face that is only used for assignments (only first

> assignments?) -- which would separate them from the two semantic units

> above.

I think ideally, there should be a face for a feature (or even multiple

faces).

For example, faces for variables in helix notation:

- @variable

- @variable.definition

- @variable.definition.parameter

- @variable.assignment

- @variable.use

13.12.2023, 21:28, "Dmitry Gutov" <[email-masked]>:

On 13/12/2023 05:49, Yuan Fu wrote:

Python doesn't have special keywords for variable declarations (unlike
'let' in JavaScript or typed declaration in C), so the first time a
variable is introduced serves as its declaration. For assignments, we
can't easily determine which is the first time for a given scope, but
examples like 'for var in ...' or 'except ZeroDivisionError as e:' or
'[... for var in ...]' are all unambiguously variable definitions.

Sure, I don't really care too much about which feature should a rule be
in; what I do care about is to keep first and second fontification level
relatively quite and minimal, and keep level 3 reasonably conservative.
And people that want a lot of highlight can turn on level 4.

I don't mind if assignments in python-ts-mode go to level 3, that's what
ruby-ts-mode does anyway. But '[... for var in ...]' really should use
variable-name-face and it should be in the default config (level 3 at
most). I think the 'definition' feature is good for it (going by the
name, since it's an implicit variable declaration), but it could be
split off into a separate feature too.

in c-ts-mode highlighting for 'int i = 4' is split between
'definition' and 'assignment' (the latter seemingly redundant);

Should've been in assignment IMO. I probably overlooked it.

The current state is that the query in 'definition' can highlight both
'int i;' and 'int i = 4;'. The query in 'assignment' in c-ts-mode only
highlights 'int i = 4;'.

If you just keep the latter query, 'int i;' would stay unfontified. If
you move the corresponding query from 'definition' to 'assignment', it
would start matching non-assignment declarations too. Might seem odd.

typescript-ts-mode and rust-ts-mode also follow the principle, more or
less.

Well, the only ts-mode that I actually wrote is python-ts-mode. For
other major modes, I can only suggest. Even for python-ts-mode, I don't
want to exert my personal opinion onto it too much, except for keeping
font-lock level 1 and 2 quiet.

For my part, I mostly care about keeping the level 3 feature-rich
enough, but precise at the same time. And without frivolous highlights
(only a little more fruit-salady than the pre-treesit modes).

My thoughts about parameters. I started to extend rules for them
since they are very limited now.
But I'm not sure what face to use for them.
I would like to not use the same face as for assignments, because
I'd want to highlight them differently.
It seems that there is no appropriate face in font-lock.el, so I
ended up creating my own face in my config.
Does it make sense to add new face for parameters in font-lock.el?
Or it is too small feature for its own face?
I also apply this face for keyword argument in function calls.

To be honest, I don't have any good ideas. Perhaps we can add a
parameter face that inherits from variable name face by default,
Dmitry, WDYT?

As per above, parameters don't seem too different from any other
variable declarations from my POV. They are similarly useful, so I'd
highlight them the same way.

Do we want to have a common face which would inherit from
font-lock-variable-name-face and would be used solely for
function/methods parameters and nothing else? I don't object, but I
don't quite see the point either.

I agree.

Then I suppose we should clarify whether Denis wants a face that only
matches function parameters, or implicit variable declarations as well.
Or maybe instead a face that is only used for assignments (only first
assignments?) -- which would separate them from the two semantic units
above.