From 2a77eac11df348c4ebf07f63f27619affa3b2e98 Mon Sep 17 00:00:00 2001 From: Helmut Haensel Date: Wed, 11 Dec 2019 10:37:16 +0100 Subject: [PATCH 1/8] Handling `AbstractIrrational`: add a new number type 'v' (variable), which plots number symbols right-aligned --- src/fmt.jl | 5 +++-- src/fmtspec.jl | 9 +++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/fmt.jl b/src/fmt.jl index 61df286..b0b5f5b 100644 --- a/src/fmt.jl +++ b/src/fmt.jl @@ -29,7 +29,7 @@ default_spec!(::Type{T}, ::Type{K}) where {T,K} = (DEFAULT_FORMATTERS[T] = DEFAULT_FORMATTERS[K]; nothing) # seed it with some basic default formatters -for (t, c) in [(Integer,'d'), (AbstractFloat,'f'), (AbstractChar,'c'), (AbstractString,'s')] +for (t, c) in [(Integer,'d'), (AbstractFloat,'f'), (AbstractChar,'c'), (AbstractString,'s'), (AbstractIrrational,'v')] default_spec!(t, c) end @@ -66,6 +66,7 @@ default_spec(::Type{<:Integer}) = DEFAULT_FORMATTERS[Integer] default_spec(::Type{<:AbstractFloat}) = DEFAULT_FORMATTERS[AbstractFloat] default_spec(::Type{<:AbstractString}) = DEFAULT_FORMATTERS[AbstractString] default_spec(::Type{<:AbstractChar}) = DEFAULT_FORMATTERS[AbstractChar] +default_spec(::Type{<:AbstractIrrational}) = DEFAULT_FORMATTERS[AbstractIrrational] default_spec(::Type{T}) where {T} = get(DEFAULT_FORMATTERS, T) do @@ -176,7 +177,7 @@ function fmt end # TODO: do more caching to optimize repeated calls # creates a new FormatSpec by overriding the defaults and passes it to pyfmt -# note: adding kwargs is only appropriate for one-off formatting. +# note: adding kwargs is only appropriate for one-off formatting. # normally it will be much faster to change the fmt_default formatting as needed function fmt(x; kwargs...) fspec = fmt_default(x) diff --git a/src/fmtspec.jl b/src/fmtspec.jl index 95d4916..b963461 100644 --- a/src/fmtspec.jl +++ b/src/fmtspec.jl @@ -9,7 +9,7 @@ # width ::= # prec ::= # type ::= 'b' | 'c' | 'd' | 'e' | 'E' | 'f' | 'F' | 'g' | 'G' | -# 'n' | 'o' | 'x' | 'X' | 's' +# 'n' | 'o' | 'x' | 'X' | 's' | 'v' # # Please refer to http://docs.python.org/2/library/string.html#formatspec # for more details @@ -17,13 +17,14 @@ ## FormatSpec type -const _numtypchars = Set(['b', 'd', 'e', 'E', 'f', 'F', 'g', 'G', 'n', 'o', 'x', 'X']) +const _numtypchars = Set(['b', 'd', 'e', 'E', 'f', 'F', 'g', 'G', 'n', 'o', 'x', 'X', 'v']) _tycls(c::AbstractChar) = (c == 'd' || c == 'n' || c == 'b' || c == 'o' || c == 'x') ? 'i' : (c == 'e' || c == 'f' || c == 'g') ? 'f' : (c == 'c') ? 'c' : (c == 's') ? 's' : + (c == 'v') ? 'v' : error("Invalid type char $(c)") struct FormatSpec @@ -84,7 +85,7 @@ end ## parse FormatSpec from a string -const _spec_regex = r"^(.?[<>])?([ +-])?(#)?(\d+)?(,)?(.\d+)?([bcdeEfFgGnosxX])?$" +const _spec_regex = r"^(.?[<>])?([ +-])?(#)?(\d+)?(,)?(.\d+)?([bcdeEfFgGnosxXv])?$" function FormatSpec(s::AbstractString) # default spec @@ -184,7 +185,7 @@ function printfmt(io::IO, fs::FormatSpec, x) else _pfmt_specialf(io, fs, fx) end - elseif cls == 's' + elseif cls == 's' || cls == 'v' _pfmt_s(io, fs, _srepr(x)) else # cls == 'c' _pfmt_s(io, fs, Char(x)) From e19db3938aa999e37bf90573e9d2f92d10e4714c Mon Sep 17 00:00:00 2001 From: Helmut Haensel Date: Wed, 11 Dec 2019 11:11:06 +0100 Subject: [PATCH 2/8] add tests for type 'v' (e.g. AbstractIrrational) --- test/fmt.jl | 4 ++++ test/fmtspec.jl | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/test/fmt.jl b/test/fmt.jl index 2c2f740..072d502 100644 --- a/test/fmt.jl +++ b/test/fmt.jl @@ -41,3 +41,7 @@ fmt_default!(UInt16, 'd', :commas) fmt_default!(UInt32, UInt16, width=20) @test fmt(0xfffff) == " 1,048,575" +v = pi + +@test fmt(v) == "π" +@test fmt(v; width=10) == " π" diff --git a/test/fmtspec.jl b/test/fmtspec.jl index a1121b2..5740bde 100644 --- a/test/fmtspec.jl +++ b/test/fmtspec.jl @@ -234,3 +234,9 @@ end @test pyfmt("*>5f", Inf) == "**Inf" @test pyfmt("⋆>5f", Inf) == "⋆⋆Inf" end + +@testset "Format variable (v) for Irrationals" begin + @test pyfmt("10v", pi) == " π" + @test pyfmt("3v", MathConstants.eulergamma) == " γ" + @test pyfmt("<3v", MathConstants.e) == "ℯ " +end From bfac4e11542fd01b017cd0f46b6f37f9997fe07b Mon Sep 17 00:00:00 2001 From: Helmut Haensel Date: Wed, 11 Dec 2019 21:41:22 +0100 Subject: [PATCH 3/8] add print method for Irrationals for verions < 1.2 --- src/fmtspec.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/fmtspec.jl b/src/fmtspec.jl index b963461..6060e12 100644 --- a/src/fmtspec.jl +++ b/src/fmtspec.jl @@ -165,6 +165,9 @@ _srepr(x) = repr(x) _srepr(x::AbstractString) = x _srepr(x::AbstractChar) = string(x) _srepr(x::Enum) = string(x) +@static if VERSION < v"1.2.0-DEV" + _srepr(x::Irrational{sym}) where {sym} = string(sym) +end function printfmt(io::IO, fs::FormatSpec, x) cls = fs.cls From 67ad47f41a1900f651c77f5d47bc71e373236c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Helmut=20H=C3=A4nsel?= Date: Sun, 15 Dec 2019 01:22:59 +0100 Subject: [PATCH 4/8] Introduction of abstract `Number`s --- src/fmt.jl | 3 ++- src/fmtcore.jl | 37 +++++++++++++++++++++++++++++++++++++ src/fmtspec.jl | 12 ++++++++++-- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/fmt.jl b/src/fmt.jl index b0b5f5b..6b48289 100644 --- a/src/fmt.jl +++ b/src/fmt.jl @@ -29,7 +29,7 @@ default_spec!(::Type{T}, ::Type{K}) where {T,K} = (DEFAULT_FORMATTERS[T] = DEFAULT_FORMATTERS[K]; nothing) # seed it with some basic default formatters -for (t, c) in [(Integer,'d'), (AbstractFloat,'f'), (AbstractChar,'c'), (AbstractString,'s'), (AbstractIrrational,'v')] +for (t, c) in [(Integer,'d'), (AbstractFloat,'f'), (AbstractChar,'c'), (AbstractString,'s'), (Number, 'v')] default_spec!(t, c) end @@ -67,6 +67,7 @@ default_spec(::Type{<:AbstractFloat}) = DEFAULT_FORMATTERS[AbstractFloat] default_spec(::Type{<:AbstractString}) = DEFAULT_FORMATTERS[AbstractString] default_spec(::Type{<:AbstractChar}) = DEFAULT_FORMATTERS[AbstractChar] default_spec(::Type{<:AbstractIrrational}) = DEFAULT_FORMATTERS[AbstractIrrational] +default_spec(::Type{<:Number}) = DEFAULT_FORMATTERS[Number] default_spec(::Type{T}) where {T} = get(DEFAULT_FORMATTERS, T) do diff --git a/src/fmtcore.jl b/src/fmtcore.jl index 712b675..5fe0eb7 100644 --- a/src/fmtcore.jl +++ b/src/fmtcore.jl @@ -262,3 +262,40 @@ function _pfmt_specialf(out::IO, fs::FormatSpec, x::AbstractFloat) end end +function _pfmt_Number_f(out::IO, fs::FormatSpec, x::Number, _pf::Function) + fsi = FormatSpec(fs, width = -1) + f = x::AbstractFloat->begin + io = IOBuffer() + _pf(io, fsi, x) + String(take!(io)) + end + s = _fmt_Number(x, f) + _pfmt_s(out, fs, s) +end + +function _pfmt_Number_i(out::IO, fs::FormatSpec, x::Number, op::Op, _pf::Function) where {Op} + fsi = FormatSpec(fs, width = -1) + f = x::Integer->begin + io = IOBuffer() + _pf(io, fsi, x, op) + String(take!(io)) + end + s = _fmt_Number(x, f) + _pfmt_s(out, fs, s) +end + +function _pfmt_i(out::IO, fs::FormatSpec, x::Number, op::Op) where {Op} + _pfmt_Number_i(out, fs, x, op, _pfmt_i) +end + +function _pfmt_f(out::IO, fs::FormatSpec, x::Number) + _pfmt_Number_f(out, fs, x, _pfmt_f) +end + +function _pfmt_e(out::IO, fs::FormatSpec, x::Number) + _pfmt_Number_f(out, fs, x, _pfmt_e) +end + +function _fmt_Number(x::Complex, f::Function) + s = f(real(x)) * (imag(x) >= 0 ? " + " : " - ") * f(abs(imag(x))) * "im" +end diff --git a/src/fmtspec.jl b/src/fmtspec.jl index 6060e12..7328c80 100644 --- a/src/fmtspec.jl +++ b/src/fmtspec.jl @@ -173,14 +173,22 @@ function printfmt(io::IO, fs::FormatSpec, x) cls = fs.cls ty = fs.typ if cls == 'i' - ix = Integer(x) + ix = x + try + ix = Integer(x) + catch + end ty == 'd' || ty == 'n' ? _pfmt_i(io, fs, ix, _Dec()) : ty == 'x' ? _pfmt_i(io, fs, ix, _Hex()) : ty == 'X' ? _pfmt_i(io, fs, ix, _HEX()) : ty == 'o' ? _pfmt_i(io, fs, ix, _Oct()) : _pfmt_i(io, fs, ix, _Bin()) elseif cls == 'f' - fx = float(x) + fx = x + try + fx = float(x) + catch + end if isfinite(fx) ty == 'f' || ty == 'F' ? _pfmt_f(io, fs, fx) : ty == 'e' || ty == 'E' ? _pfmt_e(io, fs, fx) : From ddbc9813e6b29a9b0c574390bc8e72bfe63477a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Helmut=20H=C3=A4nsel?= Date: Mon, 16 Dec 2019 00:05:00 +0100 Subject: [PATCH 5/8] include complex numbers and allow for any other type to be formatted --- src/fmt.jl | 16 ++++++++++++---- src/fmtcore.jl | 7 ++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/fmt.jl b/src/fmt.jl index 6b48289..f100bc3 100644 --- a/src/fmt.jl +++ b/src/fmt.jl @@ -18,7 +18,7 @@ mutable struct DefaultSpec DefaultSpec(c::AbstractChar) = new(Char(c), FormatSpec(c)) end -const DEFAULT_FORMATTERS = Dict{DataType, DefaultSpec}() +const DEFAULT_FORMATTERS = Dict{Union{DataType, UnionAll}, DefaultSpec}() # adds a new default formatter for this type default_spec!(::Type{T}, c::AbstractChar) where {T} = @@ -29,7 +29,10 @@ default_spec!(::Type{T}, ::Type{K}) where {T,K} = (DEFAULT_FORMATTERS[T] = DEFAULT_FORMATTERS[K]; nothing) # seed it with some basic default formatters -for (t, c) in [(Integer,'d'), (AbstractFloat,'f'), (AbstractChar,'c'), (AbstractString,'s'), (Number, 'v')] +ComplexInteger = Complex{T} where T<:Integer +ComplexFloat = Complex{T} where T<:AbstractFloat +for (t, c) in [(Integer,'d'), (AbstractFloat,'f'), (AbstractChar,'c'), (AbstractString,'s'), + (ComplexInteger, 'd'), (ComplexFloat, 'f'), (Number,'s'), (AbstractIrrational,'s')] default_spec!(t, c) end @@ -66,8 +69,10 @@ default_spec(::Type{<:Integer}) = DEFAULT_FORMATTERS[Integer] default_spec(::Type{<:AbstractFloat}) = DEFAULT_FORMATTERS[AbstractFloat] default_spec(::Type{<:AbstractString}) = DEFAULT_FORMATTERS[AbstractString] default_spec(::Type{<:AbstractChar}) = DEFAULT_FORMATTERS[AbstractChar] -default_spec(::Type{<:AbstractIrrational}) = DEFAULT_FORMATTERS[AbstractIrrational] -default_spec(::Type{<:Number}) = DEFAULT_FORMATTERS[Number] +default_spec(::Type{<:AbstractIrrational}) = DEFAULT_FORMATTERS[AbstractIrrational] +default_spec(::Type{<:Number}) = DEFAULT_FORMATTERS[Number] +default_spec(::ComplexInteger) = DEFAULT_FORMATTERS[ComplexInteger] +default_spec(::ComplexFloat) = DEFAULT_FORMATTERS[ComplexFloat] default_spec(::Type{T}) where {T} = get(DEFAULT_FORMATTERS, T) do @@ -202,3 +207,6 @@ function fmt(x, syms::Symbol...; kwargs...) d = _add_kwargs_from_symbols(kwargs, syms...) fmt(x; d...) end + +fmt_default!(AbstractIrrational, 's', :right) +fmt_default!(Number, 's', :right) diff --git a/src/fmtcore.jl b/src/fmtcore.jl index 5fe0eb7..b7b6c64 100644 --- a/src/fmtcore.jl +++ b/src/fmtcore.jl @@ -1,4 +1,5 @@ # core formatting functions +export fmt_Number ### auxiliary functions @@ -269,7 +270,7 @@ function _pfmt_Number_f(out::IO, fs::FormatSpec, x::Number, _pf::Function) _pf(io, fsi, x) String(take!(io)) end - s = _fmt_Number(x, f) + s = fmt_Number(x, f) _pfmt_s(out, fs, s) end @@ -280,7 +281,7 @@ function _pfmt_Number_i(out::IO, fs::FormatSpec, x::Number, op::Op, _pf::Functio _pf(io, fsi, x, op) String(take!(io)) end - s = _fmt_Number(x, f) + s = fmt_Number(x, f) _pfmt_s(out, fs, s) end @@ -296,6 +297,6 @@ function _pfmt_e(out::IO, fs::FormatSpec, x::Number) _pfmt_Number_f(out, fs, x, _pfmt_e) end -function _fmt_Number(x::Complex, f::Function) +function fmt_Number(x::Complex, f::Function) s = f(real(x)) * (imag(x) >= 0 ? " + " : " - ") * f(abs(imag(x))) * "im" end From 643dc79375004dd2e1c59d0ccec021ad06611eec Mon Sep 17 00:00:00 2001 From: Helmut Haensel Date: Mon, 16 Dec 2019 13:19:00 +0100 Subject: [PATCH 6/8] Add some tests for `Real` and `Complex` --- test/fmt.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/fmt.jl b/test/fmt.jl index 072d502..a79892c 100644 --- a/test/fmt.jl +++ b/test/fmt.jl @@ -20,8 +20,10 @@ i = 1234567 @test fmt(i) == "1234567" @test fmt(i,:commas) == "1,234,567" -@test_throws ErrorException fmt_default(Real) -@test_throws ErrorException fmt_default(Complex) +fmt(3//4, 10) == " 3//4" +fmt(2 - 3im, 10) == " 2 - 3im" +fmt(pi - 3im, 15, 2) == " 3.14 - 3.00im" +fmt(1//2 + 6//2 * im, 15) == " 1//2 + 3//1*im" fmt_default!(Int, :commas, width = 12) @test fmt(i) == " 1,234,567" From f33aba0f88afc24d5bd74b1032c47be5e0ac9806 Mon Sep 17 00:00:00 2001 From: Helmut Haensel Date: Mon, 16 Dec 2019 13:52:19 +0100 Subject: [PATCH 7/8] Replace 'v' by 'S', add some tests, code beautifying --- src/fmt.jl | 20 ++++++++++---------- src/fmtspec.jl | 12 ++++++------ test/fmt.jl | 5 ++++- test/fmtspec.jl | 9 +++++---- 4 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/fmt.jl b/src/fmt.jl index f100bc3..6cac949 100644 --- a/src/fmt.jl +++ b/src/fmt.jl @@ -32,7 +32,7 @@ default_spec!(::Type{T}, ::Type{K}) where {T,K} = ComplexInteger = Complex{T} where T<:Integer ComplexFloat = Complex{T} where T<:AbstractFloat for (t, c) in [(Integer,'d'), (AbstractFloat,'f'), (AbstractChar,'c'), (AbstractString,'s'), - (ComplexInteger, 'd'), (ComplexFloat, 'f'), (Number,'s'), (AbstractIrrational,'s')] + (ComplexInteger, 'd'), (ComplexFloat, 'f'), (Number,'S'), (AbstractIrrational,'S')] default_spec!(t, c) end @@ -65,14 +65,14 @@ end # methods to get the current default objects # note: if you want to set a default for an abstract type (i.e. AbstractFloat) # you'll need to extend this method like here: -default_spec(::Type{<:Integer}) = DEFAULT_FORMATTERS[Integer] -default_spec(::Type{<:AbstractFloat}) = DEFAULT_FORMATTERS[AbstractFloat] -default_spec(::Type{<:AbstractString}) = DEFAULT_FORMATTERS[AbstractString] -default_spec(::Type{<:AbstractChar}) = DEFAULT_FORMATTERS[AbstractChar] +default_spec(::Type{<:Integer}) = DEFAULT_FORMATTERS[Integer] +default_spec(::Type{<:AbstractFloat}) = DEFAULT_FORMATTERS[AbstractFloat] +default_spec(::Type{<:AbstractString}) = DEFAULT_FORMATTERS[AbstractString] +default_spec(::Type{<:AbstractChar}) = DEFAULT_FORMATTERS[AbstractChar] default_spec(::Type{<:AbstractIrrational}) = DEFAULT_FORMATTERS[AbstractIrrational] -default_spec(::Type{<:Number}) = DEFAULT_FORMATTERS[Number] -default_spec(::ComplexInteger) = DEFAULT_FORMATTERS[ComplexInteger] -default_spec(::ComplexFloat) = DEFAULT_FORMATTERS[ComplexFloat] +default_spec(::Type{<:Number}) = DEFAULT_FORMATTERS[Number] +default_spec(::ComplexInteger) = DEFAULT_FORMATTERS[ComplexInteger] +default_spec(::ComplexFloat) = DEFAULT_FORMATTERS[ComplexFloat] default_spec(::Type{T}) where {T} = get(DEFAULT_FORMATTERS, T) do @@ -208,5 +208,5 @@ function fmt(x, syms::Symbol...; kwargs...) fmt(x; d...) end -fmt_default!(AbstractIrrational, 's', :right) -fmt_default!(Number, 's', :right) +#fmt_default!(AbstractIrrational, 's', :right) +#fmt_default!(Number, 's', :right) diff --git a/src/fmtspec.jl b/src/fmtspec.jl index 7328c80..2e006d3 100644 --- a/src/fmtspec.jl +++ b/src/fmtspec.jl @@ -9,7 +9,7 @@ # width ::= # prec ::= # type ::= 'b' | 'c' | 'd' | 'e' | 'E' | 'f' | 'F' | 'g' | 'G' | -# 'n' | 'o' | 'x' | 'X' | 's' | 'v' +# 'n' | 'o' | 'x' | 'X' | 's' | 'S' # # Please refer to http://docs.python.org/2/library/string.html#formatspec # for more details @@ -17,18 +17,18 @@ ## FormatSpec type -const _numtypchars = Set(['b', 'd', 'e', 'E', 'f', 'F', 'g', 'G', 'n', 'o', 'x', 'X', 'v']) +const _numtypchars = Set(['b', 'd', 'e', 'E', 'f', 'F', 'g', 'G', 'n', 'o', 'x', 'X', 'S']) _tycls(c::AbstractChar) = (c == 'd' || c == 'n' || c == 'b' || c == 'o' || c == 'x') ? 'i' : (c == 'e' || c == 'f' || c == 'g') ? 'f' : (c == 'c') ? 'c' : (c == 's') ? 's' : - (c == 'v') ? 'v' : + (c == 'S') ? 'S' : error("Invalid type char $(c)") struct FormatSpec - cls::Char # category: 'i' | 'f' | 'c' | 's' + cls::Char # category: 'i' | 'f' | 'c' | 's' | 'S' typ::Char fill::Char align::Char @@ -85,7 +85,7 @@ end ## parse FormatSpec from a string -const _spec_regex = r"^(.?[<>])?([ +-])?(#)?(\d+)?(,)?(.\d+)?([bcdeEfFgGnosxXv])?$" +const _spec_regex = r"^(.?[<>])?([ +-])?(#)?(\d+)?(,)?(.\d+)?([bcdeEfFgGnosxXS])?$" function FormatSpec(s::AbstractString) # default spec @@ -196,7 +196,7 @@ function printfmt(io::IO, fs::FormatSpec, x) else _pfmt_specialf(io, fs, fx) end - elseif cls == 's' || cls == 'v' + elseif cls == 's' || cls == 'S' _pfmt_s(io, fs, _srepr(x)) else # cls == 'c' _pfmt_s(io, fs, Char(x)) diff --git a/test/fmt.jl b/test/fmt.jl index a79892c..dfee680 100644 --- a/test/fmt.jl +++ b/test/fmt.jl @@ -44,6 +44,9 @@ fmt_default!(UInt32, UInt16, width=20) @test fmt(0xfffff) == " 1,048,575" v = pi - @test fmt(v) == "π" @test fmt(v; width=10) == " π" + +v = MathConstants.eulergamma +@test fmt(v, 10, 2) == " γ" +@test pyfmt("10.2f", v) == " 0.58" diff --git a/test/fmtspec.jl b/test/fmtspec.jl index 5740bde..6a1679a 100644 --- a/test/fmtspec.jl +++ b/test/fmtspec.jl @@ -235,8 +235,9 @@ end @test pyfmt("⋆>5f", Inf) == "⋆⋆Inf" end -@testset "Format variable (v) for Irrationals" begin - @test pyfmt("10v", pi) == " π" - @test pyfmt("3v", MathConstants.eulergamma) == " γ" - @test pyfmt("<3v", MathConstants.e) == "ℯ " +@testset "Format Symbols (S) for Irrationals" begin + @test pyfmt("10S", pi) == " π" + @test pyfmt("3S", MathConstants.eulergamma) == " γ" + @test pyfmt("10.2f", MathConstants.eulergamma) == " 0.58" + @test pyfmt("<3S", MathConstants.e) == "ℯ " end From 34feb56def91c1b2874002ec932bacc21699e046 Mon Sep 17 00:00:00 2001 From: Helmut Haensel Date: Mon, 16 Dec 2019 14:55:50 +0100 Subject: [PATCH 8/8] Adding a default type for `Rational` and `ComplexRational` plus some tests --- src/fmt.jl | 6 +++++- test/fmt.jl | 18 +++++++++++++----- test/fmtspec.jl | 6 ++++++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/fmt.jl b/src/fmt.jl index 6cac949..c0c6495 100644 --- a/src/fmt.jl +++ b/src/fmt.jl @@ -31,8 +31,10 @@ default_spec!(::Type{T}, ::Type{K}) where {T,K} = # seed it with some basic default formatters ComplexInteger = Complex{T} where T<:Integer ComplexFloat = Complex{T} where T<:AbstractFloat +ComplexRational = Complex{T} where T<:Rational for (t, c) in [(Integer,'d'), (AbstractFloat,'f'), (AbstractChar,'c'), (AbstractString,'s'), - (ComplexInteger, 'd'), (ComplexFloat, 'f'), (Number,'S'), (AbstractIrrational,'S')] + (ComplexInteger,'d'), (ComplexFloat,'f'), (Number,'S'), (AbstractIrrational,'S'), + (Rational,'S'), (ComplexRational,'S')] default_spec!(t, c) end @@ -73,6 +75,8 @@ default_spec(::Type{<:AbstractIrrational}) = DEFAULT_FORMATTERS[AbstractIrration default_spec(::Type{<:Number}) = DEFAULT_FORMATTERS[Number] default_spec(::ComplexInteger) = DEFAULT_FORMATTERS[ComplexInteger] default_spec(::ComplexFloat) = DEFAULT_FORMATTERS[ComplexFloat] +default_spec(::Rational) = DEFAULT_FORMATTERS[Rational] +default_spec(::ComplexRational) = DEFAULT_FORMATTERS[ComplexRational] default_spec(::Type{T}) where {T} = get(DEFAULT_FORMATTERS, T) do diff --git a/test/fmt.jl b/test/fmt.jl index dfee680..9fed6b4 100644 --- a/test/fmt.jl +++ b/test/fmt.jl @@ -20,10 +20,19 @@ i = 1234567 @test fmt(i) == "1234567" @test fmt(i,:commas) == "1,234,567" -fmt(3//4, 10) == " 3//4" -fmt(2 - 3im, 10) == " 2 - 3im" -fmt(pi - 3im, 15, 2) == " 3.14 - 3.00im" -fmt(1//2 + 6//2 * im, 15) == " 1//2 + 3//1*im" +@test fmt(2 - 3im, 10) == " 2 - 3im" +@test fmt(pi - 3im, 15, 2) == " 3.14 - 3.00im" + +@test fmt(3//4, 10) == " 3//4" +@test fmt(1//2 + 6//2 * im, 15) == " 1//2 + 3//1*im" + +fmt_default!(Rational, 'f', prec = 2) +fmt_default!(Format.ComplexRational, 'f', prec = 2) + +@test fmt(3//4, 10, 2) == " 0.75" +@test fmt(3//4, 10, 1) == " 0.8" +@test fmt(1//2 + 6//2 * im, 23) == " 0.500000 + 3.000000im" +@test fmt(1//2 + 6//2 * im, 15, 2) == " 0.50 + 3.00im" fmt_default!(Int, :commas, width = 12) @test fmt(i) == " 1,234,567" @@ -49,4 +58,3 @@ v = pi v = MathConstants.eulergamma @test fmt(v, 10, 2) == " γ" -@test pyfmt("10.2f", v) == " 0.58" diff --git a/test/fmtspec.jl b/test/fmtspec.jl index 6a1679a..b0c01da 100644 --- a/test/fmtspec.jl +++ b/test/fmtspec.jl @@ -241,3 +241,9 @@ end @test pyfmt("10.2f", MathConstants.eulergamma) == " 0.58" @test pyfmt("<3S", MathConstants.e) == "ℯ " end + +@testset "Format Symbols (S) for Irrationals" begin + pyfmt("10s", 3//4) == "3//4 " + pyfmt("10S", 3//4) == " 3//4" + pyfmt("10.1f", 3//4) == " 0.8" +end