-
-
Notifications
You must be signed in to change notification settings - Fork 10
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
Resolve Face eagerly when constructing StyledString #99
base: main
Are you sure you want to change the base?
Conversation
The tests will need adjusting for this - I haven't done that yet sorry They currently expect that most Faces are unresolved in the AnnotatedStrings we produce |
@@ -802,20 +803,22 @@ function read_face_or_keyval!(state::State, i::Int, char::Char, newstyles) | |||
push!(newstyles, | |||
(i, i + state.offset + ncodeunits('{'), | |||
if key isa String && !(value isa Symbol || value isa Expr) | |||
Pair{Symbol, Any}(Symbol(key), value) | |||
# TODO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could use some help filling this logic in here
if key
might be :face
and we want that to display properly, we need to force resolution here too
This is the JuliaSyntaxHighlighting counterpart to: JuliaLang/StyledStrings.jl#99
This is the JuliaSyntaxHighlighting counterpart to: JuliaLang/StyledStrings.jl#99
This is the Markdown counterpart to JuliaLang/StyledStrings.jl#99 which is step 1 to solve the type-piracy in StyledStrings
This is the Markdown counterpart to JuliaLang/StyledStrings.jl#99 which is step 1 to solve the type-piracy in StyledStrings
This is step 1 to eliminating our type-piracy problems StyledStrings needs to put some type that it owns into its AnnotatedStrings so that we have a right to hook into the display logic (and the display logic can know which copy of StyledStrings to delegate to). It is also a semantic change to how constructing StyledStrings behaves, but overall I think it's a lot more intuitive to have a StyledString actually compute its style information at construction Resolves #87
3da75af
to
3f2a7c3
Compare
This is the Markdown counterpart to JuliaLang/StyledStrings.jl#99 which is step 1 to solve the type-piracy in StyledStrings
Great to see this work take shape! I'm yet to go through all of your recent flurry of PRs, but from this and a few others, I've developed two linked concerns that I think are worth discussing. Both concerns stem from the more eager use of Baking in different values, unexpectedlyFirstly, if a string is constructed at compile time/before customisations are loaded, a later use of the same face can look different. Here's an example to illustrate: # in some package Foo
@define_faces!(:my_foo => Face(foreground=:red, underline=:yellow)) # Assuming future work
const reused_string_or_similar = styled"... {my_foo:stuff} ..."
function something_a(io::IO)
...
println(io, reused_string_or_similar)
...
end
function something_b(io::IO)
...
println(io, styled"... {my_foo:other stuff} ...")
...
end In this scenario, should Inability to customise downstreamOne of the features of the current design is to remap faces on the fly. There are particular use-cases I see this enabling. For instance, say const DOCUMENTER_THEME_X = Dict(:julia_number => Face(...), ...)
const DOCUMENTER_THEME_Y = Dict(:julia_number => Face(...), ...)
# ...
function html_highlight_julia(code::String, themes::Vector{Dict{Symbol, Face}})
hl_code = highlight(code)
map(themes) do theme
withfaces(theme) do
sprint(show, MIME("text/html"), hl_code)
end
end
end Here the code is highlighted once, and then styled with multiple different themes. From what I can tell, this pattern wouldn't be possible with this PR. In this particular example, you could accept the overhead to re-parse the code and apply the faces for each theme before display, but are also other cases where you might want to pass some content across functions/packages this would be a more major impediment. Closing thoughtsI see how this gets us closer to avoiding type piracy by avoiding a Base-owned type as the value, making it possible to call the annotation owner's specialised printing function. However, I'm not quite onboard with the specific tradeoffs made here, and wonder if there's a better balance that could be struck. Considering this together with our discussions on effectively implementing custom face namespaces, I wonder if a |
I think For me, it's just as surprising that this doesn't work: @define_faces!(:my_foo => Face(foreground=:red, underline=:yellow)) # Assuming future work
const face = getface(:my_foo) # my_foo... wasn't defined yet?
const str = make_annotated("Test string", face) It's fine to have
I think that use case can be handled just by a There are other design problems to make the fully-lazy approach behave correctly though.. The The eager solution lets you perform the |
For that use case, you can use an That way, you still have the same functionality effectively, but it's obvious to the user that something important is happening when That seems better to me than resolving implicitly at every display (which is also a lot of repeated, unnecessary computation) |
Indeed, but that doesn't prevent the behaviour I describe.
I'm not quite sure what you're referring to here, if we presume
We could branch out into lazy and non-lazy versions, but if we can reasonably get away with just one that seems preferable to me.
I don't quite see the respect in which inheritance is non-lazy currently, could you elaborate?
I'm tempted to see how far we can get by having a single lazy form, but offering a |
Yeah I'm referring to this code: Lines 527 to 528 in 729f56c
Yeah - We're on the same page about the two "types" of strings at least (and the reify operation) I just have a very hard time that it's called a "StyledString" and it's not... actually styled yet - it's just marked-up / tagged We can have those lazy semantics, but if you want the string to know how to resolve its style automatically, we need to add a edit: Actually I think you're right that |
This is step 1 to eliminating our type-piracy struggles
StyledStrings needs to put some type that it owns into its AnnotatedStrings so that we have a right to hook into the display logic (and the display logic can know which copy of StyledStrings to delegate to).
It is also a semantic change to how constructing StyledStrings behaves, but overall I think it's a lot more intuitive to have a StyledString actually compute its style information at construction rather than defer it to be looked up at display time (let know if you agree @tecosaur)
Resolves #87
Made on top of #95, since that will probably be landed first.