sku-pg
Version:
Skulpt is a Javascript implementation of Python 2.x. Python that runs in your browser!
343 lines (311 loc) • 12.4 kB
JavaScript
var format = function (kwa) {
// following PEP 3101
var a, args, key, kwargs;
var ret;
var regex;
var index;
var replFunc;
var arg_dict = {};
Sk.builtin.pyCheckArgs("format", arguments, 0, Infinity, true, true);
args = new Sk.builtins["tuple"](Array.prototype.slice.call(arguments, 1)); /*vararg*/
kwargs = new Sk.builtins["dict"](kwa);
if (arguments[1] === undefined) {
return args.v;
}
index = 0;
regex = /{(((?:\d+)|(?:\w+))?((?:\.(\w+))|(?:\[((?:\d+)|(?:\w+))\])?))?(?:\!([rs]))?(?:\:((?:(.)?([<\>\=\^]))?([\+\-\s])?(#)?(0)?(\d+)?(,)?(?:\.(\d+))?([bcdeEfFgGnosxX%])?))?}/g;
// ex: {o.name!r:*^+#030,.9b}
// Field 1, Field_name, o.name
// Field 2, arg_name, o
// Field 3, attribute_name/Element_index , .name
// Field 4, Attribute name, name
// Field 5, element_index, [0]
// Field 6, conversion, r
// Field 7, format_spec,*^+#030,.9b
// Field 9, fill_character,*
// Field 10, fill_align, ^
// Field 11, sign, +
// Field 12, 0x, #
// Filed 13, sign-aware 0 padding, 0
// Field 14, width, 30
// Field 15, comma, ,
// Field 16, precision, .9
// Field 17, conversionType, b
// Detect empty/int/complex name
// retrive field value
// hand off format spec
// return resulting spec to function
if(kwargs.size !== 0){
var kwItems = Sk.misceval.callsim(Sk.builtin.dict.prototype["items"], kwargs);
for (var n in kwItems.v){
arg_dict[kwItems.v[n].v[0].v] = kwItems.v[n].v[1].v;
}
}
for(var i in args.v){
if(i !== "0") {
arg_dict[i-1] = args.v[i].v;
}
}
replFunc = function (substring, field_name, arg_name, attr_name, attribute_name, element_index, conversion, format_spec, fill_char, fill_align, sign, zero_pad, sign_aware, fieldWidth, comma, precision, conversionType,
offset, str_whole){
var return_str;
var formatNumber;
var formatFormat;
var result;
var base;
var value;
var handleWidth;
var alternateForm;
var precedeWithSign;
var blankBeforePositive;
var leftAdjust;
var centerAdjust;
var zeroPad;
var convName;
var convValue;
var percent;
fieldWidth = Sk.builtin.asnum$(fieldWidth);
precision = Sk.builtin.asnum$(precision);
if(element_index !== undefined && element_index !== ""){
value = arg_dict[arg_name][element_index].v;
index++;
} else if(attribute_name !== undefined && attribute_name !== ""){
value = arg_dict[arg_name][attribute_name].v;
index++;
} else if(arg_name !== undefined && arg_name !== ""){
value = arg_dict[arg_name];
index++;
} else if(field_name === undefined || field_name === ""){
return_str = arg_dict[index];
index++;
value = return_str;
} else if(field_name instanceof Sk.builtin.int_ ||
field_name instanceof Sk.builtin.float_ ||
field_name instanceof Sk.builtin.lng || !isNaN(parseInt(field_name, 10))){
return_str = arg_dict[field_name];
index++;
value = return_str;
}
if (precision === "") { // ff passes '' here aswell causing problems with G,g, etc.
precision = undefined;
}
if(fill_char === undefined || fill_char === ""){
fill_char = " ";
}
zeroPad = false;
leftAdjust = false;
centerAdjust = false;
blankBeforePositive = false;
precedeWithSign = false;
alternateForm = false;
if (format_spec) {
if(sign !== undefined && sign !== ""){
if ("-".indexOf(sign) !== -1) {
leftAdjust = true;
} else if ("+".indexOf(sign) !== -1) {
precedeWithSign = true;
} else if (" ".indexOf(sign) !== -1) {
blankBeforePositive = true;
}
}
if(zero_pad){
alternateForm = "#".indexOf(zero_pad) !== -1;
}
if(fieldWidth !== undefined && fieldWidth !== ""){
if(fill_char === undefined || fill_char === ""){
fill_char = " ";
}
}
if("%".indexOf(conversionType) !== -1){
percent = true;
}
}
if (precision) {
precision = parseInt(precision, 10);
}
formatFormat = function(value){
var r;
var s;
if(conversion === undefined || conversion === ""){
return value;
} else if( conversion == "r"){
s = new Sk.builtin.str(value);
r = Sk.builtin.repr(s);
return r.v;
} else if(conversion == "s"){
r = new Sk.builtin.str(value);
return r.v;
}
};
handleWidth = function (prefix, r) {
// print(prefix);
var totLen;
var j;
if(percent){
r = r +"%";
}
if (fieldWidth !== undefined && fieldWidth !== "") {
fieldWidth = parseInt(fieldWidth, 10);
totLen = r.length + prefix.length;
if (zeroPad) {
for (j = totLen; j < fieldWidth; ++j) {
r = "0" + r;
}
} else if (leftAdjust) {
for (j = totLen; j < fieldWidth; ++j) {
r = r + fill_char;
}
} else if(">".indexOf(fill_align) !== -1){
for (j = totLen; j < fieldWidth; ++j) {
prefix = fill_char + prefix;
}
} else if("^".indexOf(fill_align) !== -1){
for (j = totLen; j < fieldWidth; ++j) {
if(j % 2 === 0){
prefix = fill_char + prefix;
} else if ( j % 2 === 1){
r = r + fill_char;
}
}
} else if("=".indexOf(fill_align) !== -1){
for (j = totLen; j < fieldWidth; ++j) {
r = fill_char + r;
}
} else{
for (j = totLen; j < fieldWidth; ++j) {
r = r + fill_char;
}
}
}
return formatFormat(prefix + r);
};
formatNumber = function(n, base){
var precZeroPadded;
var prefix;
var neg;
var r;
base = Sk.builtin.asnum$(base);
neg = false;
if(format_spec === undefined){
return formatFormat(value);
}
if (typeof n === "number" && !(precision)) {
if (n < 0) {
n = -n;
neg = true;
}
r = n.toString(base);
} else if (precision) {
if (n < 0) {
n = -n;
neg = true;
}
n = Number(n.toString(base));
r = n.toFixed(precision);
} else if (n instanceof Sk.builtin.float_) {
r = n.str$(base, false);
if (r.length > 2 && r.substr(-2) === ".0") {
r = r.substr(0, r.length - 2);
}
neg = n.nb$isnegative();
} else if (n instanceof Sk.builtin.int_) {
r = n.str$(base, false);
neg = n.nb$isnegative();
} else if (n instanceof Sk.builtin.lng) {
r = n.str$(base, false);
neg = n.nb$isnegative(); // neg = n.size$ < 0; RNL long.js change
} else{
r = n;
}
precZeroPadded = false;
prefix = "";
if (neg) {
prefix = "-";
} else if (precedeWithSign) {
prefix = "+" ;
} else if (blankBeforePositive) {
prefix = " " ;
}
if (alternateForm) {
if (base === 16) {
prefix += "0x";
} else if (base === 8 && !precZeroPadded && r !== "0") {
prefix += "0o";
} else if (base === 2 && !precZeroPadded && r !== "0"){
prefix += "0b";
}
}
if(conversionType === "n"){
r=r.toLocaleString();
} else if(",".indexOf(comma) !== -1){
var parts = r.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
r = parts.join(".");
}
return handleWidth(prefix, r);
};
base = 10;
if(conversionType === "d" || conversionType === "n" || conversionType === "" || conversionType === undefined){
return formatNumber(value, 10);
}else if (conversionType === "b") {
return formatNumber(value, 2);
}else if (conversionType === "o") {
return formatNumber(value, 8);
} else if (conversionType === "x") {
return formatNumber(value, 16);
} else if (conversionType === "X") {
return formatNumber(value, 16).toUpperCase();
} else if (conversionType === "f" || conversionType === "F" || conversionType === "e" || conversionType === "E" || conversionType === "g" || conversionType === "G") {
if(alternateForm){
throw new Sk.builtin.ValueError("Alternate form (#) not allowed in float format specifier");
}
convValue = Sk.builtin.asnum$(value);
if (typeof convValue === "string") {
convValue = Number(convValue);
}
if (convValue === Infinity) {
return handleWidth("","inf");
}
if (convValue === -Infinity) {
return handleWidth("-","inf");
}
if (isNaN(convValue)) {
return handleWidth("","nan");
}
convName = ["toExponential", "toFixed", "toPrecision"]["efg".indexOf(conversionType.toLowerCase())];
if (precision === undefined || precision === "") {
if (conversionType === "e" || conversionType === "E" || conversionType === "%") {
precision = parseInt(6, 10);
} else if (conversionType === "f" || conversionType === "F") {
precision = parseInt(6, 10);
}
}
result = (convValue)[convName](precision);
if ("EFG".indexOf(conversionType) !== -1) {
result = result.toUpperCase();
}
return formatNumber(result, 10);
} else if (conversionType === "c") {
if (typeof value === "number") {
return handleWidth("", String.fromCharCode(value));
} else if (value instanceof Sk.builtin.int_) {
return handleWidth("", String.fromCharCode(value.v));
} else if (value instanceof Sk.builtin.float_) {
return handleWidth("", String.fromCharCode(value.v));
} else if (value instanceof Sk.builtin.lng) {
return handleWidth("", String.fromCharCode(value.str$(10, false)[0]));
} else if (value.constructor === Sk.builtin.str) {
return handleWidth("", value.v.substr(0, 1));
} else {
throw new Sk.builtin.TypeError("an integer is required");
}
} else if (percent) {
if(precision === undefined){precision = parseInt(7,10);}
return formatNumber(value*100, 10);
}
};
ret = args.v[0].v.replace(regex, replFunc);
return new Sk.builtin.str(ret);
};
format["co_kwargs"] = true;
Sk.builtin.str.prototype["format"] = new Sk.builtin.func(format);