Skip to content

Commit 1b43f6b

Browse files
committed
Introduce AnnotatedIOBuffer
This allows for styled content to be constructed incrementally, without resorting to repeated concatenation. It operates very similarly to IOContext, just with a special `write` method and specifically wrapping an IOBuffer.
1 parent b5a531a commit 1b43f6b

1 file changed

Lines changed: 48 additions & 0 deletions

File tree

base/strings/annotated.jl

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,3 +386,51 @@ annotations(s::SubString{<:AnnotatedString}, pos::UnitRange{<:Integer}) =
386386
Get all annotations of `chr`.
387387
"""
388388
annotations(c::AnnotatedChar) = c.annotations
389+
390+
## AnnotatedIOBuffer
391+
392+
struct AnnotatedIOBuffer <: IO
393+
io::IOBuffer
394+
annotations::Vector{Tuple{UnitRange{Int}, Pair{Symbol, Any}}}
395+
end
396+
397+
AnnotatedIOBuffer(io::IOBuffer) = AnnotatedIOBuffer(io, Vector{Tuple{UnitRange{Int}, Pair{Symbol, Any}}}())
398+
AnnotatedIOBuffer() = AnnotatedIOBuffer(IOBuffer())
399+
400+
function show(io::IO, annio::AnnotatedIOBuffer)
401+
show(io, AnnotatedIOBuffer)
402+
print(io, '(', annio.io.size, " bytes)")
403+
end
404+
405+
position(io::AnnotatedIOBuffer) = position(io.io)
406+
lock(io::AnnotatedIOBuffer) = lock(io.io)
407+
unlock(io::AnnotatedIOBuffer) = unlock(io.io)
408+
409+
function write(io::AnnotatedIOBuffer, astr::Union{AnnotatedString, SubString{<:AnnotatedString}})
410+
astr = AnnotatedString(astr)
411+
offset = position(io.io)
412+
for (region, annot) in astr.annotations
413+
start, stop = first(region), last(region)
414+
push!(io.annotations, (start+offset:stop+offset, annot))
415+
end
416+
write(io.io, astr)
417+
end
418+
write(io::AnnotatedIOBuffer, achr::AnnotatedChar) = write(io, AnnotatedString(achr))
419+
write(io::AnnotatedIOBuffer, x::AbstractString) = write(io.io, x)
420+
write(io::AnnotatedIOBuffer, s::Union{SubString{String}, String}) = write(io.io, x)
421+
write(io::AnnotatedIOBuffer, x::UInt8) = write(io.io, x)
422+
423+
"""
424+
read(io::AnnotatedIOBuffer, AnnotatedString)
425+
426+
Read the entirety of `io`, as an `AnnotatedString`. This preserves the
427+
annotations of any `AnnotatedString`s written to `io` and otherwise acts like
428+
`read(io::IO, String)`.
429+
"""
430+
function read(io::AnnotatedIOBuffer, ::Type{AnnotatedString{>:String}})
431+
str = String(take!(io.io))
432+
annots = copy(io.annotations)
433+
empty!(io.annotations)
434+
seekstart(io.io)
435+
AnnotatedString(str, annotss)
436+
end

0 commit comments

Comments
 (0)