# How to detect in \`show\` that you are computing display for the REPL?

**URL:** <https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951>\
**Category:** New to Julia\
**Created:** [December 23, 2018, 10:45pm UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951 "2018-12-23T22:45:52Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [December 23, 2018, 10:45pm UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/1 "2018-12-23T22:45:52Z")

</div>

I have my own type “cyclotomics” (sums of roots of unity) for which I have a fancy display which I want to see at the REPL. I want also to have a function which can output my numbers in a way which can be read back in (I assume this function should be `repr` but perhaps there is a better choice).

In other terms, I want to see at the REPL:

```julia
julia> l
4×4 Array{Cyc{Int64},2}:
    2 0 -ζ₃² 1+ζ₄
    0 -2 2ζ₃+ζ₃² -1+ζ₄
 -ζ₃² 2ζ₃+ζ₃² 2ζ₃ ζ₁₂⁴-ζ₁₂⁷-ζ₁₂¹¹
 1+ζ₄ -1+ζ₄ ζ₁₂⁴-ζ₁₂⁷-ζ₁₂¹¹ 2ζ₄

```

while

```julia
julia> repr(l)
"Cyc{Int64}[2 0 -E(3,2) 1+E(4); 0 -2 2E(3)+E(3,2) -1+E(4); -E(3,2) 2E(3)+E(3,2) 2E(3) E(12,4)-E(12,7)-E(12,11); 1+E(4) -1+E(4) E(12,4)-E(12,7)-E(12,11) 2E(4)]"

```

To be able to achieve this, I need to detect within `show` that I am somewhere deep below a call starting from the REPL. Is there a way? Or is my design wrong and there is another way to accomplish the same aim?

---

<div class="post-metadata">

**Author:** ![purplishrock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/purplishrock/32/13451_2.png) [@purplishrock](https://discourse.julialang.org/u/purplishrock)\
**Post date:** [December 23, 2018, 10:57pm UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/2 "2018-12-23T22:57:44Z")

</div>

I’m not exactly clear on why you need to know you are in the REPL, but…

you can define show specific to your datatype, i.e.

```julia
show(io::IO, Array{Cyc{T},2}) where T

```

(I think).  
That will get you your REPL display function. Now assuming you need to know you are in the REPL, you should be able to use

[`Base.atreplinit`](https://docs.julialang.org/en/v1/stdlib/REPL/index.html#Base.atreplinit) — Function.

to set a global variable to indicate the REPL is active. I suspect that there must be something set in the global environment when the REPL is active but I wasn’t able to find one.

Which raises an interesting question, is it possible to list all of the global variables that currently defined in the REPL ?

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [December 23, 2018, 11:01pm UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/3 "2018-12-23T23:01:06Z")

</div>

That does not answer my question. I do not need to know if the REPL is active, but that the display being computed is destined to the REPL or not. Even if I am under the REPL (the REPL is active), I still want my `repr` function to return a parsable string. I know that a call directly made by the REPL has the form  
show(io,MIME::“text/plain”,x) but this call will in turn make other calls to display an array and I want to know  
if I am in one of these other calls.

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [December 24, 2018, 12:41am UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/4 "2018-12-24T00:41:14Z")

</div>

I presume that you could look at the stack trace to figure out where it’s called from, but that sounds very hacky. Can’t you just override `repr` for your type to not call `show`? Or create a different function altogether, like `serialize_to_string`.

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [December 24, 2018, 12:48am UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/5 "2018-12-24T00:48:59Z")

</div>

If I create a function which does not exists like `serialize_to_string` I have to teach it how to serialize everything. I will explore if overriding `repr` for my type does the job. It would be nice if printing at the REPL  
would set a property in the `IOContext` so one could know that its being done.

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [December 24, 2018, 12:57am UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/6 "2018-12-24T00:57:36Z")

</div>

> [@Jean\_Michel](#):
>
> If I create a function which does not exists like `serialize_to_string` I have to teach it how to serialize everything.

That is trivial: have it forward to `repr` by default, and override it for your type. But then your better off just overriding `repr` in the first place.

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [December 24, 2018, 1:20am UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/7 "2018-12-24T01:20:13Z")

</div>

Your solutions do not work: `repr` calls internally show, not recursively `repr`

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [December 24, 2018, 1:31am UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/8 "2018-12-24T01:31:20Z")

</div>

? Yes it calls `show`, that’s why you need to override it to not call `show`. Could you paste some code so that we can see what you’re trying?

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [December 24, 2018, 1:41am UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/9 "2018-12-24T01:41:13Z")

</div>

I have a function `format` which computes the string I want

```julia
julia> Cycs.format(E(3),:fancy)
"ζ₃"

julia> Cycs.format(E(3),:plain)
"E(3)"

```

Then I tried the following:

```julia
Base.show(io::IO, p::Cyc)=print(io,format(p,:fancy))
Base.repr(p::Cyc)=format(p,:plain)

```

but `repr` for an array, for instance, will not call _my_ repr

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [December 24, 2018, 2:17am UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/10 "2018-12-24T02:17:14Z")

</div>

Ah, I see. Then I’d try using the `context` keyword in `repr`. It gets forwarded to `show`. I think this should work recursively. Or create your own custom `IO` and pass to `show`.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [December 24, 2018, 4:42am UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/11 "2018-12-24T04:42:07Z")

</div>

> [@Jean\_Michel](#):
>
> I have my own type “cyclotomics” (sums of roots of unity) for which I have a fancy display which I want to see at the REPL. I want also to have a function which can output my numbers in a way which can be read back in (I assume this function should be `repr` but perhaps there is a better choice).

Overload `show(io::IO, x::Cyc)` for simple output (used in `print`, `repr`, etcetera), and overload `show(io::IO, ::MIME"text/plain", x::Cyc)` for more verbose output (used in REPL `display`) etcetera, as [explained in the manual](https://docs.julialang.org/en/v1/manual/types/#man-custom-pretty-printing-1). _Don’t_ overload `repr`, `print`, or similar.

However, note that output of arrays and other containers, even in the REPL, outputs individual _elements_ using `print` for compact output. If you want fancier interactive output for `Array{Cyc}`, one option is to overload `show(io::IO, ::MIME"text/plain", a::AbstractArray{<:Cyc})`. For example, the [Colors.jl package does this](https://github.com/JuliaGraphics/Colors.jl/blob/835d4454e36b34fcec4bd5255779202ca2b5a358/src/display.jl#L22-L25) to get custom graphical output for an array of colors.

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [December 24, 2018, 9:42am UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/12 "2018-12-24T09:42:08Z")

</div>

Looking at the code for `Colors.jl` it seems to me that `show(io::IO, ::MIME"text/plain", a::AbstractArray{<:Color})` does all the job of computing the display of the array. I do not want to do that,  
I just want this function to do its usual job, but detect in show(io,x::Cyc) that I have been called by it.

I could do that if my overloaded version added a property to the IOcontext, then called the non-overloaded  
version. Is there a way to overload a function but then call inside the overloading code the non-overloaded version?

---

<div class="post-metadata">

**Author:** ![improbable22](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/improbable22/32/5464_2.png) [@improbable22](https://discourse.julialang.org/u/improbable22)\
**Post date:** [December 24, 2018, 11:10am UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/13 "2018-12-24T11:10:57Z")

</div>

You can print `pretty.(a)`. Or like this, to print the original type:

```julia
show(io::IO, ::MIME"text/plain", a::AbstractArray{<:Cyc}) = 
    Base.print_array(IOContext(io, :compact => true, :limit => true), pretty.(a) )

```

Here `Base.print_array` is an internal function which changed name in 0.6 → 0.7 so you may have to fix things if it changes again.

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [December 24, 2018, 11:31am UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/14 "2018-12-24T11:31:35Z")

</div>

Using `repr` and `context`:

```julia
struct Cyc
    s::String
end

Base.show(io::IO, c::Cyc) =
    print(io, get(io, :style, :plain) ≡ :fancy ? uppercase(c.s) : c.s)

format(c, style) = repr(c; context = :style => style)

```

Result:

```julia
julia> format(Cyc("foo"), :plain)
"foo"

julia> format(Cyc("foo"), :fancy)
"FOO"

julia> format([Cyc("foo") Cyc("bar")], :plain)
"Cyc[foo bar]"

julia> format([Cyc("foo") Cyc("bar")], :fancy)
"Cyc[FOO BAR]"

```

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [December 24, 2018, 11:38am UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/15 "2018-12-24T11:38:14Z")

</div>

Yes, with your solution one could have  
`serialize_to_string(c)= repr(c; context = :serialize => true)`  
But it seems to me from various comments that `repr` itself is intended to be this `serialize_to_string`.

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [December 24, 2018, 11:54am UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/16 "2018-12-24T11:54:47Z")

</div>

How does your solution exactly works?  
When I try

```julia
Base.show(io::IO, ::MIME"text/plain", a::AbstractArray{<:Cyc}) = 
  Base.print_array(IOContext(io, :compact => true, :limit => true),
                   format.(a,:fancy) )

```

I get

```julia
julia> l
 "2" "0" "-ζ₃²" "1+ζ₄"           
 "0" "-2" "2ζ₃+ζ₃²" "-1+ζ₄"          
 "-ζ₃²" "2ζ₃+ζ₃²" "2ζ₃" "ζ₁₂⁴-ζ₁₂⁷-ζ₁₂¹¹"
 "1+ζ₄" "-1+ζ₄" "ζ₁₂⁴-ζ₁₂⁷-ζ₁₂¹¹" "2ζ₄"

```

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [December 24, 2018, 12:13pm UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/17 "2018-12-24T12:13:13Z")

</div>

Well you can do something like this to have the array version forward to the object version:

```julia
struct Cyc
    s::String
end

Base.show(io::IO, c::Cyc) = print(io, c.s)
Base.show(io::IO, ::MIME"text/plain", c::Cyc) = print(io, uppercase(c.s))
Base.show(io::IO, ::MIME"text/plain", a::AbstractArray{<:Cyc}) =
    print(map(c -> repr(MIME("text/plain"), c), a))

```

With result:

```julia
julia> Cyc("foo")
FOO

julia> repr(Cyc("foo"))
"foo"

julia> [Cyc("foo") Cyc("bar")]
["FOO" "BAR"]

julia> repr([Cyc("foo") Cyc("bar")])
"Cyc[foo bar]"

```

However, I wouldn’t use this solution, since it will only work with arrays. If you have any other collections, such as tuples or dictionaries, it won’t work:

```julia
julia> (Cyc("foo"), Cyc("bar"))
(foo, bar)

julia> repr((Cyc("foo"), Cyc("bar")))
"(foo, bar)"

```

In contrast with my previous suggestion which supports any collection:

```julia
julia> format((Cyc("foo"), Cyc("bar")), :plain)
"(foo, bar)"

julia> format((Cyc("foo"), Cyc("bar")), :fancy)
"(FOO, BAR)"

julia> format(Dict(1 => Cyc("foo"), 2 => Cyc("bar")), :plain)
"Dict(2=>bar,1=>foo)"

julia> format(Dict(1 => Cyc("foo"), 2 => Cyc("bar")), :fancy)
"Dict(2=>BAR,1=>FOO)"

```

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [December 24, 2018, 12:18pm UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/18 "2018-12-24T12:18:54Z")

</div>

It does not work either With my code:

```julia
Base.show(io::IO, c::Cyc) = print(io, format(c,:plain))
Base.show(io::IO, ::MIME"text/plain", c::Cyc) = print(io, format(c,:fancy))
Base.show(io::IO, ::MIME"text/plain", a::AbstractArray{<:Cyc}) =
    print(map(c -> repr(MIME("text/plain"), c), a))

```

gives

```julia
julia> l=[E(i)+E(j) for i in 1:4, j in 1:4]
["2" "0" "-ζ₃²" "1+ζ₄"; "0" "-2" "2ζ₃+ζ₃²" "-1+ζ₄"; "-ζ₃²" "2ζ₃+ζ₃²" "2ζ₃" "ζ₁₂⁴-ζ₁₂⁷-ζ₁₂¹¹"; "1+ζ₄" "-1+ζ₄" "ζ₁₂⁴-ζ₁₂⁷-ζ₁₂¹¹" "2ζ₄"]

```

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [December 24, 2018, 12:23pm UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/19 "2018-12-24T12:23:09Z")

</div>

Then there’s the stack trace hack that I mentioned:

```julia
struct Cyc
    s::String
end

function Base.show(io::IO, c::Cyc)
    fancy = any(startswith.(string.(stacktrace()), "run_repl("))
    print(io, fancy ? uppercase(c.s) : c.s)
end

```

With result:

```julia
julia> Cyc("foo")
FOO

julia> repr(Cyc("foo"))
"foo"

julia> [Cyc("foo") Cyc("bar")]
1×2 Array{Cyc,2}:
 FOO BAR

julia> repr([Cyc("foo") Cyc("bar")])
"Cyc[foo bar]"

```

Please don’t do this 🙂

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [December 24, 2018, 1:19pm UTC](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951/20 "2018-12-24T13:19:13Z")

</div>

> [@Jean\_Michel](#):
>
> I could do that if my overloaded version added a property to the IOcontext, then called the non-overloaded  
> version. Is there a way to overload a function but then call inside the overloading code the non-overloaded version?

Yes. Use `invoke`. For example:

```julia
function show(io::IO, m::MIME"text/plain", a::AbstractArray{<:Cyc,N}) where N
    invoke(show, Tuple{IO, MIME"text/plain", AbstractArray{<:Any,N}}, io, m, a)
end

```

where in the inner call you might replace `io` with some custom `IOContext`.

[Next page](https://discourse.julialang.org/t/how-to-detect-in-show-that-you-are-computing-display-for-the-repl/18951.md?page=2)
