From 8d6f75249c4c10b269891e664f6010867d9529e0 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Fri, 16 Feb 2018 09:38:29 +0100 Subject: [PATCH 1/2] Deprecate showcompact() There is no obvious reason to provide a special function for the :compact IOContext property but not for other properties. showcompact() used to be useful to print a single-line representation of an array at the REPL, but now show() does the same thing. So it should only be needed for collections to print their elements when implementing show(), and for tests (most of the changes here). Also improve a few docstrings. --- NEWS.md | 7 ++++- base/Enums.jl | 2 +- base/deprecated.jl | 4 +++ base/exports.jl | 1 - base/irrationals.jl | 5 +-- base/show.jl | 39 ++---------------------- base/strings/io.jl | 8 ++++- base/sysimg.jl | 8 ++--- doc/src/base/io-network.md | 1 - doc/src/manual/networking-and-streams.md | 5 +-- test/complex.jl | 4 +-- test/dict.jl | 2 +- test/float16.jl | 4 +-- test/missing.jl | 2 +- test/mpfr.jl | 6 ++-- test/numbers.jl | 18 +++++------ test/show.jl | 10 ------ 17 files changed, 48 insertions(+), 78 deletions(-) diff --git a/NEWS.md b/NEWS.md index 4a371003e328c..6730fb3339c14 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1093,7 +1093,11 @@ Deprecated or removed * `DevNull`, `STDIN`, `STDOUT`, and `STDERR` have been renamed to `devnull`, `stdin`, `stdout`, and `stderr`, respectively ([#25786]). - * `wait` and `fetch` on `Task` now resemble the interface of `Future` + * `wait` and `fetch` on `Task` now resemble the interface of `Future`. + + * `showcompact(io, x...)` has been deprecated in favor of + `show(IOContext(io, :compact => true), x...)` ([#26080]). + Use `sprint(show, x..., context=:compact => true)` instead of `sprint(showcompact, x...)`. Command-line option changes --------------------------- @@ -1391,4 +1395,5 @@ Command-line option changes [#25998]: https://github.com/JuliaLang/julia/issues/25998 [#26009]: https://github.com/JuliaLang/julia/issues/26009 [#26071]: https://github.com/JuliaLang/julia/issues/26071 +[#26080]: https://github.com/JuliaLang/julia/issues/26080 [#26149]: https://github.com/JuliaLang/julia/issues/26149 \ No newline at end of file diff --git a/base/Enums.jl b/base/Enums.jl index bf356c9490315..0cec49e77a7ad 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -150,7 +150,7 @@ macro enum(T, syms...) print(io, x) else print(io, x, "::") - showcompact(io, typeof(x)) + show(IOContext(io, :compact => true), typeof(x)) print(io, " = ", $basetype(x)) end end diff --git a/base/deprecated.jl b/base/deprecated.jl index 2703bf9e3b0be..e199cb0330301 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1495,6 +1495,10 @@ end # Issue #26248 @deprecate conj(x) x +@deprecate showcompact(x) show(IOContext(stdout, :compact => true), x) +@deprecate showcompact(io, x) show(IOContext(io, :compact => true), x) +@deprecate sprint(::typeof(showcompact), args...) sprint(show, args...; context=:compact => true) + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/exports.jl b/base/exports.jl index d030e36131e7b..1085d66ef8fa4 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -619,7 +619,6 @@ export println, printstyled, show, - showcompact, showerror, sprint, summary, diff --git a/base/irrationals.jl b/base/irrationals.jl index 986bd9e575344..5f23988f5195b 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -154,7 +154,8 @@ big(::Type{<:AbstractIrrational}) = BigFloat # align along = for nice Array printing function alignment(io::IO, x::AbstractIrrational) - m = match(r"^(.*?)(=.*)$", sprint(showcompact, x, context=io, sizehint=0)) - m === nothing ? (length(sprint(showcompact, x, context=io, sizehint=0)), 0) : + ctx = IOContext(io, :compact=>true) + m = match(r"^(.*?)(=.*)$", sprint(show, x, context=ctx, sizehint=0)) + m === nothing ? (length(sprint(show, x, context=ctx, sizehint=0)), 0) : (length(m.captures[1]), length(m.captures[2])) end diff --git a/base/show.jl b/base/show.jl index 2500ebf9dd82a..139a6280b7620 100644 --- a/base/show.jl +++ b/base/show.jl @@ -205,8 +205,8 @@ IOContext(io::IO, context::IO) = IOContext(unwrapcontext(io)[1], unwrapcontext(c Create an `IOContext` that wraps a given stream, adding the specified `key=>value` pairs to the properties of that stream (note that `io` can itself be an `IOContext`). - - use `(key => value) in dict` to see if this particular combination is in the properties set - - use `get(dict, key, default)` to retrieve the most recent value for a particular key + - use `(key => value) in io` to see if this particular combination is in the properties set + - use `get(io, key, default)` to retrieve the most recent value for a particular key The following properties are in common use: @@ -1945,41 +1945,6 @@ function Base.showarg(io::IO, r::Iterators.Pairs{<:Any, <:Any, I, D}, toplevel) print(io, "Iterators.Pairs(::$D, ::$I)") end -""" - showcompact(x) - showcompact(io::IO, x) - -Show a compact representation of a value to `io`. If `io` is not specified, the -default is to print to [`stdout`](@ref). - -This is used for printing array elements without repeating type information (which would -be redundant with that printed once for the whole array), and without line breaks inside -the representation of an element. - -To offer a compact representation different from its standard one, a custom type should -test `get(io, :compact, false)` in its normal [`show`](@ref) method. - -# Examples -```jldoctest -julia> A = [1. 2.; 3. 4] -2×2 Array{Float64,2}: - 1.0 2.0 - 3.0 4.0 - -julia> showcompact(A) -[1.0 2.0; 3.0 4.0] -``` -""" -showcompact(x) = showcompact(stdout, x) -function showcompact(io::IO, x) - if get(io, :compact, false) - show(io, x) - else - show(IOContext(io, :compact => true), x) - end -end - - # printing BitArrays # (following functions not exported - mainly intended for debug) diff --git a/base/strings/io.jl b/base/strings/io.jl index 573baf753a02a..97d43f4e0282d 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -73,6 +73,9 @@ println(io::IO, xs...) = print(io, xs..., '\n') Call the given function with an I/O stream and the supplied extra arguments. Everything written to this I/O stream is returned as a string. +`context` can be either an [`IOContext`](@ref) whose properties will be used, +or a `Pair` specifying a property and its value. `sizehint` suggests the capacity +of the buffer (in bytes). The optional keyword argument `context` can be set to `:key=>value` pair or an `IO` or [`IOContext`](@ref) object whose attributes are used for the I/O @@ -81,8 +84,11 @@ to allocate for the buffer used to write the string. # Examples ```jldoctest -julia> sprint(showcompact, 66.66666) +julia> sprint(show, 66.66666; context=:compact => true) "66.6667" + +julia> sprint(showerror, BoundsError([1], 100)) +"BoundsError: attempt to access 1-element Array{Int64,1} at index [100]" ``` """ function sprint(f::Function, args...; context=nothing, sizehint::Integer=0) diff --git a/base/sysimg.jl b/base/sysimg.jl index cf4698e5e60aa..17e965b1d3b3d 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -942,12 +942,12 @@ tot_time = tot_time_base + Base.tot_time_stdlib[] + tot_time_userimg + tot_time_ println("Sysimage built. Summary:") print("Total ─────── "); Base.time_print(tot_time * 10^9); print(" \n"); -print("Base: ─────── "); Base.time_print(tot_time_base * 10^9); print(" "); showcompact((tot_time_base / tot_time) * 100); println("%") -print("Stdlibs: ──── "); Base.time_print(Base.tot_time_stdlib[] * 10^9); print(" "); showcompact((Base.tot_time_stdlib[] / tot_time) * 100); println("%") +print("Base: ─────── "); Base.time_print(tot_time_base * 10^9); print(" "); show(IOContext(stdout, :compact=>true), (tot_time_base / tot_time) * 100); println("%") +print("Stdlibs: ──── "); Base.time_print(Base.tot_time_stdlib[] * 10^9); print(" "); show(IOContext(stdout, :compact=>true), (Base.tot_time_stdlib[] / tot_time) * 100); println("%") if isfile("userimg.jl") -print("Userimg: ──── "); Base.time_print(tot_time_userimg * 10^9); print(" "); showcompact((tot_time_userimg / tot_time) * 100); println("%") +print("Userimg: ──── "); Base.time_print(tot_time_userimg * 10^9); print(" "); show(IOContext(stdout, :compact=>true), (tot_time_userimg / tot_time) * 100); println("%") end -print("Precompile: ─ "); Base.time_print(tot_time_precompile * 10^9); print(" "); showcompact((tot_time_precompile / tot_time) * 100); println("%") +print("Precompile: ─ "); Base.time_print(tot_time_precompile * 10^9); print(" "); show(IOContext(stdout, :compact=>true), (tot_time_precompile / tot_time) * 100); println("%") end empty!(LOAD_PATH) diff --git a/doc/src/base/io-network.md b/doc/src/base/io-network.md index 9c0cf8161da23..377ee41c5bf6a 100644 --- a/doc/src/base/io-network.md +++ b/doc/src/base/io-network.md @@ -55,7 +55,6 @@ Base.IOContext(::IO, ::IOContext) ```@docs Base.show(::Any) -Base.showcompact Base.summary Base.print Base.println diff --git a/doc/src/manual/networking-and-streams.md b/doc/src/manual/networking-and-streams.md index 4d75c59729201..5fc2e6f16ebb7 100644 --- a/doc/src/manual/networking-and-streams.md +++ b/doc/src/manual/networking-and-streams.md @@ -111,8 +111,9 @@ julia> print(stdout, 0x61) Sometimes IO output can benefit from the ability to pass contextual information into show methods. The [`IOContext`](@ref) object provides this framework for associating arbitrary metadata with an IO object. -For example, [`showcompact`](@ref) adds a hinting parameter to the IO object that the invoked show method -should print a shorter output (if applicable). +For example, `:compact => true` adds a hinting parameter to the IO object that the invoked show method +should print a shorter output (if applicable). See the [`IOContext`](@ref) documentation for a list +of common properties. ## Working with Files diff --git a/test/complex.jl b/test/complex.jl index 00128852b13ef..935e67a7e9de8 100644 --- a/test/complex.jl +++ b/test/complex.jl @@ -11,8 +11,8 @@ for T in (Int64, Float64) @test complex(Complex{T}) == Complex{T} end -#showcompact -@test sprint(showcompact, complex(1, 0)) == "1+0im" +#show +@test sprint(show, complex(1, 0), context=:compact => true) == "1+0im" @test sprint(show, complex(true, true)) == "Complex(true,true)" @testset "arithmetic" begin diff --git a/test/dict.jl b/test/dict.jl index 0c1f33ec4645b..a2264bbdade66 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -350,7 +350,7 @@ end @testset "Issue #15739" begin # Compact REPL printouts of an `AbstractDict` use brackets when appropriate d = Dict((1=>2) => (3=>45), (3=>10) => (10=>11)) buf = IOBuffer() - showcompact(buf, d) + show(IOContext(buf, :compact => true), d) # Check explicitly for the expected strings, since the CPU bitness effects # dictionary ordering. diff --git a/test/float16.jl b/test/float16.jl index 6793a1dc2dbc0..4440385a28b75 100644 --- a/test/float16.jl +++ b/test/float16.jl @@ -108,7 +108,7 @@ end @test NaN16 != NaN16 @test isequal(NaN16, NaN16) @test repr(NaN16) == "NaN16" - @test sprint(showcompact, NaN16) == "NaN" + @test sprint(show, NaN16, context=:compact => true) == "NaN" @test isinf(Inf16) @test isinf(-Inf16) @@ -120,7 +120,7 @@ end @test -Inf16 < Inf16 @test isequal(Inf16, Inf16) @test repr(Inf16) == "Inf16" - @test sprint(showcompact, Inf16) == "Inf" + @test sprint(show, Inf16, context=:compact => true) == "Inf" @test isnan(reinterpret(Float16,0x7c01)) @test !isinf(reinterpret(Float16,0x7c01)) diff --git a/test/missing.jl b/test/missing.jl index 5265fe0e78da1..79e739974cf0d 100644 --- a/test/missing.jl +++ b/test/missing.jl @@ -197,7 +197,7 @@ end @testset "printing" begin @test sprint(show, missing) == "missing" - @test sprint(showcompact, missing) == "missing" + @test sprint(show, missing, context=:compact => true) == "missing" @test sprint(show, [missing]) == "$Missing[missing]" @test sprint(show, [1 missing]) == "$(Union{Int, Missing})[1 missing]" b = IOBuffer() diff --git a/test/mpfr.jl b/test/mpfr.jl index f139633392349..0a1daac1ec70c 100644 --- a/test/mpfr.jl +++ b/test/mpfr.jl @@ -895,7 +895,7 @@ end ends::String="", starts::String="") sx = sprint(show, x) - scx = sprint(showcompact, x) + scx = sprint(show, x, context=:compact => true) strx = string(x) @test sx == strx @test length(scx) < 20 @@ -915,8 +915,8 @@ end test_show_bigfloat(big"-2.3457645687563543266576889678956787e-10000", starts="-2.345", ends="e-10000") for to_string in [string, - x->sprint(show, x), - x->sprint(showcompact,x)] + x->sprint(show, x), + x->sprint(show, x, context=:compact => true)] @test to_string(big"0.0") == "0.0" @test to_string(big"-0.0") == "-0.0" @test to_string(big"1.0") == "1.0" diff --git a/test/numbers.jl b/test/numbers.jl index 76fdb399b756d..1fd4c4bb78a3a 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -410,14 +410,14 @@ end @test repr(-NaN) == "NaN" @test repr(Float64(pi)) == "3.141592653589793" # issue 6608 - @test sprint(showcompact, 666666.6) == "6.66667e5" - @test sprint(showcompact, 666666.049) == "666666.0" - @test sprint(showcompact, 666665.951) == "666666.0" - @test sprint(showcompact, 66.66666) == "66.6667" - @test sprint(showcompact, -666666.6) == "-6.66667e5" - @test sprint(showcompact, -666666.049) == "-666666.0" - @test sprint(showcompact, -666665.951) == "-666666.0" - @test sprint(showcompact, -66.66666) == "-66.6667" + @test sprint(show, 666666.6, context=:compact => true) == "6.66667e5" + @test sprint(show, 666666.049, context=:compact => true) == "666666.0" + @test sprint(show, 666665.951, context=:compact => true) == "666666.0" + @test sprint(show, 66.66666, context=:compact => true) == "66.6667" + @test sprint(show, -666666.6, context=:compact => true) == "-6.66667e5" + @test sprint(show, -666666.049, context=:compact => true) == "-666666.0" + @test sprint(show, -666665.951, context=:compact => true) == "-666666.0" + @test sprint(show, -66.66666, context=:compact => true) == "-66.6667" @test repr(1.0f0) == "1.0f0" @test repr(-1.0f0) == "-1.0f0" @@ -2564,7 +2564,7 @@ end (-T(Inf), "-Inf")] @assert x isa T @test string(x) == sx - @test sprint(io -> show(IOContext(io, :compact => true), x)) == sx + @test sprint(show, x, context=:compact => true) == sx @test sprint(print, x) == sx end end diff --git a/test/show.jl b/test/show.jl index 79a3c284bad0f..10291439faf9a 100644 --- a/test/show.jl +++ b/test/show.jl @@ -747,16 +747,6 @@ end @test !contains(repr(fill(1.,10,10)), "\u2026") @test contains(sprint((io, x) -> show(IOContext(io, :limit => true), x), fill(1.,30,30)), "\u2026") -# showcompact() also sets :multiline=>false (#16817) -let io = IOBuffer(), - x = [1, 2] - - showcompact(io, x) - @test String(take!(io)) == "[1, 2]" - showcompact(IOContext(io, :compact => true), x) - @test String(take!(io)) == "[1, 2]" -end - let io = IOBuffer() ioc = IOContext(io, :limit => true) @test sprint(show, ioc) == "IOContext($(sprint(show, ioc.io)))" From e2b151f3b7649b084b2f22aad8fcd78bff8d348b Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Fri, 9 Mar 2018 14:50:09 +0100 Subject: [PATCH 2/2] Add documentation for IOContext's :compact property in Custom pretty-printing section --- doc/src/manual/networking-and-streams.md | 5 +++- doc/src/manual/types.md | 33 +++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/networking-and-streams.md b/doc/src/manual/networking-and-streams.md index 5fc2e6f16ebb7..51b691255c9f7 100644 --- a/doc/src/manual/networking-and-streams.md +++ b/doc/src/manual/networking-and-streams.md @@ -100,13 +100,16 @@ Note that `a` is written to [`stdout`](@ref) by the [`write`](@ref) function and value is `1` (since `0x61` is one byte). For text I/O, use the [`print`](@ref) or [`show`](@ref) methods, depending on your needs (see -the Julia Base reference for a detailed discussion of the difference between the two): +the documentation for these two methods for a detailed discussion of the difference between them): ```jldoctest julia> print(stdout, 0x61) 97 ``` +See [Custom pretty-printing](@ref man-custom-pretty-printing) for more information on how to +implement display methods for custom types. + ## IO Output Contextual Properties Sometimes IO output can benefit from the ability to pass contextual information into show methods. diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index 1b56c7ce75412..20c40c3ca97c6 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -1187,7 +1187,7 @@ Closest candidates are: supertype(!Matched::UnionAll) at operators.jl:47 ``` -## Custom pretty-printing +## [Custom pretty-printing](@id man-custom-pretty-printing) Often, one wants to customize how instances of a type are displayed. This is accomplished by overloading the [`show`](@ref) function. For example, suppose we define a type to represent @@ -1321,6 +1321,37 @@ julia> :($a == 2) :(3.0 * exp(4.0im) == 2) ``` +In some cases, it is useful to adjust the behavior of `show` methods depending +on the context. This can be achieved via the [`IOContext`](@ref) type, which allows +passing contextual properties together with a wrapped IO stream. +For example, we can build a shorter representation in our `show` method +when the `:compact` property is set to `true`, falling back to the long +representation if the property is `false` or absent: +```jldoctest polartype +julia> function Base.show(io::IO, z::Polar) + if get(io, :compact, false) + print(io, z.r, "ℯ", z.Θ, "im") + else + print(io, z.r, " * exp(", z.Θ, "im)") + end + end +``` + +This new compact representation will be used when the passed IO stream is an `IOContext` +object with the `:compact` property set. In particular, this is the case when printing +arrays with multiple columns (where horizontal space is limited): +```jldoctest polartype +julia> show(IOContext(stdout, :compact=>true), Polar(3, 4.0)) +3.0ℯ4.0im + +julia> [Polar(3, 4.0) Polar(4.0,5.3)] +1×2 Array{Polar{Float64},2}: + 3.0ℯ4.0im 4.0ℯ5.3im +``` + +See the [`IOContext`](@ref) documentation for a list of common properties which can be used +to adjust printing. + ## "Value types" In Julia, you can't dispatch on a *value* such as `true` or `false`. However, you can dispatch