[format] Add 'x' format specifier and field width

Sometimes it is useful to print numbers in hex format - add the
appropriate specifier. Also support a minimum field width to
pad the formatted string with spaces (or zeros if the width is
prefixed with '0').

https://bugzilla.gnome.org/show_bug.cgi?id=622597
This commit is contained in:
Florian Müllner 2010-06-23 23:46:59 +02:00
parent 83689e494c
commit a84e2e3307
2 changed files with 31 additions and 8 deletions

View File

@ -6,8 +6,10 @@
* It has to be set up using String.prototype.format = Format.format; * It has to be set up using String.prototype.format = Format.format;
* Usage: * Usage:
* "somestring %s %d".format('hello', 5); * "somestring %s %d".format('hello', 5);
* It supports %s, %d and %f, for %f it also support precisions like * It supports %s, %d, %x and %f, for %f it also support precisions like
* "%.2f".format(1.526) * "%.2f".format(1.526). All specifiers can be prefixed with a minimum
* field width, e.g. "%5s".format("foo"). Unless the width is prefixed
* with '0', the formatted string will be padded with spaces.
*/ */
function format() { function format() {
@ -15,30 +17,44 @@ function format() {
let i = 0; let i = 0;
let args = arguments; let args = arguments;
return str.replace(/%(?:\.([0-9]+))?(.)/g, function (str, precisionGroup, genericGroup) { return str.replace(/%([0-9]+)?(?:\.([0-9]+))?(.)/g, function (str, widthGroup, precisionGroup, genericGroup) {
if (precisionGroup != '' && genericGroup != 'f') if (precisionGroup != '' && genericGroup != 'f')
throw new Error("Precision can only be specified for 'f'"); throw new Error("Precision can only be specified for 'f'");
let fillChar = (widthGroup[0] == '0') ? '0' : ' ';
let width = parseInt(widthGroup, 10) || 0;
function fillWidth(s, c, w) {
let fill = '';
for (let i = 0; i < w; i++)
fill += c;
return fill.substr(s.length) + s;
}
let s = '';
switch (genericGroup) { switch (genericGroup) {
case '%': case '%':
return '%'; return '%';
break; break;
case 's': case 's':
return args[i++].toString(); s = args[i++].toString();
break; break;
case 'd': case 'd':
return parseInt(args[i++]); s = parseInt(args[i++]).toString();
break;
case 'x':
s = parseInt(args[i++]).toString(16);
break; break;
case 'f': case 'f':
if (precisionGroup == '') if (precisionGroup == '')
return parseFloat(args[i++]); s = parseFloat(args[i++]).toString();
else else
return parseFloat(args[i++]).toFixed(parseInt(precisionGroup)); s = parseFloat(args[i++]).toFixed(parseInt(precisionGroup));
break; break;
default: default:
throw new Error('Unsupported conversion character %' + genericGroup); throw new Error('Unsupported conversion character %' + genericGroup);
} }
return ""; // Suppress warning return fillWidth(s, fillChar, width);
}); });
} }

View File

@ -20,8 +20,15 @@ assertEquals("%s", "%%s".format('foo'));
assertEquals("%%s", "%%%%s".format('foo')); assertEquals("%%s", "%%%%s".format('foo'));
assertEquals("foo 5", "%s %d".format('foo', 5)); assertEquals("foo 5", "%s %d".format('foo', 5));
assertEquals("8", "%d".format(8)); assertEquals("8", "%d".format(8));
assertEquals("f", "%x".format(15));
assertEquals("2.58 6.96", "%f %.2f".format(2.58, 6.958)); assertEquals("2.58 6.96", "%f %.2f".format(2.58, 6.958));
// Test field width
assertEquals("007 foo", "%03d %4s".format(7, 'foo'));
assertEquals(" 2.58 06.96", "%5f %05.2f".format(2.58, 6.958));
assertEquals("cafe", "%2x".format(0xcafe));
assertEquals("foo", "%0s".format('foo'));
// Precision is only allowed for %f // Precision is only allowed for %f
assertRaises(function() { "%.2d".format(5.21) }); assertRaises(function() { "%.2d".format(5.21) });