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

Apply syntax highlighting to Exprs in REPL #54446

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

tecosaur
Copy link
Contributor

As discussed on slack a while ago, it's now near trivial to make inspecting large Exprs much more pleasant with JuliaSyntax highlighting.

See the commit message for more details.

Screenshots

image

image

@tecosaur tecosaur added stdlib:REPL Julia's REPL (Read Eval Print Loop) domain:display and printing Aesthetics and correctness of printed representations of objects. labels May 12, 2024
@tecosaur
Copy link
Contributor Author

If anyone's up for it, I think this should be a pretty quick and easy review & merge 🙂

Comment on lines 120 to 121
show(io::IO, ::MIME"text/plain", ex::Expr) =
print(io, JuliaSyntaxHighlighting.highlight(sprint(show, ex)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is type-piracy so I guess this should be caught higher up in the REPLDisplay code somewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose line 120 doesn't look that high up, but it is just after the using and exports lines.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type piracy means that one defines a method where one neither owns the function or any of the types (which is the case here).

With "higher up" it doesn't mean literally higher up in the file but higher up in the "dependency chain" (here this means in Base since Base owns show and Expr).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The REPL stdlib has it's own display and I guess this is something that should be implemented there, i.e. how REPL display Exprs and not how they are showd.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, doing this in Base isn't really an option since we're using two stdlibs here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll just switch from implementing a show method to a display method then :)

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hehe, display is also a Base function. Instead of

 show(io, mime, x[]) 

in the REPL you could add something like

...
if x[] is a Expr
   print(io, JuliaSyntaxHighlighting.highlight(sprint(show, ex)))
else
  show(io, mime, x[]) 
end
...

to

show(io, mime, x[])

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The display type is owned by REPL though, but I think perhaps in this case it is cleaner to change

show(io, mime, x[])
to

show_repl(io, mime, x[])

with implementations

show_repl(io::IO, mime::MIME, x) = show(io, mime, x)
show_repl(io::IO, mime::MIME, x::Expr) = ...

?

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The display type is owned by REPL though

Yes, it's the function I am suggesting to edit here heh, but it sets up various iocontexts etc which is also why adding a new overload to it isn't that good.

It would also be good to check that #38028 doesn't regress.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just pushed the change that @fredrikekre suggested 🙂

Copy link
Sponsor Member

@KristofferC KristofferC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be done without type piracy and respect the REPL IOContext:

Before:

julia> :(quote 123.32132132132 end)
:($(Expr(:quote, quote
    #= REPL[1]:1 =#
    123.32132132132
end)))

julia> Base.active_repl.options.iocontext[:compact] = true
true

julia> :(quote 123.32132132132 end)
:($(Expr(:quote, quote
    #= REPL[3]:1 =#
    123.321
end)))

After

julia> :(quote 123.32132132132 end)
:($(Expr(:quote, quote
    #= REPL[1]:1 =#
    123.32132132132
end)))

julia> Base.active_repl.options.iocontext[:compact] = true
true

julia> :(quote 123.32132132132 end)
:($(Expr(:quote, quote
    #= REPL[3]:1 =#
    123.32132132132
end)))

@tecosaur
Copy link
Contributor Author

@fredrikekre / @KristofferC any thoughts on the current version of the code?

@@ -23,6 +23,7 @@ using Base.Meta

import Markdown
import StyledStrings
import JuliaSyntaxHighlighting
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm actually not sure, there was some conversation I had (on Slack) which concluded with the import StyledStrings line being needed in #51869 even though it's not used in precompile.jl, so I've just "followed the pattern" here.

I could just try dropping the line and seeing what happens?

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a mechanism for how it should be needed so it's probably good to try to remove it and see what happens.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying... 🤞

@KristofferC
Copy link
Sponsor Member

The current version seems ok to me at least. Does it still obey --color=no?

@tecosaur
Copy link
Contributor Author

Yep, since it's just printing via. StyledStrings now, and StyledStrings respects the colour property as expected.

Large exprs (such as those produced by @macroexpand) can be hard to read
and interpret. This is a problem made easier by JuliaSyntaxHighlighting,
and with it we can easily apply syntax highlighting when showing exprs.

Normally this would be implemented in Base's show method for Exprs,
however since JuliaSyntaxHighlighting is a stdlib we must look
elsewhere, and REPL seems like a sensible place.

To ensure that the IOContext of the REPL IO is properly respected,
we change the show invocation within the REPL display method to use
show_repl which falls back to just calling show, as before. We then add
a show_repl(::IO, ::MIME"text/plain", ::Expr) specialisation, which
prints expressions with syntax highlighting.
Copy link
Contributor

@fingolfin fingolfin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks fine to me now, but it'd be great if @KristofferC and/or @fredrikekre could have a final look (and then perhaps directly merge it if they are happy)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:display and printing Aesthetics and correctness of printed representations of objects. stdlib:REPL Julia's REPL (Read Eval Print Loop)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants