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
1754 lines (1573 sloc)
55.4 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
303
}
304
305
// gG
306
var floating_point_format = function(val, upper, flags) {
307
val = _float_helper(val, flags)
308
var v = val.toString()
309
var v_len = v.length
310
var dot_idx = v.indexOf('.')
311
if (dot_idx < 0) {
312
dot_idx = v_len
313
}
314
if (val < 1 && val > -1) {
315
var zeros = leading_zeros.exec(v)
316
var numzeros
317
if (zeros) {
318
numzeros = zeros[1].length
319
} else {
320
numzeros = 0
321
}
322
if (numzeros >= 4) {
323
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
324
if (!flags.alternate) {
325
var trl = trailing_zeros.exec(val)
326
if (trl) {
327
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
333
}
334
return format_padding(val, flags)
335
}
336
flags.precision += numzeros
337
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
338
function(val, precision) {
339
val = val.toFixed(min(precision, v_len - dot_idx) + numzeros)
340
}), flags)
341
}
342
343
if (dot_idx > flags.precision) {
344
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
345
if (!flags.alternate) {
346
var trl = trailing_zeros.exec(val)
347
if (trl) {
348
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
349
}
350
} else {
351
if (flags.precision <= 1) {
352
val = val[0] + '.' + val.substring(1)
353
}
354
}
355
return format_padding(val, flags)
356
}
357
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
358
function(val, precision) {
359
if (!flags.decimal_point) {
360
precision = min(v_len - 1, 6)
361
} else if (precision > v_len) {
362
if (!flags.alternate) {
363
precision = v_len
365
}
366
if (precision < dot_idx) {
367
precision = dot_idx
368
}
369
return val.toFixed(precision - dot_idx)
370
}), flags)
371
}
373
var _floating_g_exp_helper = function(val, precision, flags, upper) {
374
if (precision) {
375
--precision
376
}
377
val = val.toExponential(precision)
378
// pad exponent to two digits
379
var e_idx = val.lastIndexOf('e')
380
if (e_idx > val.length - 4) {
381
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
382
}
383
if (upper) {
384
return val.toUpperCase()
385
}
386
return val
387
}
388
389
// fF
390
var floating_point_decimal_format = function(val, upper, flags) {
391
val = _float_helper(val, flags)
392
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
393
function(val, precision, flags) {
394
val = val.toFixed(precision)
395
if (precision === 0 && flags.alternate) {
396
val += '.'
397
}
398
return val
399
}), flags)
400
}
401
402
var _floating_exp_helper = function(val, precision, flags, upper) {
403
val = val.toExponential(precision)
404
// pad exponent to two digits
405
var e_idx = val.lastIndexOf('e')
406
if (e_idx > val.length - 4) {
407
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
408
}
409
if (upper) {
410
return val.toUpperCase()
411
}
412
return val
413
}
414
415
// eE
416
var floating_point_exponential_format = function(val, upper, flags) {
417
val = _float_helper(val, flags)
418
419
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_exp_helper), flags)
420
}
421
422
var signed_hex_format = function(val, upper, flags) {
425
426
if (val.__class__ === $B.LongInt.$dict) {
427
ret=$B.LongInt.$dict.to_base(val, 16)
428
} else {
429
ret = parseInt(val)
430
ret = ret.toString(16)
431
}
432
ret = format_int_precision(ret, flags)
433
if (upper) {
434
ret = ret.toUpperCase()
435
}
436
if (flags.pad_char === '0') {
437
if (val < 0) {
438
ret = ret.substring(1)
439
ret = '-' + format_padding(ret, flags, true)
440
}
441
var sign = format_sign(val, flags)
442
if (sign !== '') {
443
ret = sign + format_padding(ret, flags, true)
445
}
446
447
if (flags.alternate) {
448
if (ret.charAt(0) === '-') {
449
if (upper) {
450
ret = "-0X" + ret.slice(1)
451
} else {
452
ret = "-0x" + ret.slice(1)
453
}
454
} else {
455
if (upper) {
456
ret = "0X" + ret
457
} else {
458
ret = "0x" + ret
459
}
460
}
461
}
462
return format_padding(format_sign(val, flags) + ret, flags)
463
}
467
var ret
468
469
if (val.__class__ === $B.LongInt.$dict) {
470
ret = $B.LongInt.$dict.to_base(8)
471
} else {
472
ret = parseInt(val)
473
ret = ret.toString(8)
474
}
475
478
if (flags.pad_char === '0') {
479
if (val < 0) {
480
ret = ret.substring(1)
481
ret = '-' + format_padding(ret, flags, true)
482
}
483
var sign = format_sign(val, flags)
484
if (sign !== '') {
485
ret = sign + format_padding(ret, flags, true)
486
}
488
489
if (flags.alternate) {
490
if (ret.charAt(0) === '-') {
491
ret = "-0o" + ret.slice(1)
492
} else {
493
ret = "0o" + ret
494
}
496
return format_padding(ret, flags)
497
}
498
499
var single_char_format = function(val, flags) {
500
if(isinstance(val,str) && val.length==1) return val
501
try {
502
val = _b_.int(val) // yes, floats are valid (they are cast to int)
503
} catch (err) {
504
throw _b_.TypeError('%c requires int or char')
505
}
506
return format_padding(chr(val), flags)
507
}
508
509
var num_flag = function(c, flags) {
510
if (c === '0' && !flags.padding && !flags.decimal_point && !flags.left) {
511
flags.pad_char = '0'
512
return
513
}
514
if (!flags.decimal_point) {
515
flags.padding = (flags.padding || "") + c
516
} else {
517
flags.precision = (flags.precision || "") + c
518
}
519
}
520
521
var decimal_point_flag = function(val, flags) {
522
if (flags.decimal_point) {
523
// can only have one decimal point
524
throw new UnsupportedChar()
525
}
526
flags.decimal_point = true
527
}
528
529
var neg_flag = function(val, flags) {
530
flags.pad_char = ' ' // overrides '0' flag
531
flags.left = true
532
}
533
534
var space_flag = function(val, flags) {
535
flags.space = true
536
}
537
538
var sign_flag = function(val, flags) {
539
flags.sign = true
540
}
541
542
var alternate_flag = function(val, flags) {
543
flags.alternate = true
544
}
545
547
's': str_format,
548
'd': num_format,
549
'i': num_format,
550
'u': num_format,
551
'o': octal_format,
552
'r': repr_format,
553
'a': ascii_format,
554
'g': function(val, flags) {return floating_point_format(val, false, flags)},
555
'G': function(val, flags) {return floating_point_format(val, true, flags)},
556
'f': function(val, flags) {return floating_point_decimal_format(val, false, flags)},
557
'F': function(val, flags) {return floating_point_decimal_format(val, true, flags)},
558
'e': function(val, flags) {return floating_point_exponential_format(val, false, flags)},
559
'E': function(val, flags) {return floating_point_exponential_format(val, true, flags)},
560
'x': function(val, flags) {return signed_hex_format(val, false, flags)},
561
'X': function(val, flags) {return signed_hex_format(val, true, flags)},
562
'c': single_char_format,
563
'0': function(val, flags) {return num_flag('0', flags)},
564
'1': function(val, flags) {return num_flag('1', flags)},
565
'2': function(val, flags) {return num_flag('2', flags)},
566
'3': function(val, flags) {return num_flag('3', flags)},
567
'4': function(val, flags) {return num_flag('4', flags)},
568
'5': function(val, flags) {return num_flag('5', flags)},
569
'6': function(val, flags) {return num_flag('6', flags)},
570
'7': function(val, flags) {return num_flag('7', flags)},
571
'8': function(val, flags) {return num_flag('8', flags)},
572
'9': function(val, flags) {return num_flag('9', flags)},
573
'-': neg_flag,
574
' ': space_flag,
575
'+': sign_flag,
576
'.': decimal_point_flag,
577
'#': alternate_flag
578
}
579
580
// exception thrown when an unsupported char is encountered in legacy format
581
var UnsupportedChar = function() {
582
this.name = "UnsupportedChar"
583
}
584
596
++pos
597
var rslt = kwarg_key.exec(s.substring(newpos))
598
if (!rslt) {
599
throw _b_.ValueError("incomplete format key")
600
}
601
var key = rslt[1]
602
newpos += rslt[0].length
603
try {
605
} catch(err) {
606
if (err.name === "KeyError") {
607
throw err
608
}
609
throw _b_.TypeError("format requires a mapping")
610
}
625
}
626
catch(err) {
627
if (err.name === "IndexError") {
628
throw _b_.TypeError("not enough arguments for format string")
629
} else {
630
throw err
631
}
637
// todo: get flags, type
638
// todo: string value based on flags, type, value
639
var flags = {'pad_char': ' '}
640
do {
647
if (ret !== undefined) {
648
return ret
649
}
650
++newpos
651
}
652
} catch (err) {
653
if (err.name === "UnsupportedChar") {
654
invalid_char = s[newpos]
655
if (invalid_char === undefined) {
656
throw _b_.ValueError("incomplete format")
657
}
658
throw _b_.ValueError("unsupported format character '" + invalid_char +
659
"' (0x" + invalid_char.charCodeAt(0).toString(16) + ") at index " + newpos)
660
} else if (err.name === "NotANumber") {
661
var try_char = s[newpos]
668
}
669
} else {
670
cls = cls.__name__
671
}
672
throw _b_.TypeError("%" + try_char + " format: a number is required, not " + cls)
673
} else {
674
throw err
675
}
697
}
698
}
699
} else {
700
// % at end of string
701
throw _b_.ValueError("incomplete format")
702
}
703
pos = newpos + 1
704
} while (pos < length)
705
708
709
$StringDict.__mro__ = [$StringDict,$ObjectDict]
710
711
$StringDict.__mul__ = function(self,other){
712
if(!isinstance(other,_b_.int)){throw _b_.TypeError(
713
"Can't multiply sequence by non-int of type '"+
714
$B.get_class(other).__name__+"'")}
715
$res = ''
716
for(var i=0;i<other;i++){$res+=self.valueOf()}
717
return $res
718
}
719
720
$StringDict.__ne__ = function(self,other){return other!==self.valueOf()}
721
722
$StringDict.__repr__ = function(self){
723
var res = self.replace(/\n/g,'\\\\n')
724
// escape the escape char
725
res = res.replace(/\\/g, '\\\\')
726
if(res.search('"')==-1 && res.search("'")==-1){
727
return "'"+res+"'"
736
$StringDict.__setattr__ = function(self,attr,value){return setattr(self,attr,value)}
737
738
$StringDict.__setitem__ = function(self,attr,value){
739
throw _b_.TypeError("'str' object does not support item assignment")
740
}
741
$StringDict.__str__ = function(self){
742
if(self===undefined) return "<class 'str'>"
743
return self.toString()
744
}
745
$StringDict.toString = function(){return 'string!'}
746
747
// generate comparison methods
748
var $comp_func = function(self,other){
749
if(typeof other !=="string"){throw _b_.TypeError(
750
"unorderable types: 'str' > "+$B.get_class(other).__name__+"()")}
751
return self > other
752
}
753
$comp_func += '' // source code
754
var $comps = {'>':'gt','>=':'ge','<':'lt','<=':'le'}
755
for(var $op in $comps){
756
eval("$StringDict.__"+$comps[$op]+'__ = '+$comp_func.replace(/>/gm,$op))
757
}
758
759
// add "reflected" methods
760
$B.make_rmethods($StringDict)
761
762
// unsupported operations
763
var $notimplemented = function(self,other){
764
throw NotImplementedError("OPERATOR not implemented for class str")
765
}
766
767
$StringDict.capitalize = function(self){
768
if(self.length==0) return ''
769
return self.charAt(0).toUpperCase()+self.substr(1).toLowerCase()
770
}
771
772
$StringDict.casefold = function(self) {
773
throw _b_.NotImplementedError("function casefold not implemented yet");
774
}
775
776
$StringDict.center = function(self,width,fillchar){
777
var $=$B.args("center",3,
778
{self:null, width:null, fillchar:null},
779
['self', 'width', 'fillchar'],
780
arguments,{fillchar:' '},null,null)
781
782
if($.width<=self.length) return self
791
$StringDict.count = function(){
792
var $ = $B.args('count', 4, {self:null, sub:null, start:null, stop:null},
797
var substr = $.self
798
if($.start!==null){
799
var _slice
800
if($.stop!==null){_slice = _b_.slice($.start, $.stop)}
801
else{_slice = _b_.slice($.start,$.self.length)}
802
substr = $StringDict.__getitem__.apply(null, [$.self].concat(_slice))
803
}else{
804
if($.self.length+$.sub.length==0){return 1} // ''.count('') = 1
805
}
806
if($.sub.length==0){
807
if($.start==$.self.length){return 1} // 'aaa'.count('',3) = 1
808
else if(substr.length==0){return 0} // 'aaa'.count('',4) = 0
809
return substr.length+1
810
}
811
var n=0, pos=0
812
while(pos<substr.length){
813
pos=substr.indexOf($.sub,pos)
815
}
816
return n
817
}
818
819
$StringDict.encode = function(self, encoding) {
820
if (encoding === undefined) encoding='utf-8'
821
if(encoding=='rot13' || encoding=='rot_13'){
822
// Special case : returns a string
823
var res = ''
824
for(var i=0, _len = self.length; i<_len ; i++){
825
var char = self.charAt(i)
826
if(('a'<=char && char<='m') || ('A'<=char && char<='M')){
827
res += String.fromCharCode(String.charCodeAt(char)+13)
828
}else if(('m'<char && char<='z') || ('M'<char && char<='Z')){
829
res += String.fromCharCode(String.charCodeAt(char)-13)
830
}else{res += char}
831
}
832
return res
833
}
838
// Return True if the string ends with the specified suffix, otherwise
839
// return False. suffix can also be a tuple of suffixes to look for.
840
// With optional start, test beginning at that position. With optional
841
// end, stop comparing at that position.
843
{self:null, suffix:null, start:null, end:null},
844
['self', 'suffix', 'start', 'end'],
845
arguments,{start:0, end:null},null,null)
846
847
normalize_start_end($)
848
849
var suffixes = $.suffix
855
if(!_b_.isinstance(suffix, str)){throw _b_.TypeError(
856
"endswith first arg must be str or a tuple of str, not int")}
857
if(suffix.length<=s.length &&
858
s.substr(s.length-suffix.length)==suffix) return true
859
}
860
return false
861
}
862
863
$StringDict.expandtabs = function(self, tabsize) {
864
var $ = $B.args('expandtabs', 2, {self:null, tabsize:null},
865
['self', 'tabsize'], arguments, {tabsize:8}, null, null)
866
var s=$B.$GetInt($.tabsize), col=0,pos=0,res=''
867
if(s==1){return self.replace(/\t/g,' ')}
868
while(pos<self.length){
869
var car = self.charAt(pos)
870
switch(car){
871
case '\t':
872
while(col%s > 0){res += ' ';col++}
873
break
874
case '\r':
875
case '\n':
876
res += car
877
col = 0
878
break
879
default:
880
res += car
881
col++
882
break
883
}
884
pos++
885
}
886
887
return res
891
// Return the lowest index in the string where substring sub is found,
892
// such that sub is contained in the slice s[start:end]. Optional
893
// arguments start and end are interpreted as in slice notation.
894
// Return -1 if sub is not found.
898
arguments,{start:0,end:null},null,null)
899
if(!isinstance($.sub,str)){throw _b_.TypeError(
900
"Can't convert '"+$B.get_class($.sub).__name__+
901
"' object to str implicitly")}
905
throw _b_.TypeError(
906
"slice indices must be integers or None or have an __index__ method")}
907
var s = $.self.substring($.start,$.end)
908
909
if($.sub.length==0 && $.start==$.self.length){return $.self.length}
910
if(s.length+$.sub.length==0){return -1}
911
912
var last_search = s.length-$.sub.length
913
for(var i=0;i<=last_search;i++){
914
if(s.substr(i, $.sub.length)==$.sub){return $.start+i}
923
// Parse a "format string", as described in the Python documentation
924
// Return a format object. For the format string
925
// a.x[z]!r:...
926
// the object has attributes :
927
// - name : "a"
928
// - name_ext : [".x", "[z]"]
929
// - conv : r
930
// - spec : rest of string after :
932
var elts = fmt_string.split(':'), name, conv, spec, name_ext=[]
933
if(elts.length==1){
934
// No : in the string : it only contains a name
935
name = fmt_string
936
}else{
937
// name is before the first ":"
938
// spec (the format specification) is after
939
name = elts[0]
940
spec = elts.splice(1).join(':')
941
}
942
943
var elts = name.split('!')
944
if(elts.length>1){
945
name=elts[0]
946
conv=elts[1] // conversion flag
947
if(conv.length!==1 || 'ras'.search(conv)==-1){
948
throw _b_.ValueError('wrong conversion flag '+conv)
949
}
950
}
952
if(name!==undefined){
953
// "name' may be a subscription or attribute
954
// Put these "extensions" in the list "name_ext"
955
function name_repl(match){
956
name_ext.push(match)
957
return ''
958
}
959
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
960
name = name.replace(name_ext_re, name_repl)
961
}
970
arguments, {}, 'args', 'kw')
971
972
// Parse self to detect formatting instructions
973
// Create a list "parts" made of sections of the string :
974
// - elements of even rank are literal text
975
// - elements of odd rank are "format objects", built from the
976
// format strings in self (of the form {...})
977
var pos=0, _len=self.length, car, text='', parts=[], rank=0, defaults={}
978
979
while(pos<_len){
980
car = self.charAt(pos)
981
if(car=='{' && self.charAt(pos+1)=='{'){
982
// replace {{ by literal {
983
text += '{'
984
pos+=2
985
}else if(car=='}' && self.charAt(pos+1)=='}'){
986
// replace }} by literal }
987
text += '}'
988
pos+=2
989
}else if(car=='{'){
990
// Start of a format string
991
992
// Store current literal text
993
parts.push(text)
994
995
// Search the end of the format string, ie the } closing the
996
// opening {. Since the string can contain other pairs {} for
997
// nested formatting, an integer nb is incremented for each { and
998
// decremented for each } ; the end of the format string is
999
// reached when nb==0
1000
var end = pos+1, nb=1
1001
while(end<_len){
1002
if(self.charAt(end)=='{'){nb++;end++}
1003
else if(self.charAt(end)=='}'){
1004
nb--;end++
1005
if(nb==0){
1006
// End of format string
1007
var fmt_string = self.substring(pos+1, end-1)
1008
1009
// Create a format object, by function parse_format
1010
var fmt_obj = parse_format(fmt_string)
1011
1012
// If no name is explicitely provided, use the rank
1013
if(!fmt_obj.name){
1014
fmt_obj.name=rank+''
1015
rank++
1016
}
1019
// "spec" may contain "nested replacement fields"
1020
// In this case, evaluate them using the keyword
1021
// arguments passed to format()
1022
function replace_nested(name, key){
1025
}
1026
fmt_obj.spec = fmt_obj.spec.replace(/\{(.+?)\}/g,
1027
replace_nested)
1028
}
1029
1030
// Store format object in list "parts"
1031
parts.push(fmt_obj)
1032
text = ''
1033
break
1034
}
1035
}else{end++}
1037
if(nb>0){throw ValueError("wrong format "+self)}
1038
pos = end
1039
}else{text += car;pos++}
1043
// Apply formatting to the values passed to format()
1044
var res = '', fmt
1045
for(var i=0;i<parts.length;i++){
1046
// Literal text is added unchanged
1047
if(typeof parts[i]=='string'){res += parts[i];continue}
1048
1049
// Format objects
1050
fmt = parts[i]
1051
if(fmt.name.charAt(0).search(/\d/)>-1){
1052
// Numerical reference : use positional arguments
1053
var pos = parseInt(fmt.name),
1054
value = _b_.tuple.$dict.__getitem__($.args, pos)
1055
}else{
1056
// Use keyword arguments
1057
var value = _b_.dict.$dict.__getitem__($.kw, fmt.name)
1058
}
1059
// If name has extensions (attributes or subscriptions)
1060
for(var j=0;j<fmt.name_ext.length;j++){
1061
var ext = fmt.name_ext[j]
1062
if(ext.charAt(0)=='.'){
1063
// Attribute
1064
value = _b_.getattr(value, ext.substr(1))
1065
}else{
1066
// Subscription
1067
var key = ext.substr(1, ext.length-2)
1068
// An index made of digits is transformed into an integer
1069
if(key.charAt(0).search(/\d/)>-1){key = parseInt(key)}
1070
value = _b_.getattr(value, '__getitem__')(key)
1071
}
1072
}
1073
// If the conversion flag is set, first call a function to convert
1074
// the value
1075
if(fmt.conv=='a'){value = _b_.ascii(value)}
1076
else if(fmt.conv=='r'){value = _b_.repr(value)}
1077
else if(fmt.conv=='s'){value = _b_.str(value)}
1078
1079
// Call attribute __format__ to perform the actual formatting
1080
res += _b_.getattr(value, '__format__')(fmt.spec)
1083
}
1084
1085
$StringDict.format_map = function(self) {
1086
throw NotImplementedError("function format_map not implemented yet");
1087
}
1088
1089
$StringDict.index = function(self){
1090
// Like find(), but raise ValueError when the substring is not found.
1092
if(res===-1) throw _b_.ValueError("substring not found")
1093
return res
1094
}
1095
1096
$StringDict.isalnum = function() {
1097
var $=$B.args('isalnum',1,{self:null},['self'],arguments,{},null,null)
1098
return /^[a-z0-9]+$/i.test($.self)
1099
}
1101
$StringDict.isalpha = function(self) {
1102
var $=$B.args('isalpha',1,{self:null},['self'],arguments,{},null,null)
1103
return /^[a-z]+$/i.test($.self)
1104
}
1106
$StringDict.isdecimal = function(){
1107
var $=$B.args('isdecimal',1,{self:null},['self'],arguments,{},null,null)
1109
return /^[0-9]+$/.test($.self)
1110
}
1111
1112
$StringDict.isdigit = function() {
1113
var $=$B.args('isdigit',1,{self:null},['self'],arguments,{},null,null)
1114
return /^[0-9]+$/.test($.self)
1115
}
1116
1117
$StringDict.isidentifier = function() {
1118
var $=$B.args('isidentifier',1,{self:null},['self'],arguments,{},null,null)
1119
1120
switch($.self) {
1121
case 'False':
1122
case 'None':
1123
case 'True':
1124
case 'and':
1125
case 'as':
1126
case 'assert':
1127
case 'break':
1128
case 'class':
1129
case 'continue':
1130
case 'def':
1131
case 'del':
1132
case 'elif':
1133
case 'else':
1134
case 'except':
1135
case 'finally':
1136
case 'for':
1137
case 'from':
1138
case 'global':
1139
case 'if':
1140
case 'import':
1141
case 'in':
1142
case 'is':
1143
case 'lambda':
1144
case 'nonlocal':
1145
case 'not':
1146
case 'or':
1147
case 'pass':
1148
case 'raise':
1149
case 'return':
1150
case 'try':
1151
case 'while':
1152
case 'with':
1153
case 'yield':
1154
return true
1155
}
1156
1157
// fixme.. this isn't complete but should be a good start
1158
return /^[a-z][0-9a-z_]+$/i.test($.self)
1159
}
1160
1161
$StringDict.islower = function() {
1162
var $=$B.args('islower',1,{self:null},['self'],arguments,{},null,null)
1163
// A string only made of whitespace is not lower for Python
1164
return $.self==$.self.toLowerCase() && $.self.search(/^\s*$/)==-1
1168
$StringDict.isnumeric = function() {
1169
var $=$B.args('isnumeric',1,{self:null},['self'],arguments,{},null,null)
1170
return /^[0-9]+$/.test($.self)
1171
}
1174
$StringDict.isprintable = function() {
1175
var $=$B.args('isprintable',1,{self:null},['self'],arguments,{},null,null)
1176
return !/[^ -~]/.test($.self)
1177
}
1179
$StringDict.isspace = function() {
1180
var $=$B.args('isspace',1,{self:null},['self'],arguments,{},null,null)
1181
return /^\s+$/i.test($.self)
1182
}
1184
$StringDict.istitle = function() {
1185
var $=$B.args('istitle',1,{self:null},['self'],arguments,{},null,null)
1186
if($.self.search(/^\s*$/)>-1){return false}
1187
1188
function get_case(char){
1189
if(char.toLowerCase()==char.toUpperCase()){return false}
1190
else if(char==char.toLowerCase()){return 'lower'}
1191
else{return 'upper'}
1192
}
1193
var pos=0,char,previous=false
1194
while(pos<$.self.length){
1195
char = $.self.charAt(pos)
1196
if(previous===undefined){previous=get_case(char)}
1197
else{
1198
_case = get_case(char)
1199
if(_case=='upper' && previous){return false}
1200
else if(_case=='lower' && !previous){return false}
1201
previous=_case
1202
}
1203
pos++
1204
}
1205
return true
1206
}
1208
$StringDict.isupper = function() {
1209
var $=$B.args('isupper',1,{self:null},['self'],arguments,{},null,null)
1210
return $.self==$.self.toUpperCase() && $.self.search(/^\s*$/)==-1
1211
}
1212
1213
$StringDict.join = function(self,obj){
1214
var iterable=iter(obj)
1215
var res = '',count=0
1216
while(1){
1217
try{
1218
var obj2 = next(iterable)
1219
if(!isinstance(obj2,str)){throw _b_.TypeError(
1220
"sequence item "+count+": expected str instance, "+$B.get_class(obj2).__name__+" found")}
1221
res += obj2+self
1222
count++
1223
}catch(err){
1225
else{throw err}
1226
}
1227
}
1228
if(count==0) return ''
1229
return res.substr(0,res.length-self.length)
1230
}
1231
1232
$StringDict.ljust = function(self) {
1233
var $=$B.args('ljust',3,{self:null,width:null,fillchar:null},
1234
['self','width','fillchar'],arguments,{fillchar:' '},null,null)
1235
1236
if ($.width <= self.length) return self
1237
return self + $.fillchar.repeat($.width - self.length)
1240
$StringDict.lower = function(){
1241
var $=$B.args('lower',1,{self:null},['self'],arguments,{},null,null)
1242
return $.self.toLowerCase()
1243
}
1246
var $=$B.args('lstrip',2,{self:null,chars:null},['self','chars'],
1247
arguments,{chars:_b_.None},null,null)
1248
if($.chars===_b_.None){return $.self.replace(/^\s+/,'')}
1249
return $.self.replace(new RegExp("^["+$.chars+"]*"),"")
1250
}
1251
1252
// note, maketrans should be a static function.
1253
$StringDict.maketrans = function(from, to) {
1254
var _t=[]
1255
// make 'default' translate table
1256
for(var i=0; i < 256; i++) _t[i]=String.fromCharCode(i)
1257
1258
// make substitution in the translation table
1260
var _ndx=from.source[i].charCodeAt(0) //retrieve ascii code of char
1261
_t[_ndx]=to.source[i]
1262
}
1263
1264
// create a data structure that string.translate understands
1268
}
1269
return _d
1270
}
1271
1272
$StringDict.partition = function(self,sep) {
1273
if (sep === undefined) {
1274
throw Error("sep argument is required");
1275
return
1276
}
1277
var i=self.indexOf(sep)
1278
if (i== -1) return _b_.tuple([self, '', ''])
1279
return _b_.tuple([self.substring(0,i), sep, self.substring(i+sep.length)])
1280
}
1281
1282
function $re_escape(str)
1283
{
1284
var specials = "[.*+?|()$^"
1286
var re = new RegExp('\\'+specials.charAt(i),'g')
1287
str = str.replace(re, "\\"+specials.charAt(i))
1288
}
1289
return str
1290
}
1291
1292
$StringDict.replace = function(self, old, _new, count) {
1293
// Replaces occurrences of 'old' by '_new'. Count references
1294
// the number of times to replace. In CPython, negative or undefined
1295
// values of count means replace all.
1296
var $ = $B.args('replace', 4, {self:null,old:null,$$new:null,count:null},
1297
['self','old','$$new','count'], arguments, {count:-1},null,null),
1298
count=$.count,self=$.self,old=$.old,_new=$.$$new
1301
throw _b_.TypeError("Can't convert '" + $B.get_class(old).__name__ +
1302
"' object to str implicitly");
1303
}
1304
if (!isinstance(_new,_b_.str)) {
1305
throw _b_.TypeError("Can't convert '" + $B.get_class(_new).__name__ +
1306
"' object to str implicitly");
1307
}
1308
// Validate instance type of 'count'
1309
if (!isinstance(count,[_b_.int,_b_.float])) {
1310
throw _b_.TypeError("'" + $B.get_class(count).__name__ +
1311
"' object cannot be interpreted as an integer");
1312
} else if (isinstance(count, _b_.float)) {
1313
throw _b_.TypeError("integer argument expected, got float");
1314
}
1315
if(count==0){return self}
1316
if(count.__class__==$B.LongInt.$dict){count=parseInt(count.value)}
1317
if(old==''){
1318
if(_new==''){return self}
1319
if(self==''){return _new}
1320
var elts=self.split('')
1321
if(count>-1 && elts.length>=count){
1322
var rest = elts.slice(count).join('')
1323
return _new+elts.slice(0, count).join(_new)+rest
1324
}else{return _new+elts.join(_new)+_new}
1325
}else{
1326
var elts = $StringDict.split(self,old,count)
1329
var res = self, pos = -1
1330
if(old.length==0){
1331
var res = _new
1332
for(var i=0;i<elts.length;i++){
1333
res += elts[i]+_new
1334
}
1335
return res+rest
1336
}
1337
1338
if (count < 0) count = res.length;
1339
while (count > 0) {
1340
pos = res.indexOf(old, pos);
1341
if (pos < 0)
1342
break;
1343
res = res.substr(0, pos) + _new + res.substr(pos + old.length);
1344
pos = pos + _new.length;
1345
count--;
1346
}
1347
return res;
1348
}
1349
1350
$StringDict.rfind = function(self){
1351
// Return the highest index in the string where substring sub is found,
1352
// such that sub is contained within s[start:end]. Optional arguments
1353
// start and end are interpreted as in slice notation. Return -1 on failure.
1359
normalize_start_end($)
1360
1361
if(!isinstance($.sub,str)){throw _b_.TypeError(
1362
"Can't convert '"+$B.get_class($.sub).__name__+"' object to str implicitly")}
1364
if($.sub.length==0){
1365
if($.start>$.self.length){return -1}
1366
else{return $.self.length}
1367
}
1368
var sublen = $.sub.length
1369
1370
for(var i=$.end-sublen;i>=$.start;i--){
1371
if($.self.substr(i, sublen)==$.sub){return i}
1372
}
1373
return -1
1374
}
1375
1376
$StringDict.rindex = function(){
1377
// Like rfind() but raises ValueError when the substring sub is not found
1379
if(res==-1){throw _b_.ValueError("substring not found")}
1380
return res
1381
}
1382
1383
$StringDict.rjust = function(self) {
1385
{self:null, width:null, fillchar:null},
1386
['self', 'width', 'fillchar'],
1387
arguments,{fillchar:' '},null,null)
1392
}
1393
1394
$StringDict.rpartition = function(self,sep) {
1395
if (sep === undefined) {
1396
throw Error("sep argument is required");
1397
return
1398
}
1399
var pos=self.length-sep.length
1400
while(1){
1401
if(self.substr(pos,sep.length)==sep){
1402
return _b_.tuple([self.substr(0,pos),sep,self.substr(pos+sep.length)])
1403
}else{
1404
pos--
1405
if(pos<0){return _b_.tuple(['','',self])}
1406
}
1407
}
1408
}
1409
1410
$StringDict.rsplit = function(self) {
1411
var $=$B.args("rsplit",3,{self:null,sep:null,maxsplit:null},
1412
['self','sep','maxsplit'],arguments,
1413
{sep:_b_.None, maxsplit:-1},null,null),
1414
sep=$.sep,maxsplit=$.maxsplit,self=$.self
1415
1416
// Use split on the reverse of the string and of separator
1417
var rev_str = $.self.split('').reverse().join(''),
1418
rev_sep = sep === _b_.None ? sep : $.sep.split('').reverse().join(''),
1419
rev_res = $StringDict.split(rev_str, rev_sep, $.maxsplit)
1421
// Reverse the list, then each string inside the list
1422
rev_res.reverse()
1423
for(var i=0;i<rev_res.length;i++){
1424
rev_res[i] = rev_res[i].split('').reverse().join('')
1425
}
1426
return rev_res
1430
var $=$B.args('rstrip',2,{self:null,chars:null},['self','chars'],
1431
arguments,{chars:_b_.None},null,null)
1432
if($.chars===_b_.None){return $.self.replace(/\s+$/,'')}
1433
return $.self.replace(new RegExp("["+$.chars+"]*$"),"")
1438
var $=$B.args("split",3,{self:null,sep:null,maxsplit:null},
1439
['self','sep','maxsplit'],arguments,
1440
{sep:_b_.None, maxsplit:-1},null,null)
1441
var sep=$.sep,maxsplit=$.maxsplit,self=$.self
1442
if(maxsplit.__class__===$B.LongInt.$dict){maxsplit=parseInt(maxsplit.value)}
1445
var res = []
1446
var pos = 0
1447
while(pos<self.length&&self.charAt(pos).search(/\s/)>-1){pos++}
1449
var name = ''
1450
while(1){
1451
if(self.charAt(pos).search(/\s/)===-1){
1452
if(name===''){name=self.charAt(pos)}
1453
else{name+=self.charAt(pos)}
1454
}else{
1455
if(name!==''){
1456
res.push(name)
1457
if(maxsplit!==-1&&res.length===maxsplit+1){
1458
res.pop()
1459
res.push(name+self.substr(pos))
1460
return res
1461
}
1462
name=''
1463
}
1464
}
1465
pos++
1466
if(pos>self.length-1){
1467
if(name){res.push(name)}
1468
break
1469
}
1470
}
1471
return res
1472
}else{
1473
var res = [],s='',pos=0,seplen=sep.length
1474
if(maxsplit==0){return [self]}
1475
while(pos<self.length){
1476
if(self.substr(pos,seplen)==sep){
1477
res.push(s)
1478
pos += seplen
1479
if(maxsplit>-1 && res.length>=maxsplit){
1480
res.push(self.substr(pos))
1481
return res
1482
}
1483
s= ''
1484
}else{
1485
s += self.charAt(pos)
1486
pos++
1491
}
1492
}
1493
1494
$StringDict.splitlines = function(self){return $StringDict.split(self,'\n')}
1495
1496
$StringDict.startswith = function(self){
1497
// Return True if string starts with the prefix, otherwise return False.
1498
// prefix can also be a tuple of prefixes to look for. With optional
1499
// start, test string beginning at that position. With optional end,
1500
// stop comparing string at that position.
1502
{self:null, prefix:null, start:null, end:null},
1503
['self', 'prefix', 'start', 'end'],
1504
arguments,{start:0, end:self.length-1},null,null)
1505
var prefixes = $ns['prefix']
1506
if(!isinstance(prefixes,_b_.tuple)){prefixes=[prefixes]}
1517
$StringDict.strip = function(){
1518
var $=$B.args('strip',2,{self:null,chars:null},['self','chars'],
1519
arguments,{chars:_b_.None},null,null)
1520
return $StringDict.rstrip($StringDict.lstrip($.self,$.chars),$.chars)
1526
//inspired by http://www.geekpedia.com/code69_Swap-string-case-using-JavaScript.html
1528
{ return ($1) ? $0.toUpperCase() : $0.toLowerCase()
1529
})
1530
}
1531
1532
$StringDict.title = function(self) {
1533
//inspired from http://stackoverflow.com/questions/196972/convert-string-to-title-case-with-javascript
1534
return self.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
1535
}
1536
1537
$StringDict.translate = function(self,table) {
1542
if(repl==-1){res[pos++]=self.charAt(i)}
1543
else if(repl!==None){res[pos++]=repl}
1549
$StringDict.upper = function(){
1550
var $=$B.args('lower',1,{self:null},['self'],arguments,{},null,null)
1551
return $.self.toUpperCase()
1552
}
1555
var $=$B.args('zfill',2,{self:null,width:null},
1556
['self','width'],arguments,{},null,null)
1557
if ($.width <= self.length) {return self}
1558
switch(self.charAt(0)){
1559
case '+':
1560
case '-':
1561
return self.charAt(0)+'0'.repeat($.width-self.length)+self.substr(1)
1562
default:
1563
return '0'.repeat(width - self.length)+self
1564
}
1569
switch(typeof arg) {
1570
case 'string': return arg
1571
case 'number': return arg.toString()
1572
}
1578
// class or its subclasses, but the attribute __str__ of the
1579
// class metaclass (usually "type") or its subclasses (usually
1580
// "object")
1581
// The metaclass is the attribute __class__ of the class dictionary
1582
var func = $B.$type.__getattribute__(arg.$dict.__class__,'__str__')
1587
var f = getattr(arg,'__str__')
1588
// XXX fix : if not better than object.__str__, try __repr__
1589
return f()
1590
}
1591
catch(err){
1597
if($B.debug>1){console.log(err)}
1598
console.log('Warning - no method __str__ or __repr__, default to toString', arg)
1600
}
1601
}
1602
}
1603
str.__class__ = $B.$factory
1604
str.$dict = $StringDict
1605
$StringDict.$factory = str
1606
$StringDict.__new__ = function(cls){
1607
if(cls===undefined){
1608
throw _b_.TypeError('str.__new__(): not enough arguments')
1609
}
1610
return {__class__:cls.$dict}
1611
}
1612
1615
// dictionary and factory for subclasses of string
1616
var $StringSubclassDict = {
1617
__class__:$B.$type,
1618
__name__:'str'
1619
}
1620
1621
// the methods in subclass apply the methods in $StringDict to the
1622
// result of instance.valueOf(), which is a Javascript string
1623
for(var $attr in $StringDict){
1624
if(typeof $StringDict[$attr]=='function'){
1625
$StringSubclassDict[$attr]=(function(attr){
1626
return function(){
1632
}
1633
}
1634
return $StringDict[attr].apply(null,args)
1635
}
1636
})($attr)
1637
}
1638
}
1639
$StringSubclassDict.__mro__ = [$StringSubclassDict,$ObjectDict]
1640
1641
// factory for str subclasses
1642
$B.$StringSubclassFactory = {
1643
__class__:$B.$factory,
1644
$dict:$StringSubclassDict
1645
}
1646
1647
_b_.str = str
1648
1649
// Function to parse the 2nd argument of format()
1650
$B.parse_format_spec = function(spec){
1660
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1))!=-1){
1661
// If the second char is also an alignment specifier, the
1662
// first char is the fill value
1663
this.fill = spec.charAt(0)
1664
this.align = spec.charAt(1)
1665
pos = 2
1666
}else{
1667
// The first character defines alignment : fill defaults to ' '
1668
this.align=aligns[align_pos];
1669
this.fill=' ';
1670
pos++
1671
}
1672
}else{
1673
align_pos = aligns.indexOf(spec.charAt(1))
1674
if(spec.charAt(1) && align_pos!=-1){
1675
// The second character defines alignment : fill is the first one
1676
this.align=aligns[align_pos]
1677
this.fill=spec.charAt(0)
1678
pos = 2
1679
}
1680
}
1681
var car = spec.charAt(pos)
1682
if(car=='+'||car=='-'||car==' '){
1683
this.sign=car;
1684
pos++;
1685
car=spec.charAt(pos);
1688
if(car=='0'){
1689
// sign-aware : equivalent to fill=0 and align=='='
1690
this.fill='0'
1691
this.align = '='
1692
pos++;car=spec.charAt(pos)
1693
}
1695
if(this.width===undefined){this.width=car}
1696
else{this.width+=car}
1697
pos++;car=spec.charAt(pos)
1699
if(this.width!==undefined){this.width=parseInt(this.width)}
1700
if(car==','){this.comma=true;pos++;car=spec.charAt(pos)}
1701
if(car=='.'){
1702
if(digits.indexOf(spec.charAt(pos+1))==-1){
1703
throw _b_.ValueError("Missing precision in format spec")
1704
}
1705
this.precision = spec.charAt(pos+1)
1706
pos+=2;car=spec.charAt(pos)
1707
while(car && digits.indexOf(car)>-1){
1708
this.precision+=car;pos++;car=spec.charAt(pos)
1709
}
1710
this.precision = parseInt(this.precision)
1711
}
1712
if(car && types.indexOf(car)>-1){this.type=car;pos++;car=spec.charAt(pos)}
1713
if(pos!==spec.length){
1714
console.log('error', spec, this, pos, spec.charAt(pos))
1715
throw _b_.ValueError("Invalid format specifier")
1716
}
1717
}
1718
this.toString = function(){
1719
return (this.fill===undefined ? '' : _b_.str(this.fill))+
1720
(this.align||'')+
1721
(this.sign||'')+
1722
(this.alternate ? '#' : '')+
1723
(this.sign_aware ? '0' : '')+
1724
(this.width || '')+
1725
(this.comma ? ',' : '')+
1726
(this.precision ? '.'+this.precision : '')+
1727
(this.type || '')
1728
}
1729
}
1730
1731
$B.format_width = function(s, fmt){
1732
if(fmt.width && s.length<fmt.width){
1733
var fill=fmt.fill || ' ', align = fmt.align || '<',
1734
missing = fmt.width-s.length
1735
switch(align){
1736
case '<':
1737
return s+fill.repeat(missing)
1738
case '>':
1739
return fill.repeat(missing)+s
1740
case '=':
1741
if('+-'.indexOf(s.charAt(0))>-1){
1742
return s.charAt(0)+fill.repeat(missing)+s.substr(1)
1743
}else{
1744
return fill.repeat(missing)+s
1745
}
1746
case '^':
1747
left = parseInt(missing/2)