opal 0.3.43 → 0.3.44
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +19 -0
- data/README.md +1 -0
- data/Rakefile +29 -19
- data/examples/native/Gemfile +3 -0
- data/examples/native/README.md +17 -0
- data/examples/native/app/app.rb +38 -0
- data/examples/native/config.ru +8 -0
- data/examples/native/index.html.erb +12 -0
- data/lib/opal/lexer.rb +5 -1
- data/lib/opal/parser.rb +36 -10
- data/lib/opal/processor.rb +10 -9
- data/lib/opal/server.rb +17 -7
- data/lib/opal/target_scope.rb +2 -2
- data/lib/opal/version.rb +1 -1
- data/opal/opal-browser/script_loader.rb +8 -13
- data/opal/opal.rb +23 -5
- data/opal/opal/array.rb +128 -14
- data/opal/opal/boolean.rb +1 -1
- data/opal/opal/class.rb +92 -18
- data/opal/opal/enumerable.rb +90 -0
- data/opal/opal/error.rb +1 -1
- data/opal/opal/hash.rb +2 -2
- data/opal/opal/kernel.rb +3 -3
- data/opal/opal/numeric.rb +1 -1
- data/opal/opal/proc.rb +1 -1
- data/opal/opal/regexp.rb +31 -31
- data/opal/opal/runtime.js +181 -69
- data/opal/opal/string.rb +561 -40
- data/opal/opal/time.rb +1 -1
- data/opal/rbconfig.rb +17 -3
- data/opal/strscan.rb +41 -5
- data/spec/opal/class/new_spec.rb +27 -0
- data/spec/opal/native_spec.rb +127 -0
- data/spec/ospec/runner.rb +0 -2
- data/spec/parser/strscan/get_byte_spec.rb +29 -0
- data/spec/parser/strscan/skip_spec.rb +40 -0
- data/spec/rubyspec/core/array/each_spec.rb +1 -1
- data/spec/rubyspec/core/array/intersection_spec.rb +5 -0
- data/spec/rubyspec/core/array/max_spec.rb +32 -0
- data/spec/rubyspec/core/array/min_spec.rb +32 -0
- data/spec/rubyspec/core/array/minus_spec.rb +7 -5
- data/spec/rubyspec/core/array/multiply_spec.rb +1 -1
- data/spec/rubyspec/core/array/plus_spec.rb +1 -1
- data/spec/rubyspec/core/array/pop_spec.rb +1 -1
- data/spec/rubyspec/core/array/push_spec.rb +1 -1
- data/spec/rubyspec/core/array/rassoc_spec.rb +1 -1
- data/spec/rubyspec/core/array/reject_spec.rb +2 -2
- data/spec/rubyspec/core/array/reverse_each_spec.rb +2 -2
- data/spec/rubyspec/core/array/rindex_spec.rb +2 -2
- data/spec/rubyspec/core/array/select_spec.rb +1 -1
- data/spec/rubyspec/core/array/shift_spec.rb +1 -1
- data/spec/rubyspec/core/array/slice_spec.rb +1 -1
- data/spec/rubyspec/core/array/sort_spec.rb +15 -15
- data/spec/rubyspec/core/array/to_a_spec.rb +1 -1
- data/spec/rubyspec/core/array/to_ary_spec.rb +1 -1
- data/spec/rubyspec/core/array/uniq_spec.rb +1 -1
- data/spec/rubyspec/core/array/unshift_spec.rb +1 -1
- data/spec/rubyspec/core/array/zip_spec.rb +1 -1
- data/spec/rubyspec/core/enumerable/select_spec.rb +4 -1
- data/spec/rubyspec/core/module/const_defined_spec.rb +86 -0
- data/spec/rubyspec/core/module/const_get_spec.rb +55 -3
- data/spec/rubyspec/core/module/const_set_spec.rb +2 -2
- data/spec/rubyspec/core/module/constants_spec.rb +49 -0
- data/spec/rubyspec/core/regexp/match_spec.rb +66 -1
- data/spec/rubyspec/core/string/center_spec.rb +71 -0
- data/spec/rubyspec/core/string/chomp_spec.rb +6 -1
- data/spec/rubyspec/core/string/clone_spec.rb +8 -0
- data/spec/rubyspec/core/string/dup_spec.rb +8 -0
- data/spec/rubyspec/core/string/end_with_spec.rb +5 -1
- data/spec/rubyspec/core/string/gsub_spec.rb +15 -1
- data/spec/rubyspec/core/string/lines_spec.rb +9 -0
- data/spec/rubyspec/core/string/ljust_spec.rb +17 -0
- data/spec/rubyspec/core/string/match_spec.rb +25 -3
- data/spec/rubyspec/core/string/rindex_spec.rb +50 -0
- data/spec/rubyspec/core/string/rjust_spec.rb +17 -0
- data/spec/rubyspec/core/string/scan_spec.rb +66 -0
- data/spec/rubyspec/core/string/sub_spec.rb +17 -1
- data/spec/rubyspec/core/string/tr_s_spec.rb +31 -0
- data/spec/rubyspec/core/string/tr_spec.rb +31 -0
- data/spec/rubyspec/fixtures/constants.rb +6 -0
- data/spec/rubyspec/language/class_spec.rb +4 -8
- data/spec/rubyspec/language/numbers_spec.rb +10 -4
- data/spec/rubyspec/language/predefined_spec.rb +69 -2
- data/spec/rubyspec/library/rbconfig/config_spec.rb +47 -0
- data/spec/rubyspec/spec_helper.rb +6 -0
- metadata +46 -25
- data/opal/opal-eventable.rb +0 -26
- data/opal/opal/native.rb +0 -115
- data/spec/opal/eventable_spec.rb +0 -75
- data/spec/opal/native/element_reference_spec.rb +0 -40
- data/spec/opal/native/equal_spec.rb +0 -17
- data/spec/opal/native/fixtures/classes.rb +0 -27
- data/spec/opal/native/global_spec.rb +0 -12
- data/spec/opal/native/initialize_spec.rb +0 -8
- data/spec/opal/native/method_missing_spec.rb +0 -53
- data/spec/opal/native/to_native_spec.rb +0 -8
- data/spec/rubyspec/core/string/demodulize_spec.rb +0 -10
- data/spec/rubyspec/core/string/underscore_spec.rb +0 -17
data/opal/opal/string.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
class String
|
1
|
+
class String
|
2
2
|
include Comparable
|
3
3
|
|
4
4
|
`def._isString = true`
|
@@ -165,6 +165,19 @@ class String < `String`
|
|
165
165
|
}
|
166
166
|
end
|
167
167
|
|
168
|
+
def center(width, padstr = ' ')
|
169
|
+
%x{
|
170
|
+
if (width <= #{self}.length) {
|
171
|
+
return #{self};
|
172
|
+
}
|
173
|
+
else {
|
174
|
+
var ljustified = #{self.ljust( ((width + self.size)/2).floor, padstr)};
|
175
|
+
var rjustified = #{self.rjust( ((width + self.size)/2).ceil, padstr)};
|
176
|
+
return ljustified + rjustified.slice(#{self}.length);
|
177
|
+
}
|
178
|
+
}
|
179
|
+
end
|
180
|
+
|
168
181
|
def chars
|
169
182
|
%x{
|
170
183
|
for (var i = 0, length = #{self}.length; i < length; i++) {
|
@@ -175,13 +188,30 @@ class String < `String`
|
|
175
188
|
|
176
189
|
def chomp(separator = $/)
|
177
190
|
%x{
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
191
|
+
var strlen = #{self}.length;
|
192
|
+
var seplen = separator.length;
|
193
|
+
if (strlen > 0) {
|
194
|
+
if (separator === "\\n") {
|
195
|
+
var last = #{self}.charAt(strlen - 1);
|
196
|
+
if (last === "\\n" || last == "\\r") {
|
197
|
+
var result = #{self}.substr(0, strlen - 1);
|
198
|
+
if (strlen > 1 && #{self}.charAt(strlen - 2) === "\\r") {
|
199
|
+
result = #{self}.substr(0, strlen - 2);
|
200
|
+
}
|
201
|
+
return result;
|
202
|
+
}
|
203
|
+
}
|
204
|
+
else if (separator === "") {
|
205
|
+
return #{self}.replace(/(?:\\n|\\r\\n)+$/, '');
|
206
|
+
}
|
207
|
+
else if (strlen >= seplen) {
|
208
|
+
var tail = #{self}.substr(-1 * seplen);
|
209
|
+
if (tail === separator) {
|
210
|
+
return #{self}.substr(0, strlen - seplen);
|
211
|
+
}
|
212
|
+
}
|
183
213
|
}
|
184
|
-
return #{self}
|
214
|
+
return #{self}
|
185
215
|
}
|
186
216
|
end
|
187
217
|
|
@@ -193,39 +223,49 @@ class String < `String`
|
|
193
223
|
`#{self}.charAt(0)`
|
194
224
|
end
|
195
225
|
|
196
|
-
def
|
197
|
-
|
226
|
+
def clone
|
227
|
+
`#{self}.slice()`
|
198
228
|
end
|
199
229
|
|
200
|
-
def
|
201
|
-
|
202
|
-
.replace(/([A-Z\\d]+)([A-Z][a-z])/g, '$1-$2')
|
203
|
-
.replace(/([a-z\\d])([A-Z])/g, '$1-$2')
|
204
|
-
.toLowerCase()`
|
230
|
+
def count(str)
|
231
|
+
`(#{self}.length - #{self}.replace(new RegExp(str,"g"), '').length) / str.length`
|
205
232
|
end
|
206
233
|
|
207
|
-
|
208
|
-
%x{
|
209
|
-
var idx = #{self}.lastIndexOf('::');
|
210
|
-
|
211
|
-
if (idx > -1) {
|
212
|
-
return #{self}.substr(idx + 2);
|
213
|
-
}
|
214
|
-
|
215
|
-
return #{self};
|
216
|
-
}
|
217
|
-
end
|
234
|
+
alias dup clone
|
218
235
|
|
219
236
|
alias_native :downcase, :toLowerCase
|
220
237
|
|
221
238
|
alias each_char chars
|
222
239
|
|
223
240
|
def each_line (separator = $/)
|
241
|
+
return self.split(separator).each unless block_given?
|
242
|
+
|
224
243
|
%x{
|
225
|
-
var
|
244
|
+
var chomped = #{self.chomp};
|
245
|
+
var trailing_separator = #{self}.length != chomped.length
|
246
|
+
var splitted = chomped.split(separator);
|
247
|
+
|
248
|
+
if (!#{block_given?}) {
|
249
|
+
result = []
|
250
|
+
for (var i = 0, length = splitted.length; i < length; i++) {
|
251
|
+
if (i < length - 1 || trailing_separator) {
|
252
|
+
result.push(splitted[i] + separator);
|
253
|
+
}
|
254
|
+
else {
|
255
|
+
result.push(splitted[i]);
|
256
|
+
}
|
257
|
+
}
|
258
|
+
|
259
|
+
return #{`result`.each};
|
260
|
+
}
|
226
261
|
|
227
262
|
for (var i = 0, length = splitted.length; i < length; i++) {
|
228
|
-
|
263
|
+
if (i < length - 1 || trailing_separator) {
|
264
|
+
#{yield `splitted[i] + separator`}
|
265
|
+
}
|
266
|
+
else {
|
267
|
+
#{yield `splitted[i]`}
|
268
|
+
}
|
229
269
|
}
|
230
270
|
}
|
231
271
|
end
|
@@ -239,7 +279,7 @@ class String < `String`
|
|
239
279
|
for (var i = 0, length = suffixes.length; i < length; i++) {
|
240
280
|
var suffix = suffixes[i];
|
241
281
|
|
242
|
-
if (#{self}.
|
282
|
+
if (#{self}.length >= suffix.length && #{self}.substr(0 - suffix.length) === suffix) {
|
243
283
|
return true;
|
244
284
|
}
|
245
285
|
}
|
@@ -352,8 +392,19 @@ class String < `String`
|
|
352
392
|
`#{self}.length`
|
353
393
|
end
|
354
394
|
|
355
|
-
def ljust(
|
356
|
-
|
395
|
+
def ljust(width, padstr = ' ')
|
396
|
+
%x{
|
397
|
+
if (width <= #{self}.length) {
|
398
|
+
return #{self};
|
399
|
+
}
|
400
|
+
else {
|
401
|
+
var n_chars = Math.floor(width - #{self}.length)
|
402
|
+
var n_patterns = Math.floor(n_chars/padstr.length);
|
403
|
+
var result = Array(n_patterns + 1).join(padstr);
|
404
|
+
var remaining = n_chars - result.length;
|
405
|
+
return result + padstr.slice(0, remaining) + #{self};
|
406
|
+
}
|
407
|
+
}
|
357
408
|
end
|
358
409
|
|
359
410
|
def lstrip
|
@@ -394,10 +445,95 @@ class String < `String`
|
|
394
445
|
`#{self}.split('').reverse().join('')`
|
395
446
|
end
|
396
447
|
|
448
|
+
# TODO handle case where search is regexp
|
449
|
+
def rindex(search, offset = undefined)
|
450
|
+
%x{
|
451
|
+
var search_type = (search == null ? Opal.NilClass : search.$class());
|
452
|
+
if (search_type != String && search_type != RegExp) {
|
453
|
+
var msg = "type mismatch: " + search_type + " given";
|
454
|
+
#{raise TypeError.new(`msg`)};
|
455
|
+
}
|
456
|
+
|
457
|
+
if (#{self}.length == 0) {
|
458
|
+
return search.length == 0 ? 0 : nil;
|
459
|
+
}
|
460
|
+
|
461
|
+
var result = -1;
|
462
|
+
if (offset != null) {
|
463
|
+
if (offset < 0) {
|
464
|
+
offset = #{self}.length + offset;
|
465
|
+
}
|
466
|
+
|
467
|
+
if (search_type == String) {
|
468
|
+
result = #{self}.lastIndexOf(search, offset);
|
469
|
+
}
|
470
|
+
else {
|
471
|
+
result = #{self}.substr(0, offset + 1).$reverse().search(search);
|
472
|
+
if (result !== -1) {
|
473
|
+
result = offset - result;
|
474
|
+
}
|
475
|
+
}
|
476
|
+
}
|
477
|
+
else {
|
478
|
+
if (search_type == String) {
|
479
|
+
result = #{self}.lastIndexOf(search);
|
480
|
+
}
|
481
|
+
else {
|
482
|
+
result = #{self}.$reverse().search(search);
|
483
|
+
if (result !== -1) {
|
484
|
+
result = #{self}.length - 1 - result;
|
485
|
+
}
|
486
|
+
}
|
487
|
+
}
|
488
|
+
|
489
|
+
return result === -1 ? nil : result;
|
490
|
+
}
|
491
|
+
end
|
492
|
+
|
493
|
+
def rjust(width, padstr = ' ')
|
494
|
+
%x{
|
495
|
+
if (width <= #{self}.length) {
|
496
|
+
return #{self};
|
497
|
+
}
|
498
|
+
else {
|
499
|
+
var ljustified = #{ self.ljust(width, padstr) };
|
500
|
+
return #{self} + ljustified.slice(0, -#{self}.length);
|
501
|
+
}
|
502
|
+
}
|
503
|
+
end
|
504
|
+
|
397
505
|
def rstrip
|
398
506
|
`#{self}.replace(/\\s*$/, '')`
|
399
507
|
end
|
400
508
|
|
509
|
+
def scan(pattern, &block)
|
510
|
+
%x{
|
511
|
+
if (pattern.global) {
|
512
|
+
// should we clear it afterwards too?
|
513
|
+
pattern.lastIndex = 0;
|
514
|
+
}
|
515
|
+
else {
|
516
|
+
// rewrite regular expression to add the global flag to capture pre/post match
|
517
|
+
pattern = new RegExp(pattern.source, 'g' + (pattern.multiline ? 'm' : '') + (pattern.ignoreCase ? 'i' : ''));
|
518
|
+
}
|
519
|
+
|
520
|
+
var result = [];
|
521
|
+
var match;
|
522
|
+
|
523
|
+
while ((match = pattern.exec(#{self})) != null) {
|
524
|
+
var match_data = #{MatchData.new `pattern`, `match`};
|
525
|
+
if (block === nil) {
|
526
|
+
match.length == 1 ? result.push(match[0]) : result.push(match.slice(1));
|
527
|
+
}
|
528
|
+
else {
|
529
|
+
match.length == 1 ? block(match[0]) : block.apply(#{self}, match.slice(1));
|
530
|
+
}
|
531
|
+
}
|
532
|
+
|
533
|
+
return (block !== nil ? #{self} : result);
|
534
|
+
}
|
535
|
+
end
|
536
|
+
|
401
537
|
alias size length
|
402
538
|
|
403
539
|
alias slice []
|
@@ -425,12 +561,35 @@ class String < `String`
|
|
425
561
|
def sub(pattern, replace = undefined, &block)
|
426
562
|
%x{
|
427
563
|
if (typeof(replace) === 'string') {
|
564
|
+
// convert Ruby back reference to JavaScript back reference
|
565
|
+
replace = replace.replace(/\\\\([1-9])/g, '$$$1')
|
428
566
|
return #{self}.replace(pattern, replace);
|
429
567
|
}
|
430
568
|
if (block !== nil) {
|
431
|
-
return #{self}.replace(pattern, function(
|
432
|
-
|
433
|
-
|
569
|
+
return #{self}.replace(pattern, function() {
|
570
|
+
// FIXME: this should be a formal MatchData object with all the goodies
|
571
|
+
var match_data = []
|
572
|
+
for (var i = 0, len = arguments.length; i < len; i++) {
|
573
|
+
var arg = arguments[i];
|
574
|
+
if (arg == undefined) {
|
575
|
+
match_data.push(nil);
|
576
|
+
}
|
577
|
+
else {
|
578
|
+
match_data.push(arg);
|
579
|
+
}
|
580
|
+
}
|
581
|
+
|
582
|
+
var str = match_data.pop();
|
583
|
+
var offset = match_data.pop();
|
584
|
+
var match_len = match_data.length;
|
585
|
+
|
586
|
+
// $1, $2, $3 not being parsed correctly in Ruby code
|
587
|
+
//for (var i = 1; i < match_len; i++) {
|
588
|
+
// __gvars[String(i)] = match_data[i];
|
589
|
+
//}
|
590
|
+
#{$& = `match_data[0]`};
|
591
|
+
#{$~ = `match_data`};
|
592
|
+
return block(match_data[0]);
|
434
593
|
});
|
435
594
|
}
|
436
595
|
else if (replace !== undefined) {
|
@@ -452,7 +611,9 @@ class String < `String`
|
|
452
611
|
}
|
453
612
|
}
|
454
613
|
else {
|
455
|
-
|
614
|
+
// convert Ruby back reference to JavaScript back reference
|
615
|
+
replace = replace.toString().replace(/\\\\([1-9])/g, '$$$1')
|
616
|
+
return #{self}.replace(pattern, replace);
|
456
617
|
}
|
457
618
|
}
|
458
619
|
end
|
@@ -533,15 +694,375 @@ class String < `String`
|
|
533
694
|
alias to_str to_s
|
534
695
|
|
535
696
|
alias to_sym intern
|
536
|
-
|
537
|
-
def
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
697
|
+
|
698
|
+
def tr(from, to)
|
699
|
+
%x{
|
700
|
+
if (from.length == 0 || from === to) {
|
701
|
+
return #{self};
|
702
|
+
}
|
703
|
+
|
704
|
+
var subs = {};
|
705
|
+
var from_chars = from.split('');
|
706
|
+
var from_length = from_chars.length;
|
707
|
+
var to_chars = to.split('');
|
708
|
+
var to_length = to_chars.length;
|
709
|
+
|
710
|
+
var inverse = false;
|
711
|
+
var global_sub = null;
|
712
|
+
if (from_chars[0] === '^') {
|
713
|
+
inverse = true;
|
714
|
+
from_chars.shift();
|
715
|
+
global_sub = to_chars[to_length - 1]
|
716
|
+
from_length -= 1;
|
717
|
+
}
|
718
|
+
|
719
|
+
var from_chars_expanded = [];
|
720
|
+
var last_from = null;
|
721
|
+
var in_range = false;
|
722
|
+
for (var i = 0; i < from_length; i++) {
|
723
|
+
var char = from_chars[i];
|
724
|
+
if (last_from == null) {
|
725
|
+
last_from = char;
|
726
|
+
from_chars_expanded.push(char);
|
727
|
+
}
|
728
|
+
else if (char === '-') {
|
729
|
+
if (last_from === '-') {
|
730
|
+
from_chars_expanded.push('-');
|
731
|
+
from_chars_expanded.push('-');
|
732
|
+
}
|
733
|
+
else if (i == from_length - 1) {
|
734
|
+
from_chars_expanded.push('-');
|
735
|
+
}
|
736
|
+
else {
|
737
|
+
in_range = true;
|
738
|
+
}
|
739
|
+
}
|
740
|
+
else if (in_range) {
|
741
|
+
var start = last_from.charCodeAt(0) + 1;
|
742
|
+
var end = char.charCodeAt(0);
|
743
|
+
for (var c = start; c < end; c++) {
|
744
|
+
from_chars_expanded.push(String.fromCharCode(c));
|
745
|
+
}
|
746
|
+
from_chars_expanded.push(char);
|
747
|
+
in_range = null;
|
748
|
+
last_from = null;
|
749
|
+
}
|
750
|
+
else {
|
751
|
+
from_chars_expanded.push(char);
|
752
|
+
}
|
753
|
+
}
|
754
|
+
|
755
|
+
from_chars = from_chars_expanded;
|
756
|
+
from_length = from_chars.length;
|
757
|
+
|
758
|
+
if (inverse) {
|
759
|
+
for (var i = 0; i < from_length; i++) {
|
760
|
+
subs[from_chars[i]] = true;
|
761
|
+
}
|
762
|
+
}
|
763
|
+
else {
|
764
|
+
if (to_length > 0) {
|
765
|
+
var to_chars_expanded = [];
|
766
|
+
var last_to = null;
|
767
|
+
var in_range = false;
|
768
|
+
for (var i = 0; i < to_length; i++) {
|
769
|
+
var char = to_chars[i];
|
770
|
+
if (last_from == null) {
|
771
|
+
last_from = char;
|
772
|
+
to_chars_expanded.push(char);
|
773
|
+
}
|
774
|
+
else if (char === '-') {
|
775
|
+
if (last_to === '-') {
|
776
|
+
to_chars_expanded.push('-');
|
777
|
+
to_chars_expanded.push('-');
|
778
|
+
}
|
779
|
+
else if (i == to_length - 1) {
|
780
|
+
to_chars_expanded.push('-');
|
781
|
+
}
|
782
|
+
else {
|
783
|
+
in_range = true;
|
784
|
+
}
|
785
|
+
}
|
786
|
+
else if (in_range) {
|
787
|
+
var start = last_from.charCodeAt(0) + 1;
|
788
|
+
var end = char.charCodeAt(0);
|
789
|
+
for (var c = start; c < end; c++) {
|
790
|
+
to_chars_expanded.push(String.fromCharCode(c));
|
791
|
+
}
|
792
|
+
to_chars_expanded.push(char);
|
793
|
+
in_range = null;
|
794
|
+
last_from = null;
|
795
|
+
}
|
796
|
+
else {
|
797
|
+
to_chars_expanded.push(char);
|
798
|
+
}
|
799
|
+
}
|
800
|
+
|
801
|
+
to_chars = to_chars_expanded;
|
802
|
+
to_length = to_chars.length;
|
803
|
+
}
|
804
|
+
|
805
|
+
var length_diff = from_length - to_length;
|
806
|
+
if (length_diff > 0) {
|
807
|
+
var pad_char = (to_length > 0 ? to_chars[to_length - 1] : '');
|
808
|
+
for (var i = 0; i < length_diff; i++) {
|
809
|
+
to_chars.push(pad_char);
|
810
|
+
}
|
811
|
+
}
|
812
|
+
|
813
|
+
for (var i = 0; i < from_length; i++) {
|
814
|
+
subs[from_chars[i]] = to_chars[i];
|
815
|
+
}
|
816
|
+
}
|
817
|
+
|
818
|
+
var new_str = ''
|
819
|
+
for (var i = 0, length = #{self}.length; i < length; i++) {
|
820
|
+
var char = #{self}.charAt(i);
|
821
|
+
var sub = subs[char];
|
822
|
+
if (inverse) {
|
823
|
+
new_str += (sub == null ? global_sub : char);
|
824
|
+
}
|
825
|
+
else {
|
826
|
+
new_str += (sub != null ? sub : char);
|
827
|
+
}
|
828
|
+
}
|
829
|
+
return new_str;
|
830
|
+
}
|
831
|
+
end
|
832
|
+
|
833
|
+
def tr_s(from, to)
|
834
|
+
%x{
|
835
|
+
if (from.length == 0) {
|
836
|
+
return #{self};
|
837
|
+
}
|
838
|
+
|
839
|
+
var subs = {};
|
840
|
+
var from_chars = from.split('');
|
841
|
+
var from_length = from_chars.length;
|
842
|
+
var to_chars = to.split('');
|
843
|
+
var to_length = to_chars.length;
|
844
|
+
|
845
|
+
var inverse = false;
|
846
|
+
var global_sub = null;
|
847
|
+
if (from_chars[0] === '^') {
|
848
|
+
inverse = true;
|
849
|
+
from_chars.shift();
|
850
|
+
global_sub = to_chars[to_length - 1]
|
851
|
+
from_length -= 1;
|
852
|
+
}
|
853
|
+
|
854
|
+
var from_chars_expanded = [];
|
855
|
+
var last_from = null;
|
856
|
+
var in_range = false;
|
857
|
+
for (var i = 0; i < from_length; i++) {
|
858
|
+
var char = from_chars[i];
|
859
|
+
if (last_from == null) {
|
860
|
+
last_from = char;
|
861
|
+
from_chars_expanded.push(char);
|
862
|
+
}
|
863
|
+
else if (char === '-') {
|
864
|
+
if (last_from === '-') {
|
865
|
+
from_chars_expanded.push('-');
|
866
|
+
from_chars_expanded.push('-');
|
867
|
+
}
|
868
|
+
else if (i == from_length - 1) {
|
869
|
+
from_chars_expanded.push('-');
|
870
|
+
}
|
871
|
+
else {
|
872
|
+
in_range = true;
|
873
|
+
}
|
874
|
+
}
|
875
|
+
else if (in_range) {
|
876
|
+
var start = last_from.charCodeAt(0) + 1;
|
877
|
+
var end = char.charCodeAt(0);
|
878
|
+
for (var c = start; c < end; c++) {
|
879
|
+
from_chars_expanded.push(String.fromCharCode(c));
|
880
|
+
}
|
881
|
+
from_chars_expanded.push(char);
|
882
|
+
in_range = null;
|
883
|
+
last_from = null;
|
884
|
+
}
|
885
|
+
else {
|
886
|
+
from_chars_expanded.push(char);
|
887
|
+
}
|
888
|
+
}
|
889
|
+
|
890
|
+
from_chars = from_chars_expanded;
|
891
|
+
from_length = from_chars.length;
|
892
|
+
|
893
|
+
if (inverse) {
|
894
|
+
for (var i = 0; i < from_length; i++) {
|
895
|
+
subs[from_chars[i]] = true;
|
896
|
+
}
|
897
|
+
}
|
898
|
+
else {
|
899
|
+
if (to_length > 0) {
|
900
|
+
var to_chars_expanded = [];
|
901
|
+
var last_to = null;
|
902
|
+
var in_range = false;
|
903
|
+
for (var i = 0; i < to_length; i++) {
|
904
|
+
var char = to_chars[i];
|
905
|
+
if (last_from == null) {
|
906
|
+
last_from = char;
|
907
|
+
to_chars_expanded.push(char);
|
908
|
+
}
|
909
|
+
else if (char === '-') {
|
910
|
+
if (last_to === '-') {
|
911
|
+
to_chars_expanded.push('-');
|
912
|
+
to_chars_expanded.push('-');
|
913
|
+
}
|
914
|
+
else if (i == to_length - 1) {
|
915
|
+
to_chars_expanded.push('-');
|
916
|
+
}
|
917
|
+
else {
|
918
|
+
in_range = true;
|
919
|
+
}
|
920
|
+
}
|
921
|
+
else if (in_range) {
|
922
|
+
var start = last_from.charCodeAt(0) + 1;
|
923
|
+
var end = char.charCodeAt(0);
|
924
|
+
for (var c = start; c < end; c++) {
|
925
|
+
to_chars_expanded.push(String.fromCharCode(c));
|
926
|
+
}
|
927
|
+
to_chars_expanded.push(char);
|
928
|
+
in_range = null;
|
929
|
+
last_from = null;
|
930
|
+
}
|
931
|
+
else {
|
932
|
+
to_chars_expanded.push(char);
|
933
|
+
}
|
934
|
+
}
|
935
|
+
|
936
|
+
to_chars = to_chars_expanded;
|
937
|
+
to_length = to_chars.length;
|
938
|
+
}
|
939
|
+
|
940
|
+
var length_diff = from_length - to_length;
|
941
|
+
if (length_diff > 0) {
|
942
|
+
var pad_char = (to_length > 0 ? to_chars[to_length - 1] : '');
|
943
|
+
for (var i = 0; i < length_diff; i++) {
|
944
|
+
to_chars.push(pad_char);
|
945
|
+
}
|
946
|
+
}
|
947
|
+
|
948
|
+
for (var i = 0; i < from_length; i++) {
|
949
|
+
subs[from_chars[i]] = to_chars[i];
|
950
|
+
}
|
951
|
+
}
|
952
|
+
var new_str = ''
|
953
|
+
var last_substitute = null
|
954
|
+
for (var i = 0, length = #{self}.length; i < length; i++) {
|
955
|
+
var char = #{self}.charAt(i);
|
956
|
+
var sub = subs[char]
|
957
|
+
if (inverse) {
|
958
|
+
if (sub == null) {
|
959
|
+
if (last_substitute == null) {
|
960
|
+
new_str += global_sub;
|
961
|
+
last_substitute = true;
|
962
|
+
}
|
963
|
+
}
|
964
|
+
else {
|
965
|
+
new_str += char;
|
966
|
+
last_substitute = null;
|
967
|
+
}
|
968
|
+
}
|
969
|
+
else {
|
970
|
+
if (sub != null) {
|
971
|
+
if (last_substitute == null || last_substitute !== sub) {
|
972
|
+
new_str += sub;
|
973
|
+
last_substitute = sub;
|
974
|
+
}
|
975
|
+
}
|
976
|
+
else {
|
977
|
+
new_str += char;
|
978
|
+
last_substitute = null;
|
979
|
+
}
|
980
|
+
}
|
981
|
+
}
|
982
|
+
return new_str;
|
983
|
+
}
|
542
984
|
end
|
543
985
|
|
544
986
|
alias_native :upcase, :toUpperCase
|
545
987
|
end
|
546
988
|
|
547
989
|
Symbol = String
|
990
|
+
|
991
|
+
class MatchData < Array
|
992
|
+
attr_reader :post_match, :pre_match, :regexp, :string
|
993
|
+
|
994
|
+
def self.new(regexp, match_groups)
|
995
|
+
%x{
|
996
|
+
var instance = new Opal.MatchData;
|
997
|
+
for (var i = 0, len = match_groups.length; i < len; i++) {
|
998
|
+
var group = match_groups[i];
|
999
|
+
if (group == undefined) {
|
1000
|
+
instance.push(nil);
|
1001
|
+
}
|
1002
|
+
else {
|
1003
|
+
instance.push(group);
|
1004
|
+
}
|
1005
|
+
}
|
1006
|
+
instance._begin = match_groups.index;
|
1007
|
+
instance.regexp = regexp;
|
1008
|
+
instance.string = match_groups.input;
|
1009
|
+
instance.pre_match = #{$` = `instance.string.substr(0, regexp.lastIndex - instance[0].length)`};
|
1010
|
+
instance.post_match = #{$' = `instance.string.substr(regexp.lastIndex)`};
|
1011
|
+
return #{$~ = `instance`};
|
1012
|
+
}
|
1013
|
+
end
|
1014
|
+
|
1015
|
+
def begin(pos)
|
1016
|
+
%x{
|
1017
|
+
if (pos == 0 || pos == 1) {
|
1018
|
+
return #{self}._begin;
|
1019
|
+
}
|
1020
|
+
else {
|
1021
|
+
#{raise ArgumentError, 'MatchData#begin only supports 0th element'};
|
1022
|
+
}
|
1023
|
+
}
|
1024
|
+
end
|
1025
|
+
|
1026
|
+
def captures
|
1027
|
+
`#{self}.slice(1)`
|
1028
|
+
end
|
1029
|
+
|
1030
|
+
def inspect
|
1031
|
+
%x{
|
1032
|
+
var str = "<#MatchData " + #{self}[0].$inspect()
|
1033
|
+
for (var i = 1, len = #{self}.length; i < len; i++) {
|
1034
|
+
str += " " + i + ":" + #{self}[i].$inspect();
|
1035
|
+
}
|
1036
|
+
str += ">";
|
1037
|
+
return str;
|
1038
|
+
}
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
def to_s
|
1042
|
+
`#{self}[0]`
|
1043
|
+
end
|
1044
|
+
|
1045
|
+
def values_at(*indexes)
|
1046
|
+
%x{
|
1047
|
+
var vals = [];
|
1048
|
+
var match_length = #{self}.length;
|
1049
|
+
for (var i = 0, length = indexes.length; i < length; i++) {
|
1050
|
+
var pos = indexes[i];
|
1051
|
+
if (pos >= 0) {
|
1052
|
+
vals.push(#{self}[pos]);
|
1053
|
+
}
|
1054
|
+
else {
|
1055
|
+
pos = match_length + pos;
|
1056
|
+
if (pos > 0) {
|
1057
|
+
vals.push(#{self}[pos]);
|
1058
|
+
}
|
1059
|
+
else {
|
1060
|
+
vals.push(nil);
|
1061
|
+
}
|
1062
|
+
}
|
1063
|
+
}
|
1064
|
+
|
1065
|
+
return vals;
|
1066
|
+
}
|
1067
|
+
end
|
1068
|
+
end
|