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
Jan 1, 2015
Jan 1, 2015
Newer
100644
1791 lines (1602 sloc)
56.1 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
}
1014
// "spec" may contain "nested replacement fields"
1015
// In this case, evaluate them using the keyword
1016
// arguments passed to format()
1017
function replace_nested(name, key){
1020
}
1021
fmt_obj.spec = fmt_obj.spec.replace(/\{(.+?)\}/g,
1022
replace_nested)
1023
}
1024
1025
// Store format object in list "parts"
1026
parts.push(fmt_obj)
1027
text = ''
1028
break
1029
}
1030
}else{end++}
1032
if(nb>0){throw ValueError("wrong format "+self)}
1033
pos = end
1034
}else{text += car;pos++}
1038
// Apply formatting to the values passed to format()
1039
var res = '', fmt
1040
for(var i=0;i<parts.length;i++){
1041
// Literal text is added unchanged
1042
if(typeof parts[i]=='string'){res += parts[i];continue}
1043
1044
// Format objects
1045
fmt = parts[i]
1046
if(fmt.name.charAt(0).search(/\d/)>-1){
1047
// Numerical reference : use positional arguments
1048
var pos = parseInt(fmt.name),
1049
value = _b_.tuple.$dict.__getitem__($.args, pos)
1050
}else{
1051
// Use keyword arguments
1052
var value = _b_.dict.$dict.__getitem__($.kw, fmt.name)
1053
}
1054
// If name has extensions (attributes or subscriptions)
1055
for(var j=0;j<fmt.name_ext.length;j++){
1056
var ext = fmt.name_ext[j]
1057
if(ext.charAt(0)=='.'){
1058
// Attribute
1059
value = _b_.getattr(value, ext.substr(1))
1060
}else{
1061
// Subscription
1062
var key = ext.substr(1, ext.length-2)
1063
// An index made of digits is transformed into an integer
1064
if(key.charAt(0).search(/\d/)>-1){key = parseInt(key)}
1065
value = _b_.getattr(value, '__getitem__')(key)
1066
}
1067
}
1068
// If the conversion flag is set, first call a function to convert
1069
// the value
1070
if(fmt.conv=='a'){value = _b_.ascii(value)}
1071
else if(fmt.conv=='r'){value = _b_.repr(value)}
1072
else if(fmt.conv=='s'){value = _b_.str(value)}
1073
1074
// Call attribute __format__ to perform the actual formatting
1075
res += _b_.getattr(value, '__format__')(fmt.spec)
1078
}
1079
1080
$StringDict.format_map = function(self) {
1081
throw NotImplementedError("function format_map not implemented yet");
1082
}
1083
1084
$StringDict.index = function(self){
1085
// Like find(), but raise ValueError when the substring is not found.
1087
if(res===-1) throw _b_.ValueError("substring not found")
1088
return res
1089
}
1090
1091
$StringDict.isalnum = function() {
1092
var $=$B.args('isalnum',1,{self:null},['self'],arguments,{},null,null)
1093
return /^[a-z0-9]+$/i.test($.self)
1094
}
1096
$StringDict.isalpha = function(self) {
1097
var $=$B.args('isalpha',1,{self:null},['self'],arguments,{},null,null)
1098
return /^[a-z]+$/i.test($.self)
1099
}
1101
$StringDict.isdecimal = function(){
1102
var $=$B.args('isdecimal',1,{self:null},['self'],arguments,{},null,null)
1104
return /^[0-9]+$/.test($.self)
1105
}
1106
1107
$StringDict.isdigit = function() {
1108
var $=$B.args('isdigit',1,{self:null},['self'],arguments,{},null,null)
1109
return /^[0-9]+$/.test($.self)
1110
}
1111
1112
$StringDict.isidentifier = function() {
1113
var $=$B.args('isidentifier',1,{self:null},['self'],arguments,{},null,null)
1114
1115
switch($.self) {
1116
case 'False':
1117
case 'None':
1118
case 'True':
1119
case 'and':
1120
case 'as':
1121
case 'assert':
1122
case 'break':
1123
case 'class':
1124
case 'continue':
1125
case 'def':
1126
case 'del':
1127
case 'elif':
1128
case 'else':
1129
case 'except':
1130
case 'finally':
1131
case 'for':
1132
case 'from':
1133
case 'global':
1134
case 'if':
1135
case 'import':
1136
case 'in':
1137
case 'is':
1138
case 'lambda':
1139
case 'nonlocal':
1140
case 'not':
1141
case 'or':
1142
case 'pass':
1143
case 'raise':
1144
case 'return':
1145
case 'try':
1146
case 'while':
1147
case 'with':
1148
case 'yield':
1149
return true
1150
}
1151
1152
// fixme.. this isn't complete but should be a good start
1153
return /^[a-z][0-9a-z_]+$/i.test($.self)
1154
}
1155
1156
$StringDict.islower = function() {
1157
var $=$B.args('islower',1,{self:null},['self'],arguments,{},null,null)
1158
// A string only made of whitespace is not lower for Python
1159
return $.self==$.self.toLowerCase() && $.self.search(/^\s*$/)==-1
1163
$StringDict.isnumeric = function() {
1164
var $=$B.args('isnumeric',1,{self:null},['self'],arguments,{},null,null)
1165
return /^[0-9]+$/.test($.self)
1166
}
1169
$StringDict.isprintable = function() {
1170
var $=$B.args('isprintable',1,{self:null},['self'],arguments,{},null,null)
1171
return !/[^ -~]/.test($.self)
1172
}
1174
$StringDict.isspace = function() {
1175
var $=$B.args('isspace',1,{self:null},['self'],arguments,{},null,null)
1176
return /^\s+$/i.test($.self)
1177
}
1179
$StringDict.istitle = function() {
1180
var $=$B.args('istitle',1,{self:null},['self'],arguments,{},null,null)
1181
if($.self.search(/^\s*$/)>-1){return false}
1182
1183
function get_case(char){
1184
if(char.toLowerCase()==char.toUpperCase()){return false}
1185
else if(char==char.toLowerCase()){return 'lower'}
1186
else{return 'upper'}
1187
}
1188
var pos=0,char,previous=false
1189
while(pos<$.self.length){
1190
char = $.self.charAt(pos)
1191
if(previous===undefined){previous=get_case(char)}
1192
else{
1193
_case = get_case(char)
1194
if(_case=='upper' && previous){return false}
1195
else if(_case=='lower' && !previous){return false}
1196
previous=_case
1197
}
1198
pos++
1199
}
1200
return true
1201
}
1203
$StringDict.isupper = function() {
1204
var $=$B.args('isupper',1,{self:null},['self'],arguments,{},null,null)
1205
return $.self==$.self.toUpperCase() && $.self.search(/^\s*$/)==-1
1206
}
1208
$StringDict.join = function(){
1209
var $=$B.args('join',2,{self:null,iterable:null},
1210
['self', 'iterable'], arguments, {}, null, null)
1211
1212
var iterable=_b_.iter($.iterable)
1213
var res = [],count=0
1217
if(!isinstance(obj2,str)){throw _b_.TypeError(
1218
"sequence item "+count+": expected str instance, "+$B.get_class(obj2).__name__+" found")}
1228
$StringDict.ljust = function(self) {
1229
var $=$B.args('ljust',3,{self:null,width:null,fillchar:null},
1230
['self','width','fillchar'],arguments,{fillchar:' '},null,null)
1231
1232
if ($.width <= self.length) return self
1233
return self + $.fillchar.repeat($.width - self.length)
1236
$StringDict.lower = function(){
1237
var $=$B.args('lower',1,{self:null},['self'],arguments,{},null,null)
1238
return $.self.toLowerCase()
1239
}
1242
var $=$B.args('lstrip',2,{self:null,chars:null},['self','chars'],
1243
arguments,{chars:_b_.None},null,null)
1244
if($.chars===_b_.None){return $.self.replace(/^\s+/,'')}
1245
return $.self.replace(new RegExp("^["+$.chars+"]*"),"")
1246
}
1247
1248
// note, maketrans should be a static function.
1249
$StringDict.maketrans = function(from, to) {
1250
var _t=[]
1251
// make 'default' translate table
1252
for(var i=0; i < 256; i++) _t[i]=String.fromCharCode(i)
1253
1254
// make substitution in the translation table
1256
var _ndx=from.source[i].charCodeAt(0) //retrieve ascii code of char
1257
_t[_ndx]=to.source[i]
1258
}
1259
1260
// create a data structure that string.translate understands
1268
$StringDict.partition = function() {
1269
var $=$B.args('partition',2,{self:null,sep:null},['self','sep'],
1270
arguments,{},null,null)
1271
if($.sep==''){throw _b_.ValueError('empty separator')}
1272
check_str($.sep)
1273
var i=$.self.indexOf($.sep)
1274
if (i== -1) return _b_.tuple([$.self, '', ''])
1275
return _b_.tuple([$.self.substring(0,i), $.sep,
1276
$.self.substring(i+$.sep.length)])
1283
var re = new RegExp('\\'+specials.charAt(i),'g')
1284
str = str.replace(re, "\\"+specials.charAt(i))
1285
}
1286
return str
1287
}
1288
1289
$StringDict.replace = function(self, old, _new, count) {
1290
// Replaces occurrences of 'old' by '_new'. Count references
1291
// the number of times to replace. In CPython, negative or undefined
1292
// values of count means replace all.
1293
var $ = $B.args('replace', 4, {self:null,old:null,$$new:null,count:null},
1294
['self','old','$$new','count'], arguments, {count:-1},null,null),
1295
count=$.count,self=$.self,old=$.old,_new=$.$$new
1299
// Validate instance type of 'count'
1300
if (!isinstance(count,[_b_.int,_b_.float])) {
1301
throw _b_.TypeError("'" + $B.get_class(count).__name__ +
1302
"' object cannot be interpreted as an integer");
1303
} else if (isinstance(count, _b_.float)) {
1304
throw _b_.TypeError("integer argument expected, got float");
1305
}
1306
if(count==0){return self}
1307
if(count.__class__==$B.LongInt.$dict){count=parseInt(count.value)}
1308
if(old==''){
1309
if(_new==''){return self}
1310
if(self==''){return _new}
1311
var elts=self.split('')
1312
if(count>-1 && elts.length>=count){
1313
var rest = elts.slice(count).join('')
1314
return _new+elts.slice(0, count).join(_new)+rest
1315
}else{return _new+elts.join(_new)+_new}
1316
}else{
1317
var elts = $StringDict.split(self,old,count)
1320
var res = self, pos = -1
1321
if(old.length==0){
1322
var res = _new
1323
for(var i=0;i<elts.length;i++){
1324
res += elts[i]+_new
1325
}
1326
return res+rest
1327
}
1328
1329
if (count < 0) count = res.length;
1330
while (count > 0) {
1331
pos = res.indexOf(old, pos);
1332
if (pos < 0)
1333
break;
1334
res = res.substr(0, pos) + _new + res.substr(pos + old.length);
1335
pos = pos + _new.length;
1336
count--;
1337
}
1338
return res;
1339
}
1340
1341
$StringDict.rfind = function(self){
1342
// Return the highest index in the string where substring sub is found,
1343
// such that sub is contained within s[start:end]. Optional arguments
1344
// start and end are interpreted as in slice notation. Return -1 on failure.
1354
if($.sub.length==0){
1355
if($.start>$.self.length){return -1}
1356
else{return $.self.length}
1357
}
1358
var sublen = $.sub.length
1359
1360
for(var i=$.end-sublen;i>=$.start;i--){
1361
if($.self.substr(i, sublen)==$.sub){return i}
1362
}
1363
return -1
1364
}
1365
1366
$StringDict.rindex = function(){
1367
// Like rfind() but raises ValueError when the substring sub is not found
1369
if(res==-1){throw _b_.ValueError("substring not found")}
1370
return res
1371
}
1372
1373
$StringDict.rjust = function(self) {
1375
{self:null, width:null, fillchar:null},
1376
['self', 'width', 'fillchar'],
1377
arguments,{fillchar:' '},null,null)
1385
var $=$B.args('rpartition',2,{self:null,sep:null},['self','sep'],
1386
arguments,{},null,null)
1387
check_str($.sep)
1388
var self = reverse($.self),
1389
sep = reverse($.sep)
1390
var items = $StringDict.partition(self,sep).reverse()
1391
for(var i=0;i<items.length;i++){
1392
items[i]=items[i].split('').reverse().join('')
1393
}
1394
return items
1398
var $=$B.args("rsplit",3,{self:null,sep:null,maxsplit:null},
1399
['self','sep','maxsplit'],arguments,
1400
{sep:_b_.None, maxsplit:-1},null,null),
1401
sep=$.sep,maxsplit=$.maxsplit,self=$.self
1402
1403
// Use split on the reverse of the string and of separator
1404
var rev_str = reverse($.self),
1405
rev_sep = sep === _b_.None ? sep : reverse($.sep),
1408
// Reverse the list, then each string inside the list
1409
rev_res.reverse()
1410
for(var i=0;i<rev_res.length;i++){
1417
var $=$B.args('rstrip',2,{self:null,chars:null},['self','chars'],
1418
arguments,{chars:_b_.None},null,null)
1419
if($.chars===_b_.None){return $.self.replace(/\s+$/,'')}
1420
return $.self.replace(new RegExp("["+$.chars+"]*$"),"")
1425
var $=$B.args("split",3,{self:null,sep:null,maxsplit:null},
1426
['self','sep','maxsplit'],arguments,
1427
{sep:_b_.None, maxsplit:-1},null,null)
1428
var sep=$.sep,maxsplit=$.maxsplit,self=$.self
1429
if(maxsplit.__class__===$B.LongInt.$dict){maxsplit=parseInt(maxsplit.value)}
1432
var res = []
1433
var pos = 0
1434
while(pos<self.length&&self.charAt(pos).search(/\s/)>-1){pos++}
1436
var name = ''
1437
while(1){
1438
if(self.charAt(pos).search(/\s/)===-1){
1439
if(name===''){name=self.charAt(pos)}
1440
else{name+=self.charAt(pos)}
1441
}else{
1442
if(name!==''){
1443
res.push(name)
1444
if(maxsplit!==-1&&res.length===maxsplit+1){
1445
res.pop()
1446
res.push(name+self.substr(pos))
1447
return res
1448
}
1449
name=''
1450
}
1451
}
1452
pos++
1453
if(pos>self.length-1){
1454
if(name){res.push(name)}
1455
break
1456
}
1457
}
1458
return res
1459
}else{
1460
var res = [],s='',pos=0,seplen=sep.length
1461
if(maxsplit==0){return [self]}
1462
while(pos<self.length){
1463
if(self.substr(pos,seplen)==sep){
1464
res.push(s)
1465
pos += seplen
1466
if(maxsplit>-1 && res.length>=maxsplit){
1467
res.push(self.substr(pos))
1468
return res
1469
}
1470
s= ''
1471
}else{
1472
s += self.charAt(pos)
1473
pos++
1481
$StringDict.splitlines = function(self){
1482
var $=$B.args('splitlines',2,{self:null,keepends:null},
1483
['self','keepends'],arguments,{keepends:false},null,null)
1484
if(!_b_.isinstance($.keepends,[_b_.bool, _b_.int])){
1485
throw _b_.TypeError('integer argument expected, got '+
1486
$B.get_class($.keepends).__name)
1487
}
1488
var keepends = _b_.int($.keepends)
1489
// Remove trailing line breaks
1490
if(keepends){
1491
var res = [],start=pos,pos=0,x,self=$.self
1492
while(pos<self.length){
1493
if(self.substr(pos,2)=='\r\n'){
1494
res.push(self.substring(start,pos+2))
1495
start = pos+2
1496
pos = start
1497
}else if(self.charAt(pos)=='\r' || self.charAt(pos)=='\n'){
1498
res.push(self.substring(start,pos+1))
1499
start = pos+1
1500
pos = start
1501
}else{pos++}
1502
}
1503
var rest = self.substr(start)
1504
if(rest){res.push(rest)}
1505
return res
1506
}else{
1507
var self = $.self.replace(/[\r\n]$/,'')
1508
return self.split(/\n|\r\n|\r/)
1509
}
1510
}
1513
// Return True if string starts with the prefix, otherwise return False.
1514
// prefix can also be a tuple of prefixes to look for. With optional
1515
// start, test string beginning at that position. With optional end,
1516
// stop comparing string at that position.
1518
{self:null, prefix:null, start:null, end:null},
1519
['self', 'prefix', 'start', 'end'],
1522
normalize_start_end($)
1523
1524
var prefixes = $.prefix
1525
if(!isinstance(prefixes,_b_.tuple)){prefixes=[prefixes]}
1526
1527
var s = $.self.substring($.start,$.end)
1528
for(var i=0, _len_i = prefixes.length; i < _len_i;i++){
1529
prefix = prefixes[i]
1530
if(!_b_.isinstance(prefix, str)){throw _b_.TypeError(
1531
"endswith first arg must be str or a tuple of str, not int")}
1532
if(s.substr(0,prefix.length)==prefix) return true
1538
$StringDict.strip = function(){
1539
var $=$B.args('strip',2,{self:null,chars:null},['self','chars'],
1540
arguments,{chars:_b_.None},null,null)
1541
return $StringDict.rstrip($StringDict.lstrip($.self,$.chars),$.chars)
1547
//inspired by http://www.geekpedia.com/code69_Swap-string-case-using-JavaScript.html
1549
{ return ($1) ? $0.toUpperCase() : $0.toLowerCase()
1550
})
1551
}
1552
1553
$StringDict.title = function(self) {
1554
var $=$B.args('title',1,{self:null},['self'],arguments,{},null,null)
1555
1556
// Transform letters after a non-cased character to uppercase
1557
var res = '',previous=false
1558
1559
function is_cased(c){
1560
return c.toLowerCase() != c.toUpperCase()
1561
}
1562
1563
for(var i=0;i<$.self.length;i++){
1564
var char = $.self.charAt(i), cased = is_cased(char)
1565
if(!previous && cased){
1566
res += char.toUpperCase()
1567
}else if(previous){res+=char.toLowerCase()}
1568
else{res+=char}
1569
previous = cased
1570
}
1571
return res
1579
if(repl==-1){res[pos++]=self.charAt(i)}
1580
else if(repl!==None){res[pos++]=repl}
1586
$StringDict.upper = function(){
1587
var $=$B.args('lower',1,{self:null},['self'],arguments,{},null,null)
1588
return $.self.toUpperCase()
1589
}
1592
var $=$B.args('zfill',2,{self:null,width:null},
1593
['self','width'],arguments,{},null,null)
1594
if ($.width <= self.length) {return self}
1595
switch(self.charAt(0)){
1596
case '+':
1597
case '-':
1598
return self.charAt(0)+'0'.repeat($.width-self.length)+self.substr(1)
1599
default:
1600
return '0'.repeat(width - self.length)+self
1601
}
1606
switch(typeof arg) {
1607
case 'string': return arg
1608
case 'number': return arg.toString()
1609
}
1615
// class or its subclasses, but the attribute __str__ of the
1616
// class metaclass (usually "type") or its subclasses (usually
1617
// "object")
1618
// The metaclass is the attribute __class__ of the class dictionary
1619
var func = $B.$type.__getattribute__(arg.$dict.__class__,'__str__')
1624
var f = getattr(arg,'__str__')
1625
// XXX fix : if not better than object.__str__, try __repr__
1626
return f()
1627
}
1628
catch(err){
1634
if($B.debug>1){console.log(err)}
1635
console.log('Warning - no method __str__ or __repr__, default to toString', arg)
1637
}
1638
}
1639
}
1640
str.__class__ = $B.$factory
1641
str.$dict = $StringDict
1642
$StringDict.$factory = str
1643
$StringDict.__new__ = function(cls){
1644
if(cls===undefined){
1645
throw _b_.TypeError('str.__new__(): not enough arguments')
1646
}
1647
return {__class__:cls.$dict}
1648
}
1649
1652
// dictionary and factory for subclasses of string
1653
var $StringSubclassDict = {
1654
__class__:$B.$type,
1655
__name__:'str'
1656
}
1657
1658
// the methods in subclass apply the methods in $StringDict to the
1659
// result of instance.valueOf(), which is a Javascript string
1660
for(var $attr in $StringDict){
1661
if(typeof $StringDict[$attr]=='function'){
1662
$StringSubclassDict[$attr]=(function(attr){
1663
return function(){
1669
}
1670
}
1671
return $StringDict[attr].apply(null,args)
1672
}
1673
})($attr)
1674
}
1675
}
1676
$StringSubclassDict.__mro__ = [$StringSubclassDict,$ObjectDict]
1677
1678
// factory for str subclasses
1679
$B.$StringSubclassFactory = {
1680
__class__:$B.$factory,
1681
$dict:$StringSubclassDict
1682
}
1683
1684
_b_.str = str
1685
1686
// Function to parse the 2nd argument of format()
1687
$B.parse_format_spec = function(spec){
1697
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1))!=-1){
1698
// If the second char is also an alignment specifier, the
1699
// first char is the fill value
1700
this.fill = spec.charAt(0)
1701
this.align = spec.charAt(1)
1702
pos = 2
1703
}else{
1704
// The first character defines alignment : fill defaults to ' '
1705
this.align=aligns[align_pos];
1706
this.fill=' ';
1707
pos++
1708
}
1709
}else{
1710
align_pos = aligns.indexOf(spec.charAt(1))
1711
if(spec.charAt(1) && align_pos!=-1){
1712
// The second character defines alignment : fill is the first one
1713
this.align=aligns[align_pos]
1714
this.fill=spec.charAt(0)
1715
pos = 2
1716
}
1717
}
1718
var car = spec.charAt(pos)
1719
if(car=='+'||car=='-'||car==' '){
1720
this.sign=car;
1721
pos++;
1722
car=spec.charAt(pos);
1725
if(car=='0'){
1726
// sign-aware : equivalent to fill=0 and align=='='
1727
this.fill='0'
1728
this.align = '='
1729
pos++;car=spec.charAt(pos)
1730
}
1732
if(this.width===undefined){this.width=car}
1733
else{this.width+=car}
1734
pos++;car=spec.charAt(pos)
1736
if(this.width!==undefined){this.width=parseInt(this.width)}
1737
if(car==','){this.comma=true;pos++;car=spec.charAt(pos)}
1738
if(car=='.'){
1739
if(digits.indexOf(spec.charAt(pos+1))==-1){
1740
throw _b_.ValueError("Missing precision in format spec")
1741
}
1742
this.precision = spec.charAt(pos+1)
1743
pos+=2;car=spec.charAt(pos)
1744
while(car && digits.indexOf(car)>-1){
1745
this.precision+=car;pos++;car=spec.charAt(pos)
1746
}
1747
this.precision = parseInt(this.precision)
1748
}
1749
if(car && types.indexOf(car)>-1){this.type=car;pos++;car=spec.charAt(pos)}
1750
if(pos!==spec.length){
1752
throw _b_.ValueError("Invalid format specifier")
1753
}
1754
}
1755
this.toString = function(){
1756
return (this.fill===undefined ? '' : _b_.str(this.fill))+
1757
(this.align||'')+
1758
(this.sign||'')+
1759
(this.alternate ? '#' : '')+
1760
(this.sign_aware ? '0' : '')+
1761
(this.width || '')+
1762
(this.comma ? ',' : '')+
1763
(this.precision ? '.'+this.precision : '')+
1764
(this.type || '')
1765
}
1766
}
1767
1768
$B.format_width = function(s, fmt){
1769
if(fmt.width && s.length<fmt.width){
1770
var fill=fmt.fill || ' ', align = fmt.align || '<',
1771
missing = fmt.width-s.length
1772
switch(align){
1773
case '<':
1774
return s+fill.repeat(missing)
1775
case '>':
1776
return fill.repeat(missing)+s
1777
case '=':
1778
if('+-'.indexOf(s.charAt(0))>-1){
1779
return s.charAt(0)+fill.repeat(missing)+s.substr(1)
1780
}else{
1781
return fill.repeat(missing)+s
1782
}
1783
case '^':
1784
left = parseInt(missing/2)