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

[REQUEST] Make it possible to join Syntax elements with different stylings. #1829

Closed
aroberge opened this issue Jan 12, 2022 · 6 comments
Closed

Comments

@aroberge
Copy link

How would you improve Rich?

The feature request I would be interested is the ability to join Syntax items so that different parts could be highlighted in a different theme. The desire to do so is to reproduce the highlighting recently introduced by IPython for indicating the location of the part of code that causes an exception as shown in a recent tweet; image below. This obviously cannot work if each Syntax item appends a newline character by default as noted in #1827 ... However, this feature request goes well beyond what is required to "fix" #1827.

In pseudo-code, and using a line of code from the image below, I would like to be able to do something like:

code = Syntax('return ', "python") + Syntax('x[0][i]', "Text only", theme="error") + Syntax('[0]')
print(code)

FI5_l4MWUAAF6gI

What problem does it solve for you?

Being able to reproduce the new styles of IPython tracebacks (including in Jupyter notebooks) to show the location of an error, instead of using a separate line and using ^ characters.

I already do this when showing tracebacks within IDLE (not supported by Rich).

@willmcgugan
Copy link
Collaborator

Syntax objects aren't really something that can be composed because you can't always correctly highlight a portion of a file.

For instance, if I highlight the keyword "return" it will be in an entirely different color if preceded by "#".

To capture the requirement of highlighting portions of the text, Syntax would need to grow a method to apply additional styles to specific line / character ranges.

Something like the following:

syntax = Syntax(code, "python")
syntax.stylize("on yellow", (lineno, start), (lineno, end)) 

@aroberge
Copy link
Author

This would work and would likely be ideal for my use case. However, I am worried about how complicated it would be for what is possibly a niche case.

Alternatively, if the "problem" of automatically adding a newline by Syntax as noted in #1827 were to become an option, I would probably be able to do something like (pseudocode written without looking at the documentation)

begin = Syntax(begin_code, "python", no_added_nl=True)
middle = Text(middle_code).stylize("on yellow")
end_ = Syntax(end_code, "python")
print(begin, end='')
print(middle, end='')
print(end_)

The advantage of doing it this way is that I could ensure that the additional colouring done by Syntax would not yield something with too little contrast for the text with yellow background (or whatever colour is chosen).

@willmcgugan
Copy link
Collaborator

It probably isn't all that niche. Sounds like a nice feature.

There's still the problem that you can't highlight pieces of the code independently. If you want to be sure not to break the highlighting, you would have to highlight the whole first, and then slice it.

With regards to highlighting with good contrast. I think the best solution would be to calculate new colors based on theme colors. For instance if the background was blended with 20% of red.

@aroberge
Copy link
Author

By implementing my own parsing on highlighted lines, and using Text instead of Syntax, I was able to achieve what I wanted. The advantage I see with the approach I used is that the highlighted text is always visible since all the tokens are shown with the same colour, contrasted with the chosen background (which will be possible to define based on user's preference).

Proof of concept:

  1. Original information using ^ to indicate the position of an error. The entire code blocks are highlighted using Syntax.

image

  1. Replacing ^ by text highlighted. Lines that do not contain errors are highlighted using Syntax. Lines containing errors are done with Text, combining multiple parts.

image

  1. Same example but done in a Jupyter notebook with a light background.

image

  1. This method also works when multiple subparts need to be highlighted

image

For my use case, I think that I might stick with my approach, even if the proposed syntax.stylize() method is implemented.

@willmcgugan
Copy link
Collaborator

Syntax will grow the ability to highlight ranges of columns soon. Which should negate the need to join Syntax objects, which was always going to be problematic.

@github-actions
Copy link

Did I solve your problem?

Why not buy the devs a coffee to say thanks?

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

No branches or pull requests

2 participants