diff --git a/src/display.jl b/src/display.jl index c85af809..074059aa 100644 --- a/src/display.jl +++ b/src/display.jl @@ -44,10 +44,6 @@ function prefix(x::Unit) end end -function show(io::IO, x::Unit{N,D}) where {N,D} - show(io, FreeUnits{(x,), D, nothing}()) -end - abstract type BracketStyle end struct NoBrackets <: BracketStyle end @@ -89,7 +85,7 @@ brackets are not printed. """ function showval(io::IO, x::Number, brackets::Bool=true) brackets && print_opening_bracket(io, x) - show(io, x) + show(io, MIME"text/plain"(), x) brackets && print_closing_bracket(io, x) end @@ -107,20 +103,10 @@ has_unit_spacing(u) = true has_unit_spacing(u::Units{(Unit{:Degree, NoDims}(0, 1//1),), NoDims}) = false """ - show(io::IO, x::Quantity) + show(io::IO, mime::MIME"text/plain", x::Quantity) Show a unitful quantity by calling [`showval`](@ref) on the numeric value, appending a space, and then calling `show` on a units object `U()`. """ -function show(io::IO, x::Quantity) - if isunitless(unit(x)) - showval(io, x.val, false) - else - showval(io, x.val, true) - has_unit_spacing(unit(x)) && print(io, ' ') - show(io, unit(x)) - end -end - function show(io::IO, mime::MIME"text/plain", x::Quantity) if isunitless(unit(x)) showval(io, mime, x.val, false) @@ -131,42 +117,42 @@ function show(io::IO, mime::MIME"text/plain", x::Quantity) end end -function show(io::IO, r::StepRange{T}) where T<:Quantity +function show(io::IO, mime::MIME"text/plain", r::StepRange{T}) where T<:Quantity a,s,b = first(r), step(r), last(r) U = unit(a) V = absoluteunit(U) print(io, '(') if ustrip(V, s) == 1 - show(io, ustrip(U, a):ustrip(U, b)) + show(io, mime, ustrip(U, a):ustrip(U, b)) else - show(io, ustrip(U, a):ustrip(V, s):ustrip(U, b)) + show(io, mime, ustrip(U, a):ustrip(V, s):ustrip(U, b)) end print(io, ')') has_unit_spacing(U) && print(io,' ') - show(io, U) + show(io, mime, U) end -function show(io::IO, r::StepRangeLen{T}) where T<:Quantity +function show(io::IO, mime::MIME"text/plain", r::StepRangeLen{T}) where T<:Quantity a,s,b = first(r), step(r), last(r) U = unit(a) V = absoluteunit(U) print(io, '(') - show(io, StepRangeLen(ustrip(U, a), ustrip(V, s), length(r))) + show(io, mime, StepRangeLen(ustrip(U, a), ustrip(V, s), length(r))) print(io, ')') has_unit_spacing(U) && print(io,' ') - show(io, U) + show(io, mime, U) end -function show(io::IO, x::typeof(NoDims)) +function show(io::IO, ::MIME"text/plain", x::typeof(NoDims)) print(io, "NoDims") end """ - show(io::IO, x::Unitlike) + show(io::IO, ::MIME"text/plain", x::Unitlike) Call [`Unitful.showrep`](@ref) on each object in the tuple that is the type variable of a [`Unitful.Units`](@ref) or [`Unitful.Dimensions`](@ref) object. """ -function show(io::IO, x::Unitlike) +function show(io::IO, ::MIME"text/plain", x::Unitlike) showoperators = get(io, :showoperators, false) first = "" sep = showoperators ? "*" : " " @@ -252,3 +238,12 @@ superscript(i::Integer) = map(repr(i)) do c c == '0' ? '\u2070' : error("unexpected character") end + +Base.print(io::IO, x::AbstractQuantity) = show(io, "text/plain", x) +Base.print(io::IO, x::Dimension) = show(io, "text/plain", x) +Base.print(io::IO, x::Unit) = show(io, "text/plain", x) +Base.print(io::IO, x::Union{StepRange{T},StepRangeLen{T}}) where T<:Quantity = show(io, "text/plain", x) +Base.print(io::IO, x::Unitlike) = show(io, "text/plain", x) +Base.print(io::IO, x::MixedUnits) = show(io, "text/plain", x) +Base.print(io::IO, x::LogScaled) = show(io, "text/plain", x) +Base.print(io::IO, x::IsRootPowerRatio) = show(io, "text/plain", x) diff --git a/src/logarithm.jl b/src/logarithm.jl index 58d76beb..a9d9daa4 100644 --- a/src/logarithm.jl +++ b/src/logarithm.jl @@ -84,11 +84,11 @@ tolog(L,x) = (1+isrootpower(L)) * prefactor(L()) * (logfn(L()))(x) fromlog(L,S,x) = unwrap(S) * expfn(L())( x / ((1+isrootpower(S))*prefactor(L())) ) fromlog(L,x) = expfn(L())( x / ((1+isrootpower(L))*prefactor(L())) ) -function Base.show(io::IO, x::MixedUnits{T,U}) where {T,U} +function Base.show(io::IO, mime::MIME"text/plain", x::MixedUnits{T,U}) where {T,U} print(io, abbr(x)) if x.units != NoUnits print(io, " ") - show(io, x.units) + show(io, mime, x.units) end end @@ -312,11 +312,11 @@ function Base.promote_rule(::Type{G}, ::Type{N}) where {L,S,T1, G<:Gain{L,S,T1}, end Base.promote_rule(A::Type{G}, B::Type{L}) where {G<:Gain, L2, L<:Level{L2}} = LogScaled{L2} -function Base.show(io::IO, x::Gain) +function Base.show(io::IO, mime::MIME"text/plain", x::Gain) print(io, x.val, " ", abbr(x)) nothing end -function Base.show(io::IO, x::Level) +function Base.show(io::IO, mime::MIME"text/plain", x::Level) print(io, ustrip(x), " ", abbr(x)) nothing end diff --git a/src/types.jl b/src/types.jl index a50dbeb4..58e03b99 100644 --- a/src/types.jl +++ b/src/types.jl @@ -286,7 +286,7 @@ struct IsRootPowerRatio{S,T} val::T end IsRootPowerRatio{S}(x) where {S} = IsRootPowerRatio{S, typeof(x)}(x) -Base.show(io::IO, x::IsRootPowerRatio{S}) where {S} = +Base.show(io::IO, ::MIME"text/plain", x::IsRootPowerRatio{S}) where {S} = print(io, ifelse(S, "root-power ratio", "power ratio"), " with reference ", x.val) const PowerRatio{T} = IsRootPowerRatio{false,T} const RootPowerRatio{T} = IsRootPowerRatio{true,T} diff --git a/src/user.jl b/src/user.jl index 8df784c9..875fe8d9 100644 --- a/src/user.jl +++ b/src/user.jl @@ -291,7 +291,7 @@ macro affineunit(symb, abbr, offset) s = Symbol(symb) return esc(quote Base.@__doc__ const global $s = $affineunit($offset) - $Base.show(io::$IO, ::$genericunit($s)) = $print(io, $abbr) + $Base.show(io::$IO, mime::$(MIME"text/plain"), ::$genericunit($s)) = $print(io, $abbr) end) end diff --git a/src/utils.jl b/src/utils.jl index c0975ce5..5c8df828 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -235,7 +235,7 @@ struct DimensionError <: Exception end Base.showerror(io::IO, e::DimensionError) = - print(io, "DimensionError: $(e.x) and $(e.y) are not dimensionally compatible."); + print(io, "DimensionError: ", e.x, " and ", e.y, " are not dimensionally compatible."); """ struct AffineError <: Exception @@ -245,4 +245,4 @@ struct AffineError <: Exception x end -Base.showerror(io::IO, e::AffineError) = print(io, "AffineError: $(e.x)") +Base.showerror(io::IO, e::AffineError) = print(io, "AffineError: ", e.x) diff --git a/test/runtests.jl b/test/runtests.jl index 8a707747..c1fda723 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1479,21 +1479,16 @@ end withenv("UNITFUL_FANCY_EXPONENTS" => false) do @static if VERSION ≥ v"1.6.0-DEV.770" @test string(typeof(1.0m/s)) == - "Quantity{Float64, 𝐋 𝐓^-1, FreeUnits{(m, s^-1), 𝐋 𝐓^-1, nothing}}" + "Quantity{Float64, Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1), Unitful.Dimension{:Time}(-1//1))}(), FreeUnits{(Unitful.Unit{:Meter, Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1),)}()}(0, 1//1), Unitful.Unit{:Second, Unitful.Dimensions{(Unitful.Dimension{:Time}(1//1),)}()}(0, -1//1)), Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1), Unitful.Dimension{:Time}(-1//1))}(), nothing}}" @test string(typeof(m/s)) == - "FreeUnits{(m, s^-1), 𝐋 𝐓^-1, nothing}" - else - @test string(typeof(1.0m/s)) == - "Quantity{Float64,𝐋 𝐓^-1,FreeUnits{(m, s^-1),𝐋 𝐓^-1,nothing}}" - @test string(typeof(m/s)) == - "FreeUnits{(m, s^-1),𝐋 𝐓^-1,nothing}" + "FreeUnits{(Unitful.Unit{:Meter, Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1),)}()}(0, 1//1), Unitful.Unit{:Second, Unitful.Dimensions{(Unitful.Dimension{:Time}(1//1),)}()}(0, -1//1)), Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1), Unitful.Dimension{:Time}(-1//1))}(), nothing}" end @test string(dimension(1u"m/s")) == "𝐋 𝐓^-1" @test string(NoDims) == "NoDims" end @testset ":fancy_exponent IOContext property" begin - @test sprint(io -> show(IOContext(io, :fancy_exponent => true), u"m/s")) == "m s⁻¹" - @test sprint(io -> show(IOContext(io, :fancy_exponent => false), u"m/s")) == "m s^-1" + @test sprint(print, u"m/s", context = :fancy_exponent => true) == "m s⁻¹" + @test sprint(print, u"m/s", context = :fancy_exponent => false) == "m s^-1" end end @@ -1503,50 +1498,66 @@ Base.show(io::IO, ::MIME"text/plain", ::Foo) = print(io, "42.0") @testset "Show quantities" begin withenv("UNITFUL_FANCY_EXPONENTS" => false) do - @test repr(1.0 * u"m * s * kg^-1") == "1.0 m s kg^-1" + @static if VERSION ≥ v"1.6.0-DEV.770" + @test repr(1.0 * u"m * s * kg^-1") == "Quantity{Float64, Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1), Unitful.Dimension{:Mass}(-1//1), Unitful.Dimension{:Time}(1//1))}(), FreeUnits{(Unitful.Unit{:Gram, Unitful.Dimensions{(Unitful.Dimension{:Mass}(1//1),)}()}(3, -1//1), Unitful.Unit{:Meter, Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1),)}()}(0, 1//1), Unitful.Unit{:Second, Unitful.Dimensions{(Unitful.Dimension{:Time}(1//1),)}()}(0, 1//1)), Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1), Unitful.Dimension{:Mass}(-1//1), Unitful.Dimension{:Time}(1//1))}(), nothing}}(1.0)" + @test repr(Foo() * u"m * s * kg^-1") == "Quantity{Foo, Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1), Unitful.Dimension{:Mass}(-1//1), Unitful.Dimension{:Time}(1//1))}(), FreeUnits{(Unitful.Unit{:Gram, Unitful.Dimensions{(Unitful.Dimension{:Mass}(1//1),)}()}(3, -1//1), Unitful.Unit{:Meter, Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1),)}()}(0, 1//1), Unitful.Unit{:Second, Unitful.Dimensions{(Unitful.Dimension{:Time}(1//1),)}()}(0, 1//1)), Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1), Unitful.Dimension{:Mass}(-1//1), Unitful.Dimension{:Time}(1//1))}(), nothing}}(1)" + @test repr((1+2im) * u"m/s") == "Quantity{Complex{Int64}, Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1), Unitful.Dimension{:Time}(-1//1))}(), FreeUnits{(Unitful.Unit{:Meter, Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1),)}()}(0, 1//1), Unitful.Unit{:Second, Unitful.Dimensions{(Unitful.Dimension{:Time}(1//1),)}()}(0, -1//1)), Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1), Unitful.Dimension{:Time}(-1//1))}(), nothing}}(1 + 2im)" + @test sprint(show, 1.0°) == "Quantity{Float64, Unitful.Dimensions{()}(), FreeUnits{(Unitful.Unit{:Degree, Unitful.Dimensions{()}()}(0, 1//1),), Unitful.Dimensions{()}(), nothing}}(1.0)" + end @test repr("text/plain", 1.0 * u"m * s * kg^-1") == "1.0 m s kg^-1" - @test repr(Foo() * u"m * s * kg^-1") == "1 m s kg^-1" @test repr("text/plain", Foo() * u"m * s * kg^-1") == "42.0 m s kg^-1" # Complex quantities - @test repr((1+2im) * u"m/s") == "(1 + 2im) m s^-1" @test repr("text/plain", (1+2im) * u"m/s") == "(1 + 2im) m s^-1" # Angular degree printing #253 - @test sprint(show, 1.0°) == "1.0°" @test repr("text/plain", 1.0°) == "1.0°" # Concise printing of ranges - @test repr((1:10)*u"kg/m^3") == "(1:10) kg m^-3" - @test repr((1.0:0.1:10.0)*u"kg/m^3") == "(1.0:0.1:10.0) kg m^-3" - @test repr((1:10)*°) == "(1:10)°" - @test repr(range(1.0+2.0im, length=5)*u"m") == "(1.0 + 2.0im:1.0 + 0.0im:5.0 + 2.0im) m" - @test repr(range(1+2im, step=1+1im, length=5)*u"m") == "(1 + 2im:1 + 1im:5 + 6im) m" - @test repr(StepRange((1//1)u"m", 1u"cm", (2//1)u"m")) == "(1//1:1//100:2//1) m" - @test repr(StepRangeLen(1.0u"m", 1.0u"cm", 101)) == "(1.0:0.01:2.0) m" + @test repr("text/plain", (1:10)*u"kg/m^3") == "(1:10) kg m^-3" + @test repr("text/plain", (1.0:0.1:10.0)*u"kg/m^3") == "(1.0:0.1:10.0) kg m^-3" + @test repr("text/plain", (1:10)*°) == "(1:10)°" + @test repr("text/plain", range(1.0+2.0im, length=5)*u"m") == "(1.0 + 2.0im:1.0 + 0.0im:5.0 + 2.0im) m" + @test repr("text/plain", range(1+2im, step=1+1im, length=5)*u"m") == "(1 + 2im:1 + 1im:5 + 6im) m" + @test repr("text/plain", StepRange((1//1)u"m", 1u"cm", (2//1)u"m")) == "(1//1:1//100:2//1) m" + @test repr("text/plain", StepRangeLen(1.0u"m", 1.0u"cm", 101)) == "(1.0:0.01:2.0) m" # Concise printing of affine ranges with mixed step unit - @test repr(StepRange(1u"°C", 1u"K", 3u"°C")) == "(1:3) °C" - @test repr(StepRange(1u"°C", 1.0u"K", 3u"°C")) == "(1:3) °C" - @test repr(StepRange(1.0u"°C", 1u"K", 3.0u"°C")) == "(1.0:1.0:3.0) °C" - @test repr(StepRange(1.0u"°C", 1.0u"K", 3.0u"°C")) == "(1.0:1.0:3.0) °C" - @test repr(StepRange((0//1)u"°F", 1u"K", (9//1)u"°F")) == "(0//1:9//5:9//1) °F" - @test repr(StepRangeLen{typeof(1.0u"°C"),typeof(1.0u"°C"),typeof(1u"K")}(1.0u"°C", 1u"K", 3, 1)) == "(1.0:1.0:3.0) °C" + @test repr("text/plain", StepRange(1u"°C", 1u"K", 3u"°C")) == "(1:3) °C" + @test repr("text/plain", StepRange(1u"°C", 1.0u"K", 3u"°C")) == "(1:3) °C" + @test repr("text/plain", StepRange(1.0u"°C", 1u"K", 3.0u"°C")) == "(1.0:1.0:3.0) °C" + @test repr("text/plain", StepRange(1.0u"°C", 1.0u"K", 3.0u"°C")) == "(1.0:1.0:3.0) °C" + @test repr("text/plain", StepRange((0//1)u"°F", 1u"K", (9//1)u"°F")) == "(0//1:9//5:9//1) °F" + @test repr("text/plain", StepRangeLen{typeof(1.0u"°C"),typeof(1.0u"°C"),typeof(1u"K")}(1.0u"°C", 1u"K", 3, 1)) == "(1.0:1.0:3.0) °C" @static if VERSION < v"1.5" @test_broken repr(StepRangeLen{typeof(1u"°C"),typeof(1u"°C"),typeof(1u"K")}(1u"°C", 1u"K", 3, 1)) == "(1:1:3) °C" @test_broken repr(StepRangeLen{typeof(1.0u"°F"),typeof(1.0u"°F"),typeof(1u"K")}(0.0u"°F", 1u"K", 6)) == "(0.0:1.8:9.0) °F" else - @test repr(StepRangeLen{typeof(1u"°C"),typeof(1u"°C"),typeof(1u"K")}(1u"°C", 1u"K", 3, 1)) == "(1:1:3) °C" - @test repr(StepRangeLen{typeof(1.0u"°F"),typeof(1.0u"°F"),typeof(1u"K")}(0.0u"°F", 1u"K", 6)) == "(0.0:1.8:9.0) °F" + @test repr("text/plain", StepRangeLen{typeof(1u"°C"),typeof(1u"°C"),typeof(1u"K")}(1u"°C", 1u"K", 3, 1)) == "(1:1:3) °C" + @test repr("text/plain", StepRangeLen{typeof(1.0u"°F"),typeof(1.0u"°F"),typeof(1u"K")}(0.0u"°F", 1u"K", 6)) == "(0.0:1.8:9.0) °F" end end withenv("UNITFUL_FANCY_EXPONENTS" => true) do - @test repr(1.0 * u"m * s * kg^(-1//2)") == "1.0 m s kg⁻¹ᐟ²" + @test repr("text/plain", 1.0 * u"m * s * kg^(-1//2)") == "1.0 m s kg⁻¹ᐟ²" end withenv("UNITFUL_FANCY_EXPONENTS" => nothing) do - @test repr(1.0 * u"m * s * kg^(-1//2)") == + @test repr("text/plain", 1.0 * u"m * s * kg^(-1//2)") == (Sys.isapple() ? "1.0 m s kg⁻¹ᐟ²" : "1.0 m s kg^-1/2") end + + @testset "roundtripping show" begin + u = u"m/s" + u2 = eval(Meta.parse(repr(u))) + @test u == u2 + + q = Quantity(5, u"m") + q2 = eval(Meta.parse(repr(q))) + @test q == q2 + + d = u"𝐌*𝐋/𝐓^2" + d2 = eval(Meta.parse(repr(d))) + @test d == d2 + end end @testset "DimensionError message" begin @@ -1880,7 +1891,9 @@ end @testset "> Display" begin withenv("UNITFUL_FANCY_EXPONENTS" => false) do - @test repr(3u"dB/Hz") == "[3 dB] Hz^-1" + @static if VERSION ≥ v"1.6.0-DEV.770" + @test repr(3u"dB/Hz") == "Quantity{Gain{LogInfo{:Decibel, 10, 10}, :?, Int64}, Unitful.Dimensions{(Unitful.Dimension{:Time}(1//1),)}(), FreeUnits{(Unitful.Unit{:Hertz, Unitful.Dimensions{(Unitful.Dimension{:Time}(-1//1),)}()}(0, -1//1),), Unitful.Dimensions{(Unitful.Dimension{:Time}(1//1),)}(), nothing}}(Gain{LogInfo{:Decibel, 10, 10}, :?, Int64}(3))" + end @test repr("text/plain", 3u"dB/Hz") == "[3 dB] Hz^-1" end @test Unitful.abbr(3u"dBm") == "dBm"