first attempt at an sprintf function.

This commit is contained in:
Christopher Jeffrey 2013-02-24 11:51:14 -06:00
parent b41ac01700
commit 1d2c2f182b
2 changed files with 109 additions and 3 deletions

View File

@ -7,6 +7,8 @@ var tput = Tput({
console.log('Max colors: %d.', tput.max_colors);
//process.stdout.write(Tput.sprintf('%-10s\n', 'hello'));
//console.log(tput.info);
//tput.compile();

View File

@ -551,8 +551,8 @@ Tput.prototype._compile = function(val) {
// as in printf, flags are [-+#] and space. Use a `:' to allow the
// next character to be a `-' flag, avoiding interpreting "%-" as an
// operator.
// e.g. %:-d %+d %#x %+10d
if (read(/^%(:-|[+# ])?(\d+(?:\.\d+)?)?([doxXs])/)) {
// if (read(/^%(:-|[+# ])?(\d+(?:\.\d+)?)?([doxXs])/)) {
if (read(/^%((?::-|[+# ]){1,4})?(\d+(?:\.\d+)?)?([doxXs])/)) {
// echo('sprintf("'+ cap[0].replace(':-', '-') + '", stack.pop())');
// var flag = cap[1], width = cap[2], type = cap[3];
echo('stack.pop()');
@ -968,6 +968,107 @@ function merge(a, b) {
return a;
}
/**
* sprintf
* http://www.cplusplus.com/reference/cstdio/printf/
*/
function sprintf(src) {
var params = Array.prototype.slice.call(arguments, 1)
, rule = /%([\-+# ]{1,4})?(\d+(?:\.\d+)?)?([doxXsc])/g
, i = 0;
return src.replace(rule, function(_, flag, width, type) {
var flags = flag.split('')
, param = params[i++] || ''
, initial = param
, width = +width
, opt = {}
, pre = '';
switch (type) {
case 'd': // signed int
param = (+param).toString(10);
break;
case 'o': // unsigned octal
param = (+param).toString(8);
break;
case 'x': // unsigned hex int
param = (+param).toString(16);
break;
case 'X': // unsigned hex int uppercase
param = (+param).toString(16).toUppercase();
break;
case 's': // string
break;
case 'c': // char
// Should return here?
param = isFinite(param)
? String.fromCharCode(param)
: param[0];
break;
}
flags.forEach(function(flag) {
switch (flag) {
// left-justify by width
case '-':
opt.left = true;
break;
// always precede numbers with their signs
case '+':
opt.signs = true;
break;
// used with o, x, X - value is preceded with 0, 0x, or 0X respectively.
// used with a, A, e, E, f, F, g, G - forces written output to contain
// a decimal point even if no more digits follow
case '#':
opt.hexpoint = true;
break;
// if no sign is going to be written, black space in front of the value
case ' ':
opt.space = true;
break;
}
});
if (opt.signs) {
if (+initial >= 0) {
pre += '+';
}
}
if (opt.space) {
if (!opt.signs && +initial >= 0) {
param = ' ' + param;
}
}
if (opt.hexpoint) {
switch (type) {
case 'o': // unsigned octal
pre += '0';
break;
case 'x': // unsigned hex int
pre += '0x';
break;
case 'X': // unsigned hex int uppercase
pre += '0X';
break;
}
}
if (opt.left) {
if (width > (pre.length + param.length)) {
width -= pre.length + param.length;
pre = Array(width + 1).join(' ') + pre;
}
}
return pre + param;
});
}
/**
* Aliases
*/
@ -1515,4 +1616,7 @@ Tput.strings = [
* Expose
*/
module.exports = Tput;
exports = Tput;
exports.sprintf = sprintf;
module.exports = exports;