motion-kramdown 0.5.0

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.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +84 -0
  3. data/lib/kramdown/compatibility.rb +36 -0
  4. data/lib/kramdown/converter/base.rb +259 -0
  5. data/lib/kramdown/converter/html.rb +461 -0
  6. data/lib/kramdown/converter/kramdown.rb +423 -0
  7. data/lib/kramdown/converter/latex.rb +600 -0
  8. data/lib/kramdown/converter/math_engine/itex2mml.rb +39 -0
  9. data/lib/kramdown/converter/math_engine/mathjax.rb +33 -0
  10. data/lib/kramdown/converter/math_engine/ritex.rb +38 -0
  11. data/lib/kramdown/converter/pdf.rb +624 -0
  12. data/lib/kramdown/converter/remove_html_tags.rb +53 -0
  13. data/lib/kramdown/converter/syntax_highlighter/coderay.rb +78 -0
  14. data/lib/kramdown/converter/syntax_highlighter/rouge.rb +37 -0
  15. data/lib/kramdown/converter/toc.rb +69 -0
  16. data/lib/kramdown/converter.rb +69 -0
  17. data/lib/kramdown/document.rb +144 -0
  18. data/lib/kramdown/element.rb +515 -0
  19. data/lib/kramdown/error.rb +17 -0
  20. data/lib/kramdown/options.rb +584 -0
  21. data/lib/kramdown/parser/base.rb +130 -0
  22. data/lib/kramdown/parser/gfm.rb +55 -0
  23. data/lib/kramdown/parser/html.rb +575 -0
  24. data/lib/kramdown/parser/kramdown/abbreviation.rb +67 -0
  25. data/lib/kramdown/parser/kramdown/autolink.rb +37 -0
  26. data/lib/kramdown/parser/kramdown/blank_line.rb +30 -0
  27. data/lib/kramdown/parser/kramdown/block_boundary.rb +33 -0
  28. data/lib/kramdown/parser/kramdown/blockquote.rb +39 -0
  29. data/lib/kramdown/parser/kramdown/codeblock.rb +56 -0
  30. data/lib/kramdown/parser/kramdown/codespan.rb +44 -0
  31. data/lib/kramdown/parser/kramdown/emphasis.rb +61 -0
  32. data/lib/kramdown/parser/kramdown/eob.rb +26 -0
  33. data/lib/kramdown/parser/kramdown/escaped_chars.rb +25 -0
  34. data/lib/kramdown/parser/kramdown/extensions.rb +201 -0
  35. data/lib/kramdown/parser/kramdown/footnote.rb +56 -0
  36. data/lib/kramdown/parser/kramdown/header.rb +59 -0
  37. data/lib/kramdown/parser/kramdown/horizontal_rule.rb +27 -0
  38. data/lib/kramdown/parser/kramdown/html.rb +160 -0
  39. data/lib/kramdown/parser/kramdown/html_entity.rb +33 -0
  40. data/lib/kramdown/parser/kramdown/line_break.rb +25 -0
  41. data/lib/kramdown/parser/kramdown/link.rb +139 -0
  42. data/lib/kramdown/parser/kramdown/list.rb +256 -0
  43. data/lib/kramdown/parser/kramdown/math.rb +54 -0
  44. data/lib/kramdown/parser/kramdown/paragraph.rb +54 -0
  45. data/lib/kramdown/parser/kramdown/smart_quotes.rb +174 -0
  46. data/lib/kramdown/parser/kramdown/table.rb +171 -0
  47. data/lib/kramdown/parser/kramdown/typographic_symbol.rb +44 -0
  48. data/lib/kramdown/parser/kramdown.rb +359 -0
  49. data/lib/kramdown/parser/markdown.rb +56 -0
  50. data/lib/kramdown/parser.rb +27 -0
  51. data/lib/kramdown/utils/configurable.rb +44 -0
  52. data/lib/kramdown/utils/entities.rb +347 -0
  53. data/lib/kramdown/utils/html.rb +75 -0
  54. data/lib/kramdown/utils/ordered_hash.rb +87 -0
  55. data/lib/kramdown/utils/string_scanner.rb +74 -0
  56. data/lib/kramdown/utils/unidecoder.rb +51 -0
  57. data/lib/kramdown/utils.rb +58 -0
  58. data/lib/kramdown/version.rb +15 -0
  59. data/lib/kramdown.rb +10 -0
  60. data/lib/motion-kramdown.rb +47 -0
  61. data/lib/rubymotion/encodings.rb +37 -0
  62. data/lib/rubymotion/rexml_shim.rb +25 -0
  63. data/lib/rubymotion/set.rb +1349 -0
  64. data/lib/rubymotion/version.rb +6 -0
  65. data/spec/document_tree.rb +48 -0
  66. data/spec/gfm_to_html.rb +95 -0
  67. data/spec/helpers/it_behaves_like.rb +27 -0
  68. data/spec/helpers/option_file.rb +46 -0
  69. data/spec/helpers/spec_options.rb +37 -0
  70. data/spec/helpers/tidy.rb +12 -0
  71. data/spec/html_to_html.rb +40 -0
  72. data/spec/html_to_kramdown_to_html.rb +46 -0
  73. data/spec/kramdown_to_xxx.rb +40 -0
  74. data/spec/test_location.rb +203 -0
  75. data/spec/test_string_scanner_kramdown.rb +19 -0
  76. data/spec/text_to_kramdown_to_html.rb +52 -0
  77. data/spec/text_to_latex.rb +33 -0
  78. metadata +164 -0
@@ -0,0 +1,1349 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # set.rb - defines the Set class
4
+ #++
5
+ # Copyright (c) 2002-2008 Akinori MUSHA <knu@iDaemons.org>
6
+ #
7
+ # Documentation by Akinori MUSHA and Gavin Sinclair.
8
+ #
9
+ # All rights reserved. You can redistribute and/or modify it under the same
10
+ # terms as Ruby.
11
+ #
12
+ # $Id: set.rb 28095 2010-05-30 13:15:17Z marcandre $
13
+ #
14
+ # == Overview
15
+ #
16
+ # This library provides the Set class, which deals with a collection
17
+ # of unordered values with no duplicates. It is a hybrid of Array's
18
+ # intuitive inter-operation facilities and Hash's fast lookup. If you
19
+ # need to keep values ordered, use the SortedSet class.
20
+ #
21
+ # The method +to_set+ is added to Enumerable for convenience.
22
+ #
23
+ # See the Set and SortedSet documentation for examples of usage.
24
+
25
+
26
+ #
27
+ # Set implements a collection of unordered values with no duplicates.
28
+ # This is a hybrid of Array's intuitive inter-operation facilities and
29
+ # Hash's fast lookup.
30
+ #
31
+ # The equality of each couple of elements is determined according to
32
+ # Object#eql? and Object#hash, since Set uses Hash as storage.
33
+ #
34
+ # Set is easy to use with Enumerable objects (implementing +each+).
35
+ # Most of the initializer methods and binary operators accept generic
36
+ # Enumerable objects besides sets and arrays. An Enumerable object
37
+ # can be converted to Set using the +to_set+ method.
38
+ #
39
+ # == Example
40
+ #
41
+ # require 'set'
42
+ # s1 = Set.new [1, 2] # -> #<Set: {1, 2}>
43
+ # s2 = [1, 2].to_set # -> #<Set: {1, 2}>
44
+ # s1 == s2 # -> true
45
+ # s1.add("foo") # -> #<Set: {1, 2, "foo"}>
46
+ # s1.merge([2, 6]) # -> #<Set: {6, 1, 2, "foo"}>
47
+ # s1.subset? s2 # -> false
48
+ # s2.subset? s1 # -> true
49
+ #
50
+ # == Contact
51
+ #
52
+ # - Akinori MUSHA <knu@iDaemons.org> (current maintainer)
53
+ #
54
+ class Set
55
+ include Enumerable
56
+
57
+ # Creates a new set containing the given objects.
58
+ def self.[](*ary)
59
+ new(ary)
60
+ end
61
+
62
+ # Creates a new set containing the elements of the given enumerable
63
+ # object.
64
+ #
65
+ # If a block is given, the elements of enum are preprocessed by the
66
+ # given block.
67
+ def initialize(enum = nil, &block) # :yields: o
68
+ @hash ||= Hash.new
69
+
70
+ enum.nil? and return
71
+
72
+ if block
73
+ do_with_enum(enum) { |o| add(block[o]) }
74
+ else
75
+ merge(enum)
76
+ end
77
+ end
78
+
79
+ def do_with_enum(enum, &block)
80
+ if enum.respond_to?(:each_entry)
81
+ enum.each_entry(&block)
82
+ elsif enum.respond_to?(:each)
83
+ enum.each(&block)
84
+ else
85
+ raise ArgumentError, "value must be enumerable"
86
+ end
87
+ end
88
+ private :do_with_enum
89
+
90
+ # Copy internal hash.
91
+ def initialize_copy(orig)
92
+ @hash = orig.instance_eval{@hash}.dup
93
+ end
94
+
95
+ def freeze # :nodoc:
96
+ super
97
+ @hash.freeze
98
+ self
99
+ end
100
+
101
+ def taint # :nodoc:
102
+ super
103
+ @hash.taint
104
+ self
105
+ end
106
+
107
+ def untaint # :nodoc:
108
+ super
109
+ @hash.untaint
110
+ self
111
+ end
112
+
113
+ # Returns the number of elements.
114
+ def size
115
+ @hash.size
116
+ end
117
+ alias length size
118
+
119
+ # Returns true if the set contains no elements.
120
+ def empty?
121
+ @hash.empty?
122
+ end
123
+
124
+ # Removes all elements and returns self.
125
+ def clear
126
+ @hash.clear
127
+ self
128
+ end
129
+
130
+ # Replaces the contents of the set with the contents of the given
131
+ # enumerable object and returns self.
132
+ def replace(enum)
133
+ if enum.class == self.class
134
+ @hash.replace(enum.instance_eval { @hash })
135
+ else
136
+ clear
137
+ merge(enum)
138
+ end
139
+
140
+ self
141
+ end
142
+
143
+ # Converts the set to an array. The order of elements is uncertain.
144
+ def to_a
145
+ @hash.keys
146
+ end
147
+
148
+ def flatten_merge(set, seen = Set.new)
149
+ set.each { |e|
150
+ if e.is_a?(Set)
151
+ if seen.include?(e_id = e.object_id)
152
+ raise ArgumentError, "tried to flatten recursive Set"
153
+ end
154
+
155
+ seen.add(e_id)
156
+ flatten_merge(e, seen)
157
+ seen.delete(e_id)
158
+ else
159
+ add(e)
160
+ end
161
+ }
162
+
163
+ self
164
+ end
165
+ protected :flatten_merge
166
+
167
+ # Returns a new set that is a copy of the set, flattening each
168
+ # containing set recursively.
169
+ def flatten
170
+ self.class.new.flatten_merge(self)
171
+ end
172
+
173
+ # Equivalent to Set#flatten, but replaces the receiver with the
174
+ # result in place. Returns nil if no modifications were made.
175
+ def flatten!
176
+ if detect { |e| e.is_a?(Set) }
177
+ replace(flatten())
178
+ else
179
+ nil
180
+ end
181
+ end
182
+
183
+ # Returns true if the set contains the given object.
184
+ def include?(o)
185
+ @hash.include?(o)
186
+ end
187
+ alias member? include?
188
+
189
+ # Returns true if the set is a superset of the given set.
190
+ def superset?(set)
191
+ set.is_a?(Set) or raise ArgumentError, "value must be a set"
192
+ return false if size < set.size
193
+ set.all? { |o| include?(o) }
194
+ end
195
+
196
+ # Returns true if the set is a proper superset of the given set.
197
+ def proper_superset?(set)
198
+ set.is_a?(Set) or raise ArgumentError, "value must be a set"
199
+ return false if size <= set.size
200
+ set.all? { |o| include?(o) }
201
+ end
202
+
203
+ # Returns true if the set is a subset of the given set.
204
+ def subset?(set)
205
+ set.is_a?(Set) or raise ArgumentError, "value must be a set"
206
+ return false if set.size < size
207
+ all? { |o| set.include?(o) }
208
+ end
209
+
210
+ # Returns true if the set is a proper subset of the given set.
211
+ def proper_subset?(set)
212
+ set.is_a?(Set) or raise ArgumentError, "value must be a set"
213
+ return false if set.size <= size
214
+ all? { |o| set.include?(o) }
215
+ end
216
+
217
+ # Calls the given block once for each element in the set, passing
218
+ # the element as parameter. Returns an enumerator if no block is
219
+ # given.
220
+ def each
221
+ block_given? or return enum_for(__method__)
222
+ @hash.each_key { |o| yield(o) }
223
+ self
224
+ end
225
+
226
+ # Adds the given object to the set and returns self. Use +merge+ to
227
+ # add many elements at once.
228
+ def add(o)
229
+ @hash[o] = true
230
+ self
231
+ end
232
+ alias << add
233
+
234
+ # Adds the given object to the set and returns self. If the
235
+ # object is already in the set, returns nil.
236
+ def add?(o)
237
+ if include?(o)
238
+ nil
239
+ else
240
+ add(o)
241
+ end
242
+ end
243
+
244
+ # Deletes the given object from the set and returns self. Use +subtract+ to
245
+ # delete many items at once.
246
+ def delete(o)
247
+ @hash.delete(o)
248
+ self
249
+ end
250
+
251
+ # Deletes the given object from the set and returns self. If the
252
+ # object is not in the set, returns nil.
253
+ def delete?(o)
254
+ if include?(o)
255
+ delete(o)
256
+ else
257
+ nil
258
+ end
259
+ end
260
+
261
+ # Deletes every element of the set for which block evaluates to
262
+ # true, and returns self.
263
+ def delete_if
264
+ block_given? or return enum_for(__method__)
265
+ to_a.each { |o| @hash.delete(o) if yield(o) }
266
+ self
267
+ end
268
+
269
+ # Deletes every element of the set for which block evaluates to
270
+ # false, and returns self.
271
+ def keep_if
272
+ block_given? or return enum_for(__method__)
273
+ to_a.each { |o| @hash.delete(o) unless yield(o) }
274
+ self
275
+ end
276
+
277
+ # Replaces the elements with ones returned by collect().
278
+ def collect!
279
+ block_given? or return enum_for(__method__)
280
+ set = self.class.new
281
+ each { |o| set << yield(o) }
282
+ replace(set)
283
+ end
284
+ alias map! collect!
285
+
286
+ # Equivalent to Set#delete_if, but returns nil if no changes were
287
+ # made.
288
+ def reject!
289
+ block_given? or return enum_for(__method__)
290
+ n = size
291
+ delete_if { |o| yield(o) }
292
+ size == n ? nil : self
293
+ end
294
+
295
+ # Equivalent to Set#keep_if, but returns nil if no changes were
296
+ # made.
297
+ def select!
298
+ block_given? or return enum_for(__method__)
299
+ n = size
300
+ keep_if { |o| yield(o) }
301
+ size == n ? nil : self
302
+ end
303
+
304
+ # Merges the elements of the given enumerable object to the set and
305
+ # returns self.
306
+ def merge(enum)
307
+ if enum.instance_of?(self.class)
308
+ @hash.update(enum.instance_variable_get(:@hash))
309
+ else
310
+ do_with_enum(enum) { |o| add(o) }
311
+ end
312
+
313
+ self
314
+ end
315
+
316
+ # Deletes every element that appears in the given enumerable object
317
+ # and returns self.
318
+ def subtract(enum)
319
+ do_with_enum(enum) { |o| delete(o) }
320
+ self
321
+ end
322
+
323
+ # Returns a new set built by merging the set and the elements of the
324
+ # given enumerable object.
325
+ def |(enum)
326
+ dup.merge(enum)
327
+ end
328
+ alias + | ##
329
+ alias union | ##
330
+
331
+ # Returns a new set built by duplicating the set, removing every
332
+ # element that appears in the given enumerable object.
333
+ def -(enum)
334
+ dup.subtract(enum)
335
+ end
336
+ alias difference - ##
337
+
338
+ # Returns a new set containing elements common to the set and the
339
+ # given enumerable object.
340
+ def &(enum)
341
+ n = self.class.new
342
+ do_with_enum(enum) { |o| n.add(o) if include?(o) }
343
+ n
344
+ end
345
+ alias intersection & ##
346
+
347
+ # Returns a new set containing elements exclusive between the set
348
+ # and the given enumerable object. (set ^ enum) is equivalent to
349
+ # ((set | enum) - (set & enum)).
350
+ def ^(enum)
351
+ n = Set.new(enum)
352
+ each { |o| if n.include?(o) then n.delete(o) else n.add(o) end }
353
+ n
354
+ end
355
+
356
+ # Returns true if two sets are equal. The equality of each couple
357
+ # of elements is defined according to Object#eql?.
358
+ def ==(other)
359
+ if self.equal?(other)
360
+ true
361
+ elsif other.instance_of?(self.class)
362
+ @hash == other.instance_variable_get(:@hash)
363
+ elsif other.is_a?(Set) && self.size == other.size
364
+ other.all? { |o| @hash.include?(o) }
365
+ else
366
+ false
367
+ end
368
+ end
369
+
370
+ def hash # :nodoc:
371
+ @hash.hash
372
+ end
373
+
374
+ def eql?(o) # :nodoc:
375
+ return false unless o.is_a?(Set)
376
+ @hash.eql?(o.instance_eval{@hash})
377
+ end
378
+
379
+ # Classifies the set by the return value of the given block and
380
+ # returns a hash of {value => set of elements} pairs. The block is
381
+ # called once for each element of the set, passing the element as
382
+ # parameter.
383
+ #
384
+ # e.g.:
385
+ #
386
+ # require 'set'
387
+ # files = Set.new(Dir.glob("*.rb"))
388
+ # hash = files.classify { |f| File.mtime(f).year }
389
+ # p hash # => {2000=>#<Set: {"a.rb", "b.rb"}>,
390
+ # # 2001=>#<Set: {"c.rb", "d.rb", "e.rb"}>,
391
+ # # 2002=>#<Set: {"f.rb"}>}
392
+ def classify # :yields: o
393
+ block_given? or return enum_for(__method__)
394
+
395
+ h = {}
396
+
397
+ each { |i|
398
+ x = yield(i)
399
+ (h[x] ||= self.class.new).add(i)
400
+ }
401
+
402
+ h
403
+ end
404
+
405
+ # Divides the set into a set of subsets according to the commonality
406
+ # defined by the given block.
407
+ #
408
+ # If the arity of the block is 2, elements o1 and o2 are in common
409
+ # if block.call(o1, o2) is true. Otherwise, elements o1 and o2 are
410
+ # in common if block.call(o1) == block.call(o2).
411
+ #
412
+ # e.g.:
413
+ #
414
+ # require 'set'
415
+ # numbers = Set[1, 3, 4, 6, 9, 10, 11]
416
+ # set = numbers.divide { |i,j| (i - j).abs == 1 }
417
+ # p set # => #<Set: {#<Set: {1}>,
418
+ # # #<Set: {11, 9, 10}>,
419
+ # # #<Set: {3, 4}>,
420
+ # # #<Set: {6}>}>
421
+ def divide(&func)
422
+ func or return enum_for(__method__)
423
+
424
+ if func.arity == 2
425
+ require 'tsort'
426
+
427
+ class << dig = {} # :nodoc:
428
+ include TSort
429
+
430
+ alias tsort_each_node each_key
431
+ def tsort_each_child(node, &block)
432
+ fetch(node).each(&block)
433
+ end
434
+ end
435
+
436
+ each { |u|
437
+ dig[u] = a = []
438
+ each{ |v| func.call(u, v) and a << v }
439
+ }
440
+
441
+ set = Set.new()
442
+ dig.each_strongly_connected_component { |css|
443
+ set.add(self.class.new(css))
444
+ }
445
+ set
446
+ else
447
+ Set.new(classify(&func).values)
448
+ end
449
+ end
450
+
451
+ InspectKey = :__inspect_key__ # :nodoc:
452
+
453
+ # Returns a string containing a human-readable representation of the
454
+ # set. ("#<Set: {element1, element2, ...}>")
455
+ def inspect
456
+ ids = (Thread.current[InspectKey] ||= [])
457
+
458
+ if ids.include?(object_id)
459
+ return sprintf('#<%s: {...}>', self.class.name)
460
+ end
461
+
462
+ begin
463
+ ids << object_id
464
+ return sprintf('#<%s: {%s}>', self.class, to_a.inspect[1..-2])
465
+ ensure
466
+ ids.pop
467
+ end
468
+ end
469
+
470
+ def pretty_print(pp) # :nodoc:
471
+ pp.text sprintf('#<%s: {', self.class.name)
472
+ pp.nest(1) {
473
+ pp.seplist(self) { |o|
474
+ pp.pp o
475
+ }
476
+ }
477
+ pp.text "}>"
478
+ end
479
+
480
+ def pretty_print_cycle(pp) # :nodoc:
481
+ pp.text sprintf('#<%s: {%s}>', self.class.name, empty? ? '' : '...')
482
+ end
483
+ end
484
+
485
+ #
486
+ # SortedSet implements a Set that guarantees that it's element are
487
+ # yielded in sorted order (according to the return values of their
488
+ # #<=> methods) when iterating over them.
489
+ #
490
+ # All elements that are added to a SortedSet must respond to the <=>
491
+ # method for comparison.
492
+ #
493
+ # Also, all elements must be <em>mutually comparable</em>: <tt>el1 <=>
494
+ # el2</tt> must not return <tt>nil</tt> for any elements <tt>el1</tt>
495
+ # and <tt>el2</tt>, else an ArgumentError will be raised when
496
+ # iterating over the SortedSet.
497
+ #
498
+ # == Example
499
+ #
500
+ # require "set"
501
+ #
502
+ # set = SortedSet.new([2, 1, 5, 6, 4, 5, 3, 3, 3])
503
+ # ary = []
504
+ #
505
+ # set.each do |obj|
506
+ # ary << obj
507
+ # end
508
+ #
509
+ # p ary # => [1, 2, 3, 4, 5, 6]
510
+ #
511
+ # set2 = SortedSet.new([1, 2, "3"])
512
+ # set2.each { |obj| } # => raises ArgumentError: comparison of Fixnum with String failed
513
+ #
514
+ class SortedSet < Set
515
+ @@setup = false
516
+
517
+ class << self
518
+ def [](*ary) # :nodoc:
519
+ new(ary)
520
+ end
521
+
522
+ def setup # :nodoc:
523
+ @@setup and return
524
+
525
+ module_eval {
526
+ # a hack to shut up warning
527
+ alias old_init initialize
528
+ remove_method :old_init
529
+ }
530
+ begin
531
+ require 'rbtree'
532
+
533
+ module_eval %{
534
+ def initialize(*args, &block)
535
+ @hash = RBTree.new
536
+ super
537
+ end
538
+
539
+ def add(o)
540
+ o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>"
541
+ super
542
+ end
543
+ alias << add
544
+ }
545
+ rescue LoadError
546
+ module_eval %{
547
+ def initialize(*args, &block)
548
+ @keys = nil
549
+ super
550
+ end
551
+
552
+ def clear
553
+ @keys = nil
554
+ super
555
+ end
556
+
557
+ def replace(enum)
558
+ @keys = nil
559
+ super
560
+ end
561
+
562
+ def add(o)
563
+ o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>"
564
+ @keys = nil
565
+ super
566
+ end
567
+ alias << add
568
+
569
+ def delete(o)
570
+ @keys = nil
571
+ @hash.delete(o)
572
+ self
573
+ end
574
+
575
+ def delete_if
576
+ block_given? or return enum_for(__method__)
577
+ n = @hash.size
578
+ super
579
+ @keys = nil if @hash.size != n
580
+ self
581
+ end
582
+
583
+ def keep_if
584
+ block_given? or return enum_for(__method__)
585
+ n = @hash.size
586
+ super
587
+ @keys = nil if @hash.size != n
588
+ self
589
+ end
590
+
591
+ def merge(enum)
592
+ @keys = nil
593
+ super
594
+ end
595
+
596
+ def each
597
+ block_given? or return enum_for(__method__)
598
+ to_a.each { |o| yield(o) }
599
+ self
600
+ end
601
+
602
+ def to_a
603
+ (@keys = @hash.keys).sort! unless @keys
604
+ @keys
605
+ end
606
+ }
607
+ end
608
+
609
+ @@setup = true
610
+ end
611
+ end
612
+
613
+ def initialize(*args, &block) # :nodoc:
614
+ SortedSet.setup
615
+ initialize(*args, &block)
616
+ end
617
+ end
618
+
619
+ module Enumerable
620
+ # Makes a set from the enumerable object with given arguments.
621
+ # Needs to +require "set"+ to use this method.
622
+ def to_set(klass = Set, *args, &block)
623
+ klass.new(self, *args, &block)
624
+ end
625
+ end
626
+
627
+ # =begin
628
+ # == RestricedSet class
629
+ # RestricedSet implements a set with restrictions defined by a given
630
+ # block.
631
+ #
632
+ # === Super class
633
+ # Set
634
+ #
635
+ # === Class Methods
636
+ # --- RestricedSet::new(enum = nil) { |o| ... }
637
+ # --- RestricedSet::new(enum = nil) { |rset, o| ... }
638
+ # Creates a new restricted set containing the elements of the given
639
+ # enumerable object. Restrictions are defined by the given block.
640
+ #
641
+ # If the block's arity is 2, it is called with the RestrictedSet
642
+ # itself and an object to see if the object is allowed to be put in
643
+ # the set.
644
+ #
645
+ # Otherwise, the block is called with an object to see if the object
646
+ # is allowed to be put in the set.
647
+ #
648
+ # === Instance Methods
649
+ # --- restriction_proc
650
+ # Returns the restriction procedure of the set.
651
+ #
652
+ # =end
653
+ #
654
+ # class RestricedSet < Set
655
+ # def initialize(*args, &block)
656
+ # @proc = block or raise ArgumentError, "missing a block"
657
+ #
658
+ # if @proc.arity == 2
659
+ # instance_eval %{
660
+ # def add(o)
661
+ # @hash[o] = true if @proc.call(self, o)
662
+ # self
663
+ # end
664
+ # alias << add
665
+ #
666
+ # def add?(o)
667
+ # if include?(o) || !@proc.call(self, o)
668
+ # nil
669
+ # else
670
+ # @hash[o] = true
671
+ # self
672
+ # end
673
+ # end
674
+ #
675
+ # def replace(enum)
676
+ # enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable"
677
+ # clear
678
+ # enum.each_entry { |o| add(o) }
679
+ #
680
+ # self
681
+ # end
682
+ #
683
+ # def merge(enum)
684
+ # enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable"
685
+ # enum.each_entry { |o| add(o) }
686
+ #
687
+ # self
688
+ # end
689
+ # }
690
+ # else
691
+ # instance_eval %{
692
+ # def add(o)
693
+ # if @proc.call(o)
694
+ # @hash[o] = true
695
+ # end
696
+ # self
697
+ # end
698
+ # alias << add
699
+ #
700
+ # def add?(o)
701
+ # if include?(o) || !@proc.call(o)
702
+ # nil
703
+ # else
704
+ # @hash[o] = true
705
+ # self
706
+ # end
707
+ # end
708
+ # }
709
+ # end
710
+ #
711
+ # super(*args)
712
+ # end
713
+ #
714
+ # def restriction_proc
715
+ # @proc
716
+ # end
717
+ # end
718
+
719
+ if $0 == __FILE__
720
+ eval DATA.read, nil, $0, __LINE__+4
721
+ end
722
+
723
+ __END__
724
+
725
+ require 'test/unit'
726
+
727
+ class TC_Set < Test::Unit::TestCase
728
+ def test_aref
729
+ assert_nothing_raised {
730
+ Set[]
731
+ Set[nil]
732
+ Set[1,2,3]
733
+ }
734
+
735
+ assert_equal(0, Set[].size)
736
+ assert_equal(1, Set[nil].size)
737
+ assert_equal(1, Set[[]].size)
738
+ assert_equal(1, Set[[nil]].size)
739
+
740
+ set = Set[2,4,6,4]
741
+ assert_equal(Set.new([2,4,6]), set)
742
+ end
743
+
744
+ def test_s_new
745
+ assert_nothing_raised {
746
+ Set.new()
747
+ Set.new(nil)
748
+ Set.new([])
749
+ Set.new([1,2])
750
+ Set.new('a'..'c')
751
+ }
752
+ assert_raises(ArgumentError) {
753
+ Set.new(false)
754
+ }
755
+ assert_raises(ArgumentError) {
756
+ Set.new(1)
757
+ }
758
+ assert_raises(ArgumentError) {
759
+ Set.new(1,2)
760
+ }
761
+
762
+ assert_equal(0, Set.new().size)
763
+ assert_equal(0, Set.new(nil).size)
764
+ assert_equal(0, Set.new([]).size)
765
+ assert_equal(1, Set.new([nil]).size)
766
+
767
+ ary = [2,4,6,4]
768
+ set = Set.new(ary)
769
+ ary.clear
770
+ assert_equal(false, set.empty?)
771
+ assert_equal(3, set.size)
772
+
773
+ ary = [1,2,3]
774
+
775
+ s = Set.new(ary) { |o| o * 2 }
776
+ assert_equal([2,4,6], s.sort)
777
+ end
778
+
779
+ def test_clone
780
+ set1 = Set.new
781
+ set2 = set1.clone
782
+ set1 << 'abc'
783
+ assert_equal(Set.new, set2)
784
+ end
785
+
786
+ def test_dup
787
+ set1 = Set[1,2]
788
+ set2 = set1.dup
789
+
790
+ assert_not_same(set1, set2)
791
+
792
+ assert_equal(set1, set2)
793
+
794
+ set1.add(3)
795
+
796
+ assert_not_equal(set1, set2)
797
+ end
798
+
799
+ def test_size
800
+ assert_equal(0, Set[].size)
801
+ assert_equal(2, Set[1,2].size)
802
+ assert_equal(2, Set[1,2,1].size)
803
+ end
804
+
805
+ def test_empty?
806
+ assert_equal(true, Set[].empty?)
807
+ assert_equal(false, Set[1, 2].empty?)
808
+ end
809
+
810
+ def test_clear
811
+ set = Set[1,2]
812
+ ret = set.clear
813
+
814
+ assert_same(set, ret)
815
+ assert_equal(true, set.empty?)
816
+ end
817
+
818
+ def test_replace
819
+ set = Set[1,2]
820
+ ret = set.replace('a'..'c')
821
+
822
+ assert_same(set, ret)
823
+ assert_equal(Set['a','b','c'], set)
824
+ end
825
+
826
+ def test_to_a
827
+ set = Set[1,2,3,2]
828
+ ary = set.to_a
829
+
830
+ assert_equal([1,2,3], ary.sort)
831
+ end
832
+
833
+ def test_flatten
834
+ # test1
835
+ set1 = Set[
836
+ 1,
837
+ Set[
838
+ 5,
839
+ Set[7,
840
+ Set[0]
841
+ ],
842
+ Set[6,2],
843
+ 1
844
+ ],
845
+ 3,
846
+ Set[3,4]
847
+ ]
848
+
849
+ set2 = set1.flatten
850
+ set3 = Set.new(0..7)
851
+
852
+ assert_not_same(set2, set1)
853
+ assert_equal(set3, set2)
854
+
855
+ # test2; destructive
856
+ orig_set1 = set1
857
+ set1.flatten!
858
+
859
+ assert_same(orig_set1, set1)
860
+ assert_equal(set3, set1)
861
+
862
+ # test3; multiple occurrences of a set in an set
863
+ set1 = Set[1, 2]
864
+ set2 = Set[set1, Set[set1, 4], 3]
865
+
866
+ assert_nothing_raised {
867
+ set2.flatten!
868
+ }
869
+
870
+ assert_equal(Set.new(1..4), set2)
871
+
872
+ # test4; recursion
873
+ set2 = Set[]
874
+ set1 = Set[1, set2]
875
+ set2.add(set1)
876
+
877
+ assert_raises(ArgumentError) {
878
+ set1.flatten!
879
+ }
880
+
881
+ # test5; miscellaneous
882
+ empty = Set[]
883
+ set = Set[Set[empty, "a"],Set[empty, "b"]]
884
+
885
+ assert_nothing_raised {
886
+ set.flatten
887
+ }
888
+
889
+ set1 = empty.merge(Set["no_more", set])
890
+
891
+ assert_nil(Set.new(0..31).flatten!)
892
+
893
+ x = Set[Set[],Set[1,2]].flatten!
894
+ y = Set[1,2]
895
+
896
+ assert_equal(x, y)
897
+ end
898
+
899
+ def test_include?
900
+ set = Set[1,2,3]
901
+
902
+ assert_equal(true, set.include?(1))
903
+ assert_equal(true, set.include?(2))
904
+ assert_equal(true, set.include?(3))
905
+ assert_equal(false, set.include?(0))
906
+ assert_equal(false, set.include?(nil))
907
+
908
+ set = Set["1",nil,"2",nil,"0","1",false]
909
+ assert_equal(true, set.include?(nil))
910
+ assert_equal(true, set.include?(false))
911
+ assert_equal(true, set.include?("1"))
912
+ assert_equal(false, set.include?(0))
913
+ assert_equal(false, set.include?(true))
914
+ end
915
+
916
+ def test_superset?
917
+ set = Set[1,2,3]
918
+
919
+ assert_raises(ArgumentError) {
920
+ set.superset?()
921
+ }
922
+
923
+ assert_raises(ArgumentError) {
924
+ set.superset?(2)
925
+ }
926
+
927
+ assert_raises(ArgumentError) {
928
+ set.superset?([2])
929
+ }
930
+
931
+ assert_equal(true, set.superset?(Set[]))
932
+ assert_equal(true, set.superset?(Set[1,2]))
933
+ assert_equal(true, set.superset?(Set[1,2,3]))
934
+ assert_equal(false, set.superset?(Set[1,2,3,4]))
935
+ assert_equal(false, set.superset?(Set[1,4]))
936
+
937
+ assert_equal(true, Set[].superset?(Set[]))
938
+ end
939
+
940
+ def test_proper_superset?
941
+ set = Set[1,2,3]
942
+
943
+ assert_raises(ArgumentError) {
944
+ set.proper_superset?()
945
+ }
946
+
947
+ assert_raises(ArgumentError) {
948
+ set.proper_superset?(2)
949
+ }
950
+
951
+ assert_raises(ArgumentError) {
952
+ set.proper_superset?([2])
953
+ }
954
+
955
+ assert_equal(true, set.proper_superset?(Set[]))
956
+ assert_equal(true, set.proper_superset?(Set[1,2]))
957
+ assert_equal(false, set.proper_superset?(Set[1,2,3]))
958
+ assert_equal(false, set.proper_superset?(Set[1,2,3,4]))
959
+ assert_equal(false, set.proper_superset?(Set[1,4]))
960
+
961
+ assert_equal(false, Set[].proper_superset?(Set[]))
962
+ end
963
+
964
+ def test_subset?
965
+ set = Set[1,2,3]
966
+
967
+ assert_raises(ArgumentError) {
968
+ set.subset?()
969
+ }
970
+
971
+ assert_raises(ArgumentError) {
972
+ set.subset?(2)
973
+ }
974
+
975
+ assert_raises(ArgumentError) {
976
+ set.subset?([2])
977
+ }
978
+
979
+ assert_equal(true, set.subset?(Set[1,2,3,4]))
980
+ assert_equal(true, set.subset?(Set[1,2,3]))
981
+ assert_equal(false, set.subset?(Set[1,2]))
982
+ assert_equal(false, set.subset?(Set[]))
983
+
984
+ assert_equal(true, Set[].subset?(Set[1]))
985
+ assert_equal(true, Set[].subset?(Set[]))
986
+ end
987
+
988
+ def test_proper_subset?
989
+ set = Set[1,2,3]
990
+
991
+ assert_raises(ArgumentError) {
992
+ set.proper_subset?()
993
+ }
994
+
995
+ assert_raises(ArgumentError) {
996
+ set.proper_subset?(2)
997
+ }
998
+
999
+ assert_raises(ArgumentError) {
1000
+ set.proper_subset?([2])
1001
+ }
1002
+
1003
+ assert_equal(true, set.proper_subset?(Set[1,2,3,4]))
1004
+ assert_equal(false, set.proper_subset?(Set[1,2,3]))
1005
+ assert_equal(false, set.proper_subset?(Set[1,2]))
1006
+ assert_equal(false, set.proper_subset?(Set[]))
1007
+
1008
+ assert_equal(false, Set[].proper_subset?(Set[]))
1009
+ end
1010
+
1011
+ def test_each
1012
+ ary = [1,3,5,7,10,20]
1013
+ set = Set.new(ary)
1014
+
1015
+ ret = set.each { |o| }
1016
+ assert_same(set, ret)
1017
+
1018
+ e = set.each
1019
+ assert_instance_of(Enumerator, e)
1020
+
1021
+ assert_nothing_raised {
1022
+ set.each { |o|
1023
+ ary.delete(o) or raise "unexpected element: #{o}"
1024
+ }
1025
+
1026
+ ary.empty? or raise "forgotten elements: #{ary.join(', ')}"
1027
+ }
1028
+ end
1029
+
1030
+ def test_add
1031
+ set = Set[1,2,3]
1032
+
1033
+ ret = set.add(2)
1034
+ assert_same(set, ret)
1035
+ assert_equal(Set[1,2,3], set)
1036
+
1037
+ ret = set.add?(2)
1038
+ assert_nil(ret)
1039
+ assert_equal(Set[1,2,3], set)
1040
+
1041
+ ret = set.add(4)
1042
+ assert_same(set, ret)
1043
+ assert_equal(Set[1,2,3,4], set)
1044
+
1045
+ ret = set.add?(5)
1046
+ assert_same(set, ret)
1047
+ assert_equal(Set[1,2,3,4,5], set)
1048
+ end
1049
+
1050
+ def test_delete
1051
+ set = Set[1,2,3]
1052
+
1053
+ ret = set.delete(4)
1054
+ assert_same(set, ret)
1055
+ assert_equal(Set[1,2,3], set)
1056
+
1057
+ ret = set.delete?(4)
1058
+ assert_nil(ret)
1059
+ assert_equal(Set[1,2,3], set)
1060
+
1061
+ ret = set.delete(2)
1062
+ assert_equal(set, ret)
1063
+ assert_equal(Set[1,3], set)
1064
+
1065
+ ret = set.delete?(1)
1066
+ assert_equal(set, ret)
1067
+ assert_equal(Set[3], set)
1068
+ end
1069
+
1070
+ def test_delete_if
1071
+ set = Set.new(1..10)
1072
+ ret = set.delete_if { |i| i > 10 }
1073
+ assert_same(set, ret)
1074
+ assert_equal(Set.new(1..10), set)
1075
+
1076
+ set = Set.new(1..10)
1077
+ ret = set.delete_if { |i| i % 3 == 0 }
1078
+ assert_same(set, ret)
1079
+ assert_equal(Set[1,2,4,5,7,8,10], set)
1080
+ end
1081
+
1082
+ def test_collect!
1083
+ set = Set[1,2,3,'a','b','c',-1..1,2..4]
1084
+
1085
+ ret = set.collect! { |i|
1086
+ case i
1087
+ when Numeric
1088
+ i * 2
1089
+ when String
1090
+ i.upcase
1091
+ else
1092
+ nil
1093
+ end
1094
+ }
1095
+
1096
+ assert_same(set, ret)
1097
+ assert_equal(Set[2,4,6,'A','B','C',nil], set)
1098
+ end
1099
+
1100
+ def test_reject!
1101
+ set = Set.new(1..10)
1102
+
1103
+ ret = set.reject! { |i| i > 10 }
1104
+ assert_nil(ret)
1105
+ assert_equal(Set.new(1..10), set)
1106
+
1107
+ ret = set.reject! { |i| i % 3 == 0 }
1108
+ assert_same(set, ret)
1109
+ assert_equal(Set[1,2,4,5,7,8,10], set)
1110
+ end
1111
+
1112
+ def test_merge
1113
+ set = Set[1,2,3]
1114
+
1115
+ ret = set.merge([2,4,6])
1116
+ assert_same(set, ret)
1117
+ assert_equal(Set[1,2,3,4,6], set)
1118
+ end
1119
+
1120
+ def test_subtract
1121
+ set = Set[1,2,3]
1122
+
1123
+ ret = set.subtract([2,4,6])
1124
+ assert_same(set, ret)
1125
+ assert_equal(Set[1,3], set)
1126
+ end
1127
+
1128
+ def test_plus
1129
+ set = Set[1,2,3]
1130
+
1131
+ ret = set + [2,4,6]
1132
+ assert_not_same(set, ret)
1133
+ assert_equal(Set[1,2,3,4,6], ret)
1134
+ end
1135
+
1136
+ def test_minus
1137
+ set = Set[1,2,3]
1138
+
1139
+ ret = set - [2,4,6]
1140
+ assert_not_same(set, ret)
1141
+ assert_equal(Set[1,3], ret)
1142
+ end
1143
+
1144
+ def test_and
1145
+ set = Set[1,2,3,4]
1146
+
1147
+ ret = set & [2,4,6]
1148
+ assert_not_same(set, ret)
1149
+ assert_equal(Set[2,4], ret)
1150
+ end
1151
+
1152
+ def test_xor
1153
+ set = Set[1,2,3,4]
1154
+ ret = set ^ [2,4,5,5]
1155
+ assert_not_same(set, ret)
1156
+ assert_equal(Set[1,3,5], ret)
1157
+ end
1158
+
1159
+ def test_eq
1160
+ set1 = Set[2,3,1]
1161
+ set2 = Set[1,2,3]
1162
+
1163
+ assert_equal(set1, set1)
1164
+ assert_equal(set1, set2)
1165
+ assert_not_equal(Set[1], [1])
1166
+
1167
+ set1 = Class.new(Set)["a", "b"]
1168
+ set2 = Set["a", "b", set1]
1169
+ set1 = set1.add(set1.clone)
1170
+
1171
+ # assert_equal(set1, set2)
1172
+ # assert_equal(set2, set1)
1173
+ assert_equal(set2, set2.clone)
1174
+ assert_equal(set1.clone, set1)
1175
+
1176
+ assert_not_equal(Set[Exception.new,nil], Set[Exception.new,Exception.new], "[ruby-dev:26127]")
1177
+ end
1178
+
1179
+ # def test_hash
1180
+ # end
1181
+
1182
+ # def test_eql?
1183
+ # end
1184
+
1185
+ def test_classify
1186
+ set = Set.new(1..10)
1187
+ ret = set.classify { |i| i % 3 }
1188
+
1189
+ assert_equal(3, ret.size)
1190
+ assert_instance_of(Hash, ret)
1191
+ ret.each_value { |value| assert_instance_of(Set, value) }
1192
+ assert_equal(Set[3,6,9], ret[0])
1193
+ assert_equal(Set[1,4,7,10], ret[1])
1194
+ assert_equal(Set[2,5,8], ret[2])
1195
+ end
1196
+
1197
+ def test_divide
1198
+ set = Set.new(1..10)
1199
+ ret = set.divide { |i| i % 3 }
1200
+
1201
+ assert_equal(3, ret.size)
1202
+ n = 0
1203
+ ret.each { |s| n += s.size }
1204
+ assert_equal(set.size, n)
1205
+ assert_equal(set, ret.flatten)
1206
+
1207
+ set = Set[7,10,5,11,1,3,4,9,0]
1208
+ ret = set.divide { |a,b| (a - b).abs == 1 }
1209
+
1210
+ assert_equal(4, ret.size)
1211
+ n = 0
1212
+ ret.each { |s| n += s.size }
1213
+ assert_equal(set.size, n)
1214
+ assert_equal(set, ret.flatten)
1215
+ ret.each { |s|
1216
+ if s.include?(0)
1217
+ assert_equal(Set[0,1], s)
1218
+ elsif s.include?(3)
1219
+ assert_equal(Set[3,4,5], s)
1220
+ elsif s.include?(7)
1221
+ assert_equal(Set[7], s)
1222
+ elsif s.include?(9)
1223
+ assert_equal(Set[9,10,11], s)
1224
+ else
1225
+ raise "unexpected group: #{s.inspect}"
1226
+ end
1227
+ }
1228
+ end
1229
+
1230
+ def test_inspect
1231
+ set1 = Set[1]
1232
+
1233
+ assert_equal('#<Set: {1}>', set1.inspect)
1234
+
1235
+ set2 = Set[Set[0], 1, 2, set1]
1236
+ assert_equal(false, set2.inspect.include?('#<Set: {...}>'))
1237
+
1238
+ set1.add(set2)
1239
+ assert_equal(true, set1.inspect.include?('#<Set: {...}>'))
1240
+ end
1241
+
1242
+ # def test_pretty_print
1243
+ # end
1244
+
1245
+ # def test_pretty_print_cycle
1246
+ # end
1247
+ end
1248
+
1249
+ class TC_SortedSet < Test::Unit::TestCase
1250
+ def test_sortedset
1251
+ s = SortedSet[4,5,3,1,2]
1252
+
1253
+ assert_equal([1,2,3,4,5], s.to_a)
1254
+
1255
+ prev = nil
1256
+ s.each { |o| assert(prev < o) if prev; prev = o }
1257
+ assert_not_nil(prev)
1258
+
1259
+ s.map! { |o| -2 * o }
1260
+
1261
+ assert_equal([-10,-8,-6,-4,-2], s.to_a)
1262
+
1263
+ prev = nil
1264
+ ret = s.each { |o| assert(prev < o) if prev; prev = o }
1265
+ assert_not_nil(prev)
1266
+ assert_same(s, ret)
1267
+
1268
+ s = SortedSet.new([2,1,3]) { |o| o * -2 }
1269
+ assert_equal([-6,-4,-2], s.to_a)
1270
+
1271
+ s = SortedSet.new(['one', 'two', 'three', 'four'])
1272
+ a = []
1273
+ ret = s.delete_if { |o| a << o; o.start_with?('t') }
1274
+ assert_same(s, ret)
1275
+ assert_equal(['four', 'one'], s.to_a)
1276
+ assert_equal(['four', 'one', 'three', 'two'], a)
1277
+
1278
+ s = SortedSet.new(['one', 'two', 'three', 'four'])
1279
+ a = []
1280
+ ret = s.reject! { |o| a << o; o.start_with?('t') }
1281
+ assert_same(s, ret)
1282
+ assert_equal(['four', 'one'], s.to_a)
1283
+ assert_equal(['four', 'one', 'three', 'two'], a)
1284
+
1285
+ s = SortedSet.new(['one', 'two', 'three', 'four'])
1286
+ a = []
1287
+ ret = s.reject! { |o| a << o; false }
1288
+ assert_same(nil, ret)
1289
+ assert_equal(['four', 'one', 'three', 'two'], s.to_a)
1290
+ assert_equal(['four', 'one', 'three', 'two'], a)
1291
+ end
1292
+ end
1293
+
1294
+ class TC_Enumerable < Test::Unit::TestCase
1295
+ def test_to_set
1296
+ ary = [2,5,4,3,2,1,3]
1297
+
1298
+ set = ary.to_set
1299
+ assert_instance_of(Set, set)
1300
+ assert_equal([1,2,3,4,5], set.sort)
1301
+
1302
+ set = ary.to_set { |o| o * -2 }
1303
+ assert_instance_of(Set, set)
1304
+ assert_equal([-10,-8,-6,-4,-2], set.sort)
1305
+
1306
+ set = ary.to_set(SortedSet)
1307
+ assert_instance_of(SortedSet, set)
1308
+ assert_equal([1,2,3,4,5], set.to_a)
1309
+
1310
+ set = ary.to_set(SortedSet) { |o| o * -2 }
1311
+ assert_instance_of(SortedSet, set)
1312
+ assert_equal([-10,-8,-6,-4,-2], set.sort)
1313
+ end
1314
+ end
1315
+
1316
+ # class TC_RestricedSet < Test::Unit::TestCase
1317
+ # def test_s_new
1318
+ # assert_raises(ArgumentError) { RestricedSet.new }
1319
+ #
1320
+ # s = RestricedSet.new([-1,2,3]) { |o| o > 0 }
1321
+ # assert_equal([2,3], s.sort)
1322
+ # end
1323
+ #
1324
+ # def test_restriction_proc
1325
+ # s = RestricedSet.new([-1,2,3]) { |o| o > 0 }
1326
+ #
1327
+ # f = s.restriction_proc
1328
+ # assert_instance_of(Proc, f)
1329
+ # assert(f[1])
1330
+ # assert(!f[0])
1331
+ # end
1332
+ #
1333
+ # def test_replace
1334
+ # s = RestricedSet.new(-3..3) { |o| o > 0 }
1335
+ # assert_equal([1,2,3], s.sort)
1336
+ #
1337
+ # s.replace([-2,0,3,4,5])
1338
+ # assert_equal([3,4,5], s.sort)
1339
+ # end
1340
+ #
1341
+ # def test_merge
1342
+ # s = RestricedSet.new { |o| o > 0 }
1343
+ # s.merge(-5..5)
1344
+ # assert_equal([1,2,3,4,5], s.sort)
1345
+ #
1346
+ # s.merge([10,-10,-8,8])
1347
+ # assert_equal([1,2,3,4,5,8,10], s.sort)
1348
+ # end
1349
+ # end