From 7bbcfdd250b5d6fe61323a4597de7328f06e97e2 Mon Sep 17 00:00:00 2001 From: Alexander Plavin Date: Tue, 23 Jul 2024 03:39:43 -0400 Subject: [PATCH 1/2] AnnotatedString support --- src/functionlenses.jl | 9 +++++++++ test/test_functionlenses.jl | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/functionlenses.jl b/src/functionlenses.jl index 207383d3..d35ff54d 100644 --- a/src/functionlenses.jl +++ b/src/functionlenses.jl @@ -204,3 +204,12 @@ function set(s::AbstractString, o::Base.Fix2{typeof(split), <:Union{AbstractChar any(c -> occursin(o.x, c), v) && throw(ArgumentError("split components cannot contain the delimiter $(repr(o.x))")) join(v, o.x) end + +if isdefined(Base, :AnnotatedString) + # 1.11+ + using Base: AnnotatedString, annotations + set(s::AbstractString, ::typeof(annotations), anns) = AnnotatedString(s, anns) + set(s::AnnotatedString, ::typeof(annotations), anns) = AnnotatedString(s.string, anns) + delete(s::AnnotatedString, ::typeof(annotations)) = s.string + insert(s::AbstractString, ::typeof(annotations), anns) = AnnotatedString(s, anns) +end diff --git a/test/test_functionlenses.jl b/test/test_functionlenses.jl index e3c4bd13..cefc9bc5 100644 --- a/test/test_functionlenses.jl +++ b/test/test_functionlenses.jl @@ -396,6 +396,27 @@ end @test_throws ArgumentError set(" abc def ", @optic(split(_, ' ')), [" ", "y"]) end +VERSION ≥ v"1.11" && @testset "AnnotatedStrings" begin + using Base: AnnotatedChar, AnnotatedString, annotations + + s = Base.AnnotatedString("good bad", [(region=1:4, label=:sentiment, value=+1), (region=6:8, label=:sentiment, value=-1)]) + + @test (@delete annotations(s))::String == "good bad" + + snew = @delete annotations(s)[2] + @test String(snew) == "good bad" + @test annotations(snew) == [(region=1:4, label=:sentiment, value=+1)] + + snew = (@set Base.annotations(s)[1].region = 2:6) + @test String(snew) == "good bad" + @test annotations(snew) == [(region=2:6, label=:sentiment, value=+1), (region=6:8, label=:sentiment, value=-1)] + + test_getset_laws((@o annotations(_)[2].region), s, 5:5, 1:3) + test_getset_laws((@o annotations(_)[2].label), s, :abc, :def) + test_getset_laws((@o annotations(_)[2].value), s, "sad", +2) + test_insertdelete_laws((@o annotations(_)[2]), s, (region=2:2, label=:mylabel, value=+1)) +end + @testset "custom binary function" begin ↑(x, y) = x - y Accessors.set(x, f::Base.Fix1{typeof(↑)}, y) = f.x - y From bc4745f0d5973c1e7124417768247f13801b79c8 Mon Sep 17 00:00:00 2001 From: Alexander Plavin Date: Thu, 5 Dec 2024 07:38:19 -0500 Subject: [PATCH 2/2] add AnnotatedChar support --- src/functionlenses.jl | 8 +++++++- test/test_functionlenses.jl | 21 +++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/functionlenses.jl b/src/functionlenses.jl index d35ff54d..58ea5a00 100644 --- a/src/functionlenses.jl +++ b/src/functionlenses.jl @@ -207,9 +207,15 @@ end if isdefined(Base, :AnnotatedString) # 1.11+ - using Base: AnnotatedString, annotations + using Base: AnnotatedString, AnnotatedChar, annotations + set(s::AbstractString, ::typeof(annotations), anns) = AnnotatedString(s, anns) set(s::AnnotatedString, ::typeof(annotations), anns) = AnnotatedString(s.string, anns) delete(s::AnnotatedString, ::typeof(annotations)) = s.string insert(s::AbstractString, ::typeof(annotations), anns) = AnnotatedString(s, anns) + + set(s::AbstractChar, ::typeof(annotations), anns) = AnnotatedChar(s, anns) + set(s::AnnotatedChar, ::typeof(annotations), anns) = AnnotatedChar(s.char, anns) + delete(s::AnnotatedChar, ::typeof(annotations)) = s.char + insert(s::AbstractChar, ::typeof(annotations), anns) = AnnotatedChar(s, anns) end diff --git a/test/test_functionlenses.jl b/test/test_functionlenses.jl index cefc9bc5..f63733cb 100644 --- a/test/test_functionlenses.jl +++ b/test/test_functionlenses.jl @@ -399,7 +399,7 @@ end VERSION ≥ v"1.11" && @testset "AnnotatedStrings" begin using Base: AnnotatedChar, AnnotatedString, annotations - s = Base.AnnotatedString("good bad", [(region=1:4, label=:sentiment, value=+1), (region=6:8, label=:sentiment, value=-1)]) + s = AnnotatedString("good bad", [(region=1:4, label=:sentiment, value=+1), (region=6:8, label=:sentiment, value=-1)]) @test (@delete annotations(s))::String == "good bad" @@ -407,7 +407,7 @@ VERSION ≥ v"1.11" && @testset "AnnotatedStrings" begin @test String(snew) == "good bad" @test annotations(snew) == [(region=1:4, label=:sentiment, value=+1)] - snew = (@set Base.annotations(s)[1].region = 2:6) + snew = (@set annotations(s)[1].region = 2:6) @test String(snew) == "good bad" @test annotations(snew) == [(region=2:6, label=:sentiment, value=+1), (region=6:8, label=:sentiment, value=-1)] @@ -415,6 +415,23 @@ VERSION ≥ v"1.11" && @testset "AnnotatedStrings" begin test_getset_laws((@o annotations(_)[2].label), s, :abc, :def) test_getset_laws((@o annotations(_)[2].value), s, "sad", +2) test_insertdelete_laws((@o annotations(_)[2]), s, (region=2:2, label=:mylabel, value=+1)) + + + c = AnnotatedChar('x', [(label=:level, value="warning"), (label=:alphabet, value=1)]) + + @test (@delete annotations(c))::Char == 'x' + + cnew = @delete annotations(c)[2] + @test Char(cnew) == 'x' + @test annotations(cnew) == [(label=:level, value="warning")] + + cnew = (@set annotations(c)[1].label = :severity) + @test Char(cnew) == 'x' + @test annotations(cnew) == [(label=:severity, value="warning"), (label=:alphabet, value=1)] + + test_getset_laws((@o annotations(_)[2].label), c, :abc, :def) + test_getset_laws((@o annotations(_)[1].value), c, 5, "bad") + test_insertdelete_laws((@o annotations(_)[2]), c, (label=:mylabel, value=+1)) end @testset "custom binary function" begin