Skip to content

Commit

Permalink
util: add %i and %f formatting specifiers
Browse files Browse the repository at this point in the history
This change brings formatting specifiers available in `util.format` and
consequently, `console.*` closer to what is supported in all major
browsers.

- `%i` is introduced to format integer values.
- `%f` is introduced to format floating point values.

Fixes: #10292
PR-URL: #10308
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
silverwind authored and MylesBorins committed Jan 15, 2018
1 parent 00b2790 commit 7af1ad0
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 10 deletions.
4 changes: 3 additions & 1 deletion doc/api/util.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ Each placeholder token is replaced with the converted value from the
corresponding argument. Supported placeholders are:

* `%s` - String.
* `%d` - Number (both integer and float).
* `%d` - Number (integer or floating point value).
* `%i` - Integer.
* `%f` - Floating point value.
* `%j` - JSON. Replaced with the string `'[Circular]'` if the argument
contains circular references.
* `%%` - single percent sign (`'%'`). This does not consume an argument.
Expand Down
16 changes: 16 additions & 0 deletions lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,22 @@ exports.format = function(f) {
str += Number(arguments[a++]);
lastPos = i = i + 2;
continue;
case 105: // 'i'
if (a >= argLen)
break;
if (lastPos < i)
str += f.slice(lastPos, i);
str += parseInt(arguments[a++]);
lastPos = i = i + 2;
continue;
case 102: // 'f'
if (a >= argLen)
break;
if (lastPos < i)
str += f.slice(lastPos, i);
str += parseFloat(arguments[a++]);
lastPos = i = i + 2;
continue;
case 106: // 'j'
if (a >= argLen)
break;
Expand Down
46 changes: 37 additions & 9 deletions test/parallel/test-util-format.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,51 @@ assert.throws(function() {
util.format('%d', symbol);
}, /^TypeError: Cannot convert a Symbol value to a number$/);

// Number format specifier
assert.strictEqual(util.format('%d'), '%d');
assert.strictEqual(util.format('%d', 42.0), '42');
assert.strictEqual(util.format('%d', 42), '42');
assert.strictEqual(util.format('%s', 42), '42');
assert.strictEqual(util.format('%j', 42), '42');

assert.strictEqual(util.format('%d', '42.0'), '42');
assert.strictEqual(util.format('%d', '42'), '42');
assert.strictEqual(util.format('%s', '42'), '42');
assert.strictEqual(util.format('%j', '42'), '"42"');
assert.strictEqual(util.format('%d', '42.0'), '42');
assert.strictEqual(util.format('%d', 1.5), '1.5');
assert.strictEqual(util.format('%d', -0.5), '-0.5');
assert.strictEqual(util.format('%d', ''), '0');

assert.strictEqual(util.format('%%s%s', 'foo'), '%sfoo');
// Integer format specifier
assert.strictEqual(util.format('%i'), '%i');
assert.strictEqual(util.format('%i', 42.0), '42');
assert.strictEqual(util.format('%i', 42), '42');
assert.strictEqual(util.format('%i', '42'), '42');
assert.strictEqual(util.format('%i', '42.0'), '42');
assert.strictEqual(util.format('%i', 1.5), '1');
assert.strictEqual(util.format('%i', -0.5), '0');
assert.strictEqual(util.format('%i', ''), 'NaN');

// Float format specifier
assert.strictEqual(util.format('%f'), '%f');
assert.strictEqual(util.format('%f', 42.0), '42');
assert.strictEqual(util.format('%f', 42), '42');
assert.strictEqual(util.format('%f', '42'), '42');
assert.strictEqual(util.format('%f', '42.0'), '42');
assert.strictEqual(util.format('%f', 1.5), '1.5');
assert.strictEqual(util.format('%f', -0.5), '-0.5');
assert.strictEqual(util.format('%f', Math.PI), '3.141592653589793');
assert.strictEqual(util.format('%f', ''), 'NaN');

// String format specifier
assert.strictEqual(util.format('%s'), '%s');
assert.strictEqual(util.format('%s', undefined), 'undefined');
assert.strictEqual(util.format('%s', 'foo'), 'foo');
assert.strictEqual(util.format('%s', 42), '42');
assert.strictEqual(util.format('%s', '42'), '42');

// JSON format specifier
assert.strictEqual(util.format('%j'), '%j');
assert.strictEqual(util.format('%j', 42), '42');
assert.strictEqual(util.format('%j', '42'), '"42"');

// Various format specifiers
assert.strictEqual(util.format('%%s%s', 'foo'), '%sfoo');
assert.strictEqual(util.format('%s:%s'), '%s:%s');
assert.strictEqual(util.format('%s:%s', undefined), 'undefined:%s');
assert.strictEqual(util.format('%s:%s', 'foo'), 'foo:%s');
Expand All @@ -50,11 +80,9 @@ assert.strictEqual(util.format('%s:%s', 'foo', 'bar', 'baz'), 'foo:bar baz');
assert.strictEqual(util.format('%%%s%%', 'hi'), '%hi%');
assert.strictEqual(util.format('%%%s%%%%', 'hi'), '%hi%%');
assert.strictEqual(util.format('%sbc%%def', 'a'), 'abc%def');

assert.strictEqual(util.format('%d:%d', 12, 30), '12:30');
assert.strictEqual(util.format('%d:%d', 12), '12:%d');
assert.strictEqual(util.format('%d:%d'), '%d:%d');

assert.strictEqual(util.format('o: %j, a: %j', {}, []), 'o: {}, a: []');
assert.strictEqual(util.format('o: %j, a: %j', {}), 'o: {}, a: %j');
assert.strictEqual(util.format('o: %j, a: %j'), 'o: %j, a: %j');
Expand Down

0 comments on commit 7af1ad0

Please sign in to comment.