Skip to content

Instantly share code, notes, and snippets.

@Calvein
Created April 4, 2012 17:24
Show Gist options
  • Save Calvein/2304021 to your computer and use it in GitHub Desktop.
Save Calvein/2304021 to your computer and use it in GitHub Desktop.
console.sprintf()
// Sprintf from http://www.diveintojavascript.com/projects/javascript-sprintf
!function(console) {
var sprintf = (function() {
function get_type(variable) {
return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
}
var str_repeat = function(str, qty, separator){
// ~~var — is the fastest available way to convert anything to Integer in javascript.
// We'll use it extensively in this lib.
str += ''; qty = ~~qty;
for (var repeat = []; qty > 0; repeat[--qty] = str) {}
return repeat.join(separator == null ? '' : separator);
};
var str_format = function() {
if (!str_format.cache.hasOwnProperty(arguments[0][0])) {
str_format.cache[arguments[0][0]] = str_format.parse(arguments[0][0]);
}
return str_format.format.call(null, str_format.cache[arguments[0][0]], arguments[0]);
};
str_format.format = function(parse_tree, argv) {
var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
for (i = 0; i < tree_length; i++) {
node_type = get_type(parse_tree[i]);
if (node_type === 'string') {
output.push(parse_tree[i]);
}
else if (node_type === 'array') {
match = parse_tree[i]; // convenience purposes only
if (match[2]) { // keyword argument
arg = argv[cursor];
for (k = 0; k < match[2].length; k++) {
if (!arg.hasOwnProperty(match[2][k])) {
throw new Error(sprintf('[console.sprintf] property "%s" does not exist', match[2][k]));
}
arg = arg[match[2][k]];
}
} else if (match[1]) { // positional argument (explicit)
arg = argv[match[1]];
}
else { // positional argument (implicit)
arg = argv[cursor++];
}
if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
throw new Error(sprintf('[console.sprintf] expecting number but found %s', get_type(arg)));
}
switch (match[8]) {
case 'b': arg = arg.toString(2); break;
case 'c': arg = String.fromCharCode(arg); break;
case 'd': arg = parseInt(arg, 10); break;
case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
case 'o': arg = arg.toString(8); break;
case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
case 'u': arg = Math.abs(arg); break;
case 'x': arg = arg.toString(16); break;
case 'X': arg = arg.toString(16).toUpperCase(); break;
}
arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
pad_length = match[6] - String(arg).length;
pad = match[6] ? str_repeat(pad_character, pad_length) : '';
output.push(match[5] ? arg + pad : pad + arg);
}
}
if (typeof argv === 'string') {
return argv
} else {
var outputLength = output.length
return output.join('').split().concat(
[].filter.call(argv, function(arg, i) {
if (i >= outputLength)
return arg
})
)
}
};
str_format.cache = {};
str_format.parse = function(fmt) {
var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
while (_fmt) {
if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
parse_tree.push(match[0]);
}
else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
parse_tree.push('%');
}
else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
if (match[2]) {
arg_names |= 1;
var field_list = [], replacement_field = match[2], field_match = [];
if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
field_list.push(field_match[1]);
while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
field_list.push(field_match[1]);
}
else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
field_list.push(field_match[1]);
}
else {
throw new Error('[console.sprintf] huh?');
}
}
}
else {
throw new Error('[console.sprintf] huh?');
}
match[2] = field_list;
}
else {
arg_names |= 2;
}
if (arg_names === 3) {
throw new Error('[console.sprintf] mixing positional and named placeholders is not (yet) supported');
}
parse_tree.push(match);
}
else {
throw new Error('[console.sprintf] huh?');
}
_fmt = _fmt.substring(match[0].length);
}
return parse_tree;
};
return str_format;
})();
console.sprintf = function() {
console.log.apply(console, sprintf(arguments))
}
}(console)
!function(a){var b=function(){function a(a){return Object.prototype.toString.call(a).slice(8,-1).toLowerCase()}var c=function(a,b,c){a+="",b=~~b;for(var d=[];b>0;d[--b]=a);return d.join(c==null?"":c)},d=function(){return d.cache.hasOwnProperty(arguments[0][0])||(d.cache[arguments[0][0]]=d.parse(arguments[0][0])),d.format.call(null,d.cache[arguments[0][0]],arguments[0])};return d.format=function(d,e){var f=1,g=d.length,h="",i,j=[],k,l,m,n,o,p;for(k=0;k<g;k++){h=a(d[k]);if(h==="string")j.push(d[k]);else if(h==="array"){m=d[k];if(m[2]){i=e[f];for(l=0;l<m[2].length;l++){if(!i.hasOwnProperty(m[2][l]))throw new Error(b('[console.sprintf] property "%s" does not exist',m[2][l]));i=i[m[2][l]]}}else m[1]?i=e[m[1]]:i=e[f++];if(/[^s]/.test(m[8])&&a(i)!="number")throw new Error(b("[console.sprintf] expecting number but found %s",a(i)));switch(m[8]){case"b":i=i.toString(2);break;case"c":i=String.fromCharCode(i);break;case"d":i=parseInt(i,10);break;case"e":i=m[7]?i.toExponential(m[7]):i.toExponential();break;case"f":i=m[7]?parseFloat(i).toFixed(m[7]):parseFloat(i);break;case"o":i=i.toString(8);break;case"s":i=(i=String(i))&&m[7]?i.substring(0,m[7]):i;break;case"u":i=Math.abs(i);break;case"x":i=i.toString(16);break;case"X":i=i.toString(16).toUpperCase()}i=/[def]/.test(m[8])&&m[3]&&i>=0?"+"+i:i,o=m[4]?m[4]=="0"?"0":m[4].charAt(1):" ",p=m[6]-String(i).length,n=m[6]?c(o,p):"",j.push(m[5]?i+n:n+i)}}if(typeof e=="string")return e;var q=j.length;return j.join("").split().concat([].filter.call(e,function(a,b){if(b>=q)return a}))},d.cache={},d.parse=function(a){var b=a,c=[],d=[],e=0;while(b){if((c=/^[^\x25]+/.exec(b))!==null)d.push(c[0]);else if((c=/^\x25{2}/.exec(b))!==null)d.push("%");else{if((c=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(b))===null)throw new Error("[console.sprintf] huh?");if(c[2]){e|=1;var f=[],g=c[2],h=[];if((h=/^([a-z_][a-z_\d]*)/i.exec(g))===null)throw new Error("[console.sprintf] huh?");f.push(h[1]);while((g=g.substring(h[0].length))!=="")if((h=/^\.([a-z_][a-z_\d]*)/i.exec(g))!==null)f.push(h[1]);else{if((h=/^\[(\d+)\]/.exec(g))===null)throw new Error("[console.sprintf] huh?");f.push(h[1])}c[2]=f}else e|=2;if(e===3)throw new Error("[console.sprintf] mixing positional and named placeholders is not (yet) supported");d.push(c)}b=b.substring(c[0].length)}return d},d}();a.sprintf=function(){a.log.apply(a,b(arguments))}}(console);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment