From d6b654e6a941012610720eecf1a16f44c9a6e758 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Tue, 17 Sep 2019 15:10:07 +0200 Subject: [PATCH] improve REPL printing of sets --- NEWS.md | 3 +++ base/abstractset.jl | 18 +++++++++++++---- base/array.jl | 7 +++++-- base/set.jl | 9 +++++++-- base/show.jl | 47 ++++++++++++++++++++++++++++++++++++++++++++- test/show.jl | 20 +++++++++++++++---- 6 files changed, 91 insertions(+), 13 deletions(-) diff --git a/NEWS.md b/NEWS.md index 3028fc73c052c..3b7a02a4709d9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -40,6 +40,9 @@ Standard library changes * Verbose `display` of `Char` (`text/plain` output) now shows the codepoint value in standard-conforming `"U+XXXX"` format ([#33291]). +* Sets are now displayed less compactly in the REPL, as a column of elements, like vectors + and dictionaries ([#33300]). + #### Libdl #### LinearAlgebra diff --git a/base/abstractset.jl b/base/abstractset.jl index fc226e849cd10..f7399fdcd27df 100644 --- a/base/abstractset.jl +++ b/base/abstractset.jl @@ -35,7 +35,10 @@ julia> union([4, 2], 1:2) 1 julia> union(Set([1, 2]), 2:3) -Set([2, 3, 1]) +Set{Int64} with 3 elements: + 2 + 3 + 1 ``` """ function union end @@ -60,7 +63,12 @@ julia> a = Set([1, 3, 4, 5]); julia> union!(a, 1:2:8); julia> a -Set([7, 4, 3, 5, 1]) +Set{Int64} with 5 elements: + 7 + 4 + 3 + 5 + 1 ``` """ function union!(s::AbstractSet, sets...) @@ -105,7 +113,8 @@ julia> intersect([1, 4, 4, 5, 6], [4, 6, 6, 7, 8]) 6 julia> intersect(Set([1, 2]), BitSet([2, 3])) -Set([2]) +Set{Int64} with 1 element: + 2 ``` """ intersect(s::AbstractSet, itr, itrs...) = intersect!(intersect(s, itr), itrs...) @@ -160,7 +169,8 @@ julia> a = Set([1, 3, 4, 5]); julia> setdiff!(a, 1:2:6); julia> a -Set([4]) +Set{Int64} with 1 element: + 4 ``` """ function setdiff!(s::AbstractSet, itrs...) diff --git a/base/array.jl b/base/array.jl index 3449d7bc49a2d..3734860d389fa 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1076,13 +1076,16 @@ julia> A 2 julia> S = Set([1, 2]) -Set([2, 1]) +Set{Int64} with 2 elements: + 2 + 1 julia> pop!(S) 2 julia> S -Set([1]) +Set{Int64} with 1 element: + 1 julia> pop!(Dict(1=>2)) 1 => 2 diff --git a/base/set.jl b/base/set.jl index d4f91ee27d36f..d68fe52dc6676 100644 --- a/base/set.jl +++ b/base/set.jl @@ -439,7 +439,10 @@ julia> replace!([1, 2, 1, 3], 1=>0, 2=>4, count=2) 3 julia> replace!(Set([1, 2, 3]), 1=>0) -Set([0, 2, 3]) +Set{Int64} with 3 elements: + 0 + 2 + 3 ``` """ replace!(A, old_new::Pair...; count::Integer=typemax(Int)) = @@ -479,7 +482,9 @@ Dict{Int64,Int64} with 2 entries: 1 => 3 julia> replace!(x->2x, Set([3, 6])) -Set([6, 12]) +Set{Int64} with 2 elements: + 6 + 12 ``` """ replace!(new::Callable, A; count::Integer=typemax(Int)) = diff --git a/base/show.jl b/base/show.jl index e97a1eda9756c..f22d05416aaff 100644 --- a/base/show.jl +++ b/base/show.jl @@ -113,7 +113,10 @@ function show(io::IO, ::MIME"text/plain", t::AbstractDict{K,V}) where {K,V} for (i, (k, v)) in enumerate(t) print(io, "\n ") - i == rows < length(t) && (print(io, rpad("⋮", keylen), " => ⋮"); break) + if i == rows < length(t) + print(io, rpad("⋮", keylen), " => ⋮") + break + end if limit key = rpad(_truncate_at_width_or_chars(ks[i], keylen, "\r\n"), keylen) @@ -132,6 +135,48 @@ function show(io::IO, ::MIME"text/plain", t::AbstractDict{K,V}) where {K,V} end end +function summary(io::IO, t::AbstractSet) + n = length(t) + showarg(io, t, true) + print(io, " with ", n, (n==1 ? " element" : " elements")) +end + +function show(io::IO, ::MIME"text/plain", t::AbstractSet{T}) where T + # show more descriptively, with one line per value + recur_io = IOContext(io, :SHOWN_SET => t) + limit::Bool = get(io, :limit, false) + + summary(io, t) + isempty(t) && return + print(io, ":") + show_circular(io, t) && return + if limit + sz = displaysize(io) + rows, cols = sz[1] - 3, sz[2] + rows < 2 && (print(io, " …"); return) + cols -= 2 # Subtract the width of prefix " " + cols < 4 && (cols = 4) # Minimum widths of 4 for value + rows -= 1 # Subtract the summary + else + rows = cols = typemax(Int) + end + + for (i, v) in enumerate(t) + print(io, "\n ") + if i == rows < length(t) + print(io, rpad("⋮", 2)) + break + end + + if limit + str = sprint(show, v, context=recur_io, sizehint=0) + print(io, _truncate_at_width_or_chars(str, cols, "\r\n")) + else + show(recur_io, v) + end + end +end + function show(io::IO, ::MIME"text/plain", opt::JLOptions) println(io, "JLOptions(") fields = fieldnames(JLOptions) diff --git a/test/show.jl b/test/show.jl index 1eaef6c19280f..cf197dd5abb73 100644 --- a/test/show.jl +++ b/test/show.jl @@ -452,9 +452,6 @@ let a = Expr(:quote,Expr(:$,:x8d003)) @test eval(eval(Meta.parse(repr(a)))) == 2 end -# issue #9865 -@test occursin(r"^Set\(\[.+….+\]\)$", replstr(Set(1:100))) - # issue #11413 @test string(:(*{1, 2})) == "*{1, 2}" @test string(:(*{1, x})) == "*{1, x}" @@ -1275,7 +1272,7 @@ end @test replstr(view(A, [1], :)) == "1×1 view(::Array{Float64,2}, [1], :) with eltype Float64:\n 0.0" # issue #27680 - @test replstr(Set([(1.0,1.0), (2.0,2.0), (3.0, 3.0)])) == (sizeof(Int) == 8 ? + @test showstr(Set([(1.0,1.0), (2.0,2.0), (3.0, 3.0)])) == (sizeof(Int) == 8 ? "Set([(3.0, 3.0), (2.0, 2.0), (1.0, 1.0)])" : "Set([(1.0, 1.0), (2.0, 2.0), (3.0, 3.0)])") @@ -1585,3 +1582,18 @@ end @test sdastr(2, 2) == "[2, 3]" @test sdastr(3, 3) == "[3, 4, 5]" end + +@testset "show Set" begin + s = Set{Int}(1:22) + str = showstr(s) + @test startswith(str, "Set([") + @test endswith(str, "])") + @test occursin(" … ", str) + + str = replstr(s) + @test startswith(str, "Set{$Int} with 22 elements:\n") + @test endswith(str, "\n ⋮ ") + @test count(==('\n'), str) == 20 + + @test replstr(Set(['a'^100])) == "Set{String} with 1 element:\n \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa…" +end