Skip to content

Commit d9d7472

Browse files
committed
Adopt Base's annotated types/functions as API
This opens the door to shuffling parts currently implemented in Base into this stdlib without breaking any public APIs. It would be nice to actually show the relevant Annotated* docstrings, but unfortunately due to JuliaDocs/Documenter.jl#1781 it's a bit difficult to actually do so. We should re-visit this later.
1 parent da41b6a commit d9d7472

File tree

7 files changed

+77
-18
lines changed

7 files changed

+77
-18
lines changed

docs/src/examples.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ A styled string can be constructed manually, but the [`styled"..."`](@ref
1414
```@repl examples
1515
using StyledStrings
1616
str = styled"{yellow:hello} {blue:there}"
17-
(String(str), Base.annotations(str))
17+
(String(str), annotations(str))
1818
```
1919

2020
```@setup example
@@ -181,25 +181,25 @@ Sometimes it's useful to compose a string incrementally, or interoperate with
181181
other `IO`-based code. For these use-cases, the [`AnnotatedIOBuffer`](@ref Base.AnnotatedIOBuffer) is very handy, as you can [`read`](@ref Base.read) an [`AnnotatedString`](@ref Base.AnnotatedString) from it.
182182

183183
```@repl examples
184-
aio = Base.AnnotatedIOBuffer()
184+
aio = AnnotatedIOBuffer()
185185
typ = Int
186186
print(aio, typ)
187187
while typ != Any # We'll pretend that `supertypes` doesn't exist.
188188
typ = supertype(typ)
189189
print(aio, styled" {bright_red:<:} $typ")
190190
end
191-
read(seekstart(aio), Base.AnnotatedString)
191+
read(seekstart(aio), AnnotatedString)
192192
```
193193

194194
StyledStrings adds a specialised [`printstyled`](@ref) method `printstyled(::AnnotatedIOBuffer, ...)` that means that you can pass an `AnnotatedIOBuffer` as IO to "legacy" code written to use `printstyled`, and extract all the styling as though it had used [`styled"..."`](@ref @styled_str) macros.
195195

196196
```@repl
197-
aio = Base.AnnotatedIOBuffer()
197+
aio = AnnotatedIOBuffer()
198198
printstyled(aio, 'c', color=:red)
199199
printstyled(aio, 'o', color=:yellow)
200200
printstyled(aio, 'l', color=:green)
201201
printstyled(aio, 'o', color=:blue)
202202
printstyled(aio, 'r', color=:magenta)
203-
read(seekstart(aio), Base.AnnotatedString)
203+
read(seekstart(aio), AnnotatedString)
204204
read(seekstart(aio), String)
205205
```

docs/src/index.md

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# [StyledStrings](@id stdlib-styledstrings)
22

3+
```@meta
4+
CurrentModule = StyledStrings
5+
DocTestSetup = quote
6+
using StyledStrings
7+
end
8+
```
9+
310
!!! note
411
The API for StyledStrings and AnnotatedStrings is considered experimental and is subject to change between
512
Julia versions.
@@ -41,6 +48,52 @@ using StyledStrings
4148
styled"{yellow:hello} {blue:there}"
4249
```
4350

51+
## [Annotated Strings](@id man-annotated-strings)
52+
53+
It is sometimes useful to be able to hold metadata relating to regions of a
54+
string. A [`AnnotatedString`](@ref Base.AnnotatedString) wraps another string and
55+
allows for regions of it to be annotated with labelled values (`:label => value`).
56+
All generic string operations are applied to the underlying string. However,
57+
when possible, styling information is preserved. This means you can manipulate a
58+
[`AnnotatedString`](@ref Base.AnnotatedString) —taking substrings, padding them,
59+
concatenating them with other strings— and the metadata annotations will "come
60+
along for the ride".
61+
62+
This string type is fundamental to the [StyledStrings stdlib](@ref
63+
stdlib-styledstrings), which uses `:face`-labelled annotations to hold styling
64+
information.
65+
66+
When concatenating a [`AnnotatedString`](@ref Base.AnnotatedString), take care to use
67+
[`annotatedstring`](@ref StyledStrings.annotatedstring) instead of [`string`](@ref) if you want
68+
to keep the string annotations.
69+
70+
```jldoctest
71+
julia> str = AnnotatedString("hello there", [(1:5, :word => :greeting), (7:11, :label => 1)])
72+
"hello there"
73+
74+
julia> length(str)
75+
11
76+
77+
julia> lpad(str, 14)
78+
" hello there"
79+
80+
julia> typeof(lpad(str, 7))
81+
AnnotatedString{String}
82+
83+
julia> str2 = AnnotatedString(" julia", [(2:6, :face => :magenta)])
84+
" julia"
85+
86+
julia> annotatedstring(str, str2)
87+
"hello there julia"
88+
89+
julia> str * str2 == annotatedstring(str, str2) # *-concatenation works
90+
true
91+
```
92+
93+
The annotations of a [`AnnotatedString`](@ref Base.AnnotatedString) can be accessed
94+
and modified via the [`annotations`](@ref StyledStrings.annotations) and
95+
[`annotate!`](@ref StyledStrings.annotate!) functions.
96+
4497
## Styling via [`AnnotatedString`](@ref Base.AnnotatedString)s
4598

4699
## [Faces](@id stdlib-styledstrings-faces)
@@ -153,7 +206,7 @@ them to the properties list afterwards, or use the convenient [Styled String
153206
literals](@ref stdlib-styledstring-literals).
154207

155208
```@repl demo
156-
str1 = Base.AnnotatedString("blue text", [(1:9, :face => :blue)])
209+
str1 = AnnotatedString("blue text", [(1:9, :face => :blue)])
157210
str2 = styled"{blue:blue text}"
158211
str1 == str2
159212
sprint(print, str1, context = :color => true)
@@ -275,14 +328,17 @@ arbitrarily nest and overlap, \colorbox[HTML]{3a3a3a}{\color[HTML]{33d079}like
275328

276329
## [API reference](@id stdlib-styledstrings-api)
277330

331+
332+
### Styling and Faces
333+
278334
```@docs
279335
StyledStrings.@styled_str
280336
StyledStrings.styled
281337
StyledStrings.Face
282338
StyledStrings.addface!
283339
StyledStrings.withfaces
284340
StyledStrings.SimpleColor
285-
Base.parse(::Type{StyledStrings.SimpleColor}, ::String)
286-
Base.tryparse(::Type{StyledStrings.SimpleColor}, ::String)
287-
Base.merge(::StyledStrings.Face, ::StyledStrings.Face)
341+
StyledStrings.parse(::Type{StyledStrings.SimpleColor}, ::String)
342+
StyledStrings.tryparse(::Type{StyledStrings.SimpleColor}, ::String)
343+
StyledStrings.merge(::StyledStrings.Face, ::StyledStrings.Face)
288344
```

src/StyledStrings.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
module StyledStrings
44

5-
using Base: AnnotatedString, AnnotatedChar, annotations, annotate!, annotatedstring
5+
using Base: AnnotatedString, AnnotatedChar, AnnotatedIOBuffer, annotations, annotate!, annotatedstring
66
using Base.ScopedValues: ScopedValue, with, @with
77

8+
# While these are imported from Base, we claim them as part of the `StyledStrings` API.
9+
export AnnotatedString, AnnotatedChar, AnnotatedIOBuffer, annotations, annotate!, annotatedstring
10+
811
export @styled_str
912
public Face, addface!, withfaces, styled, SimpleColor
1013

src/io.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ Base.print(io::IO, s::Union{<:AnnotatedString, SubString{<:AnnotatedString}}) =
263263

264264
# We need to make sure that printing to an `AnnotatedIOBuffer` calls `write` not `print`
265265
# so we get the specialised handling that `_ansi_writer` doesn't provide.
266-
Base.print(io::Base.AnnotatedIOBuffer, s::Union{<:AnnotatedString, SubString{<:AnnotatedString}}) =
266+
Base.print(io::AnnotatedIOBuffer, s::Union{<:AnnotatedString, SubString{<:AnnotatedString}}) =
267267
(write(io, s); nothing)
268268

269269
Base.escape_string(io::IO, s::Union{<:AnnotatedString, SubString{<:AnnotatedString}},
@@ -293,7 +293,7 @@ function Base.show(io::IO, c::AnnotatedChar)
293293
end
294294
end
295295

296-
function Base.write(io::IO, aio::Base.AnnotatedIOBuffer)
296+
function Base.write(io::IO, aio::AnnotatedIOBuffer)
297297
if get(io, :color, false) == true
298298
# This does introduce an overhead that technically
299299
# could be avoided, but I'm not sure that it's currently

src/legacy.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
module Legacy
88

9-
using ..StyledStrings: SimpleColor, Face, loadface!, face!
9+
using ..StyledStrings: SimpleColor, Face, loadface!, face!, AnnotatedIOBuffer, annotatedstring
1010

1111
"""
1212
legacy_color(color::Union{String, Symbol, Int})
@@ -123,11 +123,11 @@ function load_env_colors!()
123123
end
124124
end
125125

126-
function Base.printstyled(io::Base.AnnotatedIOBuffer, msg...;
126+
function Base.printstyled(io::AnnotatedIOBuffer, msg...;
127127
bold::Bool=false, italic::Bool=false, underline::Bool=false,
128128
blink::Bool=false, reverse::Bool=false, hidden::Bool=false,
129129
color::Union{Symbol, Int}=:normal)
130-
str = Base.annotatedstring(msg...)
130+
str = annotatedstring(msg...)
131131
bold && face!(str, :bold)
132132
italic && face!(str, :italic)
133133
underline && face!(str, :underline)

src/regioniterator.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ an iterator which provides each substring and the applicable annotations as a
2828
# Examples
2929
3030
```jldoctest
31-
julia> collect(StyledStrings.eachregion(Base.AnnotatedString(
31+
julia> collect(StyledStrings.eachregion(AnnotatedString(
3232
"hey there", [(1:3, :face => :bold), (5:9, :face => :italic)])))
3333
3-element Vector{Tuple{SubString{String}, Vector{Pair{Symbol, Any}}}}:
3434
("hey", [:face => :bold])

test/runtests.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
using Test
44

55
using StyledStrings: StyledStrings, Legacy, SimpleColor, FACES, Face,
6-
@styled_str, styled, StyledMarkup, eachregion, getface, addface!, loadface!, resetfaces!
6+
@styled_str, styled, StyledMarkup, eachregion, getface, addface!, loadface!, resetfaces!,
7+
AnnotatedString, AnnotatedChar, AnnotatedIOBuffer, annotations
78
using .StyledMarkup: MalformedStylingMacro
8-
using Base: AnnotatedString, AnnotatedChar, AnnotatedIOBuffer, annotations
99

1010
const NON_STDLIB_TESTS = Main == @__MODULE__
1111
if NON_STDLIB_TESTS

0 commit comments

Comments
 (0)