diff --git a/REQUIRE b/REQUIRE index e95c29053a..e3af56c1e1 100644 --- a/REQUIRE +++ b/REQUIRE @@ -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 diff --git a/src/abstractdataframe/show.jl b/src/abstractdataframe/show.jl index d4e79e5cd1..4b4540ec48 100644 --- a/src/abstractdataframe/show.jl +++ b/src/abstractdataframe/show.jl @@ -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 @@ -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 #' @@ -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) @@ -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) @@ -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 diff --git a/test/io.jl b/test/io.jl index 7a9d9fafff..cd527946db 100644 --- a/test/io.jl +++ b/test/io.jl @@ -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 @@ -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), @@ -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 diff --git a/test/show.jl b/test/show.jl index 303392892c..4b2852f6e4 100644 --- a/test/show.jl +++ b/test/show.jl @@ -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() @@ -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) @@ -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() @@ -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