classx-pluggable 0.0.1

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 (42) hide show
  1. data/ChangeLog +221 -0
  2. data/README +88 -0
  3. data/Rakefile +52 -0
  4. data/doc/output/coverage/-Library-Ruby-Gems-gems-classx-0_0_5-lib-classx-attribute_rb.html +925 -0
  5. data/doc/output/coverage/-Library-Ruby-Gems-gems-classx-0_0_5-lib-classx-attributes_rb.html +772 -0
  6. data/doc/output/coverage/-Library-Ruby-Gems-gems-classx-0_0_5-lib-classx-bracketable_rb.html +671 -0
  7. data/doc/output/coverage/-Library-Ruby-Gems-gems-classx-0_0_5-lib-classx-role-logger_rb.html +716 -0
  8. data/doc/output/coverage/-Library-Ruby-Gems-gems-classx-0_0_5-lib-classx-validate_rb.html +663 -0
  9. data/doc/output/coverage/-Library-Ruby-Gems-gems-classx-0_0_5-lib-classx_rb.html +820 -0
  10. data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs-block_rb.html +661 -0
  11. data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs-callbacks_rb.html +932 -0
  12. data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs-change_rb.html +779 -0
  13. data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs-hunk_rb.html +867 -0
  14. data/doc/output/coverage/-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs_rb.html +1715 -0
  15. data/doc/output/coverage/-Library-Ruby-Gems-gems-rcov-0_8_1_2_0-lib-rcov_rb.html +1598 -0
  16. data/doc/output/coverage/examples-test_runner-bin-test_runner_rb.html +628 -0
  17. data/doc/output/coverage/examples-test_runner-lib-test_runner-plugin-setup_fixture_rb.html +641 -0
  18. data/doc/output/coverage/examples-test_runner-lib-test_runner-plugin-test_info_rb.html +638 -0
  19. data/doc/output/coverage/examples-test_runner-lib-test_runner-plugin-test_timer_rb.html +666 -0
  20. data/doc/output/coverage/examples-test_runner-lib-test_runner_rb.html +643 -0
  21. data/doc/output/coverage/index.html +711 -0
  22. data/doc/output/coverage/lib-classx-pluggable-plugin_rb.html +676 -0
  23. data/doc/output/coverage/lib-classx-pluggable_rb.html +841 -0
  24. data/examples/test_runner/bin/test_runner.rb +18 -0
  25. data/examples/test_runner/conf/config.yaml +19 -0
  26. data/examples/test_runner/lib/test_runner.rb +33 -0
  27. data/examples/test_runner/lib/test_runner/plugin/setup_fixture.rb +31 -0
  28. data/examples/test_runner/lib/test_runner/plugin/test_info.rb +28 -0
  29. data/examples/test_runner/lib/test_runner/plugin/test_timer.rb +56 -0
  30. data/lib/classx/pluggable.rb +231 -0
  31. data/lib/classx/pluggable/plugin.rb +66 -0
  32. data/spec/classx-pluggable-util/module2path_spec.rb +30 -0
  33. data/spec/classx-pluggable-util/nested_autoload_spec.rb +48 -0
  34. data/spec/classx-pluggable-util/nested_const_get_spec.rb +48 -0
  35. data/spec/classx-pluggable/component_class_get.rb +18 -0
  36. data/spec/classx-pluggable_spec.rb +5 -0
  37. data/spec/example_spec.rb +20 -0
  38. data/spec/spec.opts +1 -0
  39. data/spec/spec_helper.rb +6 -0
  40. data/tasks/basic_config.rake +22 -0
  41. data/tasks/basic_tasks.rake +139 -0
  42. metadata +127 -0
