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
1682 lines (1506 sloc)
52.7 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 instance type of 'count'
1244
if (!isinstance(count,[_b_.int,_b_.float])) {
1245
throw _b_.TypeError("'" + $B.get_class(count).__name__ +
1246
"' object cannot be interpreted as an integer");
1247
} else if (isinstance(count, _b_.float)) {
1248
throw _b_.TypeError("integer argument expected, got float");
1249
}
1250
if(count==0){return self}
1251
if(count.__class__==$B.LongInt.$dict){count=parseInt(count.value)}
1252
if(old==''){
1253
if(_new==''){return self}
1254
if(self==''){return _new}
1255
var elts=self.split('')
1256
if(count>-1 && elts.length>=count){
1257
var rest = elts.slice(count).join('')
1258
return _new+elts.slice(0, count).join(_new)+rest
1259
}else{return _new+elts.join(_new)+_new}
1260
}else{
1261
var elts = $StringDict.split(self,old,count)
1264
var res = self, pos = -1
1265
if(old.length==0){
1266
var res = _new
1267
for(var i=0;i<elts.length;i++){
1268
res += elts[i]+_new
1269
}
1270
return res+rest
1271
}
1272
1273
if (count < 0) count = res.length;
1274
while (count > 0) {
1275
pos = res.indexOf(old, pos);
1276
if (pos < 0)
1277
break;
1278
res = res.substr(0, pos) + _new + res.substr(pos + old.length);
1279
pos = pos + _new.length;
1280
count--;
1281
}
1282
return res;
1283
}
1284
1285
$StringDict.rfind = function(self){
1286
// Return the highest index in the string where substring sub is found,
1287
// such that sub is contained within s[start:end]. Optional arguments
1288
// start and end are interpreted as in slice notation. Return -1 on failure.
1294
normalize_start_end($)
1295
1296
if(!isinstance($.sub,str)){throw _b_.TypeError(
1297
"Can't convert '"+$B.get_class($.sub).__name__+"' object to str implicitly")}
1299
if($.sub.length==0){
1300
if($.start>$.self.length){return -1}
1301
else{return $.self.length}
1302
}
1303
var sublen = $.sub.length
1304
1305
for(var i=$.end-sublen;i>=$.start;i--){
1306
if($.self.substr(i, sublen)==$.sub){return i}
1307
}
1308
return -1
1309
}
1310
1311
$StringDict.rindex = function(){
1312
// Like rfind() but raises ValueError when the substring sub is not found
1314
if(res==-1){throw _b_.ValueError("substring not found")}
1315
return res
1316
}
1317
1318
$StringDict.rjust = function(self) {
1320
{self:null, width:null, fillchar:null},
1321
['self', 'width', 'fillchar'],
1322
arguments,{fillchar:' '},null,null)
1323
for(var attr in $ns){eval('var '+attr+'=$ns[attr]')}
1324
1325
if (width <= self.length) return self
1326
1327
return Array(width - self.length + 1).join(fillchar) + self
1328
}
1329
1330
$StringDict.rpartition = function(self,sep) {
1331
if (sep === undefined) {
1332
throw Error("sep argument is required");
1333
return
1334
}
1335
var pos=self.length-sep.length
1336
while(1){
1337
if(self.substr(pos,sep.length)==sep){
1338
return _b_.tuple([self.substr(0,pos),sep,self.substr(pos+sep.length)])
1339
}else{
1340
pos--
1341
if(pos<0){return _b_.tuple(['','',self])}
1342
}
1343
}
1344
}
1345
1346
$StringDict.rsplit = function(self) {
1347
var $=$B.args("rsplit",3,{self:null,sep:null,maxsplit:null},
1348
['self','sep','maxsplit'],arguments,
1349
{sep:_b_.None, maxsplit:-1},null,null),
1350
sep=$.sep,maxsplit=$.maxsplit,self=$.self
1351
1352
// Use split on the reverse of the string and of separator
1353
var rev_str = $.self.split('').reverse().join(''),
1354
rev_sep = sep === _b_.None ? sep : $.sep.split('').reverse().join(''),
1355
rev_res = $StringDict.split(rev_str, rev_sep, $.maxsplit)
1357
// Reverse the list, then each string inside the list
1358
rev_res.reverse()
1359
for(var i=0;i<rev_res.length;i++){
1360
rev_res[i] = rev_res[i].split('').reverse().join('')
1361
}
1362
return rev_res
1363
}
1364
1365
$StringDict.rstrip = function(self,x){
1366
if(x==undefined){var pattern="\\s*"}
1367
else{var pattern = "["+x+"]*"}
1368
sp = new RegExp(pattern+'$')
1369
return str(self.replace(sp,""))
1370
}
1371
1374
var $=$B.args("split",3,{self:null,sep:null,maxsplit:null},
1375
['self','sep','maxsplit'],arguments,
1376
{sep:_b_.None, maxsplit:-1},null,null)
1377
var sep=$.sep,maxsplit=$.maxsplit,self=$.self
1378
if(maxsplit.__class__===$B.LongInt.$dict){maxsplit=parseInt(maxsplit.value)}
1381
var res = []
1382
var pos = 0
1383
while(pos<self.length&&self.charAt(pos).search(/\s/)>-1){pos++}
1385
var name = ''
1386
while(1){
1387
if(self.charAt(pos).search(/\s/)===-1){
1388
if(name===''){name=self.charAt(pos)}
1389
else{name+=self.charAt(pos)}
1390
}else{
1391
if(name!==''){
1392
res.push(name)
1393
if(maxsplit!==-1&&res.length===maxsplit+1){
1394
res.pop()
1395
res.push(name+self.substr(pos))
1396
return res
1397
}
1398
name=''
1399
}
1400
}
1401
pos++
1402
if(pos>self.length-1){
1403
if(name){res.push(name)}
1404
break
1405
}
1406
}
1407
return res
1408
}else{
1409
var res = [],s='',pos=0,seplen=sep.length
1410
if(maxsplit==0){return [self]}
1411
while(pos<self.length){
1412
if(self.substr(pos,seplen)==sep){
1413
res.push(s)
1414
pos += seplen
1415
if(maxsplit>-1 && res.length>=maxsplit){
1416
res.push(self.substr(pos))
1417
return res
1418
}
1419
s= ''
1420
}else{
1421
s += self.charAt(pos)
1422
pos++
1427
}
1428
}
1429
1430
$StringDict.splitlines = function(self){return $StringDict.split(self,'\n')}
1431
1432
$StringDict.startswith = function(self){
1433
// Return True if string starts with the prefix, otherwise return False.
1434
// prefix can also be a tuple of prefixes to look for. With optional
1435
// start, test string beginning at that position. With optional end,
1436
// stop comparing string at that position.
1438
{self:null, prefix:null, start:null, end:null},
1439
['self', 'prefix', 'start', 'end'],
1440
arguments,{start:0, end:self.length-1},null,null)
1441
var prefixes = $ns['prefix']
1442
if(!isinstance(prefixes,_b_.tuple)){prefixes=[prefixes]}
1448
if (s.indexOf(prefixes[i]) == 0) return true
1449
}
1450
return false
1451
}
1452
1453
$StringDict.strip = function(self,x){
1454
if(x==undefined){x = "\\s"}
1455
return $StringDict.rstrip($StringDict.lstrip(self,x),x)
1456
}
1457
1458
$StringDict.swapcase = function(self) {
1459
//inspired by http://www.geekpedia.com/code69_Swap-string-case-using-JavaScript.html
1460
return self.replace(/([a-z])|([A-Z])/g, function($0,$1,$2)
1461
{ return ($1) ? $0.toUpperCase() : $0.toLowerCase()
1462
})
1463
}
1464
1465
$StringDict.title = function(self) {
1466
//inspired from http://stackoverflow.com/questions/196972/convert-string-to-title-case-with-javascript
1467
return self.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
1468
}
1469
1470
$StringDict.translate = function(self,table) {
1475
if(repl==-1){res[pos++]=self.charAt(i)}
1476
else if(repl!==None){res[pos++]=repl}
1482
$StringDict.upper = function(){
1483
var $=$B.args('lower',1,{self:null},['self'],arguments,{},null,null)
1484
return $.self.toUpperCase()
1485
}
1486
1487
$StringDict.zfill = function(self, width) {
1488
if (width === undefined || width <= self.length || !self.isnumeric()) {
1489
return self
1490
}
1491
1492
return Array(width - self.length +1).join('0');
1493
}
1494
1495
function str(arg){
1496
if(arg===undefined) return ''
1497
switch(typeof arg) {
1498
case 'string': return arg
1499
case 'number': return arg.toString()
1500
}
1506
// class or its subclasses, but the attribute __str__ of the
1507
// class metaclass (usually "type") or its subclasses (usually
1508
// "object")
1509
// The metaclass is the attribute __class__ of the class dictionary
1510
var func = $B.$type.__getattribute__(arg.$dict.__class__,'__str__')
1515
var f = getattr(arg,'__str__')
1516
// XXX fix : if not better than object.__str__, try __repr__
1517
return f()
1518
}
1519
catch(err){
1525
if($B.debug>1){console.log(err)}
1526
console.log('Warning - no method __str__ or __repr__, default to toString', arg)
1528
}
1529
}
1530
}
1531
str.__class__ = $B.$factory
1532
str.$dict = $StringDict
1533
$StringDict.$factory = str
1534
$StringDict.__new__ = function(cls){
1535
if(cls===undefined){
1536
throw _b_.TypeError('str.__new__(): not enough arguments')
1537
}
1538
return {__class__:cls.$dict}
1539
}
1540
1543
// dictionary and factory for subclasses of string
1544
var $StringSubclassDict = {
1545
__class__:$B.$type,
1546
__name__:'str'
1547
}
1548
1549
// the methods in subclass apply the methods in $StringDict to the
1550
// result of instance.valueOf(), which is a Javascript string
1551
for(var $attr in $StringDict){
1552
if(typeof $StringDict[$attr]=='function'){
1553
$StringSubclassDict[$attr]=(function(attr){
1554
return function(){
1560
}
1561
}
1562
return $StringDict[attr].apply(null,args)
1563
}
1564
})($attr)
1565
}
1566
}
1567
$StringSubclassDict.__mro__ = [$StringSubclassDict,$ObjectDict]
1568
1569
// factory for str subclasses
1570
$B.$StringSubclassFactory = {
1571
__class__:$B.$factory,
1572
$dict:$StringSubclassDict
1573
}
1574
1575
_b_.str = str
1576
1577
// Function to parse the 2nd argument of format()
1578
$B.parse_format_spec = function(spec){
1588
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1))!=-1){
1589
// If the second char is also an alignment specifier, the
1590
// first char is the fill value
1591
this.fill = spec.charAt(0)
1592
this.align = spec.charAt(1)
1593
pos = 2
1594
}else{
1595
// The first character defines alignment : fill defaults to ' '
1596
this.align=aligns[align_pos];
1597
this.fill=' ';
1598
pos++
1599
}
1600
}else{
1601
align_pos = aligns.indexOf(spec.charAt(1))
1602
if(spec.charAt(1) && align_pos!=-1){
1603
// The second character defines alignment : fill is the first one
1604
this.align=aligns[align_pos]
1605
this.fill=spec.charAt(0)
1606
pos = 2
1607
}
1608
}
1609
var car = spec.charAt(pos)
1610
if(car=='+'||car=='-'||car==' '){
1611
this.sign=car;
1612
pos++;
1613
car=spec.charAt(pos);
1616
if(car=='0'){
1617
// sign-aware : equivalent to fill=0 and align=='='
1618
this.fill='0'
1619
this.align = '='
1620
pos++;car=spec.charAt(pos)
1621
}
1623
if(this.width===undefined){this.width=car}
1624
else{this.width+=car}
1625
pos++;car=spec.charAt(pos)
1627
if(this.width!==undefined){this.width=parseInt(this.width)}
1628
if(car==','){this.comma=true;pos++;car=spec.charAt(pos)}
1629
if(car=='.'){
1630
if(digits.indexOf(spec.charAt(pos+1))==-1){
1631
throw _b_.ValueError("Missing precision in format spec")
1632
}
1633
this.precision = spec.charAt(pos+1)
1634
pos+=2;car=spec.charAt(pos)
1635
while(car && digits.indexOf(car)>-1){
1636
this.precision+=car;pos++;car=spec.charAt(pos)
1637
}
1638
this.precision = parseInt(this.precision)
1639
}
1640
if(car && types.indexOf(car)>-1){this.type=car;pos++;car=spec.charAt(pos)}
1641
if(pos!==spec.length){
1642
console.log('error', spec, this, pos, spec.charAt(pos))
1643
throw _b_.ValueError("Invalid format specifier")
1644
}
1645
}
1646
this.toString = function(){
1647
return (this.fill===undefined ? '' : _b_.str(this.fill))+
1648
(this.align||'')+
1649
(this.sign||'')+
1650
(this.alternate ? '#' : '')+
1651
(this.sign_aware ? '0' : '')+
1652
(this.width || '')+
1653
(this.comma ? ',' : '')+
1654
(this.precision ? '.'+this.precision : '')+
1655
(this.type || '')
1656
}
1657
}
1658
1659
$B.format_width = function(s, fmt){
1660
if(fmt.width && s.length<fmt.width){
1661
var fill=fmt.fill || ' ', align = fmt.align || '<',
1662
missing = fmt.width-s.length
1663
switch(align){
1664
case '<':
1665
return s+fill.repeat(missing)
1666
case '>':
1667
return fill.repeat(missing)+s
1668
case '=':
1669
if('+-'.indexOf(s.charAt(0))>-1){
1670
return s.charAt(0)+fill.repeat(missing)+s.substr(1)
1671
}else{
1672
return fill.repeat(missing)+s
1673
}
1674
case '^':
1675
left = parseInt(missing/2)