opal 0.3.43 → 0.3.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|