Skip to content

Commit

Permalink
Finished adding support for # flag in Number.toFormat()
Browse files Browse the repository at this point in the history
  • Loading branch information
Mr0grog committed May 14, 2012
1 parent b8e573a commit c3b4b4e
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 14 deletions.
11 changes: 7 additions & 4 deletions ES6StringFormat-tests.js
Expand Up @@ -78,6 +78,7 @@ assertEquals("{0:#X}".format(10), "0XA", "The 'X' type converts a number to uppe

assertEquals("{0:e}".format(5), "5 e+00", "The 'e' type converts to scientific notation with at least two digits in the exponent.");
assertEquals("{0:E}".format(5), "5 E+00", "The 'E' type converts to upper-case scientific notation with at least two digits in the exponent.");
assertEquals("{0:#e}".format(5), "5. e+00", "The 'e' type converts to scientific notation with a decimal point when the # flag is used.");

assertEquals("{0:f}".format(5), "5", "The 'f' type converts a number to fixed point.");
assertEquals("{0:f}".format(5.74392), "6", "The 'f' type converts a number to fixed point and rounds to the appropriate number of digits after the decimal.");
Expand All @@ -88,6 +89,7 @@ assertEquals("{0:f}".format(-Infinity), "-infinity", "The 'f' type converts -Inf
assertEquals("{0:F}".format(NaN), "NAN", "The 'F' type converts NaN to 'NAN'.");
assertEquals("{0:F}".format(Infinity), "INFINITY", "The 'F' type converts Infinity to 'INFINITY'.");
assertEquals("{0:F}".format(-Infinity), "-INFINITY", "The 'F' type converts -Infinity to '-INFINITY'.");
assertEquals("{0:#f}".format(5), "5.", "The 'f' type converts a number to fixed point with a decimal when the # flag is used.");

assertEquals("{0:g}".format(5), "5", "The 'g' type converts a simple number to decimal notation.");
assertEquals("{0:G}".format(5), "5", "The 'G' type converts a simple number to decimal notation.");
Expand All @@ -99,10 +101,11 @@ assertEquals("{0:g}".format(-Infinity), "-infinity", "The 'g' type converts -Inf
assertEquals("{0:G}".format(NaN), "NAN", "The 'G' type converts NaN to 'NAN'.");
assertEquals("{0:G}".format(Infinity), "INFINITY", "The 'G' type converts Infinity to 'INFINITY'.");
assertEquals("{0:G}".format(-Infinity), "-INFINITY", "The 'G' type converts -Infinity to '-INFINITY'.");
assertEquals("{0:.2g}".format(5), "5", "The 'g' does not append trailing zeroes.");
assertEquals("{0:#.2g}".format(5), "5.00", "The 'g' does append trailing zeroes when the '#' flag is used.");
assertEquals("{0:#.2g}".format(Infinity), "infinity", "The 'g' does not append trailing zeroes to Infinity when the '#' flag is used.");
assertEquals("{0:#.2g}".format(NaN), "nan", "The 'g' does not append trailing zeroes to NaN when the '#' flag is used.");
assertEquals("{0:.2g}".format(5), "5", "The 'g' type does not append trailing zeroes.");
assertEquals("{0:#g}".format(5), "5.", "The 'g' type includes a decimal point when the # flag is used.");
assertEquals("{0:#.2g}".format(5), "5.00", "The 'g' type does append trailing zeroes when the '#' flag is used.");
assertEquals("{0:#.2g}".format(Infinity), "infinity", "The 'g' type does not append trailing zeroes to Infinity when the '#' flag is used.");
assertEquals("{0:#.2g}".format(NaN), "nan", "The 'g' type does not append trailing zeroes to NaN when the '#' flag is used.");

assertEquals("Number {0} can be presented as decimal {0:d}, octex {0:o}, hex {0:x}".format(56),
"Number 56 can be presented as decimal 56, octex 70, hex 38",
Expand Down
21 changes: 11 additions & 10 deletions ES6StringFormat.js
Expand Up @@ -2,9 +2,6 @@
* An experimental implementation of the string formatting proposal from ECMAScript 6.
* Proposal: http://wiki.ecmascript.org/doku.php?id=strawman:string_format_take_two
*
* It's not quite complete; some number formatting isn't yet there:
* - The '#' flag isn't supported
*
* (c) 2012 Rob Brackett (rob@robbrackett.com)
* This code is free to use under the terms of the accompanying LICENSE.txt file
*/
Expand Down Expand Up @@ -206,6 +203,10 @@
// FIXME: not sure if the precision specifier should apply here and how
// FIXME: not sure how to behave for Infinity and NaN. Leaving it up to toExponential()
result = value.toExponential().replace("e", " e");
// # flag forces a decimal point (not sure if this is correct or if I am misinterpreting the proposal)
if (~flags.indexOf("#")) {
result = result.replace(/^(\d*)(\se)/, "$1.$2");
}
// must have at least two digits in exponent
if ((/[+\-]\d$/).test(result)) {
result = result.slice(0, -1) + "0" + result.slice(-1);
Expand All @@ -216,17 +217,13 @@
break;
// normal or exponential notation, whichever is more appropriate for its magnitude
case "g":
result = value.toString(10).toLowerCase();
// not quite clear on whether g/G ignores the precision specifier, but it seems like # should control this?
if (~flags.indexOf("#")) {
result = applyPrecision(result);
}
break;
case "G":
result = value.toString(10).toUpperCase();
result = value.toString(10)[type === "g" ? "toLowerCase" : "toUpperCase"]();
// not quite clear on whether g/G ignores the precision specifier, but it seems like # should control this?
if (~flags.indexOf("#")) {
result = applyPrecision(result);
// # flag forces a decimal point (not sure if this is correct or if I am misinterpreting the proposal)
result = result.replace(/^(\d*)(\se|$)/i, "$1.$2");
}
break;
// fixed point
Expand All @@ -235,6 +232,10 @@
// proposal talks about INF and INFINITY, but not sure when each would be used :\
// FIXME: not sure how this should behave in the absence of a precision
result = value.toFixed(precision || 0);
// # flag forces a decimal point (not sure if this is correct or if I am misinterpreting the proposal)
if (!precision && ~flags.indexOf("#")) {
result += ".";
}
result = result[type === "f" ? "toLowerCase" : "toUpperCase"]();
break;
case "s":
Expand Down
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -77,4 +77,6 @@ In implementing this, I ran across some interesting issues:
- It is not clear how the f/F type should behave in the absence of a precision. Is it an error or does it default to some value?
- The proposal mentions both "inf/INF" and "infinity/Infinity" for the f/F type. Not when each would be used.
- Not clear on how g/G differs from the s type.
- The "#" alternate flag seems a bit odd with exponential notation. (Note it's not even allowed in Python's format(), which the proposal takes cues from.)
- The "#" alternate flag adds prefixes for octal and hexadecimal, but not for binary, which seems odd.

0 comments on commit c3b4b4e

Please sign in to comment.