diff --git a/src/strings/basic.jl b/src/strings/basic.jl index 8223c85..cb23303 100644 --- a/src/strings/basic.jl +++ b/src/strings/basic.jl @@ -6,27 +6,17 @@ _isannotated(s) = _isannotated(typeof(s)) # actually from substring.jl _isannotated(::SubString{T}) where {T} = _isannotated(T) -# NOTE Too invalidating: - -# function (*)(s1::Union{AnnotatedChar, AnnotatedString}, s2::Union{AbstractChar, AbstractString}) -# annotatedstring(s1, s2) -# end - -# function (*)(s1::Union{AbstractChar, AbstractString}, s2::Union{AnnotatedChar, AnnotatedString}) -# annotatedstring(s1, s2) -# end - -# function (*)(s1::Union{AnnotatedChar, AnnotatedString}, s2::Union{AnnotatedChar, AnnotatedString}) -# annotatedstring(s1, s2) -# end - -# function (*)(s1::Union{AbstractChar, AbstractString}, s2::Union{AbstractChar, AbstractString}, ss::Union{AbstractChar, AbstractString}...) -# if _isannotated(s1) || _isannotated(s2) || any(_isannotated, ss) -# annotatedstring(s1, s2, ss...) -# else -# string(s1, s2, ss...) -# end -# end +# The following meta-programming will generate code like: +# Base.:*(s_annot::AnnotatedString, s::Union{AbstractChar,AbstractString}...) = annotatedstring(s_annot, s...) +# Base.:*(s1::Union{AbstractChar,AbstractString}, s_annot::AnnotatedString, s::Union{AbstractChar,AbstractString}...) = annotatedstring(s1, s_annot, s...) +# and so on. +for i in 0:31 + front = [Symbol('s', j) for j in 1:i] + front_typed = [:($s::Union{AbstractChar,AbstractString}) for s in front] + @eval function Base.:*($(front_typed...), s_annot::AnnotatedString, s::Union{AbstractChar,AbstractString}...) + annotatedstring($(front...), s_annot, s...) + end +end # # From io.jl # join(iterator) = _join_preserve_annotations(iterator) diff --git a/test/runtests.jl b/test/runtests.jl index d0a15f2..d7b0ca4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -670,3 +670,45 @@ end @test printstyled(aio, "e", color=:green) |> isnothing @test read(seekstart(aio), AnnotatedString) == styled"{bold:a}{italic:b}{underline:c}{inverse:d}{(fg=green):e}" end + +@testset "concatenation via *" begin + function check_annotated_equal(a::AbstractString, b::AbstractString) + if a isa AnnotatedString && b isa AnnotatedString + String(a) == String(b) && annotations(a) == annotations(b) + else + false + end + end + + s_annot = styled"{red:hello}" + + # Test (styled, styled) + @test check_annotated_equal( + s_annot * styled"{blue:world}", + styled"{red:hello}{blue:world}" + ) + + # Test (styled, regular) + @test check_annotated_equal( + s_annot * "world", + styled"{red:hello}world" + ) + + # Test (regular, styled) + @test check_annotated_equal( + "hello" * s_annot, + styled"hello{red:hello}" + ) + + # Test (styled, regular, styled) + @test check_annotated_equal( + s_annot * " " * styled"{blue:world}", + styled"{red:hello} {blue:world}" + ) + + # Test (regular, regular, styled) + @test check_annotated_equal( + "hello" * " " * s_annot, + styled"hello {red:hello}" + ) +end