Modify the behaviour of Base.show based on an environment variable


#1

Hello,

I would like to use a different Base.show based on some environment variable so for instance either using ::MIME"image/png" or ::MIME"text/plain". Something like:

import Base.show

struct Foo
    fpath::String
end

const MYENV = Dict("imshow"=>false)
toggle(b::Bool) = (MYENV["imshow"] = b)

# use this if MYENV["imshow"]
function Base.show(io, ::MIME"image/png", f::Foo)
    write(io, read(f.fpath))
    return nothing
end

# use this if !MYENV["imshow"]
function Base.show(io, ::MIME"text/plain", f::Foo)
    write(io, f.fpath)
    return nothing
end

is this possible? thanks! (a somewhat dirty hack is to toggle Atom.PlotPaneEnabled.x…)


Edit: the following seems to work but I welcome alternative ideas

import Base.show

const MYENV = Dict("imshow" => false)

toggle(b::Bool) = (MYENV["imshow"] = b)

struct Foo
    fpath::String
end

struct ImFoo
    f::Foo
end

function Base.show(io::IO, f::Foo)
    MYENV["imshow"] && display(ImFoo(f))
    write(io, f.fpath)
    return nothing
end

function Base.show(io::IO, ::MIME"image/png", o::ImFoo)
    write(io, read(o.f.fpath))
    return nothing
end

#2

I would just code two functions, eg _show1 and _show2, and branch inside the implementation of show based on the flag. Eg

const FLAG = Ref(false)
toggle() = FLAG[] = !FLAG[]
_show1(io, x) = print(io, "what a nice $x")
_show2(io, x) = print(io, "great $x we have here")
show(io::IO, x::Foo) = FLAG[] ? _show1(io, x) : _show2(io, x)

Also note that using a Dict is not optimal, so I used a RefValue, but in practice it may not matter much.


#3

You should also be able to (conditionally) throw a MethodError in Base.show(io, ::MIME"image/png", f::Foo) to disable it.


#4

Thanks both, maybe I should have given more context as to what prompted the question.

It seems to me (unless I’m mistaken) that Juno captures the fact that there exists a show method with a ::MIME"image/png" and consequently opens the plotpane (assuming the show plots in plot pane is enabled), this even if it within the body of the corresponding show, nothing happens.
This is why as far as I could tell from experimenting there needed to be a separate pathway so that Juno does not open the plotpane when the flag is false. It seems the workaround that I mentioned in my original post works fine so I’ll probably stick with it.

@Tamas_Papp would you have a pointer on what’s best practice in terms of keeping a bunch (I reckon I have a dozen or so) of environment variables which may be modified by the user? I assumed a Dict would be ok but maybe that a named tuple of refs is preferable?


#5

Ah, right. Just overload showable(::MIME"image/png", ::Foo) depending on your condition then, that should work fine with Juno.


#6

A Dict may be fine, especially if you are just using these for printing and it is not a bottleneck. If you want types inferred, you could go with a NamedTuple of RefValues.