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 14, 2015
Dec 3, 2015
Dec 3, 2015
Jan 5, 2016
Jan 1, 2015
Jan 1, 2015
Newer
100644
1765 lines (1577 sloc)
55.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 reverse(s){
26
// Reverse a string
27
return s.split('').reverse().join('')
28
}
29
30
function check_str(obj){
31
if(!_b_.isinstance(obj,str)){throw _b_.TypeError("can't convert '"+
32
$B.get_class(obj).__name__+"' object to str implicitely")}
35
$StringDict.__add__ = function(self,other){
36
if(!(typeof other==="string")){
37
try{return getattr(other,'__radd__')(self)}
38
catch(err){throw _b_.TypeError(
39
"Can't convert "+$B.get_class(other).__name__+" to str implicitely")}
40
}
41
return self+other
42
}
43
44
$StringDict.__contains__ = function(self,item){
45
if(!(typeof item==="string")){throw _b_.TypeError(
46
"'in <string>' requires string as left operand, not "+item.__class__)}
47
var nbcar = item.length
48
if(nbcar==0) return true // a string contains the empty string
49
if(self.length==0) return nbcar==0
51
if(self.substr(i,nbcar)==item) return true
52
}
53
return false
54
}
55
56
$StringDict.__delitem__ = function(){
57
throw _b_.TypeError("'str' object doesn't support item deletion")
58
}
59
60
// __dir__must be assigned explicitely because attribute resolution for builtin
61
// classes doesn't use __mro__
62
$StringDict.__dir__ = $ObjectDict.__dir__
63
64
$StringDict.__eq__ = function(self,other){
65
if(other===undefined){ // compare object "self" to class "str"
66
return self===str
67
}
68
if (_b_.isinstance(other, _b_.str)) {
69
return other.valueOf() == self.valueOf()
70
}
74
function preformat(self, fmt){
75
if(fmt.empty){return _b_.str(self)}
76
if(fmt.type && fmt.type!='s'){
77
throw _b_.ValueError("Unknown format code '"+fmt.type+
78
"' for object of type 'str'")
79
}
80
return self
81
}
82
83
$StringDict.__format__ = function(self, format_spec) {
84
var fmt = new $B.parse_format_spec(format_spec)
85
// For strings, alignment default to left
86
fmt.align = fmt.align || '<'
87
return $B.format_width(preformat(self, fmt), fmt)
88
}
89
90
$StringDict.__getitem__ = function(self,arg){
91
if(isinstance(arg,_b_.int)){
92
var pos = arg
93
if(arg<0) pos+=self.length
94
if(pos>=0 && pos<self.length) return self.charAt(pos)
95
throw _b_.IndexError('string index out of range')
96
}
97
if(isinstance(arg,slice)) {
98
var s=_b_.slice.$dict.$conv_for_seq(arg, self.length),
99
start=s.start, stop=s.stop, step=s.step
100
var res = '',i=null
101
if(step>0){
102
if(stop<=start) return ''
103
for(var i=start;i<stop;i+=step) res += self.charAt(i)
104
} else {
105
if(stop>=start) return ''
107
}
108
return res
109
}
110
if(isinstance(arg,bool)) return self.__getitem__(_b_.int(arg))
115
if (self === undefined) {
116
return $StringDict.__hashvalue__ || $B.$py_next_hash-- // for hash of string type (not instance of string)
117
}
118
119
//http://stackoverflow.com/questions/2909106/python-whats-a-correct-and-good-way-to-implement-hash
120
// this implementation for strings maybe good enough for us..
121
122
var hash=1;
124
hash=(101*hash + self.charCodeAt(i)) & 0xFFFFFFFF
125
}
126
127
return hash
128
}
129
130
$StringDict.__init__ = function(self,arg){
131
self.valueOf = function(){return arg}
132
self.toString = function(){return arg}
134
}
135
136
var $str_iterator = $B.$iterator_class('str_iterator')
137
$StringDict.__iter__ = function(self){
138
var items = self.split('') // list of all characters in string
139
return $B.$iterator(items,$str_iterator)
140
}
141
142
$StringDict.__len__ = function(self){return self.length}
143
146
var kwarg_key = new RegExp('([^\\)]*)\\)')
147
148
var NotANumber = function() {
149
this.name = 'NotANumber'
150
}
151
152
var number_check=function(s) {
153
if(!isinstance(s,[_b_.int,_b_.float])){
154
throw new NotANumber()
155
}
156
}
157
158
var get_char_array = function(size, char) {
159
if (size <= 0)
160
return ''
161
return new Array(size + 1).join(char)
162
}
163
164
var format_padding = function(s, flags, minus_one) {
165
var padding = flags.padding
166
if (!padding) { // undefined
167
return s
168
}
169
s = s.toString()
170
padding = parseInt(padding, 10)
171
if (minus_one) { // numeric formatting where sign goes in front of padding
172
padding -= 1
173
}
174
if (!flags.left) {
175
return get_char_array(padding - s.length, flags.pad_char) + s
176
} else {
177
// left adjusted
178
return s + get_char_array(padding - s.length, flags.pad_char)
179
}
180
}
181
182
var format_int_precision = function(val, flags) {
183
var precision = flags.precision
184
if (!precision) {
185
return val.toString()
186
}
187
precision = parseInt(precision, 10)
188
var s
189
if (val.__class__ === $B.LongInt.$dict) {
190
s=$B.LongInt.$dict.to_base(val, 10)
191
} else {
192
s=val.toString()
193
}
194
var sign = s[0]
195
if (s[0] === '-') {
196
return '-' + get_char_array(precision - s.length + 1, '0') + s.slice(1)
197
}
198
return get_char_array(precision - s.length, '0') + s
199
}
200
201
var format_float_precision = function(val, upper, flags, modifier) {
202
var precision = flags.precision
203
// val is a float
204
if (isFinite(val)) {
205
val = modifier(val, precision, flags, upper)
206
return val
207
}
208
if (val === Infinity) {
209
val = 'inf'
210
} else if (val === -Infinity) {
211
val = '-inf'
212
} else {
213
val = 'nan'
214
}
215
if (upper) {
216
return val.toUpperCase()
217
}
218
return val
220
}
221
222
var format_sign = function(val, flags) {
223
if (flags.sign) {
224
if (val >= 0) {
225
return "+"
227
} else if (flags.space) {
228
if (val >= 0) {
229
return " "
230
}
231
}
232
return ""
233
}
235
var str_format = function(val, flags) {
236
// string format supports left and right padding
237
flags.pad_char = " " // even if 0 padding is defined, don't use it
238
return format_padding(str(val), flags)
239
}
243
if (val.__class__ === $B.LongInt.$dict) {
244
val = $B.LongInt.$dict.to_base(val, 10)
245
} else {
246
val = parseInt(val)
247
}
248
249
var s = format_int_precision(val, flags)
250
if (flags.pad_char === '0') {
251
if (val < 0) {
252
s = s.substring(1)
253
return '-' + format_padding(s, flags, true)
254
}
255
var sign = format_sign(val, flags)
256
if (sign !== '') {
257
return sign + format_padding(s, flags, true)
258
}
259
}
260
261
return format_padding(format_sign(val, flags) + s, flags)
262
}
264
var repr_format = function(val, flags) {
265
flags.pad_char = " " // even if 0 padding is defined, don't use it
266
return format_padding(repr(val), flags)
267
}
269
var ascii_format = function(val, flags) {
270
flags.pad_char = " " // even if 0 padding is defined, don't use it
271
return format_padding(ascii(val), flags)
272
}
274
// converts to val to float and sets precision if missing
275
var _float_helper = function(val, flags) {
276
number_check(val)
277
if (!flags.precision) {
278
if (!flags.decimal_point) {
279
flags.precision = 6
280
} else {
281
flags.precision = 0
282
}
283
} else {
284
flags.precision = parseInt(flags.precision, 10)
285
validate_precision(flags.precision)
286
}
287
return parseFloat(val)
288
}
290
// used to capture and remove trailing zeroes
291
var trailing_zeros = /(.*?)(0+)([eE].*)/
292
var leading_zeros = /\.(0*)/
293
var trailing_dot = /\.$/
295
var validate_precision = function(precision) {
296
// force precision to limits of javascript
298
}
299
300
// gG
301
var floating_point_format = function(val, upper, flags) {
302
val = _float_helper(val, flags)
303
var v = val.toString()
304
var v_len = v.length
305
var dot_idx = v.indexOf('.')
306
if (dot_idx < 0) {
307
dot_idx = v_len
308
}
309
if (val < 1 && val > -1) {
310
var zeros = leading_zeros.exec(v)
311
var numzeros
312
if (zeros) {
313
numzeros = zeros[1].length
314
} else {
315
numzeros = 0
316
}
317
if (numzeros >= 4) {
318
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
319
if (!flags.alternate) {
320
var trl = trailing_zeros.exec(val)
321
if (trl) {
322
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
328
}
329
return format_padding(val, flags)
330
}
331
flags.precision += numzeros
332
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
333
function(val, precision) {
334
val = val.toFixed(min(precision, v_len - dot_idx) + numzeros)
335
}), flags)
336
}
337
338
if (dot_idx > flags.precision) {
339
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
340
if (!flags.alternate) {
341
var trl = trailing_zeros.exec(val)
342
if (trl) {
343
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
344
}
345
} else {
346
if (flags.precision <= 1) {
347
val = val[0] + '.' + val.substring(1)
348
}
349
}
350
return format_padding(val, flags)
351
}
352
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
353
function(val, precision) {
354
if (!flags.decimal_point) {
355
precision = min(v_len - 1, 6)
356
} else if (precision > v_len) {
357
if (!flags.alternate) {
358
precision = v_len
360
}
361
if (precision < dot_idx) {
362
precision = dot_idx
363
}
364
return val.toFixed(precision - dot_idx)
365
}), flags)
366
}
368
var _floating_g_exp_helper = function(val, precision, flags, upper) {
369
if (precision) {
370
--precision
371
}
372
val = val.toExponential(precision)
373
// pad exponent to two digits
374
var e_idx = val.lastIndexOf('e')
375
if (e_idx > val.length - 4) {
376
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
377
}
378
if (upper) {
379
return val.toUpperCase()
380
}
381
return val
382
}
383
384
// fF
385
var floating_point_decimal_format = function(val, upper, flags) {
386
val = _float_helper(val, flags)
387
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
388
function(val, precision, flags) {
389
val = val.toFixed(precision)
390
if (precision === 0 && flags.alternate) {
391
val += '.'
392
}
393
return val
394
}), flags)
395
}
396
397
var _floating_exp_helper = function(val, precision, flags, upper) {
398
val = val.toExponential(precision)
399
// pad exponent to two digits
400
var e_idx = val.lastIndexOf('e')
401
if (e_idx > val.length - 4) {
402
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
403
}
404
if (upper) {
405
return val.toUpperCase()
406
}
407
return val
408
}
409
410
// eE
411
var floating_point_exponential_format = function(val, upper, flags) {
412
val = _float_helper(val, flags)
413
414
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_exp_helper), flags)
415
}
416
417
var signed_hex_format = function(val, upper, flags) {
420
421
if (val.__class__ === $B.LongInt.$dict) {
422
ret=$B.LongInt.$dict.to_base(val, 16)
423
} else {
424
ret = parseInt(val)
425
ret = ret.toString(16)
426
}
427
ret = format_int_precision(ret, flags)
428
if (upper) {
429
ret = ret.toUpperCase()
430
}
431
if (flags.pad_char === '0') {
432
if (val < 0) {
433
ret = ret.substring(1)
434
ret = '-' + format_padding(ret, flags, true)
435
}
436
var sign = format_sign(val, flags)
437
if (sign !== '') {
438
ret = sign + format_padding(ret, flags, true)
440
}
441
442
if (flags.alternate) {
443
if (ret.charAt(0) === '-') {
444
if (upper) {
445
ret = "-0X" + ret.slice(1)
446
} else {
447
ret = "-0x" + ret.slice(1)
448
}
449
} else {
450
if (upper) {
451
ret = "0X" + ret
452
} else {
453
ret = "0x" + ret
454
}
455
}
456
}
457
return format_padding(format_sign(val, flags) + ret, flags)
458
}
462
var ret
463
464
if (val.__class__ === $B.LongInt.$dict) {
465
ret = $B.LongInt.$dict.to_base(8)
466
} else {
467
ret = parseInt(val)
468
ret = ret.toString(8)
469
}
470
473
if (flags.pad_char === '0') {
474
if (val < 0) {
475
ret = ret.substring(1)
476
ret = '-' + format_padding(ret, flags, true)
477
}
478
var sign = format_sign(val, flags)
479
if (sign !== '') {
480
ret = sign + format_padding(ret, flags, true)
481
}
483
484
if (flags.alternate) {
485
if (ret.charAt(0) === '-') {
486
ret = "-0o" + ret.slice(1)
487
} else {
488
ret = "0o" + ret
489
}
491
return format_padding(ret, flags)
492
}
493
494
var single_char_format = function(val, flags) {
495
if(isinstance(val,str) && val.length==1) return val
496
try {
497
val = _b_.int(val) // yes, floats are valid (they are cast to int)
498
} catch (err) {
499
throw _b_.TypeError('%c requires int or char')
500
}
501
return format_padding(chr(val), flags)
502
}
503
504
var num_flag = function(c, flags) {
505
if (c === '0' && !flags.padding && !flags.decimal_point && !flags.left) {
506
flags.pad_char = '0'
507
return
508
}
509
if (!flags.decimal_point) {
510
flags.padding = (flags.padding || "") + c
511
} else {
512
flags.precision = (flags.precision || "") + c
513
}
514
}
515
516
var decimal_point_flag = function(val, flags) {
517
if (flags.decimal_point) {
518
// can only have one decimal point
519
throw new UnsupportedChar()
520
}
521
flags.decimal_point = true
522
}
523
524
var neg_flag = function(val, flags) {
525
flags.pad_char = ' ' // overrides '0' flag
526
flags.left = true
527
}
528
529
var space_flag = function(val, flags) {
530
flags.space = true
531
}
532
533
var sign_flag = function(val, flags) {
534
flags.sign = true
535
}
536
537
var alternate_flag = function(val, flags) {
538
flags.alternate = true
539
}
540
542
's': str_format,
543
'd': num_format,
544
'i': num_format,
545
'u': num_format,
546
'o': octal_format,
547
'r': repr_format,
548
'a': ascii_format,
549
'g': function(val, flags) {return floating_point_format(val, false, flags)},
550
'G': function(val, flags) {return floating_point_format(val, true, flags)},
551
'f': function(val, flags) {return floating_point_decimal_format(val, false, flags)},
552
'F': function(val, flags) {return floating_point_decimal_format(val, true, flags)},
553
'e': function(val, flags) {return floating_point_exponential_format(val, false, flags)},
554
'E': function(val, flags) {return floating_point_exponential_format(val, true, flags)},
555
'x': function(val, flags) {return signed_hex_format(val, false, flags)},
556
'X': function(val, flags) {return signed_hex_format(val, true, flags)},
557
'c': single_char_format,
558
'0': function(val, flags) {return num_flag('0', flags)},
559
'1': function(val, flags) {return num_flag('1', flags)},
560
'2': function(val, flags) {return num_flag('2', flags)},
561
'3': function(val, flags) {return num_flag('3', flags)},
562
'4': function(val, flags) {return num_flag('4', flags)},
563
'5': function(val, flags) {return num_flag('5', flags)},
564
'6': function(val, flags) {return num_flag('6', flags)},
565
'7': function(val, flags) {return num_flag('7', flags)},
566
'8': function(val, flags) {return num_flag('8', flags)},
567
'9': function(val, flags) {return num_flag('9', flags)},
568
'-': neg_flag,
569
' ': space_flag,
570
'+': sign_flag,
571
'.': decimal_point_flag,
572
'#': alternate_flag
573
}
574
575
// exception thrown when an unsupported char is encountered in legacy format
576
var UnsupportedChar = function() {
577
this.name = "UnsupportedChar"
578
}
579
591
++pos
592
var rslt = kwarg_key.exec(s.substring(newpos))
593
if (!rslt) {
594
throw _b_.ValueError("incomplete format key")
595
}
596
var key = rslt[1]
597
newpos += rslt[0].length
598
try {
600
} catch(err) {
601
if (err.name === "KeyError") {
602
throw err
603
}
604
throw _b_.TypeError("format requires a mapping")
605
}
620
}
621
catch(err) {
622
if (err.name === "IndexError") {
623
throw _b_.TypeError("not enough arguments for format string")
624
} else {
625
throw err
626
}
632
// todo: get flags, type
633
// todo: string value based on flags, type, value
634
var flags = {'pad_char': ' '}
635
do {
642
if (ret !== undefined) {
643
return ret
644
}
645
++newpos
646
}
647
} catch (err) {
648
if (err.name === "UnsupportedChar") {
649
invalid_char = s[newpos]
650
if (invalid_char === undefined) {
651
throw _b_.ValueError("incomplete format")
652
}
653
throw _b_.ValueError("unsupported format character '" + invalid_char +
654
"' (0x" + invalid_char.charCodeAt(0).toString(16) + ") at index " + newpos)
655
} else if (err.name === "NotANumber") {
656
var try_char = s[newpos]
663
}
664
} else {
665
cls = cls.__name__
666
}
667
throw _b_.TypeError("%" + try_char + " format: a number is required, not " + cls)
668
} else {
669
throw err
670
}
692
}
693
}
694
} else {
695
// % at end of string
696
throw _b_.ValueError("incomplete format")
697
}
698
pos = newpos + 1
699
} while (pos < length)
700
703
704
$StringDict.__mro__ = [$StringDict,$ObjectDict]
705
706
$StringDict.__mul__ = function(self,other){
707
var $=$B.args('__mul__',2,{self:null,other:null},['self','other'],
708
arguments,{},null,null)
709
if(!isinstance(other,_b_.int)){throw _b_.TypeError(
710
"Can't multiply sequence by non-int of type '"+
711
$B.get_class(other).__name__+"'")}
712
$res = ''
713
for(var i=0;i<other;i++){$res+=self.valueOf()}
714
return $res
715
}
716
717
$StringDict.__ne__ = function(self,other){return other!==self.valueOf()}
718
719
$StringDict.__repr__ = function(self){
720
var res = self.replace(/\n/g,'\\\\n')
721
// escape the escape char
722
res = res.replace(/\\/g, '\\\\')
723
if(res.search('"')==-1 && res.search("'")==-1){
724
return "'"+res+"'"
733
$StringDict.__setattr__ = function(self,attr,value){return setattr(self,attr,value)}
734
735
$StringDict.__setitem__ = function(self,attr,value){
736
throw _b_.TypeError("'str' object does not support item assignment")
737
}
738
$StringDict.__str__ = function(self){
739
if(self===undefined) return "<class 'str'>"
740
return self.toString()
741
}
742
$StringDict.toString = function(){return 'string!'}
743
744
// generate comparison methods
745
var $comp_func = function(self,other){
746
if(typeof other !=="string"){throw _b_.TypeError(
747
"unorderable types: 'str' > "+$B.get_class(other).__name__+"()")}
748
return self > other
749
}
750
$comp_func += '' // source code
751
var $comps = {'>':'gt','>=':'ge','<':'lt','<=':'le'}
752
for(var $op in $comps){
753
eval("$StringDict.__"+$comps[$op]+'__ = '+$comp_func.replace(/>/gm,$op))
754
}
755
756
// add "reflected" methods
757
$B.make_rmethods($StringDict)
758
759
// unsupported operations
760
var $notimplemented = function(self,other){
761
throw NotImplementedError("OPERATOR not implemented for class str")
762
}
763
764
$StringDict.capitalize = function(self){
765
if(self.length==0) return ''
766
return self.charAt(0).toUpperCase()+self.substr(1).toLowerCase()
767
}
768
769
$StringDict.casefold = function(self) {
770
throw _b_.NotImplementedError("function casefold not implemented yet");
771
}
772
773
$StringDict.center = function(self,width,fillchar){
774
var $=$B.args("center",3,
775
{self:null, width:null, fillchar:null},
776
['self', 'width', 'fillchar'],
777
arguments,{fillchar:' '},null,null)
778
779
if($.width<=self.length) return self
788
$StringDict.count = function(){
789
var $ = $B.args('count', 4, {self:null, sub:null, start:null, stop:null},
794
var substr = $.self
795
if($.start!==null){
796
var _slice
797
if($.stop!==null){_slice = _b_.slice($.start, $.stop)}
798
else{_slice = _b_.slice($.start,$.self.length)}
799
substr = $StringDict.__getitem__.apply(null, [$.self].concat(_slice))
800
}else{
801
if($.self.length+$.sub.length==0){return 1} // ''.count('') = 1
802
}
803
if($.sub.length==0){
804
if($.start==$.self.length){return 1} // 'aaa'.count('',3) = 1
805
else if(substr.length==0){return 0} // 'aaa'.count('',4) = 0
806
return substr.length+1
807
}
808
var n=0, pos=0
809
while(pos<substr.length){
810
pos=substr.indexOf($.sub,pos)
812
}
813
return n
814
}
815
816
$StringDict.encode = function(self, encoding) {
817
if (encoding === undefined) encoding='utf-8'
818
if(encoding=='rot13' || encoding=='rot_13'){
819
// Special case : returns a string
820
var res = ''
821
for(var i=0, _len = self.length; i<_len ; i++){
822
var char = self.charAt(i)
823
if(('a'<=char && char<='m') || ('A'<=char && char<='M')){
824
res += String.fromCharCode(String.charCodeAt(char)+13)
825
}else if(('m'<char && char<='z') || ('M'<char && char<='Z')){
826
res += String.fromCharCode(String.charCodeAt(char)-13)
827
}else{res += char}
828
}
829
return res
830
}
835
// Return True if the string ends with the specified suffix, otherwise
836
// return False. suffix can also be a tuple of suffixes to look for.
837
// With optional start, test beginning at that position. With optional
838
// end, stop comparing at that position.
840
{self:null, suffix:null, start:null, end:null},
841
['self', 'suffix', 'start', 'end'],
842
arguments,{start:0, end:null},null,null)
843
844
normalize_start_end($)
845
846
var suffixes = $.suffix
852
if(!_b_.isinstance(suffix, str)){throw _b_.TypeError(
853
"endswith first arg must be str or a tuple of str, not int")}
854
if(suffix.length<=s.length &&
855
s.substr(s.length-suffix.length)==suffix) return true
856
}
857
return false
858
}
859
860
$StringDict.expandtabs = function(self, tabsize) {
861
var $ = $B.args('expandtabs', 2, {self:null, tabsize:null},
862
['self', 'tabsize'], arguments, {tabsize:8}, null, null)
863
var s=$B.$GetInt($.tabsize), col=0,pos=0,res=''
864
if(s==1){return self.replace(/\t/g,' ')}
865
while(pos<self.length){
866
var car = self.charAt(pos)
867
switch(car){
868
case '\t':
869
while(col%s > 0){res += ' ';col++}
870
break
871
case '\r':
872
case '\n':
873
res += car
874
col = 0
875
break
876
default:
877
res += car
878
col++
879
break
880
}
881
pos++
882
}
883
884
return res
888
// Return the lowest index in the string where substring sub is found,
889
// such that sub is contained in the slice s[start:end]. Optional
890
// arguments start and end are interpreted as in slice notation.
891
// Return -1 if sub is not found.
900
throw _b_.TypeError(
901
"slice indices must be integers or None or have an __index__ method")}
902
var s = $.self.substring($.start,$.end)
903
904
if($.sub.length==0 && $.start==$.self.length){return $.self.length}
905
if(s.length+$.sub.length==0){return -1}
906
907
var last_search = s.length-$.sub.length
908
for(var i=0;i<=last_search;i++){
909
if(s.substr(i, $.sub.length)==$.sub){return $.start+i}
918
// Parse a "format string", as described in the Python documentation
919
// Return a format object. For the format string
920
// a.x[z]!r:...
921
// the object has attributes :
922
// - name : "a"
923
// - name_ext : [".x", "[z]"]
924
// - conv : r
925
// - spec : rest of string after :
927
var elts = fmt_string.split(':'), name, conv, spec, name_ext=[]
928
if(elts.length==1){
929
// No : in the string : it only contains a name
930
name = fmt_string
931
}else{
932
// name is before the first ":"
933
// spec (the format specification) is after
934
name = elts[0]
935
spec = elts.splice(1).join(':')
936
}
937
938
var elts = name.split('!')
939
if(elts.length>1){
940
name=elts[0]
941
conv=elts[1] // conversion flag
942
if(conv.length!==1 || 'ras'.search(conv)==-1){
943
throw _b_.ValueError('wrong conversion flag '+conv)
944
}
945
}
947
if(name!==undefined){
948
// "name' may be a subscription or attribute
949
// Put these "extensions" in the list "name_ext"
950
function name_repl(match){
951
name_ext.push(match)
952
return ''
953
}
954
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
955
name = name.replace(name_ext_re, name_repl)
956
}
965
arguments, {}, 'args', 'kw')
966
967
// Parse self to detect formatting instructions
968
// Create a list "parts" made of sections of the string :
969
// - elements of even rank are literal text
970
// - elements of odd rank are "format objects", built from the
971
// format strings in self (of the form {...})
972
var pos=0, _len=self.length, car, text='', parts=[], rank=0, defaults={}
973
974
while(pos<_len){
975
car = self.charAt(pos)
976
if(car=='{' && self.charAt(pos+1)=='{'){
977
// replace {{ by literal {
978
text += '{'
979
pos+=2
980
}else if(car=='}' && self.charAt(pos+1)=='}'){
981
// replace }} by literal }
982
text += '}'
983
pos+=2
984
}else if(car=='{'){
985
// Start of a format string
986
987
// Store current literal text
988
parts.push(text)
989
990
// Search the end of the format string, ie the } closing the
991
// opening {. Since the string can contain other pairs {} for
992
// nested formatting, an integer nb is incremented for each { and
993
// decremented for each } ; the end of the format string is
994
// reached when nb==0
995
var end = pos+1, nb=1
996
while(end<_len){
997
if(self.charAt(end)=='{'){nb++;end++}
998
else if(self.charAt(end)=='}'){
999
nb--;end++
1000
if(nb==0){
1001
// End of format string
1002
var fmt_string = self.substring(pos+1, end-1)
1003
1004
// Create a format object, by function parse_format
1005
var fmt_obj = parse_format(fmt_string)
1006
1007
// If no name is explicitely provided, use the rank
1008
if(!fmt_obj.name){
1009
fmt_obj.name=rank+''
1010
rank++
1011
}
1015
// In this case, evaluate them using the positional
1016
// or keyword arguments passed to format()
1018
if(/\d+/.exec(key)){
1019
// If key is numeric, search in positional
1020
// arguments
1021
return _b_.tuple.$dict.__getitem__($.args,
1022
parseInt(key))
1023
}else{
1024
// Else try in keyword arguments
1025
return _b_.dict.$dict.__getitem__($.kw, key)
1026
}
1027
}
1028
fmt_obj.spec = fmt_obj.spec.replace(/\{(.+?)\}/g,
1029
replace_nested)
1030
}
1031
1032
// Store format object in list "parts"
1033
parts.push(fmt_obj)
1034
text = ''
1035
break
1036
}
1037
}else{end++}
1039
if(nb>0){throw ValueError("wrong format "+self)}
1040
pos = end
1041
}else{text += car;pos++}
1045
// Apply formatting to the values passed to format()
1046
var res = '', fmt
1047
for(var i=0;i<parts.length;i++){
1048
// Literal text is added unchanged
1049
if(typeof parts[i]=='string'){res += parts[i];continue}
1050
1051
// Format objects
1052
fmt = parts[i]
1053
if(fmt.name.charAt(0).search(/\d/)>-1){
1054
// Numerical reference : use positional arguments
1055
var pos = parseInt(fmt.name),
1056
value = _b_.tuple.$dict.__getitem__($.args, pos)
1057
}else{
1058
// Use keyword arguments
1059
var value = _b_.dict.$dict.__getitem__($.kw, fmt.name)
1060
}
1061
// If name has extensions (attributes or subscriptions)
1062
for(var j=0;j<fmt.name_ext.length;j++){
1063
var ext = fmt.name_ext[j]
1064
if(ext.charAt(0)=='.'){
1065
// Attribute
1066
value = _b_.getattr(value, ext.substr(1))
1067
}else{
1068
// Subscription
1069
var key = ext.substr(1, ext.length-2)
1070
// An index made of digits is transformed into an integer
1071
if(key.charAt(0).search(/\d/)>-1){key = parseInt(key)}
1072
value = _b_.getattr(value, '__getitem__')(key)
1073
}
1074
}
1075
// If the conversion flag is set, first call a function to convert
1076
// the value
1077
if(fmt.conv=='a'){value = _b_.ascii(value)}
1078
else if(fmt.conv=='r'){value = _b_.repr(value)}
1079
else if(fmt.conv=='s'){value = _b_.str(value)}
1080
1081
// Call attribute __format__ to perform the actual formatting
1082
res += _b_.getattr(value, '__format__')(fmt.spec)
1085
}
1086
1087
$StringDict.format_map = function(self) {
1088
throw NotImplementedError("function format_map not implemented yet");
1089
}
1090
1091
$StringDict.index = function(self){
1092
// Like find(), but raise ValueError when the substring is not found.
1094
if(res===-1) throw _b_.ValueError("substring not found")
1095
return res
1096
}
1097
1098
$StringDict.isalnum = function() {
1099
var $=$B.args('isalnum',1,{self:null},['self'],arguments,{},null,null)
1100
return /^[a-z0-9]+$/i.test($.self)
1101
}
1103
$StringDict.isalpha = function(self) {
1104
var $=$B.args('isalpha',1,{self:null},['self'],arguments,{},null,null)
1105
return /^[a-z]+$/i.test($.self)
1106
}
1108
$StringDict.isdecimal = function(){
1109
var $=$B.args('isdecimal',1,{self:null},['self'],arguments,{},null,null)
1111
return /^[0-9]+$/.test($.self)
1112
}
1113
1114
$StringDict.isdigit = function() {
1115
var $=$B.args('isdigit',1,{self:null},['self'],arguments,{},null,null)
1116
return /^[0-9]+$/.test($.self)
1117
}
1118
1119
$StringDict.isidentifier = function() {
1120
var $=$B.args('isidentifier',1,{self:null},['self'],arguments,{},null,null)
1122
if($.self.search(/\$/)>-1){return false}
1123
var last = $.self.charAt($.self.length-1)
1124
if(' \n;'.search(last)>-1){return false}
1125
var dummy = {}
1126
try{eval("dummy."+$.self); return true}
1127
catch(err){return false}
1128
}
1129
1130
$StringDict.islower = function() {
1131
var $=$B.args('islower',1,{self:null},['self'],arguments,{},null,null)
1132
// A string only made of whitespace is not lower for Python
1133
return $.self==$.self.toLowerCase() && $.self.search(/^\s*$/)==-1
1137
$StringDict.isnumeric = function() {
1138
var $=$B.args('isnumeric',1,{self:null},['self'],arguments,{},null,null)
1139
return /^[0-9]+$/.test($.self)
1140
}
1143
$StringDict.isprintable = function() {
1144
var $=$B.args('isprintable',1,{self:null},['self'],arguments,{},null,null)
1145
return !/[^ -~]/.test($.self)
1146
}
1148
$StringDict.isspace = function() {
1149
var $=$B.args('isspace',1,{self:null},['self'],arguments,{},null,null)
1150
return /^\s+$/i.test($.self)
1151
}
1153
$StringDict.istitle = function() {
1154
var $=$B.args('istitle',1,{self:null},['self'],arguments,{},null,null)
1155
if($.self.search(/^\s*$/)>-1){return false}
1156
1157
function get_case(char){
1158
if(char.toLowerCase()==char.toUpperCase()){return false}
1159
else if(char==char.toLowerCase()){return 'lower'}
1160
else{return 'upper'}
1161
}
1162
var pos=0,char,previous=false
1163
while(pos<$.self.length){
1164
char = $.self.charAt(pos)
1165
if(previous===undefined){previous=get_case(char)}
1166
else{
1167
_case = get_case(char)
1168
if(_case=='upper' && previous){return false}
1169
else if(_case=='lower' && !previous){return false}
1170
previous=_case
1171
}
1172
pos++
1173
}
1174
return true
1175
}
1177
$StringDict.isupper = function() {
1178
var $=$B.args('isupper',1,{self:null},['self'],arguments,{},null,null)
1179
return $.self==$.self.toUpperCase() && $.self.search(/^\s*$/)==-1
1180
}
1182
$StringDict.join = function(){
1183
var $=$B.args('join',2,{self:null,iterable:null},
1184
['self', 'iterable'], arguments, {}, null, null)
1185
1186
var iterable=_b_.iter($.iterable)
1187
var res = [],count=0
1191
if(!isinstance(obj2,str)){throw _b_.TypeError(
1192
"sequence item "+count+": expected str instance, "+$B.get_class(obj2).__name__+" found")}
1202
$StringDict.ljust = function(self) {
1203
var $=$B.args('ljust',3,{self:null,width:null,fillchar:null},
1204
['self','width','fillchar'],arguments,{fillchar:' '},null,null)
1205
1206
if ($.width <= self.length) return self
1207
return self + $.fillchar.repeat($.width - self.length)
1210
$StringDict.lower = function(){
1211
var $=$B.args('lower',1,{self:null},['self'],arguments,{},null,null)
1212
return $.self.toLowerCase()
1213
}
1216
var $=$B.args('lstrip',2,{self:null,chars:null},['self','chars'],
1217
arguments,{chars:_b_.None},null,null)
1218
if($.chars===_b_.None){return $.self.replace(/^\s+/,'')}
1219
return $.self.replace(new RegExp("^["+$.chars+"]*"),"")
1220
}
1221
1222
// note, maketrans should be a static function.
1223
$StringDict.maketrans = function(from, to) {
1224
var _t=[]
1225
// make 'default' translate table
1226
for(var i=0; i < 256; i++) _t[i]=String.fromCharCode(i)
1227
1228
// make substitution in the translation table
1230
var _ndx=from.source[i].charCodeAt(0) //retrieve ascii code of char
1231
_t[_ndx]=to.source[i]
1232
}
1233
1234
// create a data structure that string.translate understands
1242
$StringDict.partition = function() {
1243
var $=$B.args('partition',2,{self:null,sep:null},['self','sep'],
1244
arguments,{},null,null)
1245
if($.sep==''){throw _b_.ValueError('empty separator')}
1246
check_str($.sep)
1247
var i=$.self.indexOf($.sep)
1248
if (i== -1) return _b_.tuple([$.self, '', ''])
1249
return _b_.tuple([$.self.substring(0,i), $.sep,
1250
$.self.substring(i+$.sep.length)])
1257
var re = new RegExp('\\'+specials.charAt(i),'g')
1258
str = str.replace(re, "\\"+specials.charAt(i))
1259
}
1260
return str
1261
}
1262
1263
$StringDict.replace = function(self, old, _new, count) {
1264
// Replaces occurrences of 'old' by '_new'. Count references
1265
// the number of times to replace. In CPython, negative or undefined
1266
// values of count means replace all.
1267
var $ = $B.args('replace', 4, {self:null,old:null,$$new:null,count:null},
1268
['self','old','$$new','count'], arguments, {count:-1},null,null),
1269
count=$.count,self=$.self,old=$.old,_new=$.$$new
1273
// Validate instance type of 'count'
1274
if (!isinstance(count,[_b_.int,_b_.float])) {
1275
throw _b_.TypeError("'" + $B.get_class(count).__name__ +
1276
"' object cannot be interpreted as an integer");
1277
} else if (isinstance(count, _b_.float)) {
1278
throw _b_.TypeError("integer argument expected, got float");
1279
}
1280
if(count==0){return self}
1281
if(count.__class__==$B.LongInt.$dict){count=parseInt(count.value)}
1282
if(old==''){
1283
if(_new==''){return self}
1284
if(self==''){return _new}
1285
var elts=self.split('')
1286
if(count>-1 && elts.length>=count){
1287
var rest = elts.slice(count).join('')
1288
return _new+elts.slice(0, count).join(_new)+rest
1289
}else{return _new+elts.join(_new)+_new}
1290
}else{
1291
var elts = $StringDict.split(self,old,count)
1294
var res = self, pos = -1
1295
if(old.length==0){
1296
var res = _new
1297
for(var i=0;i<elts.length;i++){
1298
res += elts[i]+_new
1299
}
1300
return res+rest
1301
}
1302
1303
if (count < 0) count = res.length;
1304
while (count > 0) {
1305
pos = res.indexOf(old, pos);
1306
if (pos < 0)
1307
break;
1308
res = res.substr(0, pos) + _new + res.substr(pos + old.length);
1309
pos = pos + _new.length;
1310
count--;
1311
}
1312
return res;
1313
}
1314
1315
$StringDict.rfind = function(self){
1316
// Return the highest index in the string where substring sub is found,
1317
// such that sub is contained within s[start:end]. Optional arguments
1318
// start and end are interpreted as in slice notation. Return -1 on failure.
1328
if($.sub.length==0){
1329
if($.start>$.self.length){return -1}
1330
else{return $.self.length}
1331
}
1332
var sublen = $.sub.length
1333
1334
for(var i=$.end-sublen;i>=$.start;i--){
1335
if($.self.substr(i, sublen)==$.sub){return i}
1336
}
1337
return -1
1338
}
1339
1340
$StringDict.rindex = function(){
1341
// Like rfind() but raises ValueError when the substring sub is not found
1343
if(res==-1){throw _b_.ValueError("substring not found")}
1344
return res
1345
}
1346
1347
$StringDict.rjust = function(self) {
1349
{self:null, width:null, fillchar:null},
1350
['self', 'width', 'fillchar'],
1351
arguments,{fillchar:' '},null,null)
1359
var $=$B.args('rpartition',2,{self:null,sep:null},['self','sep'],
1360
arguments,{},null,null)
1361
check_str($.sep)
1362
var self = reverse($.self),
1363
sep = reverse($.sep)
1364
var items = $StringDict.partition(self,sep).reverse()
1365
for(var i=0;i<items.length;i++){
1366
items[i]=items[i].split('').reverse().join('')
1367
}
1368
return items
1372
var $=$B.args("rsplit",3,{self:null,sep:null,maxsplit:null},
1373
['self','sep','maxsplit'],arguments,
1374
{sep:_b_.None, maxsplit:-1},null,null),
1375
sep=$.sep,maxsplit=$.maxsplit,self=$.self
1376
1377
// Use split on the reverse of the string and of separator
1378
var rev_str = reverse($.self),
1379
rev_sep = sep === _b_.None ? sep : reverse($.sep),
1382
// Reverse the list, then each string inside the list
1383
rev_res.reverse()
1384
for(var i=0;i<rev_res.length;i++){
1391
var $=$B.args('rstrip',2,{self:null,chars:null},['self','chars'],
1392
arguments,{chars:_b_.None},null,null)
1393
if($.chars===_b_.None){return $.self.replace(/\s+$/,'')}
1394
return $.self.replace(new RegExp("["+$.chars+"]*$"),"")
1399
var $=$B.args("split",3,{self:null,sep:null,maxsplit:null},
1400
['self','sep','maxsplit'],arguments,
1401
{sep:_b_.None, maxsplit:-1},null,null)
1402
var sep=$.sep,maxsplit=$.maxsplit,self=$.self
1403
if(maxsplit.__class__===$B.LongInt.$dict){maxsplit=parseInt(maxsplit.value)}
1406
var res = []
1407
var pos = 0
1408
while(pos<self.length&&self.charAt(pos).search(/\s/)>-1){pos++}
1410
var name = ''
1411
while(1){
1412
if(self.charAt(pos).search(/\s/)===-1){
1413
if(name===''){name=self.charAt(pos)}
1414
else{name+=self.charAt(pos)}
1415
}else{
1416
if(name!==''){
1417
res.push(name)
1418
if(maxsplit!==-1&&res.length===maxsplit+1){
1419
res.pop()
1420
res.push(name+self.substr(pos))
1421
return res
1422
}
1423
name=''
1424
}
1425
}
1426
pos++
1427
if(pos>self.length-1){
1428
if(name){res.push(name)}
1429
break
1430
}
1431
}
1432
return res
1433
}else{
1434
var res = [],s='',pos=0,seplen=sep.length
1435
if(maxsplit==0){return [self]}
1436
while(pos<self.length){
1437
if(self.substr(pos,seplen)==sep){
1438
res.push(s)
1439
pos += seplen
1440
if(maxsplit>-1 && res.length>=maxsplit){
1441
res.push(self.substr(pos))
1442
return res
1443
}
1444
s= ''
1445
}else{
1446
s += self.charAt(pos)
1447
pos++
1455
$StringDict.splitlines = function(self){
1456
var $=$B.args('splitlines',2,{self:null,keepends:null},
1457
['self','keepends'],arguments,{keepends:false},null,null)
1458
if(!_b_.isinstance($.keepends,[_b_.bool, _b_.int])){
1459
throw _b_.TypeError('integer argument expected, got '+
1460
$B.get_class($.keepends).__name)
1461
}
1462
var keepends = _b_.int($.keepends)
1463
// Remove trailing line breaks
1464
if(keepends){
1465
var res = [],start=pos,pos=0,x,self=$.self
1466
while(pos<self.length){
1467
if(self.substr(pos,2)=='\r\n'){
1468
res.push(self.substring(start,pos+2))
1469
start = pos+2
1470
pos = start
1471
}else if(self.charAt(pos)=='\r' || self.charAt(pos)=='\n'){
1472
res.push(self.substring(start,pos+1))
1473
start = pos+1
1474
pos = start
1475
}else{pos++}
1476
}
1477
var rest = self.substr(start)
1478
if(rest){res.push(rest)}
1479
return res
1480
}else{
1481
var self = $.self.replace(/[\r\n]$/,'')
1482
return self.split(/\n|\r\n|\r/)
1483
}
1484
}
1487
// Return True if string starts with the prefix, otherwise return False.
1488
// prefix can also be a tuple of prefixes to look for. With optional
1489
// start, test string beginning at that position. With optional end,
1490
// stop comparing string at that position.
1492
{self:null, prefix:null, start:null, end:null},
1493
['self', 'prefix', 'start', 'end'],
1496
normalize_start_end($)
1497
1498
var prefixes = $.prefix
1499
if(!isinstance(prefixes,_b_.tuple)){prefixes=[prefixes]}
1500
1501
var s = $.self.substring($.start,$.end)
1502
for(var i=0, _len_i = prefixes.length; i < _len_i;i++){
1503
prefix = prefixes[i]
1504
if(!_b_.isinstance(prefix, str)){throw _b_.TypeError(
1505
"endswith first arg must be str or a tuple of str, not int")}
1506
if(s.substr(0,prefix.length)==prefix) return true
1512
$StringDict.strip = function(){
1513
var $=$B.args('strip',2,{self:null,chars:null},['self','chars'],
1514
arguments,{chars:_b_.None},null,null)
1515
return $StringDict.rstrip($StringDict.lstrip($.self,$.chars),$.chars)
1521
//inspired by http://www.geekpedia.com/code69_Swap-string-case-using-JavaScript.html
1523
{ return ($1) ? $0.toUpperCase() : $0.toLowerCase()
1524
})
1525
}
1526
1527
$StringDict.title = function(self) {
1528
var $=$B.args('title',1,{self:null},['self'],arguments,{},null,null)
1529
1530
// Transform letters after a non-cased character to uppercase
1531
var res = '',previous=false
1532
1533
function is_cased(c){
1534
return c.toLowerCase() != c.toUpperCase()
1535
}
1536
1537
for(var i=0;i<$.self.length;i++){
1538
var char = $.self.charAt(i), cased = is_cased(char)
1539
if(!previous && cased){
1540
res += char.toUpperCase()
1541
}else if(previous){res+=char.toLowerCase()}
1542
else{res+=char}
1543
previous = cased
1544
}
1545
return res
1553
if(repl==-1){res[pos++]=self.charAt(i)}
1554
else if(repl!==None){res[pos++]=repl}
1560
$StringDict.upper = function(){
1561
var $=$B.args('lower',1,{self:null},['self'],arguments,{},null,null)
1562
return $.self.toUpperCase()
1563
}
1566
var $=$B.args('zfill',2,{self:null,width:null},
1567
['self','width'],arguments,{},null,null)
1568
if ($.width <= self.length) {return self}
1569
switch(self.charAt(0)){
1570
case '+':
1571
case '-':
1572
return self.charAt(0)+'0'.repeat($.width-self.length)+self.substr(1)
1573
default:
1574
return '0'.repeat(width - self.length)+self
1575
}
1580
switch(typeof arg) {
1581
case 'string': return arg
1582
case 'number': return arg.toString()
1583
}
1589
// class or its subclasses, but the attribute __str__ of the
1590
// class metaclass (usually "type") or its subclasses (usually
1591
// "object")
1592
// The metaclass is the attribute __class__ of the class dictionary
1593
var func = $B.$type.__getattribute__(arg.$dict.__class__,'__str__')
1598
var f = getattr(arg,'__str__')
1599
// XXX fix : if not better than object.__str__, try __repr__
1600
return f()
1601
}
1602
catch(err){
1608
if($B.debug>1){console.log(err)}
1609
console.log('Warning - no method __str__ or __repr__, default to toString', arg)
1611
}
1612
}
1613
}
1614
str.__class__ = $B.$factory
1615
str.$dict = $StringDict
1616
$StringDict.$factory = str
1617
$StringDict.__new__ = function(cls){
1618
if(cls===undefined){
1619
throw _b_.TypeError('str.__new__(): not enough arguments')
1620
}
1621
return {__class__:cls.$dict}
1622
}
1623
1626
// dictionary and factory for subclasses of string
1627
var $StringSubclassDict = {
1628
__class__:$B.$type,
1629
__name__:'str'
1630
}
1631
1632
// the methods in subclass apply the methods in $StringDict to the
1633
// result of instance.valueOf(), which is a Javascript string
1634
for(var $attr in $StringDict){
1635
if(typeof $StringDict[$attr]=='function'){
1636
$StringSubclassDict[$attr]=(function(attr){
1637
return function(){
1643
}
1644
}
1645
return $StringDict[attr].apply(null,args)
1646
}
1647
})($attr)
1648
}
1649
}
1650
$StringSubclassDict.__mro__ = [$StringSubclassDict,$ObjectDict]
1651
1652
// factory for str subclasses
1653
$B.$StringSubclassFactory = {
1654
__class__:$B.$factory,
1655
$dict:$StringSubclassDict
1656
}
1657
1658
_b_.str = str
1659
1660
// Function to parse the 2nd argument of format()
1661
$B.parse_format_spec = function(spec){
1671
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1))!=-1){
1672
// If the second char is also an alignment specifier, the
1673
// first char is the fill value
1674
this.fill = spec.charAt(0)
1675
this.align = spec.charAt(1)
1676
pos = 2
1677
}else{
1678
// The first character defines alignment : fill defaults to ' '
1679
this.align=aligns[align_pos];
1680
this.fill=' ';
1681
pos++
1682
}
1683
}else{
1684
align_pos = aligns.indexOf(spec.charAt(1))
1685
if(spec.charAt(1) && align_pos!=-1){
1686
// The second character defines alignment : fill is the first one
1687
this.align=aligns[align_pos]
1688
this.fill=spec.charAt(0)
1689
pos = 2
1690
}
1691
}
1692
var car = spec.charAt(pos)
1693
if(car=='+'||car=='-'||car==' '){
1694
this.sign=car;
1695
pos++;
1696
car=spec.charAt(pos);
1699
if(car=='0'){
1700
// sign-aware : equivalent to fill=0 and align=='='
1701
this.fill='0'
1702
this.align = '='
1703
pos++;car=spec.charAt(pos)
1704
}
1706
if(this.width===undefined){this.width=car}
1707
else{this.width+=car}
1708
pos++;car=spec.charAt(pos)
1710
if(this.width!==undefined){this.width=parseInt(this.width)}
1711
if(car==','){this.comma=true;pos++;car=spec.charAt(pos)}
1712
if(car=='.'){
1713
if(digits.indexOf(spec.charAt(pos+1))==-1){
1714
throw _b_.ValueError("Missing precision in format spec")
1715
}
1716
this.precision = spec.charAt(pos+1)
1717
pos+=2;car=spec.charAt(pos)
1718
while(car && digits.indexOf(car)>-1){
1719
this.precision+=car;pos++;car=spec.charAt(pos)
1720
}
1721
this.precision = parseInt(this.precision)
1722
}
1723
if(car && types.indexOf(car)>-1){this.type=car;pos++;car=spec.charAt(pos)}
1724
if(pos!==spec.length){
1726
throw _b_.ValueError("Invalid format specifier")
1727
}
1728
}
1729
this.toString = function(){
1730
return (this.fill===undefined ? '' : _b_.str(this.fill))+
1731
(this.align||'')+
1732
(this.sign||'')+
1733
(this.alternate ? '#' : '')+
1734
(this.sign_aware ? '0' : '')+
1735
(this.width || '')+
1736
(this.comma ? ',' : '')+
1737
(this.precision ? '.'+this.precision : '')+
1738
(this.type || '')
1739
}
1740
}
1741
1742
$B.format_width = function(s, fmt){
1743
if(fmt.width && s.length<fmt.width){
1744
var fill=fmt.fill || ' ', align = fmt.align || '<',
1745
missing = fmt.width-s.length
1746
switch(align){
1747
case '<':
1748
return s+fill.repeat(missing)
1749
case '>':
1750
return fill.repeat(missing)+s
1751
case '=':
1752
if('+-'.indexOf(s.charAt(0))>-1){
1753
return s.charAt(0)+fill.repeat(missing)+s.substr(1)
1754
}else{
1755
return fill.repeat(missing)+s
1756
}
1757
case '^':
1758
left = parseInt(missing/2)