formatting.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. var format = function (kwa) {
  2. // following PEP 3101
  3. var a, args, key, kwargs;
  4. var ret;
  5. var regex;
  6. var index;
  7. var replFunc;
  8. var arg_dict = {};
  9. Sk.builtin.pyCheckArgs("format", arguments, 0, Infinity, true, true);
  10. args = new Sk.builtins["tuple"](Array.prototype.slice.call(arguments, 1)); /*vararg*/
  11. kwargs = new Sk.builtins["dict"](kwa);
  12. if (arguments[1] === undefined) {
  13. return args.v;
  14. }
  15. index = 0;
  16. regex = /{(((?:\d+)|(?:\w+))?((?:\.(\w+))|(?:\[((?:\d+)|(?:\w+))\])?))?(?:\!([rs]))?(?:\:((?:(.)?([<\>\=\^]))?([\+\-\s])?(#)?(0)?(\d+)?(,)?(?:\.(\d+))?([bcdeEfFgGnosxX%])?))?}/g;
  17. // ex: {o.name!r:*^+#030,.9b}
  18. // Field 1, Field_name, o.name
  19. // Field 2, arg_name, o
  20. // Field 3, attribute_name/Element_index , .name
  21. // Field 4, Attribute name, name
  22. // Field 5, element_index, [0]
  23. // Field 6, conversion, r
  24. // Field 7, format_spec,*^+#030,.9b
  25. // Field 9, fill_character,*
  26. // Field 10, fill_align, ^
  27. // Field 11, sign, +
  28. // Field 12, 0x, #
  29. // Filed 13, sign-aware 0 padding, 0
  30. // Field 14, width, 30
  31. // Field 15, comma, ,
  32. // Field 16, precision, .9
  33. // Field 17, conversionType, b
  34. // Detect empty/int/complex name
  35. // retrive field value
  36. // hand off format spec
  37. // return resulting spec to function
  38. if(kwargs.size !== 0){
  39. var kwItems = Sk.misceval.callsim(Sk.builtin.dict.prototype["items"], kwargs);
  40. for (var n in kwItems.v){
  41. arg_dict[kwItems.v[n].v[0].v] = kwItems.v[n].v[1].v;
  42. }
  43. }
  44. for(var i in args.v){
  45. if(i !== "0") {
  46. arg_dict[i-1] = args.v[i].v;
  47. }
  48. }
  49. 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,
  50. offset, str_whole){
  51. var return_str;
  52. var formatNumber;
  53. var formatFormat;
  54. var result;
  55. var base;
  56. var value;
  57. var handleWidth;
  58. var alternateForm;
  59. var precedeWithSign;
  60. var blankBeforePositive;
  61. var leftAdjust;
  62. var centerAdjust;
  63. var zeroPad;
  64. var convName;
  65. var convValue;
  66. var percent;
  67. fieldWidth = Sk.builtin.asnum$(fieldWidth);
  68. precision = Sk.builtin.asnum$(precision);
  69. if(element_index !== undefined && element_index !== ""){
  70. value = arg_dict[arg_name][element_index].v;
  71. index++;
  72. } else if(attribute_name !== undefined && attribute_name !== ""){
  73. value = arg_dict[arg_name][attribute_name].v;
  74. index++;
  75. } else if(arg_name !== undefined && arg_name !== ""){
  76. value = arg_dict[arg_name];
  77. index++;
  78. } else if(field_name === undefined || field_name === ""){
  79. return_str = arg_dict[index];
  80. index++;
  81. value = return_str;
  82. } else if(field_name instanceof Sk.builtin.int_ ||
  83. field_name instanceof Sk.builtin.float_ ||
  84. field_name instanceof Sk.builtin.lng || !isNaN(parseInt(field_name, 10))){
  85. return_str = arg_dict[field_name];
  86. index++;
  87. value = return_str;
  88. }
  89. if (precision === "") { // ff passes '' here aswell causing problems with G,g, etc.
  90. precision = undefined;
  91. }
  92. if(fill_char === undefined || fill_char === ""){
  93. fill_char = " ";
  94. }
  95. zeroPad = false;
  96. leftAdjust = false;
  97. centerAdjust = false;
  98. blankBeforePositive = false;
  99. precedeWithSign = false;
  100. alternateForm = false;
  101. if (format_spec) {
  102. if(sign !== undefined && sign !== ""){
  103. if ("-".indexOf(sign) !== -1) {
  104. leftAdjust = true;
  105. } else if ("+".indexOf(sign) !== -1) {
  106. precedeWithSign = true;
  107. } else if (" ".indexOf(sign) !== -1) {
  108. blankBeforePositive = true;
  109. }
  110. }
  111. if(zero_pad){
  112. alternateForm = "#".indexOf(zero_pad) !== -1;
  113. }
  114. if(fieldWidth !== undefined && fieldWidth !== ""){
  115. if(fill_char === undefined || fill_char === ""){
  116. fill_char = " ";
  117. }
  118. }
  119. if("%".indexOf(conversionType) !== -1){
  120. percent = true;
  121. }
  122. }
  123. if (precision) {
  124. precision = parseInt(precision, 10);
  125. }
  126. formatFormat = function(value){
  127. var r;
  128. var s;
  129. if(conversion === undefined || conversion === ""){
  130. return value;
  131. } else if( conversion == "r"){
  132. s = new Sk.builtin.str(value);
  133. r = Sk.builtin.repr(s);
  134. return r.v;
  135. } else if(conversion == "s"){
  136. r = new Sk.builtin.str(value);
  137. return r.v;
  138. }
  139. };
  140. handleWidth = function (prefix, r) {
  141. // print(prefix);
  142. var totLen;
  143. var j;
  144. if(percent){
  145. r = r +"%";
  146. }
  147. if (fieldWidth !== undefined && fieldWidth !== "") {
  148. fieldWidth = parseInt(fieldWidth, 10);
  149. totLen = r.length + prefix.length;
  150. if (zeroPad) {
  151. for (j = totLen; j < fieldWidth; ++j) {
  152. r = "0" + r;
  153. }
  154. } else if (leftAdjust) {
  155. for (j = totLen; j < fieldWidth; ++j) {
  156. r = r + fill_char;
  157. }
  158. } else if(">".indexOf(fill_align) !== -1){
  159. for (j = totLen; j < fieldWidth; ++j) {
  160. prefix = fill_char + prefix;
  161. }
  162. } else if("^".indexOf(fill_align) !== -1){
  163. for (j = totLen; j < fieldWidth; ++j) {
  164. if(j % 2 === 0){
  165. prefix = fill_char + prefix;
  166. } else if ( j % 2 === 1){
  167. r = r + fill_char;
  168. }
  169. }
  170. } else if("=".indexOf(fill_align) !== -1){
  171. for (j = totLen; j < fieldWidth; ++j) {
  172. r = fill_char + r;
  173. }
  174. } else{
  175. for (j = totLen; j < fieldWidth; ++j) {
  176. r = r + fill_char;
  177. }
  178. }
  179. }
  180. return formatFormat(prefix + r);
  181. };
  182. formatNumber = function(n, base){
  183. var precZeroPadded;
  184. var prefix;
  185. var neg;
  186. var r;
  187. base = Sk.builtin.asnum$(base);
  188. neg = false;
  189. if(format_spec === undefined){
  190. return formatFormat(value);
  191. }
  192. if (typeof n === "number" && !(precision)) {
  193. if (n < 0) {
  194. n = -n;
  195. neg = true;
  196. }
  197. r = n.toString(base);
  198. } else if (precision) {
  199. if (n < 0) {
  200. n = -n;
  201. neg = true;
  202. }
  203. n = Number(n.toString(base));
  204. r = n.toFixed(precision);
  205. } else if (n instanceof Sk.builtin.float_) {
  206. r = n.str$(base, false);
  207. if (r.length > 2 && r.substr(-2) === ".0") {
  208. r = r.substr(0, r.length - 2);
  209. }
  210. neg = n.nb$isnegative();
  211. } else if (n instanceof Sk.builtin.int_) {
  212. r = n.str$(base, false);
  213. neg = n.nb$isnegative();
  214. } else if (n instanceof Sk.builtin.lng) {
  215. r = n.str$(base, false);
  216. neg = n.nb$isnegative(); // neg = n.size$ < 0; RNL long.js change
  217. } else{
  218. r = n;
  219. }
  220. precZeroPadded = false;
  221. prefix = "";
  222. if (neg) {
  223. prefix = "-";
  224. } else if (precedeWithSign) {
  225. prefix = "+" ;
  226. } else if (blankBeforePositive) {
  227. prefix = " " ;
  228. }
  229. if (alternateForm) {
  230. if (base === 16) {
  231. prefix += "0x";
  232. } else if (base === 8 && !precZeroPadded && r !== "0") {
  233. prefix += "0o";
  234. } else if (base === 2 && !precZeroPadded && r !== "0"){
  235. prefix += "0b";
  236. }
  237. }
  238. if(conversionType === "n"){
  239. r=r.toLocaleString();
  240. } else if(",".indexOf(comma) !== -1){
  241. var parts = r.toString().split(".");
  242. parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  243. r = parts.join(".");
  244. }
  245. return handleWidth(prefix, r);
  246. };
  247. base = 10;
  248. if(conversionType === "d" || conversionType === "n" || conversionType === "" || conversionType === undefined){
  249. return formatNumber(value, 10);
  250. }else if (conversionType === "b") {
  251. return formatNumber(value, 2);
  252. }else if (conversionType === "o") {
  253. return formatNumber(value, 8);
  254. } else if (conversionType === "x") {
  255. return formatNumber(value, 16);
  256. } else if (conversionType === "X") {
  257. return formatNumber(value, 16).toUpperCase();
  258. } else if (conversionType === "f" || conversionType === "F" || conversionType === "e" || conversionType === "E" || conversionType === "g" || conversionType === "G") {
  259. if(alternateForm){
  260. throw new Sk.builtin.ValueError("Alternate form (#) not allowed in float format specifier");
  261. }
  262. convValue = Sk.builtin.asnum$(value);
  263. if (typeof convValue === "string") {
  264. convValue = Number(convValue);
  265. }
  266. if (convValue === Infinity) {
  267. return handleWidth("","inf");
  268. }
  269. if (convValue === -Infinity) {
  270. return handleWidth("-","inf");
  271. }
  272. if (isNaN(convValue)) {
  273. return handleWidth("","nan");
  274. }
  275. convName = ["toExponential", "toFixed", "toPrecision"]["efg".indexOf(conversionType.toLowerCase())];
  276. if (precision === undefined || precision === "") {
  277. if (conversionType === "e" || conversionType === "E" || conversionType === "%") {
  278. precision = parseInt(6, 10);
  279. } else if (conversionType === "f" || conversionType === "F") {
  280. precision = parseInt(6, 10);
  281. }
  282. }
  283. result = (convValue)[convName](precision);
  284. if ("EFG".indexOf(conversionType) !== -1) {
  285. result = result.toUpperCase();
  286. }
  287. return formatNumber(result, 10);
  288. } else if (conversionType === "c") {
  289. if (typeof value === "number") {
  290. return handleWidth("", String.fromCharCode(value));
  291. } else if (value instanceof Sk.builtin.int_) {
  292. return handleWidth("", String.fromCharCode(value.v));
  293. } else if (value instanceof Sk.builtin.float_) {
  294. return handleWidth("", String.fromCharCode(value.v));
  295. } else if (value instanceof Sk.builtin.lng) {
  296. return handleWidth("", String.fromCharCode(value.str$(10, false)[0]));
  297. } else if (value.constructor === Sk.builtin.str) {
  298. return handleWidth("", value.v.substr(0, 1));
  299. } else {
  300. throw new Sk.builtin.TypeError("an integer is required");
  301. }
  302. } else if (percent) {
  303. if(precision === undefined){precision = parseInt(7,10);}
  304. return formatNumber(value*100, 10);
  305. }
  306. };
  307. ret = args.v[0].v.replace(regex, replFunc);
  308. return new Sk.builtin.str(ret);
  309. };
  310. format["co_kwargs"] = true;
  311. Sk.builtin.str.prototype["format"] = new Sk.builtin.func(format);