@@ -0,0 +1,1715 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'><head><title>/Library/Ruby/Gems/gems/diff-lcs-1.1.2/lib/diff/lcs.rb - C0 code coverage information</title>
3
+ <style type='text/css'>body { background-color: rgb(240, 240, 245); }</style>
4
+ <style type='text/css'>span.cross-ref-title {
5
+ font-size: 140%;
6
+ }
7
+ span.cross-ref a {
8
+ text-decoration: none;
9
+ }
10
+ span.cross-ref {
11
+ background-color:#f3f7fa;
12
+ border: 1px dashed #333;
13
+ margin: 1em;
14
+ padding: 0.5em;
15
+ overflow: hidden;
16
+ }
17
+ a.crossref-toggle {
18
+ text-decoration: none;
19
+ }
20
+ span.marked0 {
21
+ background-color: rgb(185, 210, 200);
22
+ display: block;
23
+ }
24
+ span.marked1 {
25
+ background-color: rgb(190, 215, 205);
26
+ display: block;
27
+ }
28
+ span.inferred0 {
29
+ background-color: rgb(175, 200, 200);
30
+ display: block;
31
+ }
32
+ span.inferred1 {
33
+ background-color: rgb(180, 205, 205);
34
+ display: block;
35
+ }
36
+ span.uncovered0 {
37
+ background-color: rgb(225, 110, 110);
38
+ display: block;
39
+ }
40
+ span.uncovered1 {
41
+ background-color: rgb(235, 120, 120);
42
+ display: block;
43
+ }
44
+ span.overview {
45
+ border-bottom: 8px solid black;
46
+ }
47
+ div.overview {
48
+ border-bottom: 8px solid black;
49
+ }
50
+ body {
51
+ font-family: verdana, arial, helvetica;
52
+ }
53
+ div.footer {
54
+ font-size: 68%;
55
+ margin-top: 1.5em;
56
+ }
57
+ h1, h2, h3, h4, h5, h6 {
58
+ margin-bottom: 0.5em;
59
+ }
60
+ h5 {
61
+ margin-top: 0.5em;
62
+ }
63
+ .hidden {
64
+ display: none;
65
+ }
66
+ div.separator {
67
+ height: 10px;
68
+ }
69
+ /* Commented out for better readability, esp. on IE */
70
+ /*
71
+ table tr td, table tr th {
72
+ font-size: 68%;
73
+ }
74
+ td.value table tr td {
75
+ font-size: 11px;
76
+ }
77
+ */
78
+ table.percent_graph {
79
+ height: 12px;
80
+ border: #808080 1px solid;
81
+ empty-cells: show;
82
+ }
83
+ table.percent_graph td.covered {
84
+ height: 10px;
85
+ background: #00f000;
86
+ }
87
+ table.percent_graph td.uncovered {
88
+ height: 10px;
89
+ background: #e00000;
90
+ }
91
+ table.percent_graph td.NA {
92
+ height: 10px;
93
+ background: #eaeaea;
94
+ }
95
+ table.report {
96
+ border-collapse: collapse;
97
+ width: 100%;
98
+ }
99
+ table.report td.heading {
100
+ background: #dcecff;
101
+ border: #d0d0d0 1px solid;
102
+ font-weight: bold;
103
+ text-align: center;
104
+ }
105
+ table.report td.heading:hover {
106
+ background: #c0ffc0;
107
+ }
108
+ table.report td.text {
109
+ border: #d0d0d0 1px solid;
110
+ }
111
+ table.report td.value,
112
+ table.report td.lines_total,
113
+ table.report td.lines_code {
114
+ text-align: right;
115
+ border: #d0d0d0 1px solid;
116
+ }
117
+ table.report tr.light {
118
+ background-color: rgb(240, 240, 245);
119
+ }
120
+ table.report tr.dark {
121
+ background-color: rgb(230, 230, 235);
122
+ }
123
+ </style>
124
+ <script type='text/javascript'>
125
+ // <![CDATA[
126
+ function toggleCode( id ) {
127
+ if ( document.getElementById )
128
+ elem = document.getElementById( id );
129
+ else if ( document.all )
130
+ elem = eval( "document.all." + id );
131
+ else
132
+ return false;
133
+
134
+ elemStyle = elem.style;
135
+
136
+ if ( elemStyle.display != "block" ) {
137
+ elemStyle.display = "block"
138
+ } else {
139
+ elemStyle.display = "none"
140
+ }
141
+
142
+ return true;
143
+ }
144
+
145
+ // Make cross-references hidden by default
146
+ document.writeln( "<style type=\"text/css\">span.cross-ref { display: none }</style>" )
147
+ // ]]>
148
+ </script>
149
+ <style type='text/css'>span.run0 {
150
+ background-color: rgb(178, 204, 255);
151
+ display: block;
152
+ }
153
+ span.run1 {
154
+ background-color: rgb(178, 206, 255);
155
+ display: block;
156
+ }
157
+ span.run2 {
158
+ background-color: rgb(178, 209, 255);
159
+ display: block;
160
+ }
161
+ span.run3 {
162
+ background-color: rgb(178, 211, 255);
163
+ display: block;
164
+ }
165
+ span.run4 {
166
+ background-color: rgb(178, 214, 255);
167
+ display: block;
168
+ }
169
+ span.run5 {
170
+ background-color: rgb(178, 218, 255);
171
+ display: block;
172
+ }
173
+ span.run6 {
174
+ background-color: rgb(178, 220, 255);
175
+ display: block;
176
+ }
177
+ span.run7 {
178
+ background-color: rgb(178, 223, 255);
179
+ display: block;
180
+ }
181
+ span.run8 {
182
+ background-color: rgb(178, 225, 255);
183
+ display: block;
184
+ }
185
+ span.run9 {
186
+ background-color: rgb(178, 228, 255);
187
+ display: block;
188
+ }
189
+ span.run10 {
190
+ background-color: rgb(178, 232, 255);
191
+ display: block;
192
+ }
193
+ span.run11 {
194
+ background-color: rgb(178, 234, 255);
195
+ display: block;
196
+ }
197
+ span.run12 {
198
+ background-color: rgb(178, 237, 255);
199
+ display: block;
200
+ }
201
+ span.run13 {
202
+ background-color: rgb(178, 239, 255);
203
+ display: block;
204
+ }
205
+ span.run14 {
206
+ background-color: rgb(178, 242, 255);
207
+ display: block;
208
+ }
209
+ span.run15 {
210
+ background-color: rgb(178, 246, 255);
211
+ display: block;
212
+ }
213
+ span.run16 {
214
+ background-color: rgb(178, 248, 255);
215
+ display: block;
216
+ }
217
+ span.run17 {
218
+ background-color: rgb(178, 251, 255);
219
+ display: block;
220
+ }
221
+ span.run18 {
222
+ background-color: rgb(178, 253, 255);
223
+ display: block;
224
+ }
225
+ span.run19 {
226
+ background-color: rgb(178, 255, 253);
227
+ display: block;
228
+ }
229
+ span.run20 {
230
+ background-color: rgb(178, 255, 249);
231
+ display: block;
232
+ }
233
+ span.run21 {
234
+ background-color: rgb(178, 255, 247);
235
+ display: block;
236
+ }
237
+ span.run22 {
238
+ background-color: rgb(178, 255, 244);
239
+ display: block;
240
+ }
241
+ span.run23 {
242
+ background-color: rgb(178, 255, 242);
243
+ display: block;
244
+ }
245
+ span.run24 {
246
+ background-color: rgb(178, 255, 239);
247
+ display: block;
248
+ }
249
+ span.run25 {
250
+ background-color: rgb(178, 255, 235);
251
+ display: block;
252
+ }
253
+ span.run26 {
254
+ background-color: rgb(178, 255, 233);
255
+ display: block;
256
+ }
257
+ span.run27 {
258
+ background-color: rgb(178, 255, 230);
259
+ display: block;
260
+ }
261
+ span.run28 {
262
+ background-color: rgb(178, 255, 228);
263
+ display: block;
264
+ }
265
+ span.run29 {
266
+ background-color: rgb(178, 255, 225);
267
+ display: block;
268
+ }
269
+ span.run30 {
270
+ background-color: rgb(178, 255, 221);
271
+ display: block;
272
+ }
273
+ span.run31 {
274
+ background-color: rgb(178, 255, 219);
275
+ display: block;
276
+ }
277
+ span.run32 {
278
+ background-color: rgb(178, 255, 216);
279
+ display: block;
280
+ }
281
+ span.run33 {
282
+ background-color: rgb(178, 255, 214);
283
+ display: block;
284
+ }
285
+ span.run34 {
286
+ background-color: rgb(178, 255, 211);
287
+ display: block;
288
+ }
289
+ span.run35 {
290
+ background-color: rgb(178, 255, 207);
291
+ display: block;
292
+ }
293
+ span.run36 {
294
+ background-color: rgb(178, 255, 205);
295
+ display: block;
296
+ }
297
+ span.run37 {
298
+ background-color: rgb(178, 255, 202);
299
+ display: block;
300
+ }
301
+ span.run38 {
302
+ background-color: rgb(178, 255, 200);
303
+ display: block;
304
+ }
305
+ span.run39 {
306
+ background-color: rgb(178, 255, 197);
307
+ display: block;
308
+ }
309
+ span.run40 {
310
+ background-color: rgb(178, 255, 193);
311
+ display: block;
312
+ }
313
+ span.run41 {
314
+ background-color: rgb(178, 255, 191);
315
+ display: block;
316
+ }
317
+ span.run42 {
318
+ background-color: rgb(178, 255, 188);
319
+ display: block;
320
+ }
321
+ span.run43 {
322
+ background-color: rgb(178, 255, 186);
323
+ display: block;
324
+ }
325
+ span.run44 {
326
+ background-color: rgb(178, 255, 183);
327
+ display: block;
328
+ }
329
+ span.run45 {
330
+ background-color: rgb(178, 255, 179);
331
+ display: block;
332
+ }
333
+ span.run46 {
334
+ background-color: rgb(179, 255, 178);
335
+ display: block;
336
+ }
337
+ span.run47 {
338
+ background-color: rgb(182, 255, 178);
339
+ display: block;
340
+ }
341
+ span.run48 {
342
+ background-color: rgb(184, 255, 178);
343
+ display: block;
344
+ }
345
+ span.run49 {
346
+ background-color: rgb(187, 255, 178);
347
+ display: block;
348
+ }
349
+ span.run50 {
350
+ background-color: rgb(191, 255, 178);
351
+ display: block;
352
+ }
353
+ span.run51 {
354
+ background-color: rgb(193, 255, 178);
355
+ display: block;
356
+ }
357
+ span.run52 {
358
+ background-color: rgb(196, 255, 178);
359
+ display: block;
360
+ }
361
+ span.run53 {
362
+ background-color: rgb(198, 255, 178);
363
+ display: block;
364
+ }
365
+ span.run54 {
366
+ background-color: rgb(201, 255, 178);
367
+ display: block;
368
+ }
369
+ span.run55 {
370
+ background-color: rgb(205, 255, 178);
371
+ display: block;
372
+ }
373
+ span.run56 {
374
+ background-color: rgb(207, 255, 178);
375
+ display: block;
376
+ }
377
+ span.run57 {
378
+ background-color: rgb(210, 255, 178);
379
+ display: block;
380
+ }
381
+ span.run58 {
382
+ background-color: rgb(212, 255, 178);
383
+ display: block;
384
+ }
385
+ span.run59 {
386
+ background-color: rgb(215, 255, 178);
387
+ display: block;
388
+ }
389
+ span.run60 {
390
+ background-color: rgb(219, 255, 178);
391
+ display: block;
392
+ }
393
+ span.run61 {
394
+ background-color: rgb(221, 255, 178);
395
+ display: block;
396
+ }
397
+ span.run62 {
398
+ background-color: rgb(224, 255, 178);
399
+ display: block;
400
+ }
401
+ span.run63 {
402
+ background-color: rgb(226, 255, 178);
403
+ display: block;
404
+ }
405
+ span.run64 {
406
+ background-color: rgb(229, 255, 178);
407
+ display: block;
408
+ }
409
+ span.run65 {
410
+ background-color: rgb(233, 255, 178);
411
+ display: block;
412
+ }
413
+ span.run66 {
414
+ background-color: rgb(235, 255, 178);
415
+ display: block;
416
+ }
417
+ span.run67 {
418
+ background-color: rgb(238, 255, 178);
419
+ display: block;
420
+ }
421
+ span.run68 {
422
+ background-color: rgb(240, 255, 178);
423
+ display: block;
424
+ }
425
+ span.run69 {
426
+ background-color: rgb(243, 255, 178);
427
+ display: block;
428
+ }
429
+ span.run70 {
430
+ background-color: rgb(247, 255, 178);
431
+ display: block;
432
+ }
433
+ span.run71 {
434
+ background-color: rgb(249, 255, 178);
435
+ display: block;
436
+ }
437
+ span.run72 {
438
+ background-color: rgb(252, 255, 178);
439
+ display: block;
440
+ }
441
+ span.run73 {
442
+ background-color: rgb(255, 255, 178);
443
+ display: block;
444
+ }
445
+ span.run74 {
446
+ background-color: rgb(255, 252, 178);
447
+ display: block;
448
+ }
449
+ span.run75 {
450
+ background-color: rgb(255, 248, 178);
451
+ display: block;
452
+ }
453
+ span.run76 {
454
+ background-color: rgb(255, 246, 178);
455
+ display: block;
456
+ }
457
+ span.run77 {
458
+ background-color: rgb(255, 243, 178);
459
+ display: block;
460
+ }
461
+ span.run78 {
462
+ background-color: rgb(255, 240, 178);
463
+ display: block;
464
+ }
465
+ span.run79 {
466
+ background-color: rgb(255, 238, 178);
467
+ display: block;
468
+ }
469
+ span.run80 {
470
+ background-color: rgb(255, 234, 178);
471
+ display: block;
472
+ }
473
+ span.run81 {
474
+ background-color: rgb(255, 232, 178);
475
+ display: block;
476
+ }
477
+ span.run82 {
478
+ background-color: rgb(255, 229, 178);
479
+ display: block;
480
+ }
481
+ span.run83 {
482
+ background-color: rgb(255, 226, 178);
483
+ display: block;
484
+ }
485
+ span.run84 {
486
+ background-color: rgb(255, 224, 178);
487
+ display: block;
488
+ }
489
+ span.run85 {
490
+ background-color: rgb(255, 220, 178);
491
+ display: block;
492
+ }
493
+ span.run86 {
494
+ background-color: rgb(255, 218, 178);
495
+ display: block;
496
+ }
497
+ span.run87 {
498
+ background-color: rgb(255, 215, 178);
499
+ display: block;
500
+ }
501
+ span.run88 {
502
+ background-color: rgb(255, 212, 178);
503
+ display: block;
504
+ }
505
+ span.run89 {
506
+ background-color: rgb(255, 210, 178);
507
+ display: block;
508
+ }
509
+ span.run90 {
510
+ background-color: rgb(255, 206, 178);
511
+ display: block;
512
+ }
513
+ span.run91 {
514
+ background-color: rgb(255, 204, 178);
515
+ display: block;
516
+ }
517
+ span.run92 {
518
+ background-color: rgb(255, 201, 178);
519
+ display: block;
520
+ }
521
+ span.run93 {
522
+ background-color: rgb(255, 198, 178);
523
+ display: block;
524
+ }
525
+ span.run94 {
526
+ background-color: rgb(255, 196, 178);
527
+ display: block;
528
+ }
529
+ span.run95 {
530
+ background-color: rgb(255, 192, 178);
531
+ display: block;
532
+ }
533
+ span.run96 {
534
+ background-color: rgb(255, 189, 178);
535
+ display: block;
536
+ }
537
+ span.run97 {
538
+ background-color: rgb(255, 187, 178);
539
+ display: block;
540
+ }
541
+ span.run98 {
542
+ background-color: rgb(255, 184, 178);
543
+ display: block;
544
+ }
545
+ span.run99 {
546
+ background-color: rgb(255, 182, 178);
547
+ display: block;
548
+ }
549
+ span.run100 {
550
+ background-color: rgb(255, 178, 178);
551
+ display: block;
552
+ }
553
+ </style>
554
+ </head>
555
+ <body><h3>C0 code coverage information</h3>
556
+ <p>Generated on Sat Nov 08 17:43:42 +0900 2008 with <a href='http://eigenclass.org/hiki/rcov'>rcov 0.8.1.2</a>
557
+ </p>
558
+ <hr/>
559
+ <pre><span class='marked0'>Code reported as executed by Ruby looks like this...
560
+ </span><span class='marked1'>and this: this line is also marked as covered.
561
+ </span><span class='inferred0'>Lines considered as run by rcov, but not reported by Ruby, look like this,
562
+ </span><span class='inferred1'>and this: these lines were inferred by rcov (using simple heuristics).
563
+ </span><span class='uncovered0'>Finally, here&apos;s a line marked as not executed.
564
+ </span></pre>
565
+ <table class='report'><thead><tr><td class='heading'>Name</td>
566
+ <td class='heading'>Total lines</td>
567
+ <td class='heading'>Lines of code</td>
568
+ <td class='heading'>Total coverage</td>
569
+ <td class='heading'>Code coverage</td>
570
+ </tr>
571
+ </thead>
572
+ <tbody><tr class='light'><td><a href='-Library-Ruby-Gems-gems-diff-lcs-1_1_2-lib-diff-lcs_rb.html'>/Library/Ruby/Gems/gems/diff-lcs-1.1.2/lib/diff/lcs.rb</a>
573
+ </td>
574
+ <td class='lines_total'><tt>1105</tt>
575
+ </td>
576
+ <td class='lines_code'><tt>553</tt>
577
+ </td>
578
+ <td><table cellspacing='0' cellpadding='0' align='right'><tr><td><tt class='coverage_total'>46.3%</tt>
579
+ &nbsp;</td>
580
+ <td><table cellspacing='0' class='percent_graph' cellpadding='0' width='100'><tr><td class='covered' width='46'/>
581
+ <td class='uncovered' width='54'/>
582
+ </tr>
583
+ </table>
584
+ </td>
585
+ </tr>
586
+ </table>
587
+ </td>
588
+ <td><table cellspacing='0' cellpadding='0' align='right'><tr><td><tt class='coverage_code'>6.5%</tt>
589
+ &nbsp;</td>
590
+ <td><table cellspacing='0' class='percent_graph' cellpadding='0' width='100'><tr><td class='covered' width='7'/>
591
+ <td class='uncovered' width='93'/>
592
+ </tr>
593
+ </table>
594
+ </td>
595
+ </tr>
596
+ </table>
597
+ </td>
598
+ </tr>
599
+ </tbody>
600
+ </table>
601
+ <pre><span class="inferred0"><a name="line1"></a> 1 #! /usr/env/bin ruby
602
+ </span><span class="inferred1"><a name="line2"></a> 2 #--
603
+ </span><span class="inferred0"><a name="line3"></a> 3 # Copyright 2004 Austin Ziegler &lt;diff-lcs@halostatue.ca&gt;
604
+ </span><span class="inferred1"><a name="line4"></a> 4 # adapted from:
605
+ </span><span class="inferred0"><a name="line5"></a> 5 # Algorithm::Diff (Perl) by Ned Konz &lt;perl@bike-nomad.com&gt;
606
+ </span><span class="inferred1"><a name="line6"></a> 6 # Smalltalk by Mario I. Wolczko &lt;mario@wolczko.com&gt;
607
+ </span><span class="inferred0"><a name="line7"></a> 7 # implements McIlroy-Hunt diff algorithm
608
+ </span><span class="inferred1"><a name="line8"></a> 8 #
609
+ </span><span class="inferred0"><a name="line9"></a> 9 # This program is free software. It may be redistributed and/or modified
610
+ </span><span class="inferred1"><a name="line10"></a> 10 # under the terms of the GPL version 2 (or later), the Perl Artistic
611
+ </span><span class="inferred0"><a name="line11"></a> 11 # licence, or the Ruby licence.
612
+ </span><span class="inferred1"><a name="line12"></a> 12 #
613
+ </span><span class="inferred0"><a name="line13"></a> 13 # $Id: lcs.rb,v 1.9 2004/10/17 20:31:10 austin Exp $
614
+ </span><span class="inferred1"><a name="line14"></a> 14 #++
615
+ </span><span class="inferred0"><a name="line15"></a> 15
616
+ </span><span class="marked1"><a name="line16"></a> 16 module Diff
617
+ </span><span class="inferred0"><a name="line17"></a> 17 # = Diff::LCS 1.1.2
618
+ </span><span class="inferred1"><a name="line18"></a> 18 # Computes &quot;intelligent&quot; differences between two sequenced Enumerables.
619
+ </span><span class="inferred0"><a name="line19"></a> 19 # This is an implementation of the McIlroy-Hunt &quot;diff&quot; algorithm for
620
+ </span><span class="inferred1"><a name="line20"></a> 20 # Enumerable objects that include Diffable.
621
+ </span><span class="inferred0"><a name="line21"></a> 21 #
622
+ </span><span class="inferred1"><a name="line22"></a> 22 # Based on Mario I. Wolczko's &lt;mario@wolczko.com&gt; Smalltalk version
623
+ </span><span class="inferred0"><a name="line23"></a> 23 # (1.2, 1993) and Ned Konz's &lt;perl@bike-nomad.com&gt; Perl version
624
+ </span><span class="inferred1"><a name="line24"></a> 24 # (Algorithm::Diff).
625
+ </span><span class="inferred0"><a name="line25"></a> 25 #
626
+ </span><span class="inferred1"><a name="line26"></a> 26 # == Synopsis
627
+ </span><span class="inferred0"><a name="line27"></a> 27 # require 'diff/lcs'
628
+ </span><span class="inferred1"><a name="line28"></a> 28 #
629
+ </span><span class="inferred0"><a name="line29"></a> 29 # seq1 = %w(a b c e h j l m n p)
630
+ </span><span class="inferred1"><a name="line30"></a> 30 # seq2 = %w(b c d e f j k l m r s t)
631
+ </span><span class="inferred0"><a name="line31"></a> 31 #
632
+ </span><span class="inferred1"><a name="line32"></a> 32 # lcs = Diff::LCS.LCS(seq1, seq2)
633
+ </span><span class="inferred0"><a name="line33"></a> 33 # diffs = Diff::LCS.diff(seq1, seq2)
634
+ </span><span class="inferred1"><a name="line34"></a> 34 # sdiff = Diff::LCS.sdiff(seq1, seq2)
635
+ </span><span class="inferred0"><a name="line35"></a> 35 # seq = Diff::LCS.traverse_sequences(seq1, seq2, callback_obj)
636
+ </span><span class="inferred1"><a name="line36"></a> 36 # bal = Diff::LCS.traverse_balanced(seq1, seq2, callback_obj)
637
+ </span><span class="inferred0"><a name="line37"></a> 37 # seq2 == Diff::LCS.patch(seq1, diffs)
638
+ </span><span class="inferred1"><a name="line38"></a> 38 # seq2 == Diff::LCS.patch!(seq1, diffs)
639
+ </span><span class="inferred0"><a name="line39"></a> 39 # seq1 == Diff::LCS.unpatch(seq2, diffs)
640
+ </span><span class="inferred1"><a name="line40"></a> 40 # seq1 == Diff::LCS.unpatch!(seq2, diffs)
641
+ </span><span class="inferred0"><a name="line41"></a> 41 # seq2 == Diff::LCS.patch(seq1, sdiff)
642
+ </span><span class="inferred1"><a name="line42"></a> 42 # seq2 == Diff::LCS.patch!(seq1, sdiff)
643
+ </span><span class="inferred0"><a name="line43"></a> 43 # seq1 == Diff::LCS.unpatch(seq2, sdiff)
644
+ </span><span class="inferred1"><a name="line44"></a> 44 # seq1 == Diff::LCS.unpatch!(seq2, sdiff)
645
+ </span><span class="inferred0"><a name="line45"></a> 45 #
646
+ </span><span class="inferred1"><a name="line46"></a> 46 # Alternatively, objects can be extended with Diff::LCS:
647
+ </span><span class="inferred0"><a name="line47"></a> 47 #
648
+ </span><span class="inferred1"><a name="line48"></a> 48 # seq1.extend(Diff::LCS)
649
+ </span><span class="inferred0"><a name="line49"></a> 49 # lcs = seq1.lcs(seq2)
650
+ </span><span class="inferred1"><a name="line50"></a> 50 # diffs = seq1.diff(seq2)
651
+ </span><span class="inferred0"><a name="line51"></a> 51 # sdiff = seq1.sdiff(seq2)
652
+ </span><span class="inferred1"><a name="line52"></a> 52 # seq = seq1.traverse_sequences(seq2, callback_obj)
653
+ </span><span class="inferred0"><a name="line53"></a> 53 # bal = seq1.traverse_balanced(seq2, callback_obj)
654
+ </span><span class="inferred1"><a name="line54"></a> 54 # seq2 == seq1.patch(diffs)
655
+ </span><span class="inferred0"><a name="line55"></a> 55 # seq2 == seq1.patch!(diffs)
656
+ </span><span class="inferred1"><a name="line56"></a> 56 # seq1 == seq2.unpatch(diffs)
657
+ </span><span class="inferred0"><a name="line57"></a> 57 # seq1 == seq2.unpatch!(diffs)
658
+ </span><span class="inferred1"><a name="line58"></a> 58 # seq2 == seq1.patch(sdiff)
659
+ </span><span class="inferred0"><a name="line59"></a> 59 # seq2 == seq1.patch!(sdiff)
660
+ </span><span class="inferred1"><a name="line60"></a> 60 # seq1 == seq2.unpatch(sdiff)
661
+ </span><span class="inferred0"><a name="line61"></a> 61 # seq1 == seq2.unpatch!(sdiff)
662
+ </span><span class="inferred1"><a name="line62"></a> 62 #
663
+ </span><span class="inferred0"><a name="line63"></a> 63 # Default extensions are provided for Array and String objects through
664
+ </span><span class="inferred1"><a name="line64"></a> 64 # the use of 'diff/lcs/array' and 'diff/lcs/string'.
665
+ </span><span class="inferred0"><a name="line65"></a> 65 #
666
+ </span><span class="inferred1"><a name="line66"></a> 66 # == Introduction (by Mark-Jason Dominus)
667
+ </span><span class="inferred0"><a name="line67"></a> 67 #
668
+ </span><span class="inferred1"><a name="line68"></a> 68 # &lt;em&gt;The following text is from the Perl documentation. The only
669
+ </span><span class="inferred0"><a name="line69"></a> 69 # changes have been to make the text appear better in Rdoc&lt;/em&gt;.
670
+ </span><span class="inferred1"><a name="line70"></a> 70 #
671
+ </span><span class="inferred0"><a name="line71"></a> 71 # I once read an article written by the authors of +diff+; they said
672
+ </span><span class="inferred1"><a name="line72"></a> 72 # that they hard worked very hard on the algorithm until they found the
673
+ </span><span class="inferred0"><a name="line73"></a> 73 # right one.
674
+ </span><span class="inferred1"><a name="line74"></a> 74 #
675
+ </span><span class="inferred0"><a name="line75"></a> 75 # I think what they ended up using (and I hope someone will correct me,
676
+ </span><span class="inferred1"><a name="line76"></a> 76 # because I am not very confident about this) was the `longest common
677
+ </span><span class="inferred0"><a name="line77"></a> 77 # subsequence' method. In the LCS problem, you have two sequences of
678
+ </span><span class="inferred1"><a name="line78"></a> 78 # items:
679
+ </span><span class="inferred0"><a name="line79"></a> 79 #
680
+ </span><span class="inferred1"><a name="line80"></a> 80 # a b c d f g h j q z
681
+ </span><span class="inferred0"><a name="line81"></a> 81 # a b c d e f g i j k r x y z
682
+ </span><span class="inferred1"><a name="line82"></a> 82 #
683
+ </span><span class="inferred0"><a name="line83"></a> 83 # and you want to find the longest sequence of items that is present in
684
+ </span><span class="inferred1"><a name="line84"></a> 84 # both original sequences in the same order. That is, you want to find a
685
+ </span><span class="inferred0"><a name="line85"></a> 85 # new sequence *S* which can be obtained from the first sequence by
686
+ </span><span class="inferred1"><a name="line86"></a> 86 # deleting some items, and from the second sequence by deleting other
687
+ </span><span class="inferred0"><a name="line87"></a> 87 # items. You also want *S* to be as long as possible. In this case *S*
688
+ </span><span class="inferred1"><a name="line88"></a> 88 # is:
689
+ </span><span class="inferred0"><a name="line89"></a> 89 #
690
+ </span><span class="inferred1"><a name="line90"></a> 90 # a b c d f g j z
691
+ </span><span class="inferred0"><a name="line91"></a> 91 #
692
+ </span><span class="inferred1"><a name="line92"></a> 92 # From there it's only a small step to get diff-like output:
693
+ </span><span class="inferred0"><a name="line93"></a> 93 #
694
+ </span><span class="inferred1"><a name="line94"></a> 94 # e h i k q r x y
695
+ </span><span class="inferred0"><a name="line95"></a> 95 # + - + + - + + +
696
+ </span><span class="inferred1"><a name="line96"></a> 96 #
697
+ </span><span class="inferred0"><a name="line97"></a> 97 # This module solves the LCS problem. It also includes a canned function
698
+ </span><span class="inferred1"><a name="line98"></a> 98 # to generate +diff+-like output.
699
+ </span><span class="inferred0"><a name="line99"></a> 99 #
700
+ </span><span class="inferred1"><a name="line100"></a> 100 # It might seem from the example above that the LCS of two sequences is
701
+ </span><span class="inferred0"><a name="line101"></a> 101 # always pretty obvious, but that's not always the case, especially when
702
+ </span><span class="inferred1"><a name="line102"></a> 102 # the two sequences have many repeated elements. For example, consider
703
+ </span><span class="inferred0"><a name="line103"></a> 103 #
704
+ </span><span class="inferred1"><a name="line104"></a> 104 # a x b y c z p d q
705
+ </span><span class="inferred0"><a name="line105"></a> 105 # a b c a x b y c z
706
+ </span><span class="inferred1"><a name="line106"></a> 106 #
707
+ </span><span class="inferred0"><a name="line107"></a> 107 # A naive approach might start by matching up the +a+ and +b+ that
708
+ </span><span class="inferred1"><a name="line108"></a> 108 # appear at the beginning of each sequence, like this:
709
+ </span><span class="inferred0"><a name="line109"></a> 109 #
710
+ </span><span class="inferred1"><a name="line110"></a> 110 # a x b y c z p d q
711
+ </span><span class="inferred0"><a name="line111"></a> 111 # a b c a b y c z
712
+ </span><span class="inferred1"><a name="line112"></a> 112 #
713
+ </span><span class="inferred0"><a name="line113"></a> 113 # This finds the common subsequence +a b c z+. But actually, the LCS is
714
+ </span><span class="inferred1"><a name="line114"></a> 114 # +a x b y c z+:
715
+ </span><span class="inferred0"><a name="line115"></a> 115 #
716
+ </span><span class="inferred1"><a name="line116"></a> 116 # a x b y c z p d q
717
+ </span><span class="inferred0"><a name="line117"></a> 117 # a b c a x b y c z
718
+ </span><span class="inferred1"><a name="line118"></a> 118 #
719
+ </span><span class="inferred0"><a name="line119"></a> 119 # == Author
720
+ </span><span class="inferred1"><a name="line120"></a> 120 # This version is by Austin Ziegler &lt;diff-lcs@halostatue.ca&gt;.
721
+ </span><span class="inferred0"><a name="line121"></a> 121 #
722
+ </span><span class="inferred1"><a name="line122"></a> 122 # It is based on the Perl Algorithm::Diff by Ned Konz
723
+ </span><span class="inferred0"><a name="line123"></a> 123 # &lt;perl@bike-nomad.com&gt;, copyright &amp;copy; 2000 - 2002 and the Smalltalk
724
+ </span><span class="inferred1"><a name="line124"></a> 124 # diff version by Mario I. Wolczko &lt;mario@wolczko.com&gt;, copyright &amp;copy;
725
+ </span><span class="inferred0"><a name="line125"></a> 125 # 1993. Documentation includes work by Mark-Jason Dominus.
726
+ </span><span class="inferred1"><a name="line126"></a> 126 #
727
+ </span><span class="inferred0"><a name="line127"></a> 127 # == Licence
728
+ </span><span class="inferred1"><a name="line128"></a> 128 # Copyright &amp;copy; 2004 Austin Ziegler
729
+ </span><span class="inferred0"><a name="line129"></a> 129 # This program is free software; you can redistribute it and/or modify it
730
+ </span><span class="inferred1"><a name="line130"></a> 130 # under the same terms as Ruby, or alternatively under the Perl Artistic
731
+ </span><span class="inferred0"><a name="line131"></a> 131 # licence.
732
+ </span><span class="inferred1"><a name="line132"></a> 132 #
733
+ </span><span class="inferred0"><a name="line133"></a> 133 # == Credits
734
+ </span><span class="inferred1"><a name="line134"></a> 134 # Much of the documentation is taken directly from the Perl
735
+ </span><span class="inferred0"><a name="line135"></a> 135 # Algorithm::Diff implementation and was written originally by Mark-Jason
736
+ </span><span class="inferred1"><a name="line136"></a> 136 # Dominus &lt;mjd-perl-diff@plover.com&gt; and later by Ned Konz. The basic Ruby
737
+ </span><span class="inferred0"><a name="line137"></a> 137 # implementation was re-ported from the Smalltalk implementation, available
738
+ </span><span class="inferred1"><a name="line138"></a> 138 # at ftp://st.cs.uiuc.edu/pub/Smalltalk/MANCHESTER/manchester/4.0/diff.st
739
+ </span><span class="inferred0"><a name="line139"></a> 139 #
740
+ </span><span class="inferred1"><a name="line140"></a> 140 # #sdiff and #traverse_balanced were written for the Perl version by Mike
741
+ </span><span class="inferred0"><a name="line141"></a> 141 # Schilli &lt;m@perlmeister.com&gt;.
742
+ </span><span class="inferred1"><a name="line142"></a> 142 #
743
+ </span><span class="inferred0"><a name="line143"></a> 143 # &quot;The algorithm is described in &lt;em&gt;A Fast Algorithm for Computing Longest
744
+ </span><span class="inferred1"><a name="line144"></a> 144 # Common Subsequences&lt;/em&gt;, CACM, vol.20, no.5, pp.350-353, May 1977, with
745
+ </span><span class="inferred0"><a name="line145"></a> 145 # a few minor improvements to improve the speed.&quot;
746
+ </span><span class="marked1"><a name="line146"></a> 146 module LCS
747
+ </span><span class="marked0"><a name="line147"></a> 147 VERSION = '1.1.2'
748
+ </span><span class="inferred1"><a name="line148"></a> 148 end
749
+ </span><span class="inferred0"><a name="line149"></a> 149 end
750
+ </span><span class="inferred1"><a name="line150"></a> 150
751
+ </span><span class="marked0"><a name="line151"></a> 151 require 'diff/lcs/callbacks'
752
+ </span><span class="inferred1"><a name="line152"></a> 152
753
+ </span><span class="marked0"><a name="line153"></a> 153 module Diff::LCS
754
+ </span><span class="inferred1"><a name="line154"></a> 154 # Returns an Array containing the longest common subsequence(s) between
755
+ </span><span class="inferred0"><a name="line155"></a> 155 # +self+ and +other+. See Diff::LCS#LCS.
756
+ </span><span class="inferred1"><a name="line156"></a> 156 #
757
+ </span><span class="inferred0"><a name="line157"></a> 157 # lcs = seq1.lcs(seq2)
758
+ </span><span class="marked1"><a name="line158"></a> 158 def lcs(other, &amp;block) #:yields self[ii] if there are matched subsequences:
759
+ </span><span class="uncovered0"><a name="line159"></a> 159 Diff::LCS.LCS(self, other, &amp;block)
760
+ </span><span class="uncovered1"><a name="line160"></a> 160 end
761
+ </span><span class="inferred0"><a name="line161"></a> 161
762
+ </span><span class="inferred1"><a name="line162"></a> 162 # Returns the difference set between +self+ and +other+. See
763
+ </span><span class="inferred0"><a name="line163"></a> 163 # Diff::LCS#diff.
764
+ </span><span class="marked1"><a name="line164"></a> 164 def diff(other, callbacks = nil, &amp;block)
765
+ </span><span class="uncovered0"><a name="line165"></a> 165 Diff::LCS::diff(self, other, callbacks, &amp;block)
766
+ </span><span class="uncovered1"><a name="line166"></a> 166 end
767
+ </span><span class="inferred0"><a name="line167"></a> 167
768
+ </span><span class="inferred1"><a name="line168"></a> 168 # Returns the balanced (&quot;side-by-side&quot;) difference set between +self+ and
769
+ </span><span class="inferred0"><a name="line169"></a> 169 # +other+. See Diff::LCS#sdiff.
770
+ </span><span class="marked1"><a name="line170"></a> 170 def sdiff(other, callbacks = nil, &amp;block)
771
+ </span><span class="uncovered0"><a name="line171"></a> 171 Diff::LCS::sdiff(self, other, callbacks, &amp;block)
772
+ </span><span class="uncovered1"><a name="line172"></a> 172 end
773
+ </span><span class="inferred0"><a name="line173"></a> 173
774
+ </span><span class="inferred1"><a name="line174"></a> 174 # Traverses the discovered longest common subsequences between +self+ and
775
+ </span><span class="inferred0"><a name="line175"></a> 175 # +other+. See Diff::LCS#traverse_sequences.
776
+ </span><span class="marked1"><a name="line176"></a> 176 def traverse_sequences(other, callbacks = nil, &amp;block)
777
+ </span><span class="uncovered0"><a name="line177"></a> 177 traverse_sequences(self, other, callbacks || Diff::LCS::YieldingCallbacks,
778
+ </span><span class="uncovered1"><a name="line178"></a> 178 &amp;block)
779
+ </span><span class="uncovered0"><a name="line179"></a> 179 end
780
+ </span><span class="inferred1"><a name="line180"></a> 180
781
+ </span><span class="inferred0"><a name="line181"></a> 181 # Traverses the discovered longest common subsequences between +self+ and
782
+ </span><span class="inferred1"><a name="line182"></a> 182 # +other+ using the alternate, balanced algorithm. See
783
+ </span><span class="inferred0"><a name="line183"></a> 183 # Diff::LCS#traverse_balanced.
784
+ </span><span class="marked1"><a name="line184"></a> 184 def traverse_balanced(other, callbacks = nil, &amp;block)
785
+ </span><span class="uncovered0"><a name="line185"></a> 185 traverse_balanced(self, other, callbacks || Diff::LCS::YieldingCallbacks,
786
+ </span><span class="uncovered1"><a name="line186"></a> 186 &amp;block)
787
+ </span><span class="uncovered0"><a name="line187"></a> 187 end
788
+ </span><span class="inferred1"><a name="line188"></a> 188
789
+ </span><span class="inferred0"><a name="line189"></a> 189 # Attempts to patch a copy of +self+ with the provided +patchset+. See
790
+ </span><span class="inferred1"><a name="line190"></a> 190 # Diff::LCS#patch.
791
+ </span><span class="marked0"><a name="line191"></a> 191 def patch(patchset)
792
+ </span><span class="uncovered1"><a name="line192"></a> 192 Diff::LCS::patch(self.dup, patchset)
793
+ </span><span class="uncovered0"><a name="line193"></a> 193 end
794
+ </span><span class="inferred1"><a name="line194"></a> 194
795
+ </span><span class="inferred0"><a name="line195"></a> 195 # Attempts to unpatch a copy of +self+ with the provided +patchset+.
796
+ </span><span class="inferred1"><a name="line196"></a> 196 # See Diff::LCS#patch.
797
+ </span><span class="marked0"><a name="line197"></a> 197 def unpatch(patchset)
798
+ </span><span class="uncovered1"><a name="line198"></a> 198 Diff::LCS::unpatch(self.dup, patchset)
799
+ </span><span class="uncovered0"><a name="line199"></a> 199 end
800
+ </span><span class="inferred1"><a name="line200"></a> 200
801
+ </span><span class="inferred0"><a name="line201"></a> 201 # Attempts to patch +self+ with the provided +patchset+. See
802
+ </span><span class="inferred1"><a name="line202"></a> 202 # Diff::LCS#patch!. Does no autodiscovery.
803
+ </span><span class="marked0"><a name="line203"></a> 203 def patch!(patchset)
804
+ </span><span class="uncovered1"><a name="line204"></a> 204 Diff::LCS::patch!(self, patchset)
805
+ </span><span class="uncovered0"><a name="line205"></a> 205 end
806
+ </span><span class="inferred1"><a name="line206"></a> 206
807
+ </span><span class="inferred0"><a name="line207"></a> 207 # Attempts to unpatch +self+ with the provided +patchset+. See
808
+ </span><span class="inferred1"><a name="line208"></a> 208 # Diff::LCS#unpatch. Does no autodiscovery.
809
+ </span><span class="marked0"><a name="line209"></a> 209 def unpatch!(patchset)
810
+ </span><span class="uncovered1"><a name="line210"></a> 210 Diff::LCS::unpatch!(self, patchset)
811
+ </span><span class="uncovered0"><a name="line211"></a> 211 end
812
+ </span><span class="uncovered1"><a name="line212"></a> 212 end
813
+ </span><span class="inferred0"><a name="line213"></a> 213
814
+ </span><span class="marked1"><a name="line214"></a> 214 module Diff::LCS
815
+ </span><span class="marked0"><a name="line215"></a> 215 class &lt;&lt; self
816
+ </span><span class="inferred1"><a name="line216"></a> 216 # Given two sequenced Enumerables, LCS returns an Array containing their
817
+ </span><span class="inferred0"><a name="line217"></a> 217 # longest common subsequences.
818
+ </span><span class="inferred1"><a name="line218"></a> 218 #
819
+ </span><span class="inferred0"><a name="line219"></a> 219 # lcs = Diff::LCS.LCS(seq1, seq2)
820
+ </span><span class="inferred1"><a name="line220"></a> 220 #
821
+ </span><span class="inferred0"><a name="line221"></a> 221 # This array whose contents is such that:
822
+ </span><span class="inferred1"><a name="line222"></a> 222 #
823
+ </span><span class="inferred0"><a name="line223"></a> 223 # lcs.each_with_index do |ee, ii|
824
+ </span><span class="inferred1"><a name="line224"></a> 224 # assert(ee.nil? || (seq1[ii] == seq2[ee]))
825
+ </span><span class="inferred0"><a name="line225"></a> 225 # end
826
+ </span><span class="inferred1"><a name="line226"></a> 226 #
827
+ </span><span class="inferred0"><a name="line227"></a> 227 # If a block is provided, the matching subsequences will be yielded from
828
+ </span><span class="inferred1"><a name="line228"></a> 228 # +seq1+ in turn and may be modified before they are placed into the
829
+ </span><span class="inferred0"><a name="line229"></a> 229 # returned Array of subsequences.
830
+ </span><span class="marked1"><a name="line230"></a> 230 def LCS(seq1, seq2, &amp;block) #:yields seq1[ii] for each matched:
831
+ </span><span class="uncovered0"><a name="line231"></a> 231 matches = Diff::LCS.__lcs(seq1, seq2)
832
+ </span><span class="uncovered1"><a name="line232"></a> 232 ret = []
833
+ </span><span class="uncovered0"><a name="line233"></a> 233 matches.each_with_index do |ee, ii|
834
+ </span><span class="uncovered1"><a name="line234"></a> 234 unless matches[ii].nil?
835
+ </span><span class="uncovered0"><a name="line235"></a> 235 if block_given?
836
+ </span><span class="uncovered1"><a name="line236"></a> 236 ret &lt;&lt; (yield seq1[ii])
837
+ </span><span class="uncovered0"><a name="line237"></a> 237 else
838
+ </span><span class="uncovered1"><a name="line238"></a> 238 ret &lt;&lt; seq1[ii]
839
+ </span><span class="uncovered0"><a name="line239"></a> 239 end
840
+ </span><span class="uncovered1"><a name="line240"></a> 240 end
841
+ </span><span class="uncovered0"><a name="line241"></a> 241 end
842
+ </span><span class="uncovered1"><a name="line242"></a> 242 ret
843
+ </span><span class="uncovered0"><a name="line243"></a> 243 end
844
+ </span><span class="inferred1"><a name="line244"></a> 244
845
+ </span><span class="inferred0"><a name="line245"></a> 245 # Diff::LCS.diff computes the smallest set of additions and deletions
846
+ </span><span class="inferred1"><a name="line246"></a> 246 # necessary to turn the first sequence into the second, and returns a
847
+ </span><span class="inferred0"><a name="line247"></a> 247 # description of these changes.
848
+ </span><span class="inferred1"><a name="line248"></a> 248 #
849
+ </span><span class="inferred0"><a name="line249"></a> 249 # See Diff::LCS::DiffCallbacks for the default behaviour. An alternate
850
+ </span><span class="inferred1"><a name="line250"></a> 250 # behaviour may be implemented with Diff::LCS::ContextDiffCallbacks.
851
+ </span><span class="inferred0"><a name="line251"></a> 251 # If a Class argument is provided for +callbacks+, #diff will attempt
852
+ </span><span class="inferred1"><a name="line252"></a> 252 # to initialise it. If the +callbacks+ object (possibly initialised)
853
+ </span><span class="inferred0"><a name="line253"></a> 253 # responds to #finish, it will be called.
854
+ </span><span class="marked1"><a name="line254"></a> 254 def diff(seq1, seq2, callbacks = nil, &amp;block) # :yields diff changes:
855
+ </span><span class="uncovered0"><a name="line255"></a> 255 callbacks ||= Diff::LCS::DiffCallbacks
856
+ </span><span class="uncovered1"><a name="line256"></a> 256 if callbacks.kind_of?(Class)
857
+ </span><span class="uncovered0"><a name="line257"></a> 257 cb = callbacks.new rescue callbacks
858
+ </span><span class="uncovered1"><a name="line258"></a> 258 callbacks = cb
859
+ </span><span class="uncovered0"><a name="line259"></a> 259 end
860
+ </span><span class="uncovered1"><a name="line260"></a> 260 traverse_sequences(seq1, seq2, callbacks)
861
+ </span><span class="uncovered0"><a name="line261"></a> 261 callbacks.finish if callbacks.respond_to?(:finish)
862
+ </span><span class="uncovered1"><a name="line262"></a> 262
863
+ </span><span class="uncovered0"><a name="line263"></a> 263 if block_given?
864
+ </span><span class="uncovered1"><a name="line264"></a> 264 res = callbacks.diffs.map do |hunk|
865
+ </span><span class="uncovered0"><a name="line265"></a> 265 if hunk.kind_of?(Array)
866
+ </span><span class="uncovered1"><a name="line266"></a> 266 hunk = hunk.map { |block| yield block }
867
+ </span><span class="uncovered0"><a name="line267"></a> 267 else
868
+ </span><span class="uncovered1"><a name="line268"></a> 268 yield hunk
869
+ </span><span class="uncovered0"><a name="line269"></a> 269 end
870
+ </span><span class="uncovered1"><a name="line270"></a> 270 end
871
+ </span><span class="uncovered0"><a name="line271"></a> 271 res
872
+ </span><span class="uncovered1"><a name="line272"></a> 272 else
873
+ </span><span class="uncovered0"><a name="line273"></a> 273 callbacks.diffs
874
+ </span><span class="uncovered1"><a name="line274"></a> 274 end
875
+ </span><span class="uncovered0"><a name="line275"></a> 275 end
876
+ </span><span class="inferred1"><a name="line276"></a> 276
877
+ </span><span class="inferred0"><a name="line277"></a> 277 # Diff::LCS.sdiff computes all necessary components to show two sequences
878
+ </span><span class="inferred1"><a name="line278"></a> 278 # and their minimized differences side by side, just like the Unix
879
+ </span><span class="inferred0"><a name="line279"></a> 279 # utility &lt;em&gt;sdiff&lt;/em&gt; does:
880
+ </span><span class="inferred1"><a name="line280"></a> 280 #
881
+ </span><span class="inferred0"><a name="line281"></a> 281 # old &lt; -
882
+ </span><span class="inferred1"><a name="line282"></a> 282 # same same
883
+ </span><span class="inferred0"><a name="line283"></a> 283 # before | after
884
+ </span><span class="inferred1"><a name="line284"></a> 284 # - &gt; new
885
+ </span><span class="inferred0"><a name="line285"></a> 285 #
886
+ </span><span class="inferred1"><a name="line286"></a> 286 # See Diff::LCS::SDiffCallbacks for the default behaviour. An alternate
887
+ </span><span class="inferred0"><a name="line287"></a> 287 # behaviour may be implemented with Diff::LCS::ContextDiffCallbacks. If
888
+ </span><span class="inferred1"><a name="line288"></a> 288 # a Class argument is provided for +callbacks+, #diff will attempt to
889
+ </span><span class="inferred0"><a name="line289"></a> 289 # initialise it. If the +callbacks+ object (possibly initialised)
890
+ </span><span class="inferred1"><a name="line290"></a> 290 # responds to #finish, it will be called.
891
+ </span><span class="marked0"><a name="line291"></a> 291 def sdiff(seq1, seq2, callbacks = nil, &amp;block) #:yields diff changes:
892
+ </span><span class="uncovered1"><a name="line292"></a> 292 callbacks ||= Diff::LCS::SDiffCallbacks
893
+ </span><span class="uncovered0"><a name="line293"></a> 293 if callbacks.kind_of?(Class)
894
+ </span><span class="uncovered1"><a name="line294"></a> 294 cb = callbacks.new rescue callbacks
895
+ </span><span class="uncovered0"><a name="line295"></a> 295 callbacks = cb
896
+ </span><span class="uncovered1"><a name="line296"></a> 296 end
897
+ </span><span class="uncovered0"><a name="line297"></a> 297 traverse_balanced(seq1, seq2, callbacks)
898
+ </span><span class="uncovered1"><a name="line298"></a> 298 callbacks.finish if callbacks.respond_to?(:finish)
899
+ </span><span class="uncovered0"><a name="line299"></a> 299
900
+ </span><span class="uncovered1"><a name="line300"></a> 300 if block_given?
901
+ </span><span class="uncovered0"><a name="line301"></a> 301 res = callbacks.diffs.map do |hunk|
902
+ </span><span class="uncovered1"><a name="line302"></a> 302 if hunk.kind_of?(Array)
903
+ </span><span class="uncovered0"><a name="line303"></a> 303 hunk = hunk.map { |block| yield block }
904
+ </span><span class="uncovered1"><a name="line304"></a> 304 else
905
+ </span><span class="uncovered0"><a name="line305"></a> 305 yield hunk
906
+ </span><span class="uncovered1"><a name="line306"></a> 306 end
907
+ </span><span class="uncovered0"><a name="line307"></a> 307 end
908
+ </span><span class="uncovered1"><a name="line308"></a> 308 res
909
+ </span><span class="uncovered0"><a name="line309"></a> 309 else
910
+ </span><span class="uncovered1"><a name="line310"></a> 310 callbacks.diffs
911
+ </span><span class="uncovered0"><a name="line311"></a> 311 end
912
+ </span><span class="uncovered1"><a name="line312"></a> 312 end
913
+ </span><span class="inferred0"><a name="line313"></a> 313
914
+ </span><span class="inferred1"><a name="line314"></a> 314 # Diff::LCS.traverse_sequences is the most general facility provided by this
915
+ </span><span class="inferred0"><a name="line315"></a> 315 # module; +diff+ and +LCS+ are implemented as calls to it.
916
+ </span><span class="inferred1"><a name="line316"></a> 316 #
917
+ </span><span class="inferred0"><a name="line317"></a> 317 # The arguments to #traverse_sequences are the two sequences to
918
+ </span><span class="inferred1"><a name="line318"></a> 318 # traverse, and a callback object, like this:
919
+ </span><span class="inferred0"><a name="line319"></a> 319 #
920
+ </span><span class="inferred1"><a name="line320"></a> 320 # traverse_sequences(seq1, seq2, Diff::LCS::ContextDiffCallbacks.new)
921
+ </span><span class="inferred0"><a name="line321"></a> 321 #
922
+ </span><span class="inferred1"><a name="line322"></a> 322 # #diff is implemented with #traverse_sequences.
923
+ </span><span class="inferred0"><a name="line323"></a> 323 #
924
+ </span><span class="inferred1"><a name="line324"></a> 324 # == Callback Methods
925
+ </span><span class="inferred0"><a name="line325"></a> 325 # Optional callback methods are &lt;em&gt;emphasized&lt;/em&gt;.
926
+ </span><span class="inferred1"><a name="line326"></a> 326 #
927
+ </span><span class="inferred0"><a name="line327"></a> 327 # callbacks#match:: Called when +a+ and +b+ are pointing
928
+ </span><span class="inferred1"><a name="line328"></a> 328 # to common elements in +A+ and +B+.
929
+ </span><span class="inferred0"><a name="line329"></a> 329 # callbacks#discard_a:: Called when +a+ is pointing to an
930
+ </span><span class="inferred1"><a name="line330"></a> 330 # element not in +B+.
931
+ </span><span class="inferred0"><a name="line331"></a> 331 # callbacks#discard_b:: Called when +b+ is pointing to an
932
+ </span><span class="inferred1"><a name="line332"></a> 332 # element not in +A+.
933
+ </span><span class="inferred0"><a name="line333"></a> 333 # &lt;em&gt;callbacks#finished_a&lt;/em&gt;:: Called when +a+ has reached the end of
934
+ </span><span class="inferred1"><a name="line334"></a> 334 # sequence +A+.
935
+ </span><span class="inferred0"><a name="line335"></a> 335 # &lt;em&gt;callbacks#finished_b&lt;/em&gt;:: Called when +b+ has reached the end of
936
+ </span><span class="inferred1"><a name="line336"></a> 336 # sequence +B+.
937
+ </span><span class="inferred0"><a name="line337"></a> 337 #
938
+ </span><span class="inferred1"><a name="line338"></a> 338 # == Algorithm
939
+ </span><span class="inferred0"><a name="line339"></a> 339 # a---+
940
+ </span><span class="inferred1"><a name="line340"></a> 340 # v
941
+ </span><span class="inferred0"><a name="line341"></a> 341 # A = a b c e h j l m n p
942
+ </span><span class="inferred1"><a name="line342"></a> 342 # B = b c d e f j k l m r s t
943
+ </span><span class="inferred0"><a name="line343"></a> 343 # ^
944
+ </span><span class="inferred1"><a name="line344"></a> 344 # b---+
945
+ </span><span class="inferred0"><a name="line345"></a> 345 #
946
+ </span><span class="inferred1"><a name="line346"></a> 346 # If there are two arrows (+a+ and +b+) pointing to elements of
947
+ </span><span class="inferred0"><a name="line347"></a> 347 # sequences +A+ and +B+, the arrows will initially point to the first
948
+ </span><span class="inferred1"><a name="line348"></a> 348 # elements of their respective sequences. #traverse_sequences will
949
+ </span><span class="inferred0"><a name="line349"></a> 349 # advance the arrows through the sequences one element at a time,
950
+ </span><span class="inferred1"><a name="line350"></a> 350 # calling a method on the user-specified callback object before each
951
+ </span><span class="inferred0"><a name="line351"></a> 351 # advance. It will advance the arrows in such a way that if there are
952
+ </span><span class="inferred1"><a name="line352"></a> 352 # elements &lt;tt&gt;A[ii]&lt;/tt&gt; and &lt;tt&gt;B[jj]&lt;/tt&gt; which are both equal and
953
+ </span><span class="inferred0"><a name="line353"></a> 353 # part of the longest common subsequence, there will be some moment
954
+ </span><span class="inferred1"><a name="line354"></a> 354 # during the execution of #traverse_sequences when arrow +a+ is pointing
955
+ </span><span class="inferred0"><a name="line355"></a> 355 # to &lt;tt&gt;A[ii]&lt;/tt&gt; and arrow +b+ is pointing to &lt;tt&gt;B[jj]&lt;/tt&gt;. When
956
+ </span><span class="inferred1"><a name="line356"></a> 356 # this happens, #traverse_sequences will call &lt;tt&gt;callbacks#match&lt;/tt&gt;
957
+ </span><span class="inferred0"><a name="line357"></a> 357 # and then it will advance both arrows.
958
+ </span><span class="inferred1"><a name="line358"></a> 358 #
959
+ </span><span class="inferred0"><a name="line359"></a> 359 # Otherwise, one of the arrows is pointing to an element of its sequence
960
+ </span><span class="inferred1"><a name="line360"></a> 360 # that is not part of the longest common subsequence.
961
+ </span><span class="inferred0"><a name="line361"></a> 361 # #traverse_sequences will advance that arrow and will call
962
+ </span><span class="inferred1"><a name="line362"></a> 362 # &lt;tt&gt;callbacks#discard_a&lt;/tt&gt; or &lt;tt&gt;callbacks#discard_b&lt;/tt&gt;, depending
963
+ </span><span class="inferred0"><a name="line363"></a> 363 # on which arrow it advanced. If both arrows point to elements that are
964
+ </span><span class="inferred1"><a name="line364"></a> 364 # not part of the longest common subsequence, then #traverse_sequences
965
+ </span><span class="inferred0"><a name="line365"></a> 365 # will advance one of them and call the appropriate callback, but it is
966
+ </span><span class="inferred1"><a name="line366"></a> 366 # not specified which it will call.
967
+ </span><span class="inferred0"><a name="line367"></a> 367 #
968
+ </span><span class="inferred1"><a name="line368"></a> 368 # The methods for &lt;tt&gt;callbacks#match&lt;/tt&gt;, &lt;tt&gt;callbacks#discard_a&lt;/tt&gt;,
969
+ </span><span class="inferred0"><a name="line369"></a> 369 # and &lt;tt&gt;callbacks#discard_b&lt;/tt&gt; are invoked with an event comprising
970
+ </span><span class="inferred1"><a name="line370"></a> 370 # the action (&quot;=&quot;, &quot;+&quot;, or &quot;-&quot;, respectively), the indicies +ii+ and
971
+ </span><span class="inferred0"><a name="line371"></a> 371 # +jj+, and the elements &lt;tt&gt;A[ii]&lt;/tt&gt; and &lt;tt&gt;B[jj]&lt;/tt&gt;. Return
972
+ </span><span class="inferred1"><a name="line372"></a> 372 # values are discarded by #traverse_sequences.
973
+ </span><span class="inferred0"><a name="line373"></a> 373 #
974
+ </span><span class="inferred1"><a name="line374"></a> 374 # === End of Sequences
975
+ </span><span class="inferred0"><a name="line375"></a> 375 # If arrow +a+ reaches the end of its sequence before arrow +b+ does,
976
+ </span><span class="inferred1"><a name="line376"></a> 376 # #traverse_sequence try to call &lt;tt&gt;callbacks#finished_a&lt;/tt&gt; with the
977
+ </span><span class="inferred0"><a name="line377"></a> 377 # last index and element of +A+ (&lt;tt&gt;A[-1]&lt;/tt&gt;) and the current index
978
+ </span><span class="inferred1"><a name="line378"></a> 378 # and element of +B+ (&lt;tt&gt;B[jj]&lt;/tt&gt;). If &lt;tt&gt;callbacks#finished_a&lt;/tt&gt;
979
+ </span><span class="inferred0"><a name="line379"></a> 379 # does not exist, then &lt;tt&gt;callbacks#discard_b&lt;/tt&gt; will be called on
980
+ </span><span class="inferred1"><a name="line380"></a> 380 # each element of +B+ until the end of the sequence is reached (the call
981
+ </span><span class="inferred0"><a name="line381"></a> 381 # will be done with &lt;tt&gt;A[-1]&lt;/tt&gt; and &lt;tt&gt;B[jj]&lt;/tt&gt; for each element).
982
+ </span><span class="inferred1"><a name="line382"></a> 382 #
983
+ </span><span class="inferred0"><a name="line383"></a> 383 # If +b+ reaches the end of +B+ before +a+ reaches the end of +A+,
984
+ </span><span class="inferred1"><a name="line384"></a> 384 # &lt;tt&gt;callbacks#finished_b&lt;/tt&gt; will be called with the current index
985
+ </span><span class="inferred0"><a name="line385"></a> 385 # and element of +A+ (&lt;tt&gt;A[ii]&lt;/tt&gt;) and the last index and element of
986
+ </span><span class="inferred1"><a name="line386"></a> 386 # +B+ (&lt;tt&gt;A[-1]&lt;/tt&gt;). Again, if &lt;tt&gt;callbacks#finished_b&lt;/tt&gt; does not
987
+ </span><span class="inferred0"><a name="line387"></a> 387 # exist on the callback object, then &lt;tt&gt;callbacks#discard_a&lt;/tt&gt; will
988
+ </span><span class="inferred1"><a name="line388"></a> 388 # be called on each element of +A+ until the end of the sequence is
989
+ </span><span class="inferred0"><a name="line389"></a> 389 # reached (&lt;tt&gt;A[ii]&lt;/tt&gt; and &lt;tt&gt;B[-1]&lt;/tt&gt;).
990
+ </span><span class="inferred1"><a name="line390"></a> 390 #
991
+ </span><span class="inferred0"><a name="line391"></a> 391 # There is a chance that one additional &lt;tt&gt;callbacks#discard_a&lt;/tt&gt; or
992
+ </span><span class="inferred1"><a name="line392"></a> 392 # &lt;tt&gt;callbacks#discard_b&lt;/tt&gt; will be called after the end of the
993
+ </span><span class="inferred0"><a name="line393"></a> 393 # sequence is reached, if +a+ has not yet reached the end of +A+ or +b+
994
+ </span><span class="inferred1"><a name="line394"></a> 394 # has not yet reached the end of +B+.
995
+ </span><span class="marked0"><a name="line395"></a> 395 def traverse_sequences(seq1, seq2, callbacks = Diff::LCS::SequenceCallbacks, &amp;block) #:yields change events:
996
+ </span><span class="uncovered1"><a name="line396"></a> 396 matches = Diff::LCS.__lcs(seq1, seq2)
997
+ </span><span class="uncovered0"><a name="line397"></a> 397
998
+ </span><span class="uncovered1"><a name="line398"></a> 398 run_finished_a = run_finished_b = false
999
+ </span><span class="uncovered0"><a name="line399"></a> 399 string = seq1.kind_of?(String)
1000
+ </span><span class="uncovered1"><a name="line400"></a> 400
1001
+ </span><span class="uncovered0"><a name="line401"></a> 401 a_size = seq1.size
1002
+ </span><span class="uncovered1"><a name="line402"></a> 402 b_size = seq2.size
1003
+ </span><span class="uncovered0"><a name="line403"></a> 403 ai = bj = 0
1004
+ </span><span class="uncovered1"><a name="line404"></a> 404
1005
+ </span><span class="uncovered0"><a name="line405"></a> 405 (0 .. matches.size).each do |ii|
1006
+ </span><span class="uncovered1"><a name="line406"></a> 406 b_line = matches[ii]
1007
+ </span><span class="uncovered0"><a name="line407"></a> 407
1008
+ </span><span class="uncovered1"><a name="line408"></a> 408 ax = string ? seq1[ii, 1] : seq1[ii]
1009
+ </span><span class="uncovered0"><a name="line409"></a> 409 bx = string ? seq2[bj, 1] : seq2[bj]
1010
+ </span><span class="uncovered1"><a name="line410"></a> 410
1011
+ </span><span class="uncovered0"><a name="line411"></a> 411 if b_line.nil?
1012
+ </span><span class="uncovered1"><a name="line412"></a> 412 unless ax.nil?
1013
+ </span><span class="uncovered0"><a name="line413"></a> 413 event = Diff::LCS::ContextChange.new('-', ii, ax, bj, bx)
1014
+ </span><span class="uncovered1"><a name="line414"></a> 414 event = yield event if block_given?
1015
+ </span><span class="uncovered0"><a name="line415"></a> 415 callbacks.discard_a(event)
1016
+ </span><span class="uncovered1"><a name="line416"></a> 416 end
1017
+ </span><span class="uncovered0"><a name="line417"></a> 417 else
1018
+ </span><span class="uncovered1"><a name="line418"></a> 418 loop do
1019
+ </span><span class="uncovered0"><a name="line419"></a> 419 break unless bj &lt; b_line
1020
+ </span><span class="uncovered1"><a name="line420"></a> 420 bx = string ? seq2[bj, 1] : seq2[bj]
1021
+ </span><span class="uncovered0"><a name="line421"></a> 421 event = Diff::LCS::ContextChange.new('+', ii, ax, bj, bx)
1022
+ </span><span class="uncovered1"><a name="line422"></a> 422 event = yield event if block_given?
1023
+ </span><span class="uncovered0"><a name="line423"></a> 423 callbacks.discard_b(event)
1024
+ </span><span class="uncovered1"><a name="line424"></a> 424 bj += 1
1025
+ </span><span class="uncovered0"><a name="line425"></a> 425 end
1026
+ </span><span class="uncovered1"><a name="line426"></a> 426 bx = string ? seq2[bj, 1] : seq2[bj]
1027
+ </span><span class="uncovered0"><a name="line427"></a> 427 event = Diff::LCS::ContextChange.new('=', ii, ax, bj, bx)
1028
+ </span><span class="uncovered1"><a name="line428"></a> 428 event = yield event if block_given?
1029
+ </span><span class="uncovered0"><a name="line429"></a> 429 callbacks.match(event)
1030
+ </span><span class="uncovered1"><a name="line430"></a> 430 bj += 1
1031
+ </span><span class="uncovered0"><a name="line431"></a> 431 end
1032
+ </span><span class="uncovered1"><a name="line432"></a> 432 ai = ii
1033
+ </span><span class="uncovered0"><a name="line433"></a> 433 end
1034
+ </span><span class="uncovered1"><a name="line434"></a> 434 ai += 1
1035
+ </span><span class="uncovered0"><a name="line435"></a> 435
1036
+ </span><span class="uncovered1"><a name="line436"></a> 436 # The last entry (if any) processed was a match. +ai+ and +bj+ point
1037
+ </span><span class="uncovered0"><a name="line437"></a> 437 # just past the last matching lines in their sequences.
1038
+ </span><span class="uncovered1"><a name="line438"></a> 438 while (ai &lt; a_size) or (bj &lt; b_size)
1039
+ </span><span class="uncovered0"><a name="line439"></a> 439 # last A?
1040
+ </span><span class="uncovered1"><a name="line440"></a> 440 if ai == a_size and bj &lt; b_size
1041
+ </span><span class="uncovered0"><a name="line441"></a> 441 if callbacks.respond_to?(:finished_a) and not run_finished_a
1042
+ </span><span class="uncovered1"><a name="line442"></a> 442 ax = string ? seq1[-1, 1] : seq1[-1]
1043
+ </span><span class="uncovered0"><a name="line443"></a> 443 bx = string ? seq2[bj, 1] : seq2[bj]
1044
+ </span><span class="uncovered1"><a name="line444"></a> 444 event = Diff::LCS::ContextChange.new('&gt;', (a_size - 1), ax, bj, bx)
1045
+ </span><span class="uncovered0"><a name="line445"></a> 445 event = yield event if block_given?
1046
+ </span><span class="uncovered1"><a name="line446"></a> 446 callbacks.finished_a(event)
1047
+ </span><span class="uncovered0"><a name="line447"></a> 447 run_finished_a = true
1048
+ </span><span class="uncovered1"><a name="line448"></a> 448 else
1049
+ </span><span class="uncovered0"><a name="line449"></a> 449 ax = string ? seq1[ai, 1] : seq1[ai]
1050
+ </span><span class="uncovered1"><a name="line450"></a> 450 loop do
1051
+ </span><span class="uncovered0"><a name="line451"></a> 451 bx = string ? seq2[bj, 1] : seq2[bj]
1052
+ </span><span class="uncovered1"><a name="line452"></a> 452 event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
1053
+ </span><span class="uncovered0"><a name="line453"></a> 453 event = yield event if block_given?
1054
+ </span><span class="uncovered1"><a name="line454"></a> 454 callbacks.discard_b(event)
1055
+ </span><span class="uncovered0"><a name="line455"></a> 455 bj += 1
1056
+ </span><span class="uncovered1"><a name="line456"></a> 456 break unless bj &lt; b_size
1057
+ </span><span class="uncovered0"><a name="line457"></a> 457 end
1058
+ </span><span class="uncovered1"><a name="line458"></a> 458 end
1059
+ </span><span class="uncovered0"><a name="line459"></a> 459 end
1060
+ </span><span class="uncovered1"><a name="line460"></a> 460
1061
+ </span><span class="uncovered0"><a name="line461"></a> 461 # last B?
1062
+ </span><span class="uncovered1"><a name="line462"></a> 462 if bj == b_size and ai &lt; a_size
1063
+ </span><span class="uncovered0"><a name="line463"></a> 463 if callbacks.respond_to?(:finished_b) and not run_finished_b
1064
+ </span><span class="uncovered1"><a name="line464"></a> 464 ax = string ? seq1[ai, 1] : seq1[ai]
1065
+ </span><span class="uncovered0"><a name="line465"></a> 465 bx = string ? seq2[-1, 1] : seq2[-1]
1066
+ </span><span class="uncovered1"><a name="line466"></a> 466 event = Diff::LCS::ContextChange.new('&lt;', ai, ax, (b_size - 1), bx)
1067
+ </span><span class="uncovered0"><a name="line467"></a> 467 event = yield event if block_given?
1068
+ </span><span class="uncovered1"><a name="line468"></a> 468 callbacks.finished_b(event)
1069
+ </span><span class="uncovered0"><a name="line469"></a> 469 run_finished_b = true
1070
+ </span><span class="uncovered1"><a name="line470"></a> 470 else
1071
+ </span><span class="uncovered0"><a name="line471"></a> 471 bx = string ? seq2[bj, 1] : seq2[bj]
1072
+ </span><span class="uncovered1"><a name="line472"></a> 472 loop do
1073
+ </span><span class="uncovered0"><a name="line473"></a> 473 ax = string ? seq1[ai, 1] : seq1[ai]
1074
+ </span><span class="uncovered1"><a name="line474"></a> 474 event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
1075
+ </span><span class="uncovered0"><a name="line475"></a> 475 event = yield event if block_given?
1076
+ </span><span class="uncovered1"><a name="line476"></a> 476 callbacks.discard_a(event)
1077
+ </span><span class="uncovered0"><a name="line477"></a> 477 ai += 1
1078
+ </span><span class="uncovered1"><a name="line478"></a> 478 break unless bj &lt; b_size
1079
+ </span><span class="uncovered0"><a name="line479"></a> 479 end
1080
+ </span><span class="uncovered1"><a name="line480"></a> 480 end
1081
+ </span><span class="uncovered0"><a name="line481"></a> 481 end
1082
+ </span><span class="uncovered1"><a name="line482"></a> 482
1083
+ </span><span class="uncovered0"><a name="line483"></a> 483 if ai &lt; a_size
1084
+ </span><span class="uncovered1"><a name="line484"></a> 484 ax = string ? seq1[ai, 1] : seq1[ai]
1085
+ </span><span class="uncovered0"><a name="line485"></a> 485 bx = string ? seq2[bj, 1] : seq2[bj]
1086
+ </span><span class="uncovered1"><a name="line486"></a> 486 event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
1087
+ </span><span class="uncovered0"><a name="line487"></a> 487 event = yield event if block_given?
1088
+ </span><span class="uncovered1"><a name="line488"></a> 488 callbacks.discard_a(event)
1089
+ </span><span class="uncovered0"><a name="line489"></a> 489 ai += 1
1090
+ </span><span class="uncovered1"><a name="line490"></a> 490 end
1091
+ </span><span class="uncovered0"><a name="line491"></a> 491
1092
+ </span><span class="uncovered1"><a name="line492"></a> 492 if bj &lt; b_size
1093
+ </span><span class="uncovered0"><a name="line493"></a> 493 ax = string ? seq1[ai, 1] : seq1[ai]
1094
+ </span><span class="uncovered1"><a name="line494"></a> 494 bx = string ? seq2[bj, 1] : seq2[bj]
1095
+ </span><span class="uncovered0"><a name="line495"></a> 495 event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
1096
+ </span><span class="uncovered1"><a name="line496"></a> 496 event = yield event if block_given?
1097
+ </span><span class="uncovered0"><a name="line497"></a> 497 callbacks.discard_b(event)
1098
+ </span><span class="uncovered1"><a name="line498"></a> 498 bj += 1
1099
+ </span><span class="uncovered0"><a name="line499"></a> 499 end
1100
+ </span><span class="uncovered1"><a name="line500"></a> 500 end
1101
+ </span><span class="uncovered0"><a name="line501"></a> 501 end
1102
+ </span><span class="inferred1"><a name="line502"></a> 502
1103
+ </span><span class="inferred0"><a name="line503"></a> 503 # #traverse_balanced is an alternative to #traverse_sequences. It
1104
+ </span><span class="inferred1"><a name="line504"></a> 504 # uses a different algorithm to iterate through the entries in the
1105
+ </span><span class="inferred0"><a name="line505"></a> 505 # computed longest common subsequence. Instead of viewing the changes as
1106
+ </span><span class="inferred1"><a name="line506"></a> 506 # insertions or deletions from one of the sequences, #traverse_balanced
1107
+ </span><span class="inferred0"><a name="line507"></a> 507 # will report &lt;em&gt;changes&lt;/em&gt; between the sequences. To represent a
1108
+ </span><span class="inferred1"><a name="line508"></a> 508 #
1109
+ </span><span class="inferred0"><a name="line509"></a> 509 # The arguments to #traverse_balanced are the two sequences to traverse
1110
+ </span><span class="inferred1"><a name="line510"></a> 510 # and a callback object, like this:
1111
+ </span><span class="inferred0"><a name="line511"></a> 511 #
1112
+ </span><span class="inferred1"><a name="line512"></a> 512 # traverse_balanced(seq1, seq2, Diff::LCS::ContextDiffCallbacks.new)
1113
+ </span><span class="inferred0"><a name="line513"></a> 513 #
1114
+ </span><span class="inferred1"><a name="line514"></a> 514 # #sdiff is implemented with #traverse_balanced.
1115
+ </span><span class="inferred0"><a name="line515"></a> 515 #
1116
+ </span><span class="inferred1"><a name="line516"></a> 516 # == Callback Methods
1117
+ </span><span class="inferred0"><a name="line517"></a> 517 # Optional callback methods are &lt;em&gt;emphasized&lt;/em&gt;.
1118
+ </span><span class="inferred1"><a name="line518"></a> 518 #
1119
+ </span><span class="inferred0"><a name="line519"></a> 519 # callbacks#match:: Called when +a+ and +b+ are pointing
1120
+ </span><span class="inferred1"><a name="line520"></a> 520 # to common elements in +A+ and +B+.
1121
+ </span><span class="inferred0"><a name="line521"></a> 521 # callbacks#discard_a:: Called when +a+ is pointing to an
1122
+ </span><span class="inferred1"><a name="line522"></a> 522 # element not in +B+.
1123
+ </span><span class="inferred0"><a name="line523"></a> 523 # callbacks#discard_b:: Called when +b+ is pointing to an
1124
+ </span><span class="inferred1"><a name="line524"></a> 524 # element not in +A+.
1125
+ </span><span class="inferred0"><a name="line525"></a> 525 # &lt;em&gt;callbacks#change&lt;/em&gt;:: Called when +a+ and +b+ are pointing
1126
+ </span><span class="inferred1"><a name="line526"></a> 526 # to the same relative position, but
1127
+ </span><span class="inferred0"><a name="line527"></a> 527 # &lt;tt&gt;A[a]&lt;/tt&gt; and &lt;tt&gt;B[b]&lt;/tt&gt; are
1128
+ </span><span class="inferred1"><a name="line528"></a> 528 # not the same; a &lt;em&gt;change&lt;/em&gt; has
1129
+ </span><span class="inferred0"><a name="line529"></a> 529 # occurred.
1130
+ </span><span class="inferred1"><a name="line530"></a> 530 #
1131
+ </span><span class="inferred0"><a name="line531"></a> 531 # #traverse_balanced might be a bit slower than #traverse_sequences,
1132
+ </span><span class="inferred1"><a name="line532"></a> 532 # noticable only while processing huge amounts of data.
1133
+ </span><span class="inferred0"><a name="line533"></a> 533 #
1134
+ </span><span class="inferred1"><a name="line534"></a> 534 # The +sdiff+ function of this module is implemented as call to
1135
+ </span><span class="inferred0"><a name="line535"></a> 535 # #traverse_balanced.
1136
+ </span><span class="inferred1"><a name="line536"></a> 536 #
1137
+ </span><span class="inferred0"><a name="line537"></a> 537 # == Algorithm
1138
+ </span><span class="inferred1"><a name="line538"></a> 538 # a---+
1139
+ </span><span class="inferred0"><a name="line539"></a> 539 # v
1140
+ </span><span class="inferred1"><a name="line540"></a> 540 # A = a b c e h j l m n p
1141
+ </span><span class="inferred0"><a name="line541"></a> 541 # B = b c d e f j k l m r s t
1142
+ </span><span class="inferred1"><a name="line542"></a> 542 # ^
1143
+ </span><span class="inferred0"><a name="line543"></a> 543 # b---+
1144
+ </span><span class="inferred1"><a name="line544"></a> 544 #
1145
+ </span><span class="inferred0"><a name="line545"></a> 545 # === Matches
1146
+ </span><span class="inferred1"><a name="line546"></a> 546 # If there are two arrows (+a+ and +b+) pointing to elements of
1147
+ </span><span class="inferred0"><a name="line547"></a> 547 # sequences +A+ and +B+, the arrows will initially point to the first
1148
+ </span><span class="inferred1"><a name="line548"></a> 548 # elements of their respective sequences. #traverse_sequences will
1149
+ </span><span class="inferred0"><a name="line549"></a> 549 # advance the arrows through the sequences one element at a time,
1150
+ </span><span class="inferred1"><a name="line550"></a> 550 # calling a method on the user-specified callback object before each
1151
+ </span><span class="inferred0"><a name="line551"></a> 551 # advance. It will advance the arrows in such a way that if there are
1152
+ </span><span class="inferred1"><a name="line552"></a> 552 # elements &lt;tt&gt;A[ii]&lt;/tt&gt; and &lt;tt&gt;B[jj]&lt;/tt&gt; which are both equal and
1153
+ </span><span class="inferred0"><a name="line553"></a> 553 # part of the longest common subsequence, there will be some moment
1154
+ </span><span class="inferred1"><a name="line554"></a> 554 # during the execution of #traverse_sequences when arrow +a+ is pointing
1155
+ </span><span class="inferred0"><a name="line555"></a> 555 # to &lt;tt&gt;A[ii]&lt;/tt&gt; and arrow +b+ is pointing to &lt;tt&gt;B[jj]&lt;/tt&gt;. When
1156
+ </span><span class="inferred1"><a name="line556"></a> 556 # this happens, #traverse_sequences will call &lt;tt&gt;callbacks#match&lt;/tt&gt;
1157
+ </span><span class="inferred0"><a name="line557"></a> 557 # and then it will advance both arrows.
1158
+ </span><span class="inferred1"><a name="line558"></a> 558 #
1159
+ </span><span class="inferred0"><a name="line559"></a> 559 # === Discards
1160
+ </span><span class="inferred1"><a name="line560"></a> 560 # Otherwise, one of the arrows is pointing to an element of its sequence
1161
+ </span><span class="inferred0"><a name="line561"></a> 561 # that is not part of the longest common subsequence.
1162
+ </span><span class="inferred1"><a name="line562"></a> 562 # #traverse_sequences will advance that arrow and will call
1163
+ </span><span class="inferred0"><a name="line563"></a> 563 # &lt;tt&gt;callbacks#discard_a&lt;/tt&gt; or &lt;tt&gt;callbacks#discard_b&lt;/tt&gt;,
1164
+ </span><span class="inferred1"><a name="line564"></a> 564 # depending on which arrow it advanced.
1165
+ </span><span class="inferred0"><a name="line565"></a> 565 #
1166
+ </span><span class="inferred1"><a name="line566"></a> 566 # === Changes
1167
+ </span><span class="inferred0"><a name="line567"></a> 567 # If both +a+ and +b+ point to elements that are not part of the longest
1168
+ </span><span class="inferred1"><a name="line568"></a> 568 # common subsequence, then #traverse_sequences will try to call
1169
+ </span><span class="inferred0"><a name="line569"></a> 569 # &lt;tt&gt;callbacks#change&lt;/tt&gt; and advance both arrows. If
1170
+ </span><span class="inferred1"><a name="line570"></a> 570 # &lt;tt&gt;callbacks#change&lt;/tt&gt; is not implemented, then
1171
+ </span><span class="inferred0"><a name="line571"></a> 571 # &lt;tt&gt;callbacks#discard_a&lt;/tt&gt; and &lt;tt&gt;callbacks#discard_b&lt;/tt&gt; will be
1172
+ </span><span class="inferred1"><a name="line572"></a> 572 # called in turn.
1173
+ </span><span class="inferred0"><a name="line573"></a> 573 #
1174
+ </span><span class="inferred1"><a name="line574"></a> 574 # The methods for &lt;tt&gt;callbacks#match&lt;/tt&gt;, &lt;tt&gt;callbacks#discard_a&lt;/tt&gt;,
1175
+ </span><span class="inferred0"><a name="line575"></a> 575 # &lt;tt&gt;callbacks#discard_b&lt;/tt&gt;, and &lt;tt&gt;callbacks#change&lt;/tt&gt; are
1176
+ </span><span class="inferred1"><a name="line576"></a> 576 # invoked with an event comprising the action (&quot;=&quot;, &quot;+&quot;, &quot;-&quot;, or &quot;!&quot;,
1177
+ </span><span class="inferred0"><a name="line577"></a> 577 # respectively), the indicies +ii+ and +jj+, and the elements
1178
+ </span><span class="inferred1"><a name="line578"></a> 578 # &lt;tt&gt;A[ii]&lt;/tt&gt; and &lt;tt&gt;B[jj]&lt;/tt&gt;. Return values are discarded by
1179
+ </span><span class="inferred0"><a name="line579"></a> 579 # #traverse_balanced.
1180
+ </span><span class="inferred1"><a name="line580"></a> 580 #
1181
+ </span><span class="inferred0"><a name="line581"></a> 581 # === Context
1182
+ </span><span class="inferred1"><a name="line582"></a> 582 # Note that +ii+ and +jj+ may not be the same index position, even if
1183
+ </span><span class="inferred0"><a name="line583"></a> 583 # +a+ and +b+ are considered to be pointing to matching or changed
1184
+ </span><span class="inferred1"><a name="line584"></a> 584 # elements.
1185
+ </span><span class="marked0"><a name="line585"></a> 585 def traverse_balanced(seq1, seq2, callbacks = Diff::LCS::BalancedCallbacks)
1186
+ </span><span class="uncovered1"><a name="line586"></a> 586 matches = Diff::LCS.__lcs(seq1, seq2)
1187
+ </span><span class="uncovered0"><a name="line587"></a> 587 a_size = seq1.size
1188
+ </span><span class="uncovered1"><a name="line588"></a> 588 b_size = seq2.size
1189
+ </span><span class="uncovered0"><a name="line589"></a> 589 ai = bj = mb = 0
1190
+ </span><span class="uncovered1"><a name="line590"></a> 590 ma = -1
1191
+ </span><span class="uncovered0"><a name="line591"></a> 591 string = seq1.kind_of?(String)
1192
+ </span><span class="uncovered1"><a name="line592"></a> 592
1193
+ </span><span class="uncovered0"><a name="line593"></a> 593 # Process all the lines in the match vector.
1194
+ </span><span class="uncovered1"><a name="line594"></a> 594 loop do
1195
+ </span><span class="uncovered0"><a name="line595"></a> 595 # Find next match indices +ma+ and +mb+
1196
+ </span><span class="uncovered1"><a name="line596"></a> 596 loop do
1197
+ </span><span class="uncovered0"><a name="line597"></a> 597 ma += 1
1198
+ </span><span class="uncovered1"><a name="line598"></a> 598 break unless ma &lt; matches.size and matches[ma].nil?
1199
+ </span><span class="uncovered0"><a name="line599"></a> 599 end
1200
+ </span><span class="uncovered1"><a name="line600"></a> 600
1201
+ </span><span class="uncovered0"><a name="line601"></a> 601 break if ma &gt;= matches.size # end of matches?
1202
+ </span><span class="uncovered1"><a name="line602"></a> 602 mb = matches[ma]
1203
+ </span><span class="uncovered0"><a name="line603"></a> 603
1204
+ </span><span class="uncovered1"><a name="line604"></a> 604 # Change(seq2)
1205
+ </span><span class="uncovered0"><a name="line605"></a> 605 while (ai &lt; ma) or (bj &lt; mb)
1206
+ </span><span class="uncovered1"><a name="line606"></a> 606 ax = string ? seq1[ai, 1] : seq1[ai]
1207
+ </span><span class="uncovered0"><a name="line607"></a> 607 bx = string ? seq2[bj, 1] : seq2[bj]
1208
+ </span><span class="uncovered1"><a name="line608"></a> 608
1209
+ </span><span class="uncovered0"><a name="line609"></a> 609 case [(ai &lt; ma), (bj &lt; mb)]
1210
+ </span><span class="uncovered1"><a name="line610"></a> 610 when [true, true]
1211
+ </span><span class="uncovered0"><a name="line611"></a> 611 if callbacks.respond_to?(:change)
1212
+ </span><span class="uncovered1"><a name="line612"></a> 612 event = Diff::LCS::ContextChange.new('!', ai, ax, bj, bx)
1213
+ </span><span class="uncovered0"><a name="line613"></a> 613 event = yield event if block_given?
1214
+ </span><span class="uncovered1"><a name="line614"></a> 614 callbacks.change(event)
1215
+ </span><span class="uncovered0"><a name="line615"></a> 615 ai += 1
1216
+ </span><span class="uncovered1"><a name="line616"></a> 616 bj += 1
1217
+ </span><span class="uncovered0"><a name="line617"></a> 617 else
1218
+ </span><span class="uncovered1"><a name="line618"></a> 618 event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
1219
+ </span><span class="uncovered0"><a name="line619"></a> 619 event = yield event if block_given?
1220
+ </span><span class="uncovered1"><a name="line620"></a> 620 callbacks.discard_a(event)
1221
+ </span><span class="uncovered0"><a name="line621"></a> 621 ai += 1
1222
+ </span><span class="uncovered1"><a name="line622"></a> 622 ax = string ? seq1[ai, 1] : seq1[ai]
1223
+ </span><span class="uncovered0"><a name="line623"></a> 623 event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
1224
+ </span><span class="uncovered1"><a name="line624"></a> 624 event = yield event if block_given?
1225
+ </span><span class="uncovered0"><a name="line625"></a> 625 callbacks.discard_b(event)
1226
+ </span><span class="uncovered1"><a name="line626"></a> 626 bj += 1
1227
+ </span><span class="uncovered0"><a name="line627"></a> 627 end
1228
+ </span><span class="uncovered1"><a name="line628"></a> 628 when [true, false]
1229
+ </span><span class="uncovered0"><a name="line629"></a> 629 event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
1230
+ </span><span class="uncovered1"><a name="line630"></a> 630 event = yield event if block_given?
1231
+ </span><span class="uncovered0"><a name="line631"></a> 631 callbacks.discard_a(event)
1232
+ </span><span class="uncovered1"><a name="line632"></a> 632 ai += 1
1233
+ </span><span class="uncovered0"><a name="line633"></a> 633 when [false, true]
1234
+ </span><span class="uncovered1"><a name="line634"></a> 634 event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
1235
+ </span><span class="uncovered0"><a name="line635"></a> 635 event = yield event if block_given?
1236
+ </span><span class="uncovered1"><a name="line636"></a> 636 callbacks.discard_b(event)
1237
+ </span><span class="uncovered0"><a name="line637"></a> 637 bj += 1
1238
+ </span><span class="uncovered1"><a name="line638"></a> 638 end
1239
+ </span><span class="uncovered0"><a name="line639"></a> 639 end
1240
+ </span><span class="uncovered1"><a name="line640"></a> 640
1241
+ </span><span class="uncovered0"><a name="line641"></a> 641 # Match
1242
+ </span><span class="uncovered1"><a name="line642"></a> 642 ax = string ? seq1[ai, 1] : seq1[ai]
1243
+ </span><span class="uncovered0"><a name="line643"></a> 643 bx = string ? seq2[bj, 1] : seq2[bj]
1244
+ </span><span class="uncovered1"><a name="line644"></a> 644 event = Diff::LCS::ContextChange.new('=', ai, ax, bj, bx)
1245
+ </span><span class="uncovered0"><a name="line645"></a> 645 event = yield event if block_given?
1246
+ </span><span class="uncovered1"><a name="line646"></a> 646 callbacks.match(event)
1247
+ </span><span class="uncovered0"><a name="line647"></a> 647 ai += 1
1248
+ </span><span class="uncovered1"><a name="line648"></a> 648 bj += 1
1249
+ </span><span class="uncovered0"><a name="line649"></a> 649 end
1250
+ </span><span class="uncovered1"><a name="line650"></a> 650
1251
+ </span><span class="uncovered0"><a name="line651"></a> 651 while (ai &lt; a_size) or (bj &lt; b_size)
1252
+ </span><span class="uncovered1"><a name="line652"></a> 652 ax = string ? seq1[ai, 1] : seq1[ai]
1253
+ </span><span class="uncovered0"><a name="line653"></a> 653 bx = string ? seq2[bj, 1] : seq2[bj]
1254
+ </span><span class="uncovered1"><a name="line654"></a> 654
1255
+ </span><span class="uncovered0"><a name="line655"></a> 655 case [(ai &lt; a_size), (bj &lt; b_size)]
1256
+ </span><span class="uncovered1"><a name="line656"></a> 656 when [true, true]
1257
+ </span><span class="uncovered0"><a name="line657"></a> 657 if callbacks.respond_to?(:change)
1258
+ </span><span class="uncovered1"><a name="line658"></a> 658 event = Diff::LCS::ContextChange.new('!', ai, ax, bj, bx)
1259
+ </span><span class="uncovered0"><a name="line659"></a> 659 event = yield event if block_given?
1260
+ </span><span class="uncovered1"><a name="line660"></a> 660 callbacks.change(event)
1261
+ </span><span class="uncovered0"><a name="line661"></a> 661 ai += 1
1262
+ </span><span class="uncovered1"><a name="line662"></a> 662 bj += 1
1263
+ </span><span class="uncovered0"><a name="line663"></a> 663 else
1264
+ </span><span class="uncovered1"><a name="line664"></a> 664 event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
1265
+ </span><span class="uncovered0"><a name="line665"></a> 665 event = yield event if block_given?
1266
+ </span><span class="uncovered1"><a name="line666"></a> 666 callbacks.discard_a(event)
1267
+ </span><span class="uncovered0"><a name="line667"></a> 667 ai += 1
1268
+ </span><span class="uncovered1"><a name="line668"></a> 668 ax = string ? seq1[ai, 1] : seq1[ai]
1269
+ </span><span class="uncovered0"><a name="line669"></a> 669 event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
1270
+ </span><span class="uncovered1"><a name="line670"></a> 670 event = yield event if block_given?
1271
+ </span><span class="uncovered0"><a name="line671"></a> 671 callbacks.discard_b(event)
1272
+ </span><span class="uncovered1"><a name="line672"></a> 672 bj += 1
1273
+ </span><span class="uncovered0"><a name="line673"></a> 673 end
1274
+ </span><span class="uncovered1"><a name="line674"></a> 674 when [true, false]
1275
+ </span><span class="uncovered0"><a name="line675"></a> 675 event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
1276
+ </span><span class="uncovered1"><a name="line676"></a> 676 event = yield event if block_given?
1277
+ </span><span class="uncovered0"><a name="line677"></a> 677 callbacks.discard_a(event)
1278
+ </span><span class="uncovered1"><a name="line678"></a> 678 ai += 1
1279
+ </span><span class="uncovered0"><a name="line679"></a> 679 when [false, true]
1280
+ </span><span class="uncovered1"><a name="line680"></a> 680 event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
1281
+ </span><span class="uncovered0"><a name="line681"></a> 681 event = yield event if block_given?
1282
+ </span><span class="uncovered1"><a name="line682"></a> 682 callbacks.discard_b(event)
1283
+ </span><span class="uncovered0"><a name="line683"></a> 683 bj += 1
1284
+ </span><span class="uncovered1"><a name="line684"></a> 684 end
1285
+ </span><span class="uncovered0"><a name="line685"></a> 685 end
1286
+ </span><span class="uncovered1"><a name="line686"></a> 686 end
1287
+ </span><span class="inferred0"><a name="line687"></a> 687
1288
+ </span><span class="marked1"><a name="line688"></a> 688 PATCH_MAP = { #:nodoc:
1289
+ </span><span class="inferred0"><a name="line689"></a> 689 :patch =&gt; { '+' =&gt; '+', '-' =&gt; '-', '!' =&gt; '!', '=' =&gt; '=' },
1290
+ </span><span class="inferred1"><a name="line690"></a> 690 :unpatch =&gt; { '+' =&gt; '-', '-' =&gt; '+', '!' =&gt; '!', '=' =&gt; '=' }
1291
+ </span><span class="inferred0"><a name="line691"></a> 691 }
1292
+ </span><span class="inferred1"><a name="line692"></a> 692
1293
+ </span><span class="inferred0"><a name="line693"></a> 693 # Given a patchset, convert the current version to the new
1294
+ </span><span class="inferred1"><a name="line694"></a> 694 # version. If +direction+ is not specified (must be
1295
+ </span><span class="inferred0"><a name="line695"></a> 695 # &lt;tt&gt;:patch&lt;/tt&gt; or &lt;tt&gt;:unpatch&lt;/tt&gt;), then discovery of the
1296
+ </span><span class="inferred1"><a name="line696"></a> 696 # direction of the patch will be attempted.
1297
+ </span><span class="marked0"><a name="line697"></a> 697 def patch(src, patchset, direction = nil)
1298
+ </span><span class="uncovered1"><a name="line698"></a> 698 string = src.kind_of?(String)
1299
+ </span><span class="uncovered0"><a name="line699"></a> 699 # Start with a new empty type of the source's class
1300
+ </span><span class="uncovered1"><a name="line700"></a> 700 res = src.class.new
1301
+ </span><span class="uncovered0"><a name="line701"></a> 701
1302
+ </span><span class="uncovered1"><a name="line702"></a> 702 # Normalize the patchset.
1303
+ </span><span class="uncovered0"><a name="line703"></a> 703 patchset = __normalize_patchset(patchset)
1304
+ </span><span class="uncovered1"><a name="line704"></a> 704
1305
+ </span><span class="uncovered0"><a name="line705"></a> 705 direction ||= Diff::LCS.__diff_direction(src, patchset)
1306
+ </span><span class="uncovered1"><a name="line706"></a> 706 direction ||= :patch
1307
+ </span><span class="uncovered0"><a name="line707"></a> 707
1308
+ </span><span class="uncovered1"><a name="line708"></a> 708 ai = bj = 0
1309
+ </span><span class="uncovered0"><a name="line709"></a> 709
1310
+ </span><span class="uncovered1"><a name="line710"></a> 710 patchset.each do |change|
1311
+ </span><span class="uncovered0"><a name="line711"></a> 711 # Both Change and ContextChange support #action
1312
+ </span><span class="uncovered1"><a name="line712"></a> 712 action = PATCH_MAP[direction][change.action]
1313
+ </span><span class="uncovered0"><a name="line713"></a> 713
1314
+ </span><span class="uncovered1"><a name="line714"></a> 714 case change
1315
+ </span><span class="uncovered0"><a name="line715"></a> 715 when Diff::LCS::ContextChange
1316
+ </span><span class="uncovered1"><a name="line716"></a> 716 case direction
1317
+ </span><span class="uncovered0"><a name="line717"></a> 717 when :patch
1318
+ </span><span class="uncovered1"><a name="line718"></a> 718 el = change.new_element
1319
+ </span><span class="uncovered0"><a name="line719"></a> 719 op = change.old_position
1320
+ </span><span class="uncovered1"><a name="line720"></a> 720 np = change.new_position
1321
+ </span><span class="uncovered0"><a name="line721"></a> 721 when :unpatch
1322
+ </span><span class="uncovered1"><a name="line722"></a> 722 el = change.old_element
1323
+ </span><span class="uncovered0"><a name="line723"></a> 723 op = change.new_position
1324
+ </span><span class="uncovered1"><a name="line724"></a> 724 np = change.old_position
1325
+ </span><span class="uncovered0"><a name="line725"></a> 725 end
1326
+ </span><span class="uncovered1"><a name="line726"></a> 726
1327
+ </span><span class="uncovered0"><a name="line727"></a> 727 case action
1328
+ </span><span class="uncovered1"><a name="line728"></a> 728 when '-' # Remove details from the old string
1329
+ </span><span class="uncovered0"><a name="line729"></a> 729 while ai &lt; op
1330
+ </span><span class="uncovered1"><a name="line730"></a> 730 res &lt;&lt; (string ? src[ai, 1] : src[ai])
1331
+ </span><span class="uncovered0"><a name="line731"></a> 731 ai += 1
1332
+ </span><span class="uncovered1"><a name="line732"></a> 732 bj += 1
1333
+ </span><span class="uncovered0"><a name="line733"></a> 733 end
1334
+ </span><span class="uncovered1"><a name="line734"></a> 734 ai += 1
1335
+ </span><span class="uncovered0"><a name="line735"></a> 735 when '+'
1336
+ </span><span class="uncovered1"><a name="line736"></a> 736 while bj &lt; np
1337
+ </span><span class="uncovered0"><a name="line737"></a> 737 res &lt;&lt; (string ? src[ai, 1] : src[ai])
1338
+ </span><span class="uncovered1"><a name="line738"></a> 738 ai += 1
1339
+ </span><span class="uncovered0"><a name="line739"></a> 739 bj += 1
1340
+ </span><span class="uncovered1"><a name="line740"></a> 740 end
1341
+ </span><span class="uncovered0"><a name="line741"></a> 741
1342
+ </span><span class="uncovered1"><a name="line742"></a> 742 res &lt;&lt; el
1343
+ </span><span class="uncovered0"><a name="line743"></a> 743 bj += 1
1344
+ </span><span class="uncovered1"><a name="line744"></a> 744 when '='
1345
+ </span><span class="uncovered0"><a name="line745"></a> 745 # This only appears in sdiff output with the SDiff callback.
1346
+ </span><span class="uncovered1"><a name="line746"></a> 746 # Therefore, we only need to worry about dealing with a single
1347
+ </span><span class="uncovered0"><a name="line747"></a> 747 # element.
1348
+ </span><span class="uncovered1"><a name="line748"></a> 748 res &lt;&lt; el
1349
+ </span><span class="uncovered0"><a name="line749"></a> 749
1350
+ </span><span class="uncovered1"><a name="line750"></a> 750 ai += 1
1351
+ </span><span class="uncovered0"><a name="line751"></a> 751 bj += 1
1352
+ </span><span class="uncovered1"><a name="line752"></a> 752 when '!'
1353
+ </span><span class="uncovered0"><a name="line753"></a> 753 while ai &lt; op
1354
+ </span><span class="uncovered1"><a name="line754"></a> 754 res &lt;&lt; (string ? src[ai, 1] : src[ai])
1355
+ </span><span class="uncovered0"><a name="line755"></a> 755 ai += 1
1356
+ </span><span class="uncovered1"><a name="line756"></a> 756 bj += 1
1357
+ </span><span class="uncovered0"><a name="line757"></a> 757 end
1358
+ </span><span class="uncovered1"><a name="line758"></a> 758
1359
+ </span><span class="uncovered0"><a name="line759"></a> 759 bj += 1
1360
+ </span><span class="uncovered1"><a name="line760"></a> 760 ai += 1
1361
+ </span><span class="uncovered0"><a name="line761"></a> 761
1362
+ </span><span class="uncovered1"><a name="line762"></a> 762 res &lt;&lt; el
1363
+ </span><span class="uncovered0"><a name="line763"></a> 763 end
1364
+ </span><span class="uncovered1"><a name="line764"></a> 764 when Diff::LCS::Change
1365
+ </span><span class="uncovered0"><a name="line765"></a> 765 case action
1366
+ </span><span class="uncovered1"><a name="line766"></a> 766 when '-'
1367
+ </span><span class="uncovered0"><a name="line767"></a> 767 while ai &lt; change.position
1368
+ </span><span class="uncovered1"><a name="line768"></a> 768 res &lt;&lt; (string ? src[ai, 1] : src[ai])
1369
+ </span><span class="uncovered0"><a name="line769"></a> 769 ai += 1
1370
+ </span><span class="uncovered1"><a name="line770"></a> 770 bj += 1
1371
+ </span><span class="uncovered0"><a name="line771"></a> 771 end
1372
+ </span><span class="uncovered1"><a name="line772"></a> 772 ai += 1
1373
+ </span><span class="uncovered0"><a name="line773"></a> 773 when '+'
1374
+ </span><span class="uncovered1"><a name="line774"></a> 774 while bj &lt; change.position
1375
+ </span><span class="uncovered0"><a name="line775"></a> 775 res &lt;&lt; (string ? src[ai, 1] : src[ai])
1376
+ </span><span class="uncovered1"><a name="line776"></a> 776 ai += 1
1377
+ </span><span class="uncovered0"><a name="line777"></a> 777 bj += 1
1378
+ </span><span class="uncovered1"><a name="line778"></a> 778 end
1379
+ </span><span class="uncovered0"><a name="line779"></a> 779
1380
+ </span><span class="uncovered1"><a name="line780"></a> 780 bj += 1
1381
+ </span><span class="uncovered0"><a name="line781"></a> 781
1382
+ </span><span class="uncovered1"><a name="line782"></a> 782 res &lt;&lt; change.element
1383
+ </span><span class="uncovered0"><a name="line783"></a> 783 end
1384
+ </span><span class="uncovered1"><a name="line784"></a> 784 end
1385
+ </span><span class="uncovered0"><a name="line785"></a> 785 end
1386
+ </span><span class="uncovered1"><a name="line786"></a> 786
1387
+ </span><span class="uncovered0"><a name="line787"></a> 787 while ai &lt; src.size
1388
+ </span><span class="uncovered1"><a name="line788"></a> 788 res &lt;&lt; (string ? src[ai, 1] : src[ai])
1389
+ </span><span class="uncovered0"><a name="line789"></a> 789 ai += 1
1390
+ </span><span class="uncovered1"><a name="line790"></a> 790 bj += 1
1391
+ </span><span class="uncovered0"><a name="line791"></a> 791 end
1392
+ </span><span class="uncovered1"><a name="line792"></a> 792
1393
+ </span><span class="uncovered0"><a name="line793"></a> 793 res
1394
+ </span><span class="uncovered1"><a name="line794"></a> 794 end
1395
+ </span><span class="inferred0"><a name="line795"></a> 795
1396
+ </span><span class="inferred1"><a name="line796"></a> 796 # Given a set of patchset, convert the current version to the prior
1397
+ </span><span class="inferred0"><a name="line797"></a> 797 # version. Does no auto-discovery.
1398
+ </span><span class="marked1"><a name="line798"></a> 798 def unpatch!(src, patchset)
1399
+ </span><span class="uncovered0"><a name="line799"></a> 799 Diff::LCS.patch(src, patchset, :unpatch)
1400
+ </span><span class="uncovered1"><a name="line800"></a> 800 end
1401
+ </span><span class="inferred0"><a name="line801"></a> 801
1402
+ </span><span class="inferred1"><a name="line802"></a> 802 # Given a set of patchset, convert the current version to the next
1403
+ </span><span class="inferred0"><a name="line803"></a> 803 # version. Does no auto-discovery.
1404
+ </span><span class="marked1"><a name="line804"></a> 804 def patch!(src, patchset)
1405
+ </span><span class="uncovered0"><a name="line805"></a> 805 Diff::LCS.patch(src, patchset, :patch)
1406
+ </span><span class="uncovered1"><a name="line806"></a> 806 end
1407
+ </span><span class="inferred0"><a name="line807"></a> 807
1408
+ </span><span class="inferred1"><a name="line808"></a> 808 # private
1409
+ </span><span class="inferred0"><a name="line809"></a> 809 # Compute the longest common subsequence between the sequenced Enumerables
1410
+ </span><span class="inferred1"><a name="line810"></a> 810 # +a+ and +b+. The result is an array whose contents is such that
1411
+ </span><span class="inferred0"><a name="line811"></a> 811 #
1412
+ </span><span class="inferred1"><a name="line812"></a> 812 # result = Diff::LCS.__lcs(a, b)
1413
+ </span><span class="inferred0"><a name="line813"></a> 813 # result.each_with_index do |e, ii|
1414
+ </span><span class="inferred1"><a name="line814"></a> 814 # assert_equal(a[ii], b[e]) unless e.nil?
1415
+ </span><span class="inferred0"><a name="line815"></a> 815 # end
1416
+ </span><span class="marked1"><a name="line816"></a> 816 def __lcs(a, b)
1417
+ </span><span class="uncovered0"><a name="line817"></a> 817 a_start = b_start = 0
1418
+ </span><span class="uncovered1"><a name="line818"></a> 818 a_finish = a.size - 1
1419
+ </span><span class="uncovered0"><a name="line819"></a> 819 b_finish = b.size - 1
1420
+ </span><span class="uncovered1"><a name="line820"></a> 820 vector = []
1421
+ </span><span class="uncovered0"><a name="line821"></a> 821
1422
+ </span><span class="uncovered1"><a name="line822"></a> 822 # Prune off any common elements at the beginning...
1423
+ </span><span class="uncovered0"><a name="line823"></a> 823 while (a_start &lt;= a_finish) and
1424
+ </span><span class="uncovered1"><a name="line824"></a> 824 (b_start &lt;= b_finish) and
1425
+ </span><span class="uncovered0"><a name="line825"></a> 825 (a[a_start] == b[b_start])
1426
+ </span><span class="uncovered1"><a name="line826"></a> 826 vector[a_start] = b_start
1427
+ </span><span class="uncovered0"><a name="line827"></a> 827 a_start += 1
1428
+ </span><span class="uncovered1"><a name="line828"></a> 828 b_start += 1
1429
+ </span><span class="uncovered0"><a name="line829"></a> 829 end
1430
+ </span><span class="uncovered1"><a name="line830"></a> 830
1431
+ </span><span class="uncovered0"><a name="line831"></a> 831 # Now the end...
1432
+ </span><span class="uncovered1"><a name="line832"></a> 832 while (a_start &lt;= a_finish) and
1433
+ </span><span class="uncovered0"><a name="line833"></a> 833 (b_start &lt;= b_finish) and
1434
+ </span><span class="uncovered1"><a name="line834"></a> 834 (a[a_finish] == b[b_finish])
1435
+ </span><span class="uncovered0"><a name="line835"></a> 835 vector[a_finish] = b_finish
1436
+ </span><span class="uncovered1"><a name="line836"></a> 836 a_finish -= 1
1437
+ </span><span class="uncovered0"><a name="line837"></a> 837 b_finish -= 1
1438
+ </span><span class="uncovered1"><a name="line838"></a> 838 end
1439
+ </span><span class="uncovered0"><a name="line839"></a> 839
1440
+ </span><span class="uncovered1"><a name="line840"></a> 840 # Now, compute the equivalence classes of positions of elements.
1441
+ </span><span class="uncovered0"><a name="line841"></a> 841 b_matches = Diff::LCS.__position_hash(b, b_start .. b_finish)
1442
+ </span><span class="uncovered1"><a name="line842"></a> 842
1443
+ </span><span class="uncovered0"><a name="line843"></a> 843 thresh = []
1444
+ </span><span class="uncovered1"><a name="line844"></a> 844 links = []
1445
+ </span><span class="uncovered0"><a name="line845"></a> 845
1446
+ </span><span class="uncovered1"><a name="line846"></a> 846 (a_start .. a_finish).each do |ii|
1447
+ </span><span class="uncovered0"><a name="line847"></a> 847 ai = a.kind_of?(String) ? a[ii, 1] : a[ii]
1448
+ </span><span class="uncovered1"><a name="line848"></a> 848 bm = b_matches[ai]
1449
+ </span><span class="uncovered0"><a name="line849"></a> 849 kk = nil
1450
+ </span><span class="uncovered1"><a name="line850"></a> 850 bm.reverse_each do |jj|
1451
+ </span><span class="uncovered0"><a name="line851"></a> 851 if kk and (thresh[kk] &gt; jj) and (thresh[kk - 1] &lt; jj)
1452
+ </span><span class="uncovered1"><a name="line852"></a> 852 thresh[kk] = jj
1453
+ </span><span class="uncovered0"><a name="line853"></a> 853 else
1454
+ </span><span class="uncovered1"><a name="line854"></a> 854 kk = Diff::LCS.__replace_next_larger(thresh, jj, kk)
1455
+ </span><span class="uncovered0"><a name="line855"></a> 855 end
1456
+ </span><span class="uncovered1"><a name="line856"></a> 856 links[kk] = [ (kk &gt; 0) ? links[kk - 1] : nil, ii, jj ] unless kk.nil?
1457
+ </span><span class="uncovered0"><a name="line857"></a> 857 end
1458
+ </span><span class="uncovered1"><a name="line858"></a> 858 end
1459
+ </span><span class="uncovered0"><a name="line859"></a> 859
1460
+ </span><span class="uncovered1"><a name="line860"></a> 860 unless thresh.empty?
1461
+ </span><span class="uncovered0"><a name="line861"></a> 861 link = links[thresh.size - 1]
1462
+ </span><span class="uncovered1"><a name="line862"></a> 862 while not link.nil?
1463
+ </span><span class="uncovered0"><a name="line863"></a> 863 vector[link[1]] = link[2]
1464
+ </span><span class="uncovered1"><a name="line864"></a> 864 link = link[0]
1465
+ </span><span class="uncovered0"><a name="line865"></a> 865 end
1466
+ </span><span class="uncovered1"><a name="line866"></a> 866 end
1467
+ </span><span class="uncovered0"><a name="line867"></a> 867
1468
+ </span><span class="uncovered1"><a name="line868"></a> 868 vector
1469
+ </span><span class="uncovered0"><a name="line869"></a> 869 end
1470
+ </span><span class="inferred1"><a name="line870"></a> 870
1471
+ </span><span class="inferred0"><a name="line871"></a> 871 # Find the place at which +value+ would normally be inserted into the
1472
+ </span><span class="inferred1"><a name="line872"></a> 872 # Enumerable. If that place is already occupied by +value+, do nothing
1473
+ </span><span class="inferred0"><a name="line873"></a> 873 # and return +nil+. If the place does not exist (i.e., it is off the end
1474
+ </span><span class="inferred1"><a name="line874"></a> 874 # of the Enumerable), add it to the end. Otherwise, replace the element
1475
+ </span><span class="inferred0"><a name="line875"></a> 875 # at that point with +value+. It is assumed that the Enumerable's values
1476
+ </span><span class="inferred1"><a name="line876"></a> 876 # are numeric.
1477
+ </span><span class="inferred0"><a name="line877"></a> 877 #
1478
+ </span><span class="inferred1"><a name="line878"></a> 878 # This operation preserves the sort order.
1479
+ </span><span class="marked0"><a name="line879"></a> 879 def __replace_next_larger(enum, value, last_index = nil)
1480
+ </span><span class="uncovered1"><a name="line880"></a> 880 # Off the end?
1481
+ </span><span class="uncovered0"><a name="line881"></a> 881 if enum.empty? or (value &gt; enum[-1])
1482
+ </span><span class="uncovered1"><a name="line882"></a> 882 enum &lt;&lt; value
1483
+ </span><span class="uncovered0"><a name="line883"></a> 883 return enum.size - 1
1484
+ </span><span class="uncovered1"><a name="line884"></a> 884 end
1485
+ </span><span class="uncovered0"><a name="line885"></a> 885
1486
+ </span><span class="uncovered1"><a name="line886"></a> 886 # Binary search for the insertion point
1487
+ </span><span class="uncovered0"><a name="line887"></a> 887 last_index ||= enum.size
1488
+ </span><span class="uncovered1"><a name="line888"></a> 888 first_index = 0
1489
+ </span><span class="uncovered0"><a name="line889"></a> 889 while (first_index &lt;= last_index)
1490
+ </span><span class="uncovered1"><a name="line890"></a> 890 ii = (first_index + last_index) &gt;&gt; 1
1491
+ </span><span class="uncovered0"><a name="line891"></a> 891
1492
+ </span><span class="uncovered1"><a name="line892"></a> 892 found = enum[ii]
1493
+ </span><span class="uncovered0"><a name="line893"></a> 893
1494
+ </span><span class="uncovered1"><a name="line894"></a> 894 if value == found
1495
+ </span><span class="uncovered0"><a name="line895"></a> 895 return nil
1496
+ </span><span class="uncovered1"><a name="line896"></a> 896 elsif value &gt; found
1497
+ </span><span class="uncovered0"><a name="line897"></a> 897 first_index = ii + 1
1498
+ </span><span class="uncovered1"><a name="line898"></a> 898 else
1499
+ </span><span class="uncovered0"><a name="line899"></a> 899 last_index = ii - 1
1500
+ </span><span class="uncovered1"><a name="line900"></a> 900 end
1501
+ </span><span class="uncovered0"><a name="line901"></a> 901 end
1502
+ </span><span class="uncovered1"><a name="line902"></a> 902
1503
+ </span><span class="uncovered0"><a name="line903"></a> 903 # The insertion point is in first_index; overwrite the next larger
1504
+ </span><span class="uncovered1"><a name="line904"></a> 904 # value.
1505
+ </span><span class="uncovered0"><a name="line905"></a> 905 enum[first_index] = value
1506
+ </span><span class="uncovered1"><a name="line906"></a> 906 return first_index
1507
+ </span><span class="uncovered0"><a name="line907"></a> 907 end
1508
+ </span><span class="inferred1"><a name="line908"></a> 908
1509
+ </span><span class="inferred0"><a name="line909"></a> 909 # If +vector+ maps the matching elements of another collection onto this
1510
+ </span><span class="inferred1"><a name="line910"></a> 910 # Enumerable, compute the inverse +vector+ that maps this Enumerable
1511
+ </span><span class="inferred0"><a name="line911"></a> 911 # onto the collection. (Currently unused.)
1512
+ </span><span class="marked1"><a name="line912"></a> 912 def __inverse_vector(a, vector)
1513
+ </span><span class="uncovered0"><a name="line913"></a> 913 inverse = a.dup
1514
+ </span><span class="uncovered1"><a name="line914"></a> 914 (0 ... vector.size).each do |ii|
1515
+ </span><span class="uncovered0"><a name="line915"></a> 915 inverse[vector[ii]] = ii unless vector[ii].nil?
1516
+ </span><span class="uncovered1"><a name="line916"></a> 916 end
1517
+ </span><span class="uncovered0"><a name="line917"></a> 917 inverse
1518
+ </span><span class="uncovered1"><a name="line918"></a> 918 end
1519
+ </span><span class="inferred0"><a name="line919"></a> 919
1520
+ </span><span class="inferred1"><a name="line920"></a> 920 # Returns a hash mapping each element of an Enumerable to the set of
1521
+ </span><span class="inferred0"><a name="line921"></a> 921 # positions it occupies in the Enumerable, optionally restricted to the
1522
+ </span><span class="inferred1"><a name="line922"></a> 922 # elements specified in the range of indexes specified by +interval+.
1523
+ </span><span class="marked0"><a name="line923"></a> 923 def __position_hash(enum, interval = 0 .. -1)
1524
+ </span><span class="uncovered1"><a name="line924"></a> 924 hash = Hash.new { |hh, kk| hh[kk] = [] }
1525
+ </span><span class="uncovered0"><a name="line925"></a> 925 interval.each do |ii|
1526
+ </span><span class="uncovered1"><a name="line926"></a> 926 kk = enum.kind_of?(String) ? enum[ii, 1] : enum[ii]
1527
+ </span><span class="uncovered0"><a name="line927"></a> 927 hash[kk] &lt;&lt; ii
1528
+ </span><span class="uncovered1"><a name="line928"></a> 928 end
1529
+ </span><span class="uncovered0"><a name="line929"></a> 929 hash
1530
+ </span><span class="uncovered1"><a name="line930"></a> 930 end
1531
+ </span><span class="inferred0"><a name="line931"></a> 931
1532
+ </span><span class="inferred1"><a name="line932"></a> 932 # Examine the patchset and the source to see in which direction the
1533
+ </span><span class="inferred0"><a name="line933"></a> 933 # patch should be applied.
1534
+ </span><span class="inferred1"><a name="line934"></a> 934 #
1535
+ </span><span class="inferred0"><a name="line935"></a> 935 # WARNING: By default, this examines the whole patch, so this could take
1536
+ </span><span class="inferred1"><a name="line936"></a> 936 # some time. This also works better with Diff::LCS::ContextChange or
1537
+ </span><span class="inferred0"><a name="line937"></a> 937 # Diff::LCS::Change as its source, as an array will cause the creation
1538
+ </span><span class="inferred1"><a name="line938"></a> 938 # of one of the above.
1539
+ </span><span class="marked0"><a name="line939"></a> 939 def __diff_direction(src, patchset, limit = nil)
1540
+ </span><span class="uncovered1"><a name="line940"></a> 940 count = left = left_miss = right = right_miss = 0
1541
+ </span><span class="uncovered0"><a name="line941"></a> 941 string = src.kind_of?(String)
1542
+ </span><span class="uncovered1"><a name="line942"></a> 942
1543
+ </span><span class="uncovered0"><a name="line943"></a> 943 patchset.each do |change|
1544
+ </span><span class="uncovered1"><a name="line944"></a> 944 count += 1
1545
+ </span><span class="uncovered0"><a name="line945"></a> 945
1546
+ </span><span class="uncovered1"><a name="line946"></a> 946 case change
1547
+ </span><span class="uncovered0"><a name="line947"></a> 947 when Diff::LCS::Change
1548
+ </span><span class="uncovered1"><a name="line948"></a> 948 # With a simplistic change, we can't tell the difference between
1549
+ </span><span class="uncovered0"><a name="line949"></a> 949 # the left and right on '!' actions, so we ignore those. On '='
1550
+ </span><span class="uncovered1"><a name="line950"></a> 950 # actions, if there's a miss, we miss both left and right.
1551
+ </span><span class="uncovered0"><a name="line951"></a> 951 element = string ? src[change.position, 1] : src[change.position]
1552
+ </span><span class="uncovered1"><a name="line952"></a> 952
1553
+ </span><span class="uncovered0"><a name="line953"></a> 953 case change.action
1554
+ </span><span class="uncovered1"><a name="line954"></a> 954 when '-'
1555
+ </span><span class="uncovered0"><a name="line955"></a> 955 if element == change.element
1556
+ </span><span class="uncovered1"><a name="line956"></a> 956 left += 1
1557
+ </span><span class="uncovered0"><a name="line957"></a> 957 else
1558
+ </span><span class="uncovered1"><a name="line958"></a> 958 left_miss += 1
1559
+ </span><span class="uncovered0"><a name="line959"></a> 959 end
1560
+ </span><span class="uncovered1"><a name="line960"></a> 960 when '+'
1561
+ </span><span class="uncovered0"><a name="line961"></a> 961 if element == change.element
1562
+ </span><span class="uncovered1"><a name="line962"></a> 962 right += 1
1563
+ </span><span class="uncovered0"><a name="line963"></a> 963 else
1564
+ </span><span class="uncovered1"><a name="line964"></a> 964 right_miss += 1
1565
+ </span><span class="uncovered0"><a name="line965"></a> 965 end
1566
+ </span><span class="uncovered1"><a name="line966"></a> 966 when '='
1567
+ </span><span class="uncovered0"><a name="line967"></a> 967 if element != change.element
1568
+ </span><span class="uncovered1"><a name="line968"></a> 968 left_miss += 1
1569
+ </span><span class="uncovered0"><a name="line969"></a> 969 right_miss += 1
1570
+ </span><span class="uncovered1"><a name="line970"></a> 970 end
1571
+ </span><span class="uncovered0"><a name="line971"></a> 971 end
1572
+ </span><span class="uncovered1"><a name="line972"></a> 972 when Diff::LCS::ContextChange
1573
+ </span><span class="uncovered0"><a name="line973"></a> 973 case change.action
1574
+ </span><span class="uncovered1"><a name="line974"></a> 974 when '-' # Remove details from the old string
1575
+ </span><span class="uncovered0"><a name="line975"></a> 975 element = string ? src[change.old_position, 1] : src[change.old_position]
1576
+ </span><span class="uncovered1"><a name="line976"></a> 976 if element == change.old_element
1577
+ </span><span class="uncovered0"><a name="line977"></a> 977 left += 1
1578
+ </span><span class="uncovered1"><a name="line978"></a> 978 else
1579
+ </span><span class="uncovered0"><a name="line979"></a> 979 left_miss += 1
1580
+ </span><span class="uncovered1"><a name="line980"></a> 980 end
1581
+ </span><span class="uncovered0"><a name="line981"></a> 981 when '+'
1582
+ </span><span class="uncovered1"><a name="line982"></a> 982 element = string ? src[change.new_position, 1] : src[change.new_position]
1583
+ </span><span class="uncovered0"><a name="line983"></a> 983 if element == change.new_element
1584
+ </span><span class="uncovered1"><a name="line984"></a> 984 right += 1
1585
+ </span><span class="uncovered0"><a name="line985"></a> 985 else
1586
+ </span><span class="uncovered1"><a name="line986"></a> 986 right_miss += 1
1587
+ </span><span class="uncovered0"><a name="line987"></a> 987 end
1588
+ </span><span class="uncovered1"><a name="line988"></a> 988 when '='
1589
+ </span><span class="uncovered0"><a name="line989"></a> 989 le = string ? src[change.old_position, 1] : src[change.old_position]
1590
+ </span><span class="uncovered1"><a name="line990"></a> 990 re = string ? src[change.new_position, 1] : src[change.new_position]
1591
+ </span><span class="uncovered0"><a name="line991"></a> 991
1592
+ </span><span class="uncovered1"><a name="line992"></a> 992 left_miss += 1 if le != change.old_element
1593
+ </span><span class="uncovered0"><a name="line993"></a> 993 right_miss += 1 if re != change.new_element
1594
+ </span><span class="uncovered1"><a name="line994"></a> 994 when '!'
1595
+ </span><span class="uncovered0"><a name="line995"></a> 995 element = string ? src[change.old_position, 1] : src[change.old_position]
1596
+ </span><span class="uncovered1"><a name="line996"></a> 996 if element == change.old_element
1597
+ </span><span class="uncovered0"><a name="line997"></a> 997 left += 1
1598
+ </span><span class="uncovered1"><a name="line998"></a> 998 else
1599
+ </span><span class="uncovered0"><a name="line999"></a> 999 element = string ? src[change.new_position, 1] : src[change.new_position]
1600
+ </span><span class="uncovered1"><a name="line1000"></a>1000 if element == change.new_element
1601
+ </span><span class="uncovered0"><a name="line1001"></a>1001 right += 1
1602
+ </span><span class="uncovered1"><a name="line1002"></a>1002 else
1603
+ </span><span class="uncovered0"><a name="line1003"></a>1003 left_miss += 1
1604
+ </span><span class="uncovered1"><a name="line1004"></a>1004 right_miss += 1
1605
+ </span><span class="uncovered0"><a name="line1005"></a>1005 end
1606
+ </span><span class="uncovered1"><a name="line1006"></a>1006 end
1607
+ </span><span class="uncovered0"><a name="line1007"></a>1007 end
1608
+ </span><span class="uncovered1"><a name="line1008"></a>1008 end
1609
+ </span><span class="uncovered0"><a name="line1009"></a>1009
1610
+ </span><span class="uncovered1"><a name="line1010"></a>1010 break if not limit.nil? and count &gt; limit
1611
+ </span><span class="uncovered0"><a name="line1011"></a>1011 end
1612
+ </span><span class="uncovered1"><a name="line1012"></a>1012
1613
+ </span><span class="uncovered0"><a name="line1013"></a>1013 no_left = (left == 0) and (left_miss &gt;= 0)
1614
+ </span><span class="uncovered1"><a name="line1014"></a>1014 no_right = (right == 0) and (right_miss &gt;= 0)
1615
+ </span><span class="uncovered0"><a name="line1015"></a>1015
1616
+ </span><span class="uncovered1"><a name="line1016"></a>1016 case [no_left, no_right]
1617
+ </span><span class="uncovered0"><a name="line1017"></a>1017 when [false, true]
1618
+ </span><span class="uncovered1"><a name="line1018"></a>1018 return :patch
1619
+ </span><span class="uncovered0"><a name="line1019"></a>1019 when [true, false]
1620
+ </span><span class="uncovered1"><a name="line1020"></a>1020 return :unpatch
1621
+ </span><span class="uncovered0"><a name="line1021"></a>1021 else
1622
+ </span><span class="uncovered1"><a name="line1022"></a>1022 raise &quot;The provided patchset does not appear to apply to the provided value as either source or destination value.&quot;
1623
+ </span><span class="uncovered0"><a name="line1023"></a>1023 end
1624
+ </span><span class="uncovered1"><a name="line1024"></a>1024 end
1625
+ </span><span class="inferred0"><a name="line1025"></a>1025
1626
+ </span><span class="inferred1"><a name="line1026"></a>1026 # Normalize the patchset. A patchset is always a sequence of changes, but
1627
+ </span><span class="inferred0"><a name="line1027"></a>1027 # how those changes are represented may vary, depending on how they were
1628
+ </span><span class="inferred1"><a name="line1028"></a>1028 # generated. In all cases we support, we also support the array
1629
+ </span><span class="inferred0"><a name="line1029"></a>1029 # representation of the changes. The formats are:
1630
+ </span><span class="inferred1"><a name="line1030"></a>1030 #
1631
+ </span><span class="inferred0"><a name="line1031"></a>1031 # [ # patchset &lt;- Diff::LCS.diff(a, b)
1632
+ </span><span class="inferred1"><a name="line1032"></a>1032 # [ # one or more hunks
1633
+ </span><span class="inferred0"><a name="line1033"></a>1033 # Diff::LCS::Change # one or more changes
1634
+ </span><span class="inferred1"><a name="line1034"></a>1034 # ] ]
1635
+ </span><span class="inferred0"><a name="line1035"></a>1035 #
1636
+ </span><span class="inferred1"><a name="line1036"></a>1036 # [ # patchset, equivalent to the above
1637
+ </span><span class="inferred0"><a name="line1037"></a>1037 # [ # one or more hunks
1638
+ </span><span class="inferred1"><a name="line1038"></a>1038 # [ action, line, value ] # one or more changes
1639
+ </span><span class="inferred0"><a name="line1039"></a>1039 # ] ]
1640
+ </span><span class="inferred1"><a name="line1040"></a>1040 #
1641
+ </span><span class="inferred0"><a name="line1041"></a>1041 # [ # patchset &lt;- Diff::LCS.diff(a, b, Diff::LCS::ContextDiffCallbacks)
1642
+ </span><span class="inferred1"><a name="line1042"></a>1042 # # OR &lt;- Diff::LCS.sdiff(a, b, Diff::LCS::ContextDiffCallbacks)
1643
+ </span><span class="inferred0"><a name="line1043"></a>1043 # [ # one or more hunks
1644
+ </span><span class="inferred1"><a name="line1044"></a>1044 # Diff::LCS::ContextChange # one or more changes
1645
+ </span><span class="inferred0"><a name="line1045"></a>1045 # ] ]
1646
+ </span><span class="inferred1"><a name="line1046"></a>1046 #
1647
+ </span><span class="inferred0"><a name="line1047"></a>1047 # [ # patchset, equivalent to the above
1648
+ </span><span class="inferred1"><a name="line1048"></a>1048 # [ # one or more hunks
1649
+ </span><span class="inferred0"><a name="line1049"></a>1049 # [ action, [ old line, old value ], [ new line, new value ] ]
1650
+ </span><span class="inferred1"><a name="line1050"></a>1050 # # one or more changes
1651
+ </span><span class="inferred0"><a name="line1051"></a>1051 # ] ]
1652
+ </span><span class="inferred1"><a name="line1052"></a>1052 #
1653
+ </span><span class="inferred0"><a name="line1053"></a>1053 # [ # patchset &lt;- Diff::LCS.sdiff(a, b)
1654
+ </span><span class="inferred1"><a name="line1054"></a>1054 # # OR &lt;- Diff::LCS.diff(a, b, Diff::LCS::SDiffCallbacks)
1655
+ </span><span class="inferred0"><a name="line1055"></a>1055 # Diff::LCS::ContextChange # one or more changes
1656
+ </span><span class="inferred1"><a name="line1056"></a>1056 # ]
1657
+ </span><span class="inferred0"><a name="line1057"></a>1057 #
1658
+ </span><span class="inferred1"><a name="line1058"></a>1058 # [ # patchset, equivalent to the above
1659
+ </span><span class="inferred0"><a name="line1059"></a>1059 # [ action, [ old line, old value ], [ new line, new value ] ]
1660
+ </span><span class="inferred1"><a name="line1060"></a>1060 # # one or more changes
1661
+ </span><span class="inferred0"><a name="line1061"></a>1061 # ]
1662
+ </span><span class="inferred1"><a name="line1062"></a>1062 #
1663
+ </span><span class="inferred0"><a name="line1063"></a>1063 # The result of this will be either of the following.
1664
+ </span><span class="inferred1"><a name="line1064"></a>1064 #
1665
+ </span><span class="inferred0"><a name="line1065"></a>1065 # [ # patchset
1666
+ </span><span class="inferred1"><a name="line1066"></a>1066 # Diff::LCS::ContextChange # one or more changes
1667
+ </span><span class="inferred0"><a name="line1067"></a>1067 # ]
1668
+ </span><span class="inferred1"><a name="line1068"></a>1068 #
1669
+ </span><span class="inferred0"><a name="line1069"></a>1069 # [ # patchset
1670
+ </span><span class="inferred1"><a name="line1070"></a>1070 # Diff::LCS::Change # one or more changes
1671
+ </span><span class="inferred0"><a name="line1071"></a>1071 # ]
1672
+ </span><span class="inferred1"><a name="line1072"></a>1072 #
1673
+ </span><span class="inferred0"><a name="line1073"></a>1073 # If either of the above is provided, it will be returned as such.
1674
+ </span><span class="inferred1"><a name="line1074"></a>1074 #
1675
+ </span><span class="marked0"><a name="line1075"></a>1075 def __normalize_patchset(patchset)
1676
+ </span><span class="uncovered1"><a name="line1076"></a>1076 patchset.map do |hunk|
1677
+ </span><span class="uncovered0"><a name="line1077"></a>1077 case hunk
1678
+ </span><span class="uncovered1"><a name="line1078"></a>1078 when Diff::LCS::ContextChange, Diff::LCS::Change
1679
+ </span><span class="uncovered0"><a name="line1079"></a>1079 hunk
1680
+ </span><span class="uncovered1"><a name="line1080"></a>1080 when Array
1681
+ </span><span class="uncovered0"><a name="line1081"></a>1081 if (not hunk[0].kind_of?(Array)) and hunk[1].kind_of?(Array) and hunk[2].kind_of?(Array)
1682
+ </span><span class="uncovered1"><a name="line1082"></a>1082 Diff::LCS::ContextChange.from_a(hunk)
1683
+ </span><span class="uncovered0"><a name="line1083"></a>1083 else
1684
+ </span><span class="uncovered1"><a name="line1084"></a>1084 hunk.map do |change|
1685
+ </span><span class="uncovered0"><a name="line1085"></a>1085 case change
1686
+ </span><span class="uncovered1"><a name="line1086"></a>1086 when Diff::LCS::ContextChange, Diff::LCS::Change
1687
+ </span><span class="uncovered0"><a name="line1087"></a>1087 change
1688
+ </span><span class="uncovered1"><a name="line1088"></a>1088 when Array
1689
+ </span><span class="uncovered0"><a name="line1089"></a>1089 # change[1] will ONLY be an array in a ContextChange#to_a call.
1690
+ </span><span class="uncovered1"><a name="line1090"></a>1090 # In Change#to_a, it represents the line (singular).
1691
+ </span><span class="uncovered0"><a name="line1091"></a>1091 if change[1].kind_of?(Array)
1692
+ </span><span class="uncovered1"><a name="line1092"></a>1092 Diff::LCS::ContextChange.from_a(change)
1693
+ </span><span class="uncovered0"><a name="line1093"></a>1093 else
1694
+ </span><span class="uncovered1"><a name="line1094"></a>1094 Diff::LCS::Change.from_a(change)
1695
+ </span><span class="uncovered0"><a name="line1095"></a>1095 end
1696
+ </span><span class="uncovered1"><a name="line1096"></a>1096 end
1697
+ </span><span class="uncovered0"><a name="line1097"></a>1097 end
1698
+ </span><span class="uncovered1"><a name="line1098"></a>1098 end
1699
+ </span><span class="uncovered0"><a name="line1099"></a>1099 else
1700
+ </span><span class="uncovered1"><a name="line1100"></a>1100 raise ArgumentError, &quot;Cannot normalise a hunk of class #{hunk.class}.&quot;
1701
+ </span><span class="uncovered0"><a name="line1101"></a>1101 end
1702
+ </span><span class="uncovered1"><a name="line1102"></a>1102 end.flatten
1703
+ </span><span class="uncovered0"><a name="line1103"></a>1103 end
1704
+ </span><span class="uncovered1"><a name="line1104"></a>1104 end
1705
+ </span><span class="uncovered0"><a name="line1105"></a>1105 end
1706
+ </span></pre><hr/>
1707
+ <p>Generated using the <a href='http://eigenclass.org/hiki.rb?rcov'>rcov code coverage analysis tool for Ruby</a>
1708
+ version 0.8.1.2.</p>
1709
+ <p><a href='http://validator.w3.org/check/referer'><img src='http://www.w3.org/Icons/valid-xhtml10' height='31' alt='Valid XHTML 1.0!' width='88'/>
1710
+ </a>
1711
+ <a href='http://jigsaw.w3.org/css-validator/check/referer'><img src='http://jigsaw.w3.org/css-validator/images/vcss' alt='Valid CSS!' style='border:0;width:88px;height:31px'/>
1712
+ </a>
1713
+ </p>
1714
+ </body>
1715
+ </html>