Skip to content

Commit 7561f13

Browse files
authored
Add support for Python % format spec (#76)
1 parent d015534 commit 7561f13

File tree

4 files changed

+21
-7
lines changed

4 files changed

+21
-7
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ keywords = ["Strings", "Formatting"]
2323
license = "MIT"
2424
name = "Format"
2525
uuid = "1fa38f19-a742-5d3f-a2b9-30dd87b9d5f8"
26-
version = "1.3.5"
26+
version = "1.3.6"
2727

2828
[deps]
2929

src/fmtcore.jl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ end
190190
### print floating point numbers
191191

192192
function _pfmt_f(out::IO, fs::FormatSpec, x::AbstractFloat)
193+
# Handle %
194+
percentflag = (fs.typ == '%')
195+
percentflag && (x *= 100)
193196
# separate sign, integer, and decimal part
194197
prec = fs.prec
195198
rax = round(abs(x); digits = prec)
@@ -200,7 +203,7 @@ function _pfmt_f(out::IO, fs::FormatSpec, x::AbstractFloat)
200203
# calculate length
201204
xlen = ndigits(intv)
202205
numsep, numini = fs.tsep ? divrem(xlen - 1, 3) : (0, 0)
203-
xlen += ifelse(prec > 0, prec + 1, 0) + (sch != '\0') + numsep
206+
xlen += ifelse(prec > 0, prec + 1, 0) + (sch != '\0') + numsep + percentflag
204207

205208
# calculate padding needed
206209
pad = fs.width - xlen
@@ -237,6 +240,10 @@ function _pfmt_f(out::IO, fs::FormatSpec, x::AbstractFloat)
237240
nd < prec && _repprint(out, '0', prec - nd)
238241
_outint(out, idecv)
239242
end
243+
244+
# print trailing percent sign
245+
percentflag && print(out, '%')
246+
240247
# right padding
241248
postpad == 0 || _repprint(out, fs.fill, postpad)
242249
end

src/fmtspec.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@
99
# width ::= <integer>
1010
# prec ::= <integer>
1111
# type ::= 'b' | 'c' | 'd' | 'e' | 'E' | 'f' | 'F' | 'g' | 'G' |
12-
# 'n' | 'o' | 'x' | 'X' | 's'
12+
# 'n' | 'o' | 'x' | 'X' | 's' | '%'
1313
#
1414
# Please refer to http://docs.python.org/2/library/string.html#formatspec
1515
# for more details
1616
#
1717

1818
## FormatSpec type
1919

20-
const _numtypchars = Set(['b', 'd', 'e', 'E', 'f', 'F', 'g', 'G', 'n', 'o', 'x', 'X'])
20+
const _numtypchars = Set(['b', 'd', 'e', 'E', 'f', 'F', 'g', 'G', 'n', 'o', 'x', 'X', '%'])
2121

2222
_tycls(c::AbstractChar) =
2323
(c == 'd' || c == 'n' || c == 'b' || c == 'o' || c == 'x') ? 'i' :
24-
(c == 'e' || c == 'f' || c == 'g') ? 'f' :
24+
(c == 'e' || c == 'f' || c == 'g' || c == '%') ? 'f' :
2525
(c == 'c') ? 'c' :
2626
(c == 's') ? 's' :
2727
error("Invalid type char $(c)")
@@ -108,7 +108,7 @@ end
108108

109109
## parse FormatSpec from a string
110110

111-
const _spec_regex = r"^(.?[<^>])?([ +-])?(#)?(\d+)?([,_])?(.\d+)?([bcdeEfFgGnosxX])?$"
111+
const _spec_regex = r"^(.?[<^>])?([ +-])?(#)?(\d+)?([,_])?(.\d+)?([bcdeEfFgGnosxX%])?$"
112112

113113
function FormatSpec(s::AbstractString)
114114
# default spec
@@ -204,7 +204,7 @@ function printfmt(io::IO, fs::FormatSpec, x)
204204
elseif cls == 'f'
205205
fx = float(x)
206206
if isfinite(fx)
207-
ty == 'f' || ty == 'F' ? _pfmt_f(io, fs, fx) :
207+
ty == 'f' || ty == 'F' || ty == '%' ? _pfmt_f(io, fs, fx) :
208208
ty == 'e' || ty == 'E' ? _pfmt_e(io, fs, fx) : _pfmt_g(io, fs, fx)
209209
else
210210
_pfmt_specialf(io, fs, fx)

test/fmtspec.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,13 @@ end
344344
@test pyfmt(".1e", 0.0006) == "6.0e-04"
345345
end
346346

347+
@testset "Format percentage (%)" begin
348+
@test pyfmt("8.2%", 0.123456) == " 12.35%"
349+
@test pyfmt("<8.2%", 0.123456) == "12.35% "
350+
@test pyfmt("^8.2%", 0.123456) == " 12.35% "
351+
@test pyfmt(">8.2%", 0.123456) == " 12.35%"
352+
end
353+
347354
@testset "Format special floating point value" begin
348355

349356
@test pyfmt("f", NaN) == "NaN"

0 commit comments

Comments
 (0)