Skip to content

Commit

Permalink
Improve show in corner cases (#1237)
Browse files Browse the repository at this point in the history
* add * before null in show

* reworked show for corner cases

* handle no-color terminal

* accomodate to CategoricalArrays 0.2.1

* corrected color sequences

* remove CategoricalArray{Char}

* add space in all?
  • Loading branch information
bkamins authored and cjprybol committed Sep 26, 2017
1 parent f0422b3 commit f3ca566
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 33 deletions.
2 changes: 1 addition & 1 deletion REQUIRE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
julia 0.6
Nulls 0.0.6
CategoricalArrays 0.2.0
CategoricalArrays 0.2.1
StatsBase 0.11.0
SortingAlgorithms
Reexport
Expand Down
29 changes: 11 additions & 18 deletions src/abstractdataframe/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,8 @@ let
function ourstrwidth(x::Any) # -> Int
truncate(io, 0)
ourshowcompact(io, x)
return position(io)
strwidth(String(take!(io)))
end
ourstrwidth(x::AbstractString) = strwidth(x) # -> Int
ourstrwidth(s::Symbol) =
Int(ccall(:u8_strwidth,
Csize_t,
(Ptr{UInt8}, ),
Base.unsafe_convert(Ptr{UInt8}, s)))
end

#' @description
Expand All @@ -61,10 +55,8 @@ end
#' ourshowcompact(STDOUT, "abc")
#' ourshowcompact(STDOUT, 10000)
ourshowcompact(io::IO, x::Any) = showcompact(io, x) # -> Void
ourshowcompact(io::IO, x::AbstractString) = print(io, x) # -> Void
ourshowcompact(io::IO, x::Symbol) = print(io, x) # -> Void
ourshowcompact(io::IO, x::CategoricalValue{<:AbstractString}) =
print(io, String(x)) # -> Void
ourshowcompact(io::IO, x::AbstractString) = escape_string(io, x, "") # -> Void
ourshowcompact(io::IO, x::Symbol) = ourshowcompact(io, string(x)) # -> Void

#' @description
#'
Expand Down Expand Up @@ -99,10 +91,6 @@ function getmaxwidths(df::AbstractDataFrame,
rowindices1::AbstractVector{Int},
rowindices2::AbstractVector{Int},
rowlabel::Symbol) # -> Vector{Int}
# TODO: correct calculation of width for the cases:
# 1) DataFrame(a=["∀ε⫺0: x+ε⫺x"])
# 2) DataFrame(a=[[1:30;]])
# 3) decide how '\r', '\n', '\t' characters should be handled in strings
maxwidths = Vector{Int}(size(df, 2) + 1)

undefstrwidth = ourstrwidth(Base.undef_ref_str)
Expand Down Expand Up @@ -258,8 +246,13 @@ function showrowindices(io::IO,
for j in leftcol:rightcol
strlen = 0
try
strlen = ourstrwidth(df[i, j])
ourshowcompact(io, df[i, j])
s = df[i, j]
strlen = ourstrwidth(s)
if isnull(s)
print_with_color(:light_black, io, s)
else
ourshowcompact(io, s)
end
catch
strlen = ourstrwidth(Base.undef_ref_str)
ourshowcompact(io, Base.undef_ref_str)
Expand Down Expand Up @@ -589,7 +582,7 @@ function showcols(io::IO, df::AbstractDataFrame, all::Bool = false,
sprint(ourshowcompact, df[end, i]) for i in 1:ncols]
end
end
(all?showall:show)(io, metadata, true, Symbol("Col #"), false)
(all ? showall : show)(io, metadata, true, Symbol("Col #"), false)
return
end

Expand Down
10 changes: 5 additions & 5 deletions test/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module TestIO
\t1 & 1 & \\\$10.0 & \$\\alpha\$ & 1.0 & a \\\\
\t2 & 2 & M\\&F & \$\\beta\$ & 2.0 & \\\\
\t3 & 3 & A\\textasciitilde{}B & \$\\gamma\$ & & c \\\\
\t4 & 4 & \\textbackslash{}alpha & \$\\sum_{i=1}^n \\delta_i\$ & 3.0 & d \\\\
\t4 & 4 & \\textbackslash{}\\textbackslash{}alpha & \$\\sum_{i=1}^n \\delta_i\$ & 3.0 & d \\\\
\\end{tabular}
"""
@test reprmime(MIME("text/latex"), df) == str
Expand Down Expand Up @@ -44,7 +44,7 @@ module TestIO
df = DataFrame(A = 1:3,
B = 'a':'c',
C = ["A", "B", "C"],
D = CategoricalArray('a':'c'),
D = CategoricalArray(string.('a':'c')),
E = CategoricalArray(["A", "B", null]),
F = Vector{Union{Int, Null}}(1:3),
G = nulls(3),
Expand All @@ -53,9 +53,9 @@ module TestIO
@test sprint(printtable, df) ==
"""
"A","B","C","D","E","F","G","H"
1,"'a'","A","'a'","A","1",null,null
2,"'b'","B","'b'","B","2",null,null
3,"'c'","C","'c'",null,"3",null,null
1,"'a'","A","a","A","1",null,null
2,"'b'","B","b","B","2",null,null
3,"'c'","C","c",null,"3",null,null
"""

# DataStreams
Expand Down
72 changes: 63 additions & 9 deletions test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ module TestShow
using Base.Test, DataFrames

# In the future newline character \n should be added to this test case
df = DataFrame(A = Int64[1:4;], B = ["x\"", "∀ε0: x+εx", "z\$", "ABC"],
df = DataFrame(A = Int64[1:4;], B = ["x\"", "∀ε>0: x+ε>x", "z\$", "ABC"],
C = Float32[1.0, 2.0, 3.0, 4.0])

refstr = """
4×3 DataFrames.DataFrame
│ Row │ A │ B │ C │
├─────┼───┼───────────────┼─────┤
│ 1 │ 1 │ x\" │ 1.0 │
│ 2 │ 2 │ ∀ε0: x+εx │ 2.0 │
│ 3 │ 3 │ z\$ │ 3.0 │
│ 4 │ 4 │ ABC │ 4.0 │"""
│ Row │ A │ B │ C │
├─────┼───┼─────────────┼─────┤
│ 1 │ 1 │ x\" │ 1.0 │
│ 2 │ 2 │ ∀ε>0: x+ε>x │ 2.0 │
│ 3 │ 3 │ z\$ │ 3.0 │
│ 4 │ 4 │ ABC │ 4.0 │"""

for f in [show, showall], allcols in [true, false]
io = IOBuffer()
Expand Down Expand Up @@ -268,12 +268,17 @@ module TestShow
io = IOBuffer()
show(io, df)
str = String(take!(io))
@test str == """
@test str == (Base.have_color ? """
2×2 DataFrames.DataFrame
│ Row │ Fish │ Mass │
├─────┼──────┼──────┤
│ 1 │ Suzy │ 1.5 │
│ 2 │ Amir │ \e[90mnull\e[39m │""" : """
2×2 DataFrames.DataFrame
│ Row │ Fish │ Mass │
├─────┼──────┼──────┤
│ 1 │ Suzy │ 1.5 │
│ 2 │ Amir │ null │"""
│ 2 │ Amir │ null │""")

io = IOBuffer()
showcols(io, df)
Expand All @@ -285,6 +290,38 @@ module TestShow
│ 1 │ Fish │ String │ 0 │ Suzy … Amir │
│ 2 │ Mass │ Union{Float64, Nulls.Null} │ 1 │ 1.5 … null │"""

# Test showing null
df = DataFrame(A = [:Symbol, null, :null],
B = [null, "String", "null"],
C = [:null, "null", null])
io = IOBuffer()
show(io, df)
str = String(take!(io))
@test str == (Base.have_color ? """
3×3 DataFrames.DataFrame
│ Row │ A │ B │ C │
├─────┼────────┼────────┼──────┤
│ 1 │ Symbol │ \e[90mnull\e[39m │ null │
│ 2 │ \e[90mnull\e[39m │ String │ null │
│ 3 │ null │ null │ \e[90mnull\e[39m │""" : """
3×3 DataFrames.DataFrame
│ Row │ A │ B │ C │
├─────┼────────┼────────┼──────┤
│ 1 │ Symbol │ null │ null │
│ 2 │ null │ String │ null │
│ 3 │ null │ null │ null │""")

io = IOBuffer()
showcols(io, df)
str = String(take!(io))
@test str == """
3×3 DataFrames.DataFrame
│ Col # │ Name │ Eltype │ Missing │ Values │
├───────┼──────┼───────────────────────────┼─────────┼─────────────────┤
│ 1 │ A │ Union{Nulls.Null, Symbol} │ 1 │ Symbol … null │
│ 2 │ B │ Union{Nulls.Null, String} │ 1 │ null … null │
│ 3 │ C │ Any │ 1 │ null … null │"""

# Test computing width for Array{String} columns
df = DataFrame(Any[["a"]], [:x])
io = IOBuffer()
Expand All @@ -295,4 +332,21 @@ module TestShow
│ Row │ x │
├─────┼───┤
│ 1 │ a │"""

# Test escape characters
df = DataFrame(a = ["1\n1", "2\t2", "3\r3", "4\$4", "5\"5", "6\\6"])
io = IOBuffer()
show(io, df)
str = String(take!(io))
@test str == """
6×1 DataFrames.DataFrame
│ Row │ a │
├─────┼──────┤
│ 1 │ 1\\n1 │
│ 2 │ 2\\t2 │
│ 3 │ 3\\r3 │
│ 4 │ 4\$4 │
│ 5 │ 5\"5 │
│ 6 │ 6\\\\6 │"""

end

0 comments on commit f3ca566

Please sign in to comment.