Humberto
Humberto

Reputation: 7199

Native Javascript printf-like function

Browsers such as Chrome and Firefox offer a console API that enable the emission of formatted log messages, like this:

>>> console.log("%s has %d points", "Sam", "100");
Sam has 100 points

Now, suppose I want to generate a formatted string but not necessarily log it into the console. Do the browsers expose the native function that produces the log strings? Is it ECMA-stardard? Or should we be content with third party libraries such as JavaScript sprintf for now?

Upvotes: 8

Views: 12252

Answers (3)

Enrique Alamo
Enrique Alamo

Reputation: 61

Object.defineProperty(String.prototype, "printf",
        {
            value: function()
                {
                    var args = Array.from(arguments), i = 0;
                    function defaultNumber(iValue)
                    {
                        return ((iValue != undefined) && !isNaN(iValue) ? iValue: "0");
                    }
                    function defaultString(iValue)
                    {
                        return (iValue == undefined? "": "" + iValue);
                    }
                    return this.replace(/%%|%([+\-])?([^1-9])?(\d+)?(\.\d+)?([deEfhHioQqs])/g,
                        function (match, sign, filler, scale, precision, type)
                            {
                                var strOut, space, value;
                                var asNumber = false;
                                if (match == "%%")
                                    return "%";
                                if (i >= args.length)
                                    return match;
                                value = args[i];
                                while (Array.isArray(value))
                                {
                                    args.splice(i, 1);
                                    for (var j = i; value.length > 0; j++)
                                        args.splice(j, 0, value.shift());
                                    value = args[i];
                                }
                                i++;
                                if (filler == undefined)
                                    filler = " "; // default
                                if ((scale == undefined) && !isNaN(filler))
                                {
                                    scale = filler;
                                    filler = " ";
                                }
                                if (sign == undefined) sign = ("sqQ".indexOf(type) >= 0? "+": "-"); // default
                                if (scale == undefined) scale = 0; // default
                                if (precision == undefined) precision = ".0"; // default
                                scale = parseInt(scale);
                                precision = parseInt(precision.substr(1));
                                switch (type)
                                {
                                    case 'd':
                                    case 'i':
                                        // decimal integer
                                        asNumber = true;
                                        strOut = parseInt(defaultNumber(value));
                                        if (precision > 0)
                                            strOut += "." + "0".repeat(precision);
                                        break;
                                    case 'e':
                                    case 'E':
                                        // float in exponential notation
                                        asNumber = true;
                                        strOut = parseFloat(defaultNumber(value));
                                        if (precision == 0)
                                            strOut = strOut.toExponential();
                                        else
                                            strOut = strOut.toExponential(precision);
                                        if (type == 'E')
                                            strOut = strOut.replace('e', 'E');
                                        break;
                                    case 'f':
                                        // decimal float
                                        asNumber = true;
                                        strOut = parseFloat(defaultNumber(value));
                                        if (precision != 0)
                                            strOut = strOut.toFixed(precision);
                                        break;
                                    case 'o':
                                    case 'h':
                                    case 'H':
                                        // Octal or Hexagesimal integer notation
                                        strOut = '\\' + (type == 'o'? '0': type) +
                                            parseInt(defaultNumber(value)).toString((type == 'o'? 8: 16));
                                        break;
                                    case'q':
                                        // single quoted string
                                        strOut = "'" + defaultString(value) + "'";
                                        break;
                                    case'Q':
                                        // double quoted string
                                        strOut = '"' + defaultString(value) + '"';
                                        break;
                                    default:
                                        // string
                                        strOut = defaultString(value);
                                        break;
                                }
                                if (typeof strOut != "string")
                                    strOut = ("" + strOut);
                                if ((space = strOut.length) < scale)
                                {
                                    if (asNumber)
                                    {
                                        if (sign == "-")
                                        {
                                            if (strOut.indexOf('-') < 0)
                                                strOut = filler.repeat(scale - space) + strOut;
                                            else
                                                strOut = '-' + filler.repeat(scale - space) + strOut.replace("-","");
                                        }
                                        else
                                        {
                                            if (strOut.indexOf('-') < 0)
                                                strOut = '+' + filler.repeat(scale - space - 1) + strOut;
                                            else
                                                strOut = '-' + filler.repeat(scale - space) + strOut.replace("-","");
                                        }
                                    }
                                    else
                                    {
                                        if (sign == "-")
                                            strOut = filler.repeat(scale - space) + strOut;
                                        else
                                            strOut = strOut + filler.repeat(scale - space);
                                    }
                                }
                                else if (asNumber && (sign == '+') && (strOut.indexOf('-') < 0))
                                    strOut = '+' + strOut;
                                return strOut;
                            });
                }
        });

    Object.defineProperty(window, "printf",
        {
            value: function(str, ...rest)
            {
                if (typeof str == "string")
                    return String.prototype.printf.apply(str,rest);
                return "";
            }
        });
printf("Your Name is:%_30s your age is: %o\nyour wish is: %20q;", "Tom Johnson",48,"Lotto Numbers");

yields:

"Your Name is:Tom Johnson___________________ your age is: \\060
your wish is: 'Lotto Numbers'     ;"

You can also call it with:

"Your Name is:%_30s your age is: %o\nyour wish is: %20q;".printf("Tom Johnson",48,"Lotto Numbers");

Upvotes: 6

jacksonfiverniner
jacksonfiverniner

Reputation: 90

I don't think you can do it natively. You can write your own javascript toString function to handle the different options.

Alternatively you could do

var samuel = "sam";
var someNumber = 100;

var someString = samuel + " has " + someNumber + " points";

Upvotes: -4

Kevin Ennis
Kevin Ennis

Reputation: 14464

ES6 will introduce some basic string formatting in the form of:

`${name} has ${val} points`;

But there's currently no native string formatting in ES5.

Upvotes: 4

Related Questions