Skip to content

Commit

Permalink
Resolve Face eagerly when constructing StyledString
Browse files Browse the repository at this point in the history
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
  • Loading branch information
topolarity committed Oct 15, 2024
1 parent 056e843 commit 3da75af
Showing 1 changed file with 20 additions and 17 deletions.
37 changes: 20 additions & 17 deletions src/styledmarkup.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Of course, as usual, the devil is in the details.
module StyledMarkup

using Base: AnnotatedString, annotations, annotatedstring
using ..StyledStrings: Face, SimpleColor
using ..StyledStrings: Face, SimpleColor, getface

export @styled_str, styled

Expand Down Expand Up @@ -325,7 +325,7 @@ function readexpr!(state::State, pos::Int = first(popfirst!(state.s)) + 1)
if isempty(state.s)
styerr!(state,
AnnotatedString("Identifier or parenthesised expression expected after \$ in string",
[(55:55, :face, :warning)]),
[(55:55, :face, getface(:warning))]),
-1, "right here")
return "", pos
end
Expand Down Expand Up @@ -401,7 +401,7 @@ and register it in the active styles list.
"""
function begin_style!(state::State, i::Int, char::Char)
hasvalue = false
newstyles = Vector{Tuple{Int, Int, Union{Symbol, Expr, Tuple{Symbol, Any}}}}()
newstyles = Vector{Tuple{Int, Int, Union{Expr, Tuple{Symbol, Any}}}}()
while read_annotation!(state, i, char, newstyles) end
push!(state.active_styles, reverse!(newstyles))
# Adjust bytes/offset based on how much the index
Expand Down Expand Up @@ -535,9 +535,9 @@ function read_inlineface!(state::State, i::Int, char::Char, newstyles)
valid_options = join(VALID_UNDERLINE_STYLES, ", ", ", or ")
styerr!(state,
AnnotatedString("Invalid underline style '$ustyle_word' (should be $valid_options)",
[(26:25+ncodeunits(ustyle_word), :face, :warning)
[(26:25+ncodeunits(ustyle_word), :face, getface(:warning))
(28+ncodeunits(ustyle_word):39+ncodeunits(ustyle_word)+ncodeunits(valid_options),
:face, :light)]),
:face, getface(:light))]),
-length(ustyle_word) - 3)
end
ustyle = Symbol(ustyle_word)
Expand Down Expand Up @@ -658,24 +658,24 @@ function read_inlineface!(state::State, i::Int, char::Char, newstyles)
else
invalid, lastchar = readsymbol!(state, lastchar)
styerr!(state, AnnotatedString("Invalid height '$invalid', should be a natural number or positive float",
[(17:16+ncodeunits(string(invalid)), :face, :warning)]),
[(17:16+ncodeunits(string(invalid)), :face, getface(:warning))]),
-3)
end
elseif key (:weight, :slant)
v, lastchar = readalph!(state, lastchar)
if key == :weight && v VALID_WEIGHTS
valid_options = join(VALID_WEIGHTS, ", ", ", or ")
styerr!(state, AnnotatedString("Invalid weight '$v' (should be $valid_options)",
[(17:16+ncodeunits(v), :face, :warning),
[(17:16+ncodeunits(v), :face, getface(:warning)),
(19+ncodeunits(v):30+ncodeunits(v)+ncodeunits(valid_options),
:face, :light)]),
:face, getface(:light))]),
-3)
elseif key == :slant && v VALID_SLANTS
valid_options = join(VALID_SLANTS, ", ", ", or ")
styerr!(state, AnnotatedString("Invalid slant '$v' (should be $valid_options)",
[(16:15+ncodeunits(v), :face, :warning),
[(16:15+ncodeunits(v), :face, getface(:warning)),
(18+ncodeunits(v):29+ncodeunits(v)+ncodeunits(valid_options),
:face, :light)]),
:face, getface(:light))]),
-3)
end
Symbol(v) |> if ismacro(state) QuoteNode else identity end
Expand All @@ -702,7 +702,7 @@ function read_inlineface!(state::State, i::Int, char::Char, newstyles)
else
styerr!(state, AnnotatedString(
"Uses unrecognised face key '$key'. Recognised keys are: $(join(VALID_FACE_ATTRS, ", ", ", and "))",
[(29:28+ncodeunits(String(key)), :face, :warning)]),
[(29:28+ncodeunits(String(key)), :face, getface(:warning))]),
-length(str_key) - 2)
end
if ismacro(state) && !any(k -> first(k.args) == key, kwargs)
Expand All @@ -711,7 +711,7 @@ function read_inlineface!(state::State, i::Int, char::Char, newstyles)
push!(kwargs, key => val)
else
styerr!(state, AnnotatedString("Contains repeated face key '$key'",
[(29:28+ncodeunits(String(key)), :face, :warning)]),
[(29:28+ncodeunits(String(key)), :face, getface(:warning))]),
-length(str_key) - 2)
end
isempty(state.s) && styerr!(state, "Incomplete inline face declaration", -1)
Expand All @@ -727,11 +727,11 @@ function read_inlineface!(state::State, i::Int, char::Char, newstyles)
push!(newstyles,
(i, i + state.offset + 1,
if !ismacro(state)
:face, Face(; NamedTuple(kwargs)...)
(:face, Face(; NamedTuple(kwargs)...))
elseif needseval
:((:face, $face))
else
:face, hygienic_eval(state, face)
(:face, hygienic_eval(state, face))
end))
end

Expand Down Expand Up @@ -803,6 +803,7 @@ 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)
# TODO
Symbol(key), value
elseif key isa Expr || key isa Symbol
:(($key, $value))
Expand All @@ -813,9 +814,11 @@ function read_face_or_keyval!(state::State, i::Int, char::Char, newstyles)
push!(newstyles,
(i, i + state.offset + ncodeunits('{'),
if key isa Symbol || key isa Expr
:((:face, $key))
:((:face, $getface($key)))
elseif ismacro(state) # Face symbol
:((:face, $getface($(QuoteNode(Symbol(key))))))
else # Face symbol
:face, Symbol(key)
(:face, getface(Symbol(key)))
end))
end
if isempty(state.s) || last(peek(state.s)) (' ', '\t', '\n', '\r', ',', ':')
Expand Down Expand Up @@ -857,7 +860,7 @@ function run_state_machine!(state::State)
end
for incomplete in Iterators.flatten(state.active_styles)
styerr!(state, AnnotatedString("Unterminated annotation (missing closing '}')",
[(43:43, :face, :warning)]),
[(43:43, :face, getface(:warning))]),
prevind(state.content, first(incomplete)), "starts here")
end
end
Expand Down

0 comments on commit 3da75af

Please sign in to comment.