diff --git a/Readme.md b/Readme.md index a263889..ed516e6 100644 --- a/Readme.md +++ b/Readme.md @@ -35,11 +35,12 @@ Supported format specifiers: b, c, d, f, o, s, x, and X. See `man 3 printf` or `man 1 printf` for details. +Precision is supported for floating point numbers. License ======= -Copyright 2010 - 2013 Sami Samhuri sami@samhuri.net +Copyright 2010 - 2014 Sami Samhuri sami@samhuri.net [MIT license](http://sjs.mit-license.org) diff --git a/component.json b/component.json index 5db4b6a..e151f26 100644 --- a/component.json +++ b/component.json @@ -3,7 +3,7 @@ "repo": "samsonjs/format", "description": "printf, sprintf, and vsprintf for JavaScript", "keywords": ["format", "printf", "sprintf", "vsprintf", "string"], - "version": "0.2.1", + "version": "0.2.2", "main": "format.js", "scripts": ["format.js"] } diff --git a/format.js b/format.js index dafa89e..b035911 100644 --- a/format.js +++ b/format.js @@ -49,12 +49,16 @@ , c , escaped = false , arg + , tmp + , leadingZero = false , precision , nextArg = function() { return args[argIndex++]; } , slurpNumber = function() { var digits = ''; - while (fmt[i].match(/\d/)) + while (/\d/.test(fmt[i])) { digits += fmt[i++]; + c = fmt[i]; + } return digits.length > 0 ? parseInt(digits) : null; } ; @@ -62,6 +66,18 @@ c = fmt[i]; if (escaped) { escaped = false; + if (c == '.') { + leadingZero = false; + c = fmt[++i]; + } + else if (c == '0' && fmt[i + 1] == '.') { + leadingZero = true; + i += 2; + c = fmt[i]; + } + else { + leadingZero = true; + } precision = slurpNumber(); switch (c) { case 'b': // number in binary @@ -78,7 +94,8 @@ result += parseInt(nextArg(), 10); break; case 'f': // floating point number - result += parseFloat(nextArg()).toFixed(precision || 6); + tmp = String(parseFloat(nextArg()).toFixed(precision || 6)); + result += leadingZero ? tmp : tmp.replace(/^0/, ''); break; case 'o': // number in octal result += '0' + parseInt(nextArg(), 10).toString(8); diff --git a/package.json b/package.json index 13772a3..5cf5f42 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "format", "description": "printf, sprintf, and vsprintf for JavaScript", - "version": "0.2.1", + "version": "0.2.2", "homepage": "http://samhuri.net/proj/format", "author": "Sami Samhuri ", "repository": { diff --git a/test_format.js b/test_format.js index e185004..b7a7dee 100644 --- a/test_format.js +++ b/test_format.js @@ -3,23 +3,50 @@ var filename = process.argv[2] || './format.js' , printf = format.printf ; -console.log('Testing printf:'); -printf('hello'); -console.log('(expected "hello")'); -printf('hello %s', 'sami'); -console.log('(expected "hello sami")'); -printf('b: %b\nc: %c\nd: %d\nf: %f\no: %o\ns: %s\nx: %x\nX: %X', 42, 65, 42*42, 42*42*42/1000000000, 255, 'sami', 0xfeedface, 0xc0ffee); -console.log('(expected "b: 101010\nc: A\nd: 1764\nf: 0.000074\no: 0377\ns: sami\nx: 0xfeedface\nX: 0xC0FFEE")'); -console.log('(passed if the output looks ok)'); +function desc(x, indentLevel) { + indentLevel = indentLevel || 0; + var indent = new Array(indentLevel).join(' '); + if (typeof x == 'string' || (x && x.__proto__ == String.prototype)) { + return indent + '"' + x + '"'; + } + else if (Array.isArray(x)) { + return indent + '[ ' + x.map(desc).join(', ') + ' ]'; + } + else { + return '' + x; + } +} -function assertEqual(a, b) { - if (a !== b) throw new Error('assertion failed, ' + a + ' !== ' + b); +function assertFormat(args, expected) { + var fmt = args[0]; + var result = format.format.apply(format, args); + if (result !== expected) { + console.log('FORMAT: "' + fmt + '"'); + console.log('ARGS: ' + desc(args.slice(1))); + console.log('RESULT: "' + result + '"'); + throw new Error('assertion failed, ' + result + ' !== ' + expected); + } } console.log('Testing format:'); -assertEqual(format.format('hello'), 'hello'); -assertEqual(format.format('hello %s', 'sami'), 'hello sami'); -assertEqual(format.format('b: %b\nc: %c\nd: %d\nf: %f\no: %o\ns: %s\nx: %x\nX: %X', 42, 65, 42*42, 42*42*42/1000000000, 255, 'sami', 0xfeedface, 0xc0ffee), "b: 101010\nc: A\nd: 1764\nf: 0.000074\no: 0377\ns: sami\nx: 0xfeedface\nX: 0xC0FFEE"); -console.log('(pass)'); + +var tests = [ + [['hello'], 'hello'], + [['hello %s', 'sami'], 'hello sami'], + [ + ['b: %b\nc: %c\nd: %d\nf: %f\no: %o\ns: %s\nx: %x\nX: %X', 42, 65, 42*42, 42*42*42/1000000000, 255, 'sami', 0xfeedface, 0xc0ffee], + "b: 101010\nc: A\nd: 1764\nf: 0.000074\no: 0377\ns: sami\nx: 0xfeedface\nX: 0xC0FFEE" + ], + [['%.2f', 3.14159], '3.14'], + [['%0.2f', 3.14159], '3.14'], + [['%.2f', 0.1234], '.12'], + [['%0.2f', 0.1234], '0.12'] +]; +tests.forEach(function(spec) { + var args = spec[0]; + var expected = spec[1]; + assertFormat(args, expected); + console.log('pass (format ' + args[0] + ' == ' + expected + ')'); +}); console.log('all passed');