Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support display of arbitrary textual MIME types in REPL #19993

Merged
merged 1 commit into from
Jan 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 42 additions & 21 deletions base/multimedia.jl
Original file line number Diff line number Diff line change
Expand Up @@ -141,16 +141,23 @@ displayable(mime::AbstractString) = displayable(MIME(mime))
"""
TextDisplay(io::IO)

Returns a `TextDisplay <: Display`, which can display any object as the text/plain MIME type
(only), writing the text representation to the given I/O stream. (The text representation is
the same as the way an object is printed in the Julia REPL.)
Returns a `TextDisplay <: Display`, which displays any object as the text/plain MIME type
(by default), writing the text representation to the given I/O stream. (This is how
objects are printed in the Julia REPL.)
"""
immutable TextDisplay <: Display
io::IO
end
display(d::TextDisplay, M::MIME"text/plain", x) = show(d.io, M, x)
display(d::TextDisplay, x) = display(d, MIME"text/plain"(), x)

# if you explicitly call display("text/foo", x), it should work on a TextDisplay:
displayable(d::TextDisplay, M::MIME) = istextmime(M)
function display(d::TextDisplay, M::MIME, x)
displayable(d, M) || throw(MethodError(display, (d, M, x)))
show(d.io, M, x)
end

import Base: close, flush
flush(d::TextDisplay) = flush(d.io)
close(d::TextDisplay) = close(d.io)
Expand Down Expand Up @@ -178,30 +185,32 @@ function reinit_displays()
pushdisplay(TextDisplay(STDOUT))
end

macro try_display(expr)
quote
try $(esc(expr))
catch e
isa(e, MethodError) && e.f in (display, redisplay, show) ||
rethrow()
end
end
end

xdisplayable(D::Display, args...) = applicable(display, D, args...)

function display(x)
for i = length(displays):-1:1
xdisplayable(displays[i], x) &&
@try_display return display(displays[i], x)
if xdisplayable(displays[i], x)
try
return display(displays[i], x)
catch e
isa(e, MethodError) && e.f in (display, show) ||
rethrow()
end
end
end
throw(MethodError(display, (x,)))
end

function display(m::MIME, x)
for i = length(displays):-1:1
xdisplayable(displays[i], m, x) &&
@try_display return display(displays[i], m, x)
if xdisplayable(displays[i], m, x)
try
return display(displays[i], m, x)
catch e
isa(e, MethodError) && e.f == display ||
rethrow()
end
end
end
throw(MethodError(display, (m, x)))
end
Expand All @@ -226,16 +235,28 @@ end

function redisplay(x)
for i = length(displays):-1:1
xdisplayable(displays[i], x) &&
@try_display return redisplay(displays[i], x)
if xdisplayable(displays[i], x)
try
return redisplay(displays[i], x)
catch e
isa(e, MethodError) && e.f in (redisplay, display, show) ||
rethrow()
end
end
end
throw(MethodError(redisplay, (x,)))
end

function redisplay(m::Union{MIME,AbstractString}, x)
for i = length(displays):-1:1
xdisplayable(displays[i], m, x) &&
@try_display return redisplay(displays[i], m, x)
if xdisplayable(displays[i], m, x)
try
return redisplay(displays[i], m, x)
catch e
isa(e, MethodError) && e.f in (redisplay, display) ||
rethrow()
end
end
end
throw(MethodError(redisplay, (m, x)))
end
Expand Down
12 changes: 12 additions & 0 deletions test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -620,3 +620,15 @@ end

# don't use julia-specific `f` in Float32 printing (PR #18053)
@test sprint(print, 1f-7) == "1.0e-7"

# test that the REPL TextDisplay works for displaying arbitrary textual MIME types
let d = TextDisplay(IOBuffer())
display(d, "text/csv", [3 1 4])
@test String(take!(d.io)) == "3,1,4\n"
@test_throws MethodError display(d, "text/foobar", [3 1 4])
try
display(d, "text/foobar", [3 1 4])
catch e
@test e.f == show
end
end