diff --git a/base/show.jl b/base/show.jl index 079bf5a423cc0d..f456426046efff 100644 --- a/base/show.jl +++ b/base/show.jl @@ -429,6 +429,9 @@ function show_circular(io::IOContext, @nospecialize(x)) return false end +AnnotatedIOBuffer(io::IOContext{IOBuffer}) = AnnotatedIOBuffer(io.io, io.dict) +IOContext(io::AnnotatedIOBuffer) = IOContext(io.io, io.dict) + """ show([io::IO = stdout], x) diff --git a/base/strings/annotated.jl b/base/strings/annotated.jl index c0f3623f416963..8b94b2502947f0 100644 --- a/base/strings/annotated.jl +++ b/base/strings/annotated.jl @@ -386,3 +386,48 @@ annotations(s::SubString{<:AnnotatedString}, pos::UnitRange{<:Integer}) = Get all annotations of `chr`. """ annotations(c::AnnotatedChar) = c.annotations + +## AnnotatedIOBuffer + +struct AnnotatedIOBuffer <: IO + io::IOBuffer + annotations::Vector{Tuple{UnitRange{Int}, Pair{Symbol, Any}}} +end + +AnnotatedIOBuffer(io::IOBuffer) = AnnotatedIOBuffer(io, Vector{Tuple{UnitRange{Int}, Pair{Symbol, Any}}}()) +AnnotatedIOBuffer() = AnnotatedIOBuffer(IOBuffer()) + +function show(io::IO, annio::AnnotatedIOBuffer) + show(io, AnnotatedIOBuffer) + print(io, '(', annio.io.size, " bytes)") +end + +position(io::AnnotatedIOBuffer) = position(io.io) +lock(io::AnnotatedIOBuffer) = lock(io.io) +unlock(io::AnnotatedIOBuffer) = unlock(io.io) + +function write(io::AnnotatedIOBuffer, astr::Union{AnnotatedString, SubString{<:AnnotatedString}}) + astr = AnnotatedString(astr) + offset = position(io.io) + for (region, annot) in astr.annotations + start, stop = first(region), last(region) + push!(io.annotations, (start+offset:stop+offset, annot)) + end + write(io.io, astr) +end +write(io::AnnotatedIOBuffer, achr::AnnotatedChar) = write(io, AnnotatedString(achr)) +write(io::AnnotatedIOBuffer, x::AbstractString) = write(io.io, x) +write(io::AnnotatedIOBuffer, x::UInt8) = write(io.io, x) +write(io::AnnotatedIOBuffer, x::AbstractString) = write(io.io, x) +write(io::AnnotatedIOBuffer, s::Union{SubString{String}, String}) = write(io.io, x) + +function take!(aiob::AnnotatedIOBuffer) + str = String(take!(aiob.io)) + annot = copy(aiob.annotations) + empty!(aiob.annotations) + seekstart(aiob.io) + str, annot +end + +AnnotatedString((str, annots)::Tuple{<:AbstractString, Vector{Tuple{UnitRange{Int}, Pair{Symbol, Any}}}}) = + AnnotatedString(str, annots)