Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] syntax coloring of Python f-strings by default #3605

Open
peterjc opened this issue Jan 11, 2025 · 8 comments
Open

[Feature Request] syntax coloring of Python f-strings by default #3605

peterjc opened this issue Jan 11, 2025 · 8 comments

Comments

@peterjc
Copy link

peterjc commented Jan 11, 2025

Description of the problem or steps to reproduce

Current behavior of micro is to treat Python f-strings like plain strings (yellow in the default color scheme):

Screenshot 2025-01-11 at 20 48 14

This example is taken from https://docs.python.org/3/reference/lexical_analysis.html#f-strings where the variables like name in the first f-string of this example are in white (screenshot with Firefox showing coloring of the expressions with f-strings):

Screenshot 2025-01-11 at 20 45 53

Desired behaviour would be like the Python.org documentation, or similar - this is Sublime Text Build 4189 on macOS which seems to format the code snippets within f-strings like normal Python code:

Screenshot 2025-01-11 at 20 51 21

Specifications

$ micro --version
Version: 2.0.14
Commit hash: 04c57704
Compiled on August 27, 2024

Commit hash: 04c5770
OS: Linux
Terminal: Ghostty

(Same behavior on macOS with micro 2.0.14)

@Andriamanitra
Copy link
Contributor

Unfortunately the recursive nature of the f-string syntax makes this impossible to solve properly with micro's current syntax highlighting system. I actually use a custom Python syntax file that tries to highlights f-strings, but it's so buggy that I don't think it would be a good idea to have it built into the editor.

https://github.com/Andriamanitra/dotfiles/blob/c642702c048e7a045fb08f7e5792e981b41c07b7/micro/.config/micro/syntax/python3.yaml#L76-L136

screenshot

@Andriamanitra
Copy link
Contributor

And here is an attempt using the "one level of recursion" trick from #2596. Still broken for the nested fields, and I can't figure out a way to make everything after : the same color. (and for some reason the # is broken too, that might just be a bug in micro).

https://gist.github.com/Andriamanitra/7dc25fc510c0fee4e54883cd28d42487

screenshot

@peterjc
Copy link
Author

peterjc commented Jan 12, 2025

The full syntax is understandably very tricky - perhaps a minimal solution of highlighting anything matching {...} within an f-string a different color would be a safe modest improvement?

@Andriamanitra
Copy link
Contributor

The full syntax is understandably very tricky - perhaps a minimal solution of highlighting anything matching {...} within an f-string a different color would be a safe modest improvement?

This handles that up to one level of nesting, although I'm a bit worried about the regexp performance with how many wild cards the pattern is using. It likely blows up if you give it a specifically crafted string.

    - constant.string:
        start: "f\""
        end: "\""
        skip: "\\\\."
        rules:
            - constant.specialChar: "\\\\['\"nrtbf\\\\]"
            - constant.specialChar: "\\\\0[0-7]{0,2}"
            - constant.specialChar: "\\\\x[0-9A-Fa-f]{2}"
            - constant.specialChar: "\\\\u[0-9A-Fa-f]{4}"
            - constant.specialChar: "\\\\U[0-9A-Fa-f]{8}"
            # hard-coded cyan because I'm not sure which group would fit well
            - cyan: "[{](([{][^}]*[}])?[^{}]*)*[}]"
            - symbol.brackets: "[{}]"

screenshot

@JoeKar
Copy link
Collaborator

JoeKar commented Jan 12, 2025

And here is an attempt using the "one level of recursion" trick from #2596.

I think it would be more straight forward to allow recursion to a certain level. Sure, the parsing and highlighting system needs some additional tuning, but it isn't impossible.

This handles that up to one level of nesting, although I'm a bit worried about the regexp performance with how many wild cards the pattern is using. It likely blows up if you give it a specifically crafted string.

Yep, the current released highlighter isn't prepared for such stuff and already fails on "simple" html and xml.
So definitely not before #3127.

@Andriamanitra
Copy link
Contributor

And here is an attempt using the "one level of recursion" trick from #2596.

I think it would be more straight forward to allow recursion to a certain level. Sure, the parsing and highlighting system needs some additional tuning, but it isn't impossible.

Do you mean that it isn't impossible with the current system, or that it isn't impossible to change the system to make it possible? I think the parser would need some way to maintain state, as it's not possible to (ab)use the start/end/skip/rules system for nested expressions like this:

w = 7
f"{ {"width":f"{w:{w}}"} !r:{w}}"

@JoeKar
Copy link
Collaborator

JoeKar commented Jan 12, 2025

[...] or that it isn't impossible to change the system to make it possible?

Yep. The parser already maintains states. In the version with #3127 it will have the capability to remove already identified regions in case of overlaps.

[...] as it's not possible to (ab)use the start/end/skip/rules system for nested expressions like this:

Yes, it will require more features, but I'm unsure if this weird example can be solved easily. 😅

@peterjc
Copy link
Author

peterjc commented Jan 19, 2025

I think the simple one level of recursion example shown would be a worthwhile incremental improvement (e.g. it should help visually flag unmatched { and }).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants