Permalink
Jan 14, 2015
Jan 14, 2015
Jan 1, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 1, 2015
Jan 1, 2015
Newer
100644
1687 lines (1511 sloc)
52.9 KB
13
function normalize_start_end($){
14
if($.start===null||$.start===_b_.None){$.start = 0}
15
else if($.start<0){$.start += $.self.length; $.start=Math.max(0, $.start)}
16
if($.end===null||$.end===_b_.None){$.end = $.self.length}
17
else if($.end<0){$.end += $.self.length; $.end=Math.max(0, $.end)}
18
19
if(!isinstance($.start,_b_.int)||!isinstance($.end,_b_.int)){
20
throw _b_.TypeError(
21
"slice indices must be integers or None or have an __index__ method")}
22
23
}
24
25
function norm_pos(pos, s, default_if_None){
26
// For a string s, return a position >=0 is pos is negative or None
27
if(pos>=0){return pos}
28
else if(pos===_b_.None||pos===null){return default_if_None}
29
else{pos+=s.lengh;return Math.max(0, pos)}
30
}
31
32
$StringDict.__add__ = function(self,other){
33
if(!(typeof other==="string")){
34
try{return getattr(other,'__radd__')(self)}
35
catch(err){throw _b_.TypeError(
36
"Can't convert "+$B.get_class(other).__name__+" to str implicitely")}
37
}
38
return self+other
39
}
40
41
$StringDict.__contains__ = function(self,item){
42
if(!(typeof item==="string")){throw _b_.TypeError(
43
"'in <string>' requires string as left operand, not "+item.__class__)}
44
var nbcar = item.length
45
if(nbcar==0) return true // a string contains the empty string
46
if(self.length==0) return nbcar==0
48
if(self.substr(i,nbcar)==item) return true
49
}
50
return false
51
}
52
53
$StringDict.__delitem__ = function(){
54
throw _b_.TypeError("'str' object doesn't support item deletion")
55
}
56
57
// __dir__must be assigned explicitely because attribute resolution for builtin
58
// classes doesn't use __mro__
59
$StringDict.__dir__ = $ObjectDict.__dir__
60
61
$StringDict.__eq__ = function(self,other){
62
if(other===undefined){ // compare object "self" to class "str"
63
return self===str
64
}
65
if (_b_.isinstance(other, _b_.str)) {
66
return other.valueOf() == self.valueOf()
67
}
71
function preformat(self, fmt){
72
if(fmt.empty){return _b_.str(self)}
73
if(fmt.type && fmt.type!='s'){
74
throw _b_.ValueError("Unknown format code '"+fmt.type+
75
"' for object of type 'str'")
76
}
77
return self
78
}
79
80
$StringDict.__format__ = function(self, format_spec) {
81
var fmt = new $B.parse_format_spec(format_spec)
82
// For strings, alignment default to left
83
fmt.align = fmt.align || '<'
84
return $B.format_width(preformat(self, fmt), fmt)
85
}
86
87
$StringDict.__getitem__ = function(self,arg){
88
if(isinstance(arg,_b_.int)){
89
var pos = arg
90
if(arg<0) pos+=self.length
91
if(pos>=0 && pos<self.length) return self.charAt(pos)
92
throw _b_.IndexError('string index out of range')
93
}
94
if(isinstance(arg,slice)) {
95
var step = arg.step===None ? 1 : arg.step
96
if(step>0){
97
var start = arg.start===None ? 0 : arg.start
98
var stop = arg.stop===None ? getattr(self,'__len__')() : arg.stop
99
}else{
100
var start = arg.start===None ? getattr(self,'__len__')()-1 : arg.start
105
var res = '',i=null
106
if(step>0){
107
if(stop<=start) return ''
108
for(var i=start;i<stop;i+=step) res += self.charAt(i)
109
} else {
110
if(stop>=start) return ''
112
}
113
return res
114
}
115
if(isinstance(arg,bool)) return self.__getitem__(_b_.int(arg))
120
if (self === undefined) {
121
return $StringDict.__hashvalue__ || $B.$py_next_hash-- // for hash of string type (not instance of string)
122
}
123
124
//http://stackoverflow.com/questions/2909106/python-whats-a-correct-and-good-way-to-implement-hash
125
// this implementation for strings maybe good enough for us..
126
127
var hash=1;
129
hash=(101*hash + self.charCodeAt(i)) & 0xFFFFFFFF
130
}
131
132
return hash
133
}
134
135
$StringDict.__init__ = function(self,arg){
136
self.valueOf = function(){return arg}
137
self.toString = function(){return arg}
139
}
140
141
var $str_iterator = $B.$iterator_class('str_iterator')
142
$StringDict.__iter__ = function(self){
143
var items = self.split('') // list of all characters in string
144
return $B.$iterator(items,$str_iterator)
145
}
146
147
$StringDict.__len__ = function(self){return self.length}
148
151
var kwarg_key = new RegExp('([^\\)]*)\\)')
152
153
var NotANumber = function() {
154
this.name = 'NotANumber'
155
}
156
157
var number_check=function(s) {
158
if(!isinstance(s,[_b_.int,_b_.float])){
159
throw new NotANumber()
160
}
161
}
162
163
var get_char_array = function(size, char) {
164
if (size <= 0)
165
return ''
166
return new Array(size + 1).join(char)
167
}
168
169
var format_padding = function(s, flags, minus_one) {
170
var padding = flags.padding
171
if (!padding) { // undefined
172
return s
173
}
174
s = s.toString()
175
padding = parseInt(padding, 10)
176
if (minus_one) { // numeric formatting where sign goes in front of padding
177
padding -= 1
178
}
179
if (!flags.left) {
180
return get_char_array(padding - s.length, flags.pad_char) + s
181
} else {
182
// left adjusted
183
return s + get_char_array(padding - s.length, flags.pad_char)
184
}
185
}
186
187
var format_int_precision = function(val, flags) {
188
var precision = flags.precision
189
if (!precision) {
190
return val.toString()
191
}
192
precision = parseInt(precision, 10)
193
var s
194
if (val.__class__ === $B.LongInt.$dict) {
195
s=$B.LongInt.$dict.to_base(val, 10)
196
} else {
197
s=val.toString()
198
}
199
var sign = s[0]
200
if (s[0] === '-') {
201
return '-' + get_char_array(precision - s.length + 1, '0') + s.slice(1)
202
}
203
return get_char_array(precision - s.length, '0') + s
204
}
205
206
var format_float_precision = function(val, upper, flags, modifier) {
207
var precision = flags.precision
208
// val is a float
209
if (isFinite(val)) {
210
val = modifier(val, precision, flags, upper)
211
return val
212
}
213
if (val === Infinity) {
214
val = 'inf'
215
} else if (val === -Infinity) {
216
val = '-inf'
217
} else {
218
val = 'nan'
219
}
220
if (upper) {
221
return val.toUpperCase()
222
}
223
return val
225
}
226
227
var format_sign = function(val, flags) {
228
if (flags.sign) {
229
if (val >= 0) {
230
return "+"
232
} else if (flags.space) {
233
if (val >= 0) {
234
return " "
235
}
236
}
237
return ""
238
}
240
var str_format = function(val, flags) {
241
// string format supports left and right padding
242
flags.pad_char = " " // even if 0 padding is defined, don't use it
243
return format_padding(str(val), flags)
244
}
248
if (val.__class__ === $B.LongInt.$dict) {
249
val = $B.LongInt.$dict.to_base(val, 10)
250
} else {
251
val = parseInt(val)
252
}
253
254
var s = format_int_precision(val, flags)
255
if (flags.pad_char === '0') {
256
if (val < 0) {
257
s = s.substring(1)
258
return '-' + format_padding(s, flags, true)
259
}
260
var sign = format_sign(val, flags)
261
if (sign !== '') {
262
return sign + format_padding(s, flags, true)
263
}
264
}
265
266
return format_padding(format_sign(val, flags) + s, flags)
267
}
269
var repr_format = function(val, flags) {
270
flags.pad_char = " " // even if 0 padding is defined, don't use it
271
return format_padding(repr(val), flags)
272
}
274
var ascii_format = function(val, flags) {
275
flags.pad_char = " " // even if 0 padding is defined, don't use it
276
return format_padding(ascii(val), flags)
277
}
279
// converts to val to float and sets precision if missing
280
var _float_helper = function(val, flags) {
281
number_check(val)
282
if (!flags.precision) {
283
if (!flags.decimal_point) {
284
flags.precision = 6
285
} else {
286
flags.precision = 0
287
}
288
} else {
289
flags.precision = parseInt(flags.precision, 10)
290
validate_precision(flags.precision)
291
}
292
return parseFloat(val)
293
}
295
// used to capture and remove trailing zeroes
296
var trailing_zeros = /(.*?)(0+)([eE].*)/
297
var leading_zeros = /\.(0*)/
298
var trailing_dot = /\.$/
300
var validate_precision = function(precision) {
301
// force precision to limits of javascript
302
if (precision > 20) {
303
throw _b_.ValueError("precision too big")
304
}
305
}
306
307
// gG
308
var floating_point_format = function(val, upper, flags) {
309
val = _float_helper(val, flags)
310
var v = val.toString()
311
var v_len = v.length
312
var dot_idx = v.indexOf('.')
313
if (dot_idx < 0) {
314
dot_idx = v_len
315
}
316
if (val < 1 && val > -1) {
317
var zeros = leading_zeros.exec(v)
318
var numzeros
319
if (zeros) {
320
numzeros = zeros[1].length
321
} else {
322
numzeros = 0
323
}
324
if (numzeros >= 4) {
325
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
326
if (!flags.alternate) {
327
var trl = trailing_zeros.exec(val)
328
if (trl) {
329
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
335
}
336
return format_padding(val, flags)
337
}
338
flags.precision += numzeros
339
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
340
function(val, precision) {
341
val = val.toFixed(min(precision, v_len - dot_idx) + numzeros)
342
}), flags)
343
}
344
345
if (dot_idx > flags.precision) {
346
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
347
if (!flags.alternate) {
348
var trl = trailing_zeros.exec(val)
349
if (trl) {
350
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
351
}
352
} else {
353
if (flags.precision <= 1) {
354
val = val[0] + '.' + val.substring(1)
355
}
356
}
357
return format_padding(val, flags)
358
}
359
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
360
function(val, precision) {
361
if (!flags.decimal_point) {
362
precision = min(v_len - 1, 6)
363
} else if (precision > v_len) {
364
if (!flags.alternate) {
365
precision = v_len
367
}
368
if (precision < dot_idx) {
369
precision = dot_idx
370
}
371
return val.toFixed(precision - dot_idx)
372
}), flags)
373
}
375
var _floating_g_exp_helper = function(val, precision, flags, upper) {
376
if (precision) {
377
--precision
378
}
379
val = val.toExponential(precision)
380
// pad exponent to two digits
381
var e_idx = val.lastIndexOf('e')
382
if (e_idx > val.length - 4) {
383
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
384
}
385
if (upper) {
386
return val.toUpperCase()
387
}
388
return val
389
}
390
391
// fF
392
var floating_point_decimal_format = function(val, upper, flags) {
393
val = _float_helper(val, flags)
394
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
395
function(val, precision, flags) {
396
val = val.toFixed(precision)
397
if (precision === 0 && flags.alternate) {
398
val += '.'
399
}
400
return val
401
}), flags)
402
}
403
404
var _floating_exp_helper = function(val, precision, flags, upper) {
405
val = val.toExponential(precision)
406
// pad exponent to two digits
407
var e_idx = val.lastIndexOf('e')
408
if (e_idx > val.length - 4) {
409
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
410
}
411
if (upper) {
412
return val.toUpperCase()
413
}
414
return val
415
}
416
417
// eE
418
var floating_point_exponential_format = function(val, upper, flags) {
419
val = _float_helper(val, flags)
420
421
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_exp_helper), flags)
422
}
423
424
var signed_hex_format = function(val, upper, flags) {
427
428
if (val.__class__ === $B.LongInt.$dict) {
429
ret=$B.LongInt.$dict.to_base(val, 16)
430
} else {
431
ret = parseInt(val)
432
ret = ret.toString(16)
433
}
434
ret = format_int_precision(ret, flags)
435
if (upper) {
436
ret = ret.toUpperCase()
437
}
438
if (flags.pad_char === '0') {
439
if (val < 0) {
440
ret = ret.substring(1)
441
ret = '-' + format_padding(ret, flags, true)
442
}
443
var sign = format_sign(val, flags)
444
if (sign !== '') {
445
ret = sign + format_padding(ret, flags, true)
447
}
448
449
if (flags.alternate) {
450
if (ret.charAt(0) === '-') {
451
if (upper) {
452
ret = "-0X" + ret.slice(1)
453
} else {
454
ret = "-0x" + ret.slice(1)
455
}
456
} else {
457
if (upper) {
458
ret = "0X" + ret
459
} else {
460
ret = "0x" + ret
461
}
462
}
463
}
464
return format_padding(format_sign(val, flags) + ret, flags)
465
}
469
var ret
470
471
if (val.__class__ === $B.LongInt.$dict) {
472
ret = $B.LongInt.$dict.to_base(8)
473
} else {
474
ret = parseInt(val)
475
ret = ret.toString(8)
476
}
477
480
if (flags.pad_char === '0') {
481
if (val < 0) {
482
ret = ret.substring(1)
483
ret = '-' + format_padding(ret, flags, true)
484
}
485
var sign = format_sign(val, flags)
486
if (sign !== '') {
487
ret = sign + format_padding(ret, flags, true)
488
}
490
491
if (flags.alternate) {
492
if (ret.charAt(0) === '-') {
493
ret = "-0o" + ret.slice(1)
494
} else {
495
ret = "0o" + ret
496
}
498
return format_padding(ret, flags)
499
}
500
501
var single_char_format = function(val, flags) {
502
if(isinstance(val,str) && val.length==1) return val
503
try {
504
val = _b_.int(val) // yes, floats are valid (they are cast to int)
505
} catch (err) {
506
throw _b_.TypeError('%c requires int or char')
507
}
508
return format_padding(chr(val), flags)
509
}
510
511
var num_flag = function(c, flags) {
512
if (c === '0' && !flags.padding && !flags.decimal_point && !flags.left) {
513
flags.pad_char = '0'
514
return
515
}
516
if (!flags.decimal_point) {
517
flags.padding = (flags.padding || "") + c
518
} else {
519
flags.precision = (flags.precision || "") + c
520
}
521
}
522
523
var decimal_point_flag = function(val, flags) {
524
if (flags.decimal_point) {
525
// can only have one decimal point
526
throw new UnsupportedChar()
527
}
528
flags.decimal_point = true
529
}
530
531
var neg_flag = function(val, flags) {
532
flags.pad_char = ' ' // overrides '0' flag
533
flags.left = true
534
}
535
536
var space_flag = function(val, flags) {
537
flags.space = true
538
}
539
540
var sign_flag = function(val, flags) {
541
flags.sign = true
542
}
543
544
var alternate_flag = function(val, flags) {
545
flags.alternate = true
546
}
547
549
's': str_format,
550
'd': num_format,
551
'i': num_format,
552
'u': num_format,
553
'o': octal_format,
554
'r': repr_format,
555
'a': ascii_format,
556
'g': function(val, flags) {return floating_point_format(val, false, flags)},
557
'G': function(val, flags) {return floating_point_format(val, true, flags)},
558
'f': function(val, flags) {return floating_point_decimal_format(val, false, flags)},
559
'F': function(val, flags) {return floating_point_decimal_format(val, true, flags)},
560
'e': function(val, flags) {return floating_point_exponential_format(val, false, flags)},
561
'E': function(val, flags) {return floating_point_exponential_format(val, true, flags)},
562
'x': function(val, flags) {return signed_hex_format(val, false, flags)},
563
'X': function(val, flags) {return signed_hex_format(val, true, flags)},
564
'c': single_char_format,
565
'0': function(val, flags) {return num_flag('0', flags)},
566
'1': function(val, flags) {return num_flag('1', flags)},
567
'2': function(val, flags) {return num_flag('2', flags)},
568
'3': function(val, flags) {return num_flag('3', flags)},
569
'4': function(val, flags) {return num_flag('4', flags)},
570
'5': function(val, flags) {return num_flag('5', flags)},
571
'6': function(val, flags) {return num_flag('6', flags)},
572
'7': function(val, flags) {return num_flag('7', flags)},
573
'8': function(val, flags) {return num_flag('8', flags)},
574
'9': function(val, flags) {return num_flag('9', flags)},
575
'-': neg_flag,
576
' ': space_flag,
577
'+': sign_flag,
578
'.': decimal_point_flag,
579
'#': alternate_flag
580
}
581
582
// exception thrown when an unsupported char is encountered in legacy format
583
var UnsupportedChar = function() {
584
this.name = "UnsupportedChar"
585
}
586
598
++pos
599
var rslt = kwarg_key.exec(s.substring(newpos))
600
if (!rslt) {
601
throw _b_.ValueError("incomplete format key")
602
}
603
var key = rslt[1]
604
newpos += rslt[0].length
605
try {
607
} catch(err) {
608
if (err.name === "KeyError") {
609
throw err
610
}
611
throw _b_.TypeError("format requires a mapping")
612
}
627
}
628
catch(err) {
629
if (err.name === "IndexError") {
630
throw _b_.TypeError("not enough arguments for format string")
631
} else {
632
throw err
633
}
639
// todo: get flags, type
640
// todo: string value based on flags, type, value
641
var flags = {'pad_char': ' '}
642
do {
649
if (ret !== undefined) {
650
return ret
651
}
652
++newpos
653
}
654
} catch (err) {
655
if (err.name === "UnsupportedChar") {
656
invalid_char = s[newpos]
657
if (invalid_char === undefined) {
658
throw _b_.ValueError("incomplete format")
659
}
660
throw _b_.ValueError("unsupported format character '" + invalid_char +
661
"' (0x" + invalid_char.charCodeAt(0).toString(16) + ") at index " + newpos)
662
} else if (err.name === "NotANumber") {
663
var try_char = s[newpos]
670
}
671
} else {
672
cls = cls.__name__
673
}
674
throw _b_.TypeError("%" + try_char + " format: a number is required, not " + cls)
675
} else {
676
throw err
677
}
699
}
700
}
701
} else {
702
// % at end of string
703
throw _b_.ValueError("incomplete format")
704
}
705
pos = newpos + 1
706
} while (pos < length)
707
710
711
$StringDict.__mro__ = [$StringDict,$ObjectDict]
712
713
$StringDict.__mul__ = function(self,other){
714
if(!isinstance(other,_b_.int)){throw _b_.TypeError(
715
"Can't multiply sequence by non-int of type '"+
716
$B.get_class(other).__name__+"'")}
717
$res = ''
718
for(var i=0;i<other;i++){$res+=self.valueOf()}
719
return $res
720
}
721
722
$StringDict.__ne__ = function(self,other){return other!==self.valueOf()}
723
724
$StringDict.__repr__ = function(self){
725
var res = self.replace(/\n/g,'\\\\n')
726
// escape the escape char
727
res = res.replace(/\\/g, '\\\\')
728
if(res.search('"')==-1 && res.search("'")==-1){
729
return "'"+res+"'"
738
$StringDict.__setattr__ = function(self,attr,value){return setattr(self,attr,value)}
739
740
$StringDict.__setitem__ = function(self,attr,value){
741
throw _b_.TypeError("'str' object does not support item assignment")
742
}
743
$StringDict.__str__ = function(self){
744
if(self===undefined) return "<class 'str'>"
745
return self.toString()
746
}
747
$StringDict.toString = function(){return 'string!'}
748
749
// generate comparison methods
750
var $comp_func = function(self,other){
751
if(typeof other !=="string"){throw _b_.TypeError(
752
"unorderable types: 'str' > "+$B.get_class(other).__name__+"()")}
753
return self > other
754
}
755
$comp_func += '' // source code
756
var $comps = {'>':'gt','>=':'ge','<':'lt','<=':'le'}
757
for(var $op in $comps){
758
eval("$StringDict.__"+$comps[$op]+'__ = '+$comp_func.replace(/>/gm,$op))
759
}
760
761
// add "reflected" methods
762
$B.make_rmethods($StringDict)
763
764
// unsupported operations
765
var $notimplemented = function(self,other){
766
throw NotImplementedError("OPERATOR not implemented for class str")
767
}
768
769
$StringDict.capitalize = function(self){
770
if(self.length==0) return ''
771
return self.charAt(0).toUpperCase()+self.substr(1).toLowerCase()
772
}
773
774
$StringDict.casefold = function(self) {
775
throw _b_.NotImplementedError("function casefold not implemented yet");
776
}
777
778
$StringDict.center = function(self,width,fillchar){
779
if(fillchar===undefined){fillchar=' '}else{fillchar=fillchar}
780
if(width<=self.length) return self
781
782
var pad = parseInt((width-self.length)/2)
783
var res = Array(pad+1).join(fillchar) // is this statement faster than the for loop below?
784
res += self + res
785
if(res.length<width){res += fillchar}
786
return res
787
}
788
789
$StringDict.count = function(){
790
var $ = $B.args('count', 4, {self:null, sub:null, start:null, stop:null},
795
var substr = $.self
796
if($.start!==null){
797
var _slice
798
if($.stop!==null){_slice = _b_.slice($.start, $.stop)}
799
else{_slice = _b_.slice($.start,$.self.length)}
800
substr = $StringDict.__getitem__.apply(null, [$.self].concat(_slice))
801
}else{
802
if($.self.length+$.sub.length==0){return 1} // ''.count('') = 1
803
}
804
if($.sub.length==0){
805
if($.start==$.self.length){return 1} // 'aaa'.count('',3) = 1
806
else if(substr.length==0){return 0} // 'aaa'.count('',4) = 0
807
return substr.length+1
808
}
809
var n=0, pos=0
810
while(pos<substr.length){
811
pos=substr.indexOf($.sub,pos)
813
}
814
return n
815
}
816
817
$StringDict.encode = function(self, encoding) {
818
if (encoding === undefined) encoding='utf-8'
819
if(encoding=='rot13' || encoding=='rot_13'){
820
// Special case : returns a string
821
var res = ''
822
for(var i=0, _len = self.length; i<_len ; i++){
823
var char = self.charAt(i)
824
if(('a'<=char && char<='m') || ('A'<=char && char<='M')){
825
res += String.fromCharCode(String.charCodeAt(char)+13)
826
}else if(('m'<char && char<='z') || ('M'<char && char<='Z')){
827
res += String.fromCharCode(String.charCodeAt(char)-13)
828
}else{res += char}
829
}
830
return res
831
}
833
}
834
835
$StringDict.endswith = function(self){
836
// Return True if the string ends with the specified suffix, otherwise
837
// return False. suffix can also be a tuple of suffixes to look for.
838
// With optional start, test beginning at that position. With optional
839
// end, stop comparing at that position.
841
{self:null, suffix:null, start:null, end:null},
842
['self', 'suffix', 'start', 'end'],
843
arguments,{start:0, end:self.length-1},null,null)
844
var suffixes = $ns['suffix']
845
if(!isinstance(suffixes,_b_.tuple)){suffixes=[suffixes]}
850
suffix = suffixes[i]
851
if(suffix.length<=s.length &&
852
s.substr(s.length-suffix.length)==suffix) return true
853
}
854
return false
855
}
856
857
$StringDict.expandtabs = function(self, tabsize) {
858
var $ = $B.args('expandtabs', 2, {self:null, tabsize:null},
859
['self', 'tabsize'], arguments, {tabsize:8}, null, null)
860
var s=$B.$GetInt($.tabsize), col=0,pos=0,res=''
861
if(s==1){return self.replace(/\t/g,' ')}
862
while(pos<self.length){
863
var car = self.charAt(pos)
864
switch(car){
865
case '\t':
866
while(col%s > 0){res += ' ';col++}
867
break
868
case '\r':
869
case '\n':
870
res += car
871
col = 0
872
break
873
default:
874
res += car
875
col++
876
break
877
}
878
pos++
879
}
880
881
return res
885
// Return the lowest index in the string where substring sub is found,
886
// such that sub is contained in the slice s[start:end]. Optional
887
// arguments start and end are interpreted as in slice notation.
888
// Return -1 if sub is not found.
892
arguments,{start:0,end:null},null,null)
893
if(!isinstance($.sub,str)){throw _b_.TypeError(
894
"Can't convert '"+$B.get_class($.sub).__name__+
895
"' object to str implicitly")}
899
throw _b_.TypeError(
900
"slice indices must be integers or None or have an __index__ method")}
901
var s = $.self.substring($.start,$.end)
902
903
if($.sub.length==0 && $.start==$.self.length){return $.self.length}
904
if(s.length+$.sub.length==0){return -1}
905
906
var last_search = s.length-$.sub.length
907
for(var i=0;i<=last_search;i++){
908
if(s.substr(i, $.sub.length)==$.sub){return $.start+i}
917
// Parse a "format string", as described in the Python documentation
918
// Return a format object. For the format string
919
// a.x[z]!r:...
920
// the object has attributes :
921
// - name : "a"
922
// - name_ext : [".x", "[z]"]
923
// - conv : r
924
// - spec : rest of string after :
926
var elts = fmt_string.split(':'), name, conv, spec, name_ext=[]
927
if(elts.length==1){
928
// No : in the string : it only contains a name
929
name = fmt_string
930
}else{
931
// name is before the first ":"
932
// spec (the format specification) is after
933
name = elts[0]
934
spec = elts.splice(1).join(':')
935
}
936
937
var elts = name.split('!')
938
if(elts.length>1){
939
name=elts[0]
940
conv=elts[1] // conversion flag
941
if(conv.length!==1 || 'ras'.search(conv)==-1){
942
throw _b_.ValueError('wrong conversion flag '+conv)
943
}
944
}
946
if(name!==undefined){
947
// "name' may be a subscription or attribute
948
// Put these "extensions" in the list "name_ext"
949
function name_repl(match){
950
name_ext.push(match)
951
return ''
952
}
953
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
954
name = name.replace(name_ext_re, name_repl)
955
}
964
arguments, {}, 'args', 'kw')
965
966
// Parse self to detect formatting instructions
967
// Create a list "parts" made of sections of the string :
968
// - elements of even rank are literal text
969
// - elements of odd rank are "format objects", built from the
970
// format strings in self (of the form {...})
971
var pos=0, _len=self.length, car, text='', parts=[], rank=0, defaults={}
972
973
while(pos<_len){
974
car = self.charAt(pos)
975
if(car=='{' && self.charAt(pos+1)=='{'){
976
// replace {{ by literal {
977
text += '{'
978
pos+=2
979
}else if(car=='}' && self.charAt(pos+1)=='}'){
980
// replace }} by literal }
981
text += '}'
982
pos+=2
983
}else if(car=='{'){
984
// Start of a format string
985
986
// Store current literal text
987
parts.push(text)
988
989
// Search the end of the format string, ie the } closing the
990
// opening {. Since the string can contain other pairs {} for
991
// nested formatting, an integer nb is incremented for each { and
992
// decremented for each } ; the end of the format string is
993
// reached when nb==0
994
var end = pos+1, nb=1
995
while(end<_len){
996
if(self.charAt(end)=='{'){nb++;end++}
997
else if(self.charAt(end)=='}'){
998
nb--;end++
999
if(nb==0){
1000
// End of format string
1001
var fmt_string = self.substring(pos+1, end-1)
1002
1003
// Create a format object, by function parse_format
1004
var fmt_obj = parse_format(fmt_string)
1005
1006
// If no name is explicitely provided, use the rank
1007
if(!fmt_obj.name){
1008
fmt_obj.name=rank+''
1009
rank++
1010
}
1013
// "spec" may contain "nested replacement fields"
1014
// In this case, evaluate them using the keyword
1015
// arguments passed to format()
1016
function replace_nested(name, key){
1019
}
1020
fmt_obj.spec = fmt_obj.spec.replace(/\{(.+?)\}/g,
1021
replace_nested)
1022
}
1023
1024
// Store format object in list "parts"
1025
parts.push(fmt_obj)
1026
text = ''
1027
break
1028
}
1029
}else{end++}
1031
if(nb>0){throw ValueError("wrong format "+self)}
1032
pos = end
1033
}else{text += car;pos++}
1037
// Apply formatting to the values passed to format()
1038
var res = '', fmt
1039
for(var i=0;i<parts.length;i++){
1040
// Literal text is added unchanged
1041
if(typeof parts[i]=='string'){res += parts[i];continue}
1042
1043
// Format objects
1044
fmt = parts[i]
1045
if(fmt.name.charAt(0).search(/\d/)>-1){
1046
// Numerical reference : use positional arguments
1047
var pos = parseInt(fmt.name),
1048
value = _b_.tuple.$dict.__getitem__($.args, pos)
1049
}else{
1050
// Use keyword arguments
1051
var value = _b_.dict.$dict.__getitem__($.kw, fmt.name)
1052
}
1053
// If name has extensions (attributes or subscriptions)
1054
for(var j=0;j<fmt.name_ext.length;j++){
1055
var ext = fmt.name_ext[j]
1056
if(ext.charAt(0)=='.'){
1057
// Attribute
1058
value = _b_.getattr(value, ext.substr(1))
1059
}else{
1060
// Subscription
1061
var key = ext.substr(1, ext.length-2)
1062
// An index made of digits is transformed into an integer
1063
if(key.charAt(0).search(/\d/)>-1){key = parseInt(key)}
1064
value = _b_.getattr(value, '__getitem__')(key)
1065
}
1066
}
1067
// If the conversion flag is set, first call a function to convert
1068
// the value
1069
if(fmt.conv=='a'){value = _b_.ascii(value)}
1070
else if(fmt.conv=='r'){value = _b_.repr(value)}
1071
else if(fmt.conv=='s'){value = _b_.str(value)}
1072
1073
// Call attribute __format__ to perform the actual formatting
1074
res += _b_.getattr(value, '__format__')(fmt.spec)
1077
}
1078
1079
$StringDict.format_map = function(self) {
1080
throw NotImplementedError("function format_map not implemented yet");
1081
}
1082
1083
$StringDict.index = function(self){
1084
// Like find(), but raise ValueError when the substring is not found.
1086
if(res===-1) throw _b_.ValueError("substring not found")
1087
return res
1088
}
1089
1090
$StringDict.isalnum = function(self) {return /^[a-z0-9]+$/i.test(self)}
1091
1092
$StringDict.isalpha = function(self) {return /^[a-z]+$/i.test(self)}
1093
1094
$StringDict.isdecimal = function(self) {
1095
// this is not 100% correct
1096
return /^[0-9]+$/.test(self)
1097
}
1098
1099
$StringDict.isdigit = function(self) { return /^[0-9]+$/.test(self)}
1100
1101
$StringDict.isidentifier = function(self) {
1102
1103
switch(self) {
1104
case 'False':
1105
case 'None':
1106
case 'True':
1107
case 'and':
1108
case 'as':
1109
case 'assert':
1110
case 'break':
1111
case 'class':
1112
case 'continue':
1113
case 'def':
1114
case 'del':
1115
case 'elif':
1116
case 'else':
1117
case 'except':
1118
case 'finally':
1119
case 'for':
1120
case 'from':
1121
case 'global':
1122
case 'if':
1123
case 'import':
1124
case 'in':
1125
case 'is':
1126
case 'lambda':
1127
case 'nonlocal':
1128
case 'not':
1129
case 'or':
1130
case 'pass':
1131
case 'raise':
1132
case 'return':
1133
case 'try':
1134
case 'while':
1135
case 'with':
1136
case 'yield':
1137
return true
1138
}
1139
1140
// fixme.. this isn't complete but should be a good start
1141
return /^[a-z][0-9a-z_]+$/i.test(self)
1142
}
1143
1145
1146
// not sure how to handle unicode variables
1147
$StringDict.isnumeric = function(self) {return /^[0-9]+$/.test(self)}
1148
1149
// inspired by http://www.codingforums.com/archive/index.php/t-17925.html
1150
$StringDict.isprintable = function(self) {return !/[^ -~]/.test(self)}
1151
1152
$StringDict.isspace = function(self) {return /^\s+$/i.test(self)}
1153
1154
$StringDict.istitle = function(self) {return /^([A-Z][a-z]+)(\s[A-Z][a-z]+)$/i.test(self)}
1155
1157
1158
$StringDict.join = function(self,obj){
1159
var iterable=iter(obj)
1160
var res = '',count=0
1161
while(1){
1162
try{
1163
var obj2 = next(iterable)
1164
if(!isinstance(obj2,str)){throw _b_.TypeError(
1165
"sequence item "+count+": expected str instance, "+$B.get_class(obj2).__name__+" found")}
1166
res += obj2+self
1167
count++
1168
}catch(err){
1170
else{throw err}
1171
}
1172
}
1173
if(count==0) return ''
1174
return res.substr(0,res.length-self.length)
1175
}
1176
1177
$StringDict.ljust = function(self, width, fillchar) {
1178
if (width <= self.length) return self
1179
if (fillchar === undefined) fillchar=' '
1180
return self + Array(width - self.length + 1).join(fillchar)
1181
}
1182
1183
$StringDict.lower = function(){
1184
var $=$B.args('lower',1,{self:null},['self'],arguments,{},null,null)
1185
return $.self.toLowerCase()
1186
}
1187
1188
$StringDict.lstrip = function(self,x){
1189
var pattern = null
1190
if(x==undefined){pattern="\\s*"}
1191
else{pattern = "["+x+"]*"}
1192
var sp = new RegExp("^"+pattern)
1193
return self.replace(sp,"")
1194
}
1195
1196
// note, maketrans should be a static function.
1197
$StringDict.maketrans = function(from, to) {
1198
var _t=[]
1199
// make 'default' translate table
1200
for(var i=0; i < 256; i++) _t[i]=String.fromCharCode(i)
1201
1202
// make substitution in the translation table
1204
var _ndx=from.source[i].charCodeAt(0) //retrieve ascii code of char
1205
_t[_ndx]=to.source[i]
1206
}
1207
1208
// create a data structure that string.translate understands
1212
}
1213
return _d
1214
}
1215
1216
$StringDict.partition = function(self,sep) {
1217
if (sep === undefined) {
1218
throw Error("sep argument is required");
1219
return
1220
}
1221
var i=self.indexOf(sep)
1222
if (i== -1) return _b_.tuple([self, '', ''])
1223
return _b_.tuple([self.substring(0,i), sep, self.substring(i+sep.length)])
1224
}
1225
1226
function $re_escape(str)
1227
{
1228
var specials = "[.*+?|()$^"
1230
var re = new RegExp('\\'+specials.charAt(i),'g')
1231
str = str.replace(re, "\\"+specials.charAt(i))
1232
}
1233
return str
1234
}
1235
1236
$StringDict.replace = function(self, old, _new, count) {
1237
// Replaces occurrences of 'old' by '_new'. Count references
1238
// the number of times to replace. In CPython, negative or undefined
1239
// values of count means replace all.
1240
var $ = $B.args('replace', 4, {self:null,old:null,$$new:null,count:null},
1241
['self','old','$$new','count'], arguments, {count:-1},null,null),
1242
count=$.count,self=$.self,old=$.old,_new=$.$$new
1243
// Validate type of old
1244
if (!isinstance(old,_b_.str)||!isinstance(_new,_b_.str)) {
1245
throw _b_.TypeError("Can't convert '" + $B.get_class(old).__name__ +
1246
"' object to str implicitly");
1247
}
1248
// Validate instance type of 'count'
1249
if (!isinstance(count,[_b_.int,_b_.float])) {
1250
throw _b_.TypeError("'" + $B.get_class(count).__name__ +
1251
"' object cannot be interpreted as an integer");
1252
} else if (isinstance(count, _b_.float)) {
1253
throw _b_.TypeError("integer argument expected, got float");
1254
}
1255
if(count==0){return self}
1256
if(count.__class__==$B.LongInt.$dict){count=parseInt(count.value)}
1257
if(old==''){
1258
if(_new==''){return self}
1259
if(self==''){return _new}
1260
var elts=self.split('')
1261
if(count>-1 && elts.length>=count){
1262
var rest = elts.slice(count).join('')
1263
return _new+elts.slice(0, count).join(_new)+rest
1264
}else{return _new+elts.join(_new)+_new}
1265
}else{
1266
var elts = $StringDict.split(self,old,count)
1269
var res = self, pos = -1
1270
if(old.length==0){
1271
var res = _new
1272
for(var i=0;i<elts.length;i++){
1273
res += elts[i]+_new
1274
}
1275
return res+rest
1276
}
1277
1278
if (count < 0) count = res.length;
1279
while (count > 0) {
1280
pos = res.indexOf(old, pos);
1281
if (pos < 0)
1282
break;
1283
res = res.substr(0, pos) + _new + res.substr(pos + old.length);
1284
pos = pos + _new.length;
1285
count--;
1286
}
1287
return res;
1288
}
1289
1290
$StringDict.rfind = function(self){
1291
// Return the highest index in the string where substring sub is found,
1292
// such that sub is contained within s[start:end]. Optional arguments
1293
// start and end are interpreted as in slice notation. Return -1 on failure.
1299
normalize_start_end($)
1300
1301
if(!isinstance($.sub,str)){throw _b_.TypeError(
1302
"Can't convert '"+$B.get_class($.sub).__name__+"' object to str implicitly")}
1304
if($.sub.length==0){
1305
if($.start>$.self.length){return -1}
1306
else{return $.self.length}
1307
}
1308
var sublen = $.sub.length
1309
1310
for(var i=$.end-sublen;i>=$.start;i--){
1311
if($.self.substr(i, sublen)==$.sub){return i}
1312
}
1313
return -1
1314
}
1315
1316
$StringDict.rindex = function(){
1317
// Like rfind() but raises ValueError when the substring sub is not found
1319
if(res==-1){throw _b_.ValueError("substring not found")}
1320
return res
1321
}
1322
1323
$StringDict.rjust = function(self) {
1325
{self:null, width:null, fillchar:null},
1326
['self', 'width', 'fillchar'],
1327
arguments,{fillchar:' '},null,null)
1328
for(var attr in $ns){eval('var '+attr+'=$ns[attr]')}
1329
1330
if (width <= self.length) return self
1331
1332
return Array(width - self.length + 1).join(fillchar) + self
1333
}
1334
1335
$StringDict.rpartition = function(self,sep) {
1336
if (sep === undefined) {
1337
throw Error("sep argument is required");
1338
return
1339
}
1340
var pos=self.length-sep.length
1341
while(1){
1342
if(self.substr(pos,sep.length)==sep){
1343
return _b_.tuple([self.substr(0,pos),sep,self.substr(pos+sep.length)])
1344
}else{
1345
pos--
1346
if(pos<0){return _b_.tuple(['','',self])}
1347
}
1348
}
1349
}
1350
1351
$StringDict.rsplit = function(self) {
1352
var $=$B.args("rsplit",3,{self:null,sep:null,maxsplit:null},
1353
['self','sep','maxsplit'],arguments,
1354
{sep:_b_.None, maxsplit:-1},null,null),
1355
sep=$.sep,maxsplit=$.maxsplit,self=$.self
1356
1357
// Use split on the reverse of the string and of separator
1358
var rev_str = $.self.split('').reverse().join(''),
1359
rev_sep = sep === _b_.None ? sep : $.sep.split('').reverse().join(''),
1360
rev_res = $StringDict.split(rev_str, rev_sep, $.maxsplit)
1362
// Reverse the list, then each string inside the list
1363
rev_res.reverse()
1364
for(var i=0;i<rev_res.length;i++){
1365
rev_res[i] = rev_res[i].split('').reverse().join('')
1366
}
1367
return rev_res
1368
}
1369
1370
$StringDict.rstrip = function(self,x){
1371
if(x==undefined){var pattern="\\s*"}
1372
else{var pattern = "["+x+"]*"}
1373
sp = new RegExp(pattern+'$')
1374
return str(self.replace(sp,""))
1375
}
1376
1379
var $=$B.args("split",3,{self:null,sep:null,maxsplit:null},
1380
['self','sep','maxsplit'],arguments,
1381
{sep:_b_.None, maxsplit:-1},null,null)
1382
var sep=$.sep,maxsplit=$.maxsplit,self=$.self
1383
if(maxsplit.__class__===$B.LongInt.$dict){maxsplit=parseInt(maxsplit.value)}
1386
var res = []
1387
var pos = 0
1388
while(pos<self.length&&self.charAt(pos).search(/\s/)>-1){pos++}
1390
var name = ''
1391
while(1){
1392
if(self.charAt(pos).search(/\s/)===-1){
1393
if(name===''){name=self.charAt(pos)}
1394
else{name+=self.charAt(pos)}
1395
}else{
1396
if(name!==''){
1397
res.push(name)
1398
if(maxsplit!==-1&&res.length===maxsplit+1){
1399
res.pop()
1400
res.push(name+self.substr(pos))
1401
return res
1402
}
1403
name=''
1404
}
1405
}
1406
pos++
1407
if(pos>self.length-1){
1408
if(name){res.push(name)}
1409
break
1410
}
1411
}
1412
return res
1413
}else{
1414
var res = [],s='',pos=0,seplen=sep.length
1415
if(maxsplit==0){return [self]}
1416
while(pos<self.length){
1417
if(self.substr(pos,seplen)==sep){
1418
res.push(s)
1419
pos += seplen
1420
if(maxsplit>-1 && res.length>=maxsplit){
1421
res.push(self.substr(pos))
1422
return res
1423
}
1424
s= ''
1425
}else{
1426
s += self.charAt(pos)
1427
pos++
1432
}
1433
}
1434
1435
$StringDict.splitlines = function(self){return $StringDict.split(self,'\n')}
1436
1437
$StringDict.startswith = function(self){
1438
// Return True if string starts with the prefix, otherwise return False.
1439
// prefix can also be a tuple of prefixes to look for. With optional
1440
// start, test string beginning at that position. With optional end,
1441
// stop comparing string at that position.
1443
{self:null, prefix:null, start:null, end:null},
1444
['self', 'prefix', 'start', 'end'],
1445
arguments,{start:0, end:self.length-1},null,null)
1446
var prefixes = $ns['prefix']
1447
if(!isinstance(prefixes,_b_.tuple)){prefixes=[prefixes]}
1453
if (s.indexOf(prefixes[i]) == 0) return true
1454
}
1455
return false
1456
}
1457
1458
$StringDict.strip = function(self,x){
1459
if(x==undefined){x = "\\s"}
1460
return $StringDict.rstrip($StringDict.lstrip(self,x),x)
1461
}
1462
1463
$StringDict.swapcase = function(self) {
1464
//inspired by http://www.geekpedia.com/code69_Swap-string-case-using-JavaScript.html
1465
return self.replace(/([a-z])|([A-Z])/g, function($0,$1,$2)
1466
{ return ($1) ? $0.toUpperCase() : $0.toLowerCase()
1467
})
1468
}
1469
1470
$StringDict.title = function(self) {
1471
//inspired from http://stackoverflow.com/questions/196972/convert-string-to-title-case-with-javascript
1472
return self.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
1473
}
1474
1475
$StringDict.translate = function(self,table) {
1480
if(repl==-1){res[pos++]=self.charAt(i)}
1481
else if(repl!==None){res[pos++]=repl}
1487
$StringDict.upper = function(){
1488
var $=$B.args('lower',1,{self:null},['self'],arguments,{},null,null)
1489
return $.self.toUpperCase()
1490
}
1491
1492
$StringDict.zfill = function(self, width) {
1493
if (width === undefined || width <= self.length || !self.isnumeric()) {
1494
return self
1495
}
1496
1497
return Array(width - self.length +1).join('0');
1498
}
1499
1500
function str(arg){
1501
if(arg===undefined) return ''
1502
switch(typeof arg) {
1503
case 'string': return arg
1504
case 'number': return arg.toString()
1505
}
1511
// class or its subclasses, but the attribute __str__ of the
1512
// class metaclass (usually "type") or its subclasses (usually
1513
// "object")
1514
// The metaclass is the attribute __class__ of the class dictionary
1515
var func = $B.$type.__getattribute__(arg.$dict.__class__,'__str__')
1520
var f = getattr(arg,'__str__')
1521
// XXX fix : if not better than object.__str__, try __repr__
1522
return f()
1523
}
1524
catch(err){
1530
if($B.debug>1){console.log(err)}
1531
console.log('Warning - no method __str__ or __repr__, default to toString', arg)
1533
}
1534
}
1535
}
1536
str.__class__ = $B.$factory
1537
str.$dict = $StringDict
1538
$StringDict.$factory = str
1539
$StringDict.__new__ = function(cls){
1540
if(cls===undefined){
1541
throw _b_.TypeError('str.__new__(): not enough arguments')
1542
}
1543
return {__class__:cls.$dict}
1544
}
1545
1548
// dictionary and factory for subclasses of string
1549
var $StringSubclassDict = {
1550
__class__:$B.$type,
1551
__name__:'str'
1552
}
1553
1554
// the methods in subclass apply the methods in $StringDict to the
1555
// result of instance.valueOf(), which is a Javascript string
1556
for(var $attr in $StringDict){
1557
if(typeof $StringDict[$attr]=='function'){
1558
$StringSubclassDict[$attr]=(function(attr){
1559
return function(){
1565
}
1566
}
1567
return $StringDict[attr].apply(null,args)
1568
}
1569
})($attr)
1570
}
1571
}
1572
$StringSubclassDict.__mro__ = [$StringSubclassDict,$ObjectDict]
1573
1574
// factory for str subclasses
1575
$B.$StringSubclassFactory = {
1576
__class__:$B.$factory,
1577
$dict:$StringSubclassDict
1578
}
1579
1580
_b_.str = str
1581
1582
// Function to parse the 2nd argument of format()
1583
$B.parse_format_spec = function(spec){
1593
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1))!=-1){
1594
// If the second char is also an alignment specifier, the
1595
// first char is the fill value
1596
this.fill = spec.charAt(0)
1597
this.align = spec.charAt(1)
1598
pos = 2
1599
}else{
1600
// The first character defines alignment : fill defaults to ' '
1601
this.align=aligns[align_pos];
1602
this.fill=' ';
1603
pos++
1604
}
1605
}else{
1606
align_pos = aligns.indexOf(spec.charAt(1))
1607
if(spec.charAt(1) && align_pos!=-1){
1608
// The second character defines alignment : fill is the first one
1609
this.align=aligns[align_pos]
1610
this.fill=spec.charAt(0)
1611
pos = 2
1612
}
1613
}
1614
var car = spec.charAt(pos)
1615
if(car=='+'||car=='-'||car==' '){
1616
this.sign=car;
1617
pos++;
1618
car=spec.charAt(pos);
1621
if(car=='0'){
1622
// sign-aware : equivalent to fill=0 and align=='='
1623
this.fill='0'
1624
this.align = '='
1625
pos++;car=spec.charAt(pos)
1626
}
1628
if(this.width===undefined){this.width=car}
1629
else{this.width+=car}
1630
pos++;car=spec.charAt(pos)
1632
if(this.width!==undefined){this.width=parseInt(this.width)}
1633
if(car==','){this.comma=true;pos++;car=spec.charAt(pos)}
1634
if(car=='.'){
1635
if(digits.indexOf(spec.charAt(pos+1))==-1){
1636
throw _b_.ValueError("Missing precision in format spec")
1637
}
1638
this.precision = spec.charAt(pos+1)
1639
pos+=2;car=spec.charAt(pos)
1640
while(car && digits.indexOf(car)>-1){
1641
this.precision+=car;pos++;car=spec.charAt(pos)
1642
}
1643
this.precision = parseInt(this.precision)
1644
}
1645
if(car && types.indexOf(car)>-1){this.type=car;pos++;car=spec.charAt(pos)}
1646
if(pos!==spec.length){
1647
console.log('error', spec, this, pos, spec.charAt(pos))
1648
throw _b_.ValueError("Invalid format specifier")
1649
}
1650
}
1651
this.toString = function(){
1652
return (this.fill===undefined ? '' : _b_.str(this.fill))+
1653
(this.align||'')+
1654
(this.sign||'')+
1655
(this.alternate ? '#' : '')+
1656
(this.sign_aware ? '0' : '')+
1657
(this.width || '')+
1658
(this.comma ? ',' : '')+
1659
(this.precision ? '.'+this.precision : '')+
1660
(this.type || '')
1661
}
1662
}
1663
1664
$B.format_width = function(s, fmt){
1665
if(fmt.width && s.length<fmt.width){
1666
var fill=fmt.fill || ' ', align = fmt.align || '<',
1667
missing = fmt.width-s.length
1668
switch(align){
1669
case '<':
1670
return s+fill.repeat(missing)
1671
case '>':
1672
return fill.repeat(missing)+s
1673
case '=':
1674
if('+-'.indexOf(s.charAt(0))>-1){
1675
return s.charAt(0)+fill.repeat(missing)+s.substr(1)
1676
}else{
1677
return fill.repeat(missing)+s
1678
}
1679
case '^':
1680
left = parseInt(missing/2)