Skip to content

Instantly share code, notes, and snippets.

@lwr
Last active February 19, 2020 09:58
Show Gist options
  • Save lwr/c1d1eac41eb37a0b079a to your computer and use it in GitHub Desktop.
Save lwr/c1d1eac41eb37a0b079a to your computer and use it in GitHub Desktop.
String.format
String.format = function(pattern/*, args ... */) {
var result = "";
function parse() {
// %[argument_index$][flags][width][.precision][conversion]
// $0 - the entire matched part
// $1 - argument_index '$'
// $2 - flags
// $3 - width
// $4 - '.' precision
// $5 - 't' 'T' prefix for conversion
// $6 - conversion char
var specifier = /%(\d+\$)?([-#+ 0,(<]*)?(\d+)?(\.\d+)?([tT])?([a-zA-Z%])/;
var s = pattern || "";
var fsa = [];
var sa;
while (sa = specifier.exec(s)) {
if (sa.index > 0) {
fsa.push(new FormatString(s.substring(0, sa.index)));
}
fsa.push(new FormatString(sa));
s = s.substring(sa.index + sa[0].length);
}
if (s) {
fsa.push(new FormatString(s));
}
return fsa;
}
function FormatString(sa) {
this.index = 0; // ordinal index
var fixedText;
if (typeof sa == "string") { // fixed string
this.index = -2; // fixed string
fixedText = sa; // should check Text
} else {
if (sa[1]) { // %1$
this.index = parseInt(sa[1].substring(0, sa[1].length - 1));
} else if ((sa[2] || "").indexOf('<') != -1) {
this.index = -1; // relative index
} else if (sa[6] == '%') {
this.index = -2;
fixedText = "%"
}
}
this.print = function(arg) {
if (fixedText) {
result += fixedText;
} else if (arg != null) {
// todo: specifier format argument
result += arg;
}
}
}
var args = arguments;
var ordinalIndex = 0;
var lastIndex = -1;
parse().forEach(function (fs){
switch (fs.index) {
case -2: // fixed string, "%n", or "%%"
fs.print(null);
break;
case 0: // ordinary index
lastIndex = ++ordinalIndex;
fs.print(args[lastIndex]);
break;
case -1: // relative index
fs.print(args[lastIndex]);
break;
default: // explicit index
lastIndex = fs.index;
fs.print(args[lastIndex]);
break;
}
});
return result;
};
(function() {
function assertEquals(a,b) {if (a != b) console.log(a + " != " + b)}
assertEquals(String.format("%s,%s,%s", 1,2,3) , "1,2,3");
assertEquals(String.format("%d,%d,%d", 1,2,3) , "1,2,3");
assertEquals(String.format("%3$s,%2$s,%1$s", 1,2,3) , "3,2,1");
assertEquals(String.format("%3$d,%2$d,%1$d", 1,2,3) , "3,2,1");
assertEquals(String.format("%s,%s,%%", 1,2,3) , "1,2,%");
assertEquals(String.format("%d xxx %d z%% %s", 1,2) , "1 xxx 2 z% ");
console.log("test finished");
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment