What’s the best way to have both human-readable and parseable display styles for your own type, when there are both multiline and inline versions of the human-readable style?
For example, suppose I have a vector-like type which should display its components in “unit vector notation”, (e.g., 2𝒗_1 + 4𝒗_3) like so:
julia> Foo([2, 0, 4])
3-component Foo{Int64}:
2v1
4v3
I want repr
to be reflective (parseable), so that:
julia> repr(Foo([0, 10, 20]))
"Foo{Int64}([0, 10, 20])"
As I understand, array elements are displayed with show(::IO, ::MIME"text/plain", …)
, unless the result contains multiple lines, in which case it falls back to show(::IO, …)
. So by default, an array of Foo
s would show elements in the repr
-style above.
However, my Foo
type also lends itself to human-readable single-line representation, which I’d like to use for displaying in arrays:
julia> [Foo([2, 0, 4]), Foo([50, 60, 0])]
2-element Vector{Foo{Int64}}:
2v1 + 4v3
50v1 + 60v2
What’s the preferred way to achieve these three behaviours at once? I.e., human-readable multi-line, human-readable single-line, and parseable (single-line) display styles.
I’ve been able to find a bit of a hack which (seems) to work by using the presence of the IO property :typeinfo
to guess that printing is happening inside an array.
Hacky implementation
struct Foo{T}
comps::Vector{T}
end
function showcomps(io::IO, comps, inline=true, indent=1)
isfirst = true
inline && print(io, " "^indent)
for (i, x) in enumerate(comps)
iszero(x) && continue
isfirst || print(io, inline ? " + " : "\n")
print(io, " "^(indent*!inline), x, "v", i)
isfirst = false
end
end
Base.show(io::IO, f::Foo) = print(io, typeof(f), "(", f.comps, ")")
function Base.show(io::IO, ::MIME"text/plain", f::Foo)
if :typeinfo ∈ keys(io)
# assume showing as element within array
showcomps(io, f.comps, true, 0)
else
# show in full
println(io, length(f.comps), "-component ", typeof(f), ":")
showcomps(io, f.comps, false)
end
end
But I’m not sure if this is the preferred way. In particular, other array types (like DataFrame
) would use the repr
version, even when displaying in a human-readable format.
I would appreciate any extra insight into the print/show/display interface!