win32-api 1.5.3-universal-mingw32 → 1.6.0-universal-mingw32
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.
- checksums.yaml +4 -4
- data/CHANGES +174 -169
- data/Gemfile +4 -0
- data/Gemfile.lock +24 -0
- data/README +129 -131
- data/Rakefile +185 -182
- data/appveyor.yml +42 -0
- data/ext/win32/api.c +1092 -1092
- data/lib/win32/api.rb +14 -8
- data/lib/win32/ruby21_32/win32/api.so +0 -0
- data/lib/win32/ruby21_64/win32/api.so +0 -0
- data/lib/win32/ruby22_32/win32/api.so +0 -0
- data/lib/win32/ruby22_64/win32/api.so +0 -0
- data/lib/win32/ruby23_32/win32/api.so +0 -0
- data/lib/win32/ruby23_64/win32/api.so +0 -0
- data/lib/win32/ruby2_32/win32/api.so +0 -0
- data/lib/win32/ruby2_64/win32/api.so +0 -0
- data/test/test_win32_api.rb +145 -145
- data/vendor/bundle/ruby/2.2.0/bin/devkit +23 -0
- data/vendor/bundle/ruby/2.2.0/bin/devkit.bat +6 -0
- data/vendor/bundle/ruby/2.2.0/bin/rake +23 -0
- data/vendor/bundle/ruby/2.2.0/bin/rake.bat +6 -0
- data/vendor/bundle/ruby/2.2.0/gems/colorize-0.7.7/CHANGELOG +55 -0
- data/vendor/bundle/ruby/2.2.0/gems/colorize-0.7.7/LICENSE +339 -0
- data/vendor/bundle/ruby/2.2.0/gems/colorize-0.7.7/README.md +73 -0
- data/vendor/bundle/ruby/2.2.0/gems/colorize-0.7.7/Rakefile +8 -0
- data/vendor/bundle/ruby/2.2.0/gems/colorize-0.7.7/colorize.gemspec +35 -0
- data/vendor/bundle/ruby/2.2.0/gems/colorize-0.7.7/lib/colorize.rb +12 -0
- data/vendor/bundle/ruby/2.2.0/gems/colorize-0.7.7/lib/colorize/class_methods.rb +116 -0
- data/vendor/bundle/ruby/2.2.0/gems/colorize-0.7.7/lib/colorize/instance_methods.rb +135 -0
- data/vendor/bundle/ruby/2.2.0/gems/colorize-0.7.7/test/test_colorize.rb +161 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/Gemfile +4 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/LICENSE.txt +22 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/README.md +34 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/Rakefile +1 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/Rspec-example-matchers.txt +184 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/bin/devkit +87 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/devkit.gemspec +27 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/lib/devkit.rb +18 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/lib/devkit/core.rb +53 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/lib/devkit/identity.rb +78 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/lib/devkit/ssh_identity.rb +53 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/lib/devkit/version.rb +3 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/spec/devkit/core_spec.rb +46 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/spec/devkit/identity_spec.rb +1 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/spec/devkit/ssh_identity_spec.rb +1 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/spec/devkit_spec.rb +5 -0
- data/vendor/bundle/ruby/2.2.0/gems/devkit-0.1.0/spec/spec_helper.rb +8 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/AUTHORS +3 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/COPYING +339 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/Changelog.md +415 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/Gemfile +9 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/INSTALL +59 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/LICENSE +7 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/README.rdoc +74 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/Rakefile +30 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/TODO +6 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/examples/ansi_colors.rb +38 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/examples/asking_for_arrays.rb +18 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/examples/basic_usage.rb +75 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/examples/color_scheme.rb +32 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/examples/get_character.rb +12 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/examples/limit.rb +12 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/examples/menus.rb +65 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/examples/overwrite.rb +19 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/examples/page_and_wrap.rb +322 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/examples/password.rb +7 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/examples/repeat_entry.rb +21 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/examples/trapping_eof.rb +22 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/examples/using_readline.rb +17 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/highline.gemspec +37 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/lib/highline.rb +1048 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/lib/highline/color_scheme.rb +134 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/lib/highline/compatibility.rb +16 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/lib/highline/import.rb +41 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/lib/highline/menu.rb +381 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/lib/highline/question.rb +480 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/lib/highline/simulate.rb +48 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/lib/highline/style.rb +192 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/lib/highline/version.rb +4 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/setup.rb +1360 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/site/highline.css +65 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/site/images/logo.png +0 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/site/index.html +58 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/test/string_methods.rb +32 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/test/tc_color_scheme.rb +96 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/test/tc_highline.rb +1402 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/test/tc_import.rb +52 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/test/tc_menu.rb +439 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/test/tc_simulator.rb +23 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/test/tc_string_highline.rb +38 -0
- data/vendor/bundle/ruby/2.2.0/gems/highline-1.7.8/test/tc_style.rb +578 -0
- data/vendor/bundle/ruby/2.2.0/gems/power_assert-0.3.0/BSDL +22 -0
- data/vendor/bundle/ruby/2.2.0/gems/power_assert-0.3.0/COPYING +57 -0
- data/vendor/bundle/ruby/2.2.0/gems/power_assert-0.3.0/Gemfile +9 -0
- data/vendor/bundle/ruby/2.2.0/gems/power_assert-0.3.0/LEGAL +4 -0
- data/vendor/bundle/ruby/2.2.0/gems/power_assert-0.3.0/README.rdoc +19 -0
- data/vendor/bundle/ruby/2.2.0/gems/power_assert-0.3.0/Rakefile +16 -0
- data/vendor/bundle/ruby/2.2.0/gems/power_assert-0.3.0/benchmarks/bm_yhpg.rb +59 -0
- data/vendor/bundle/ruby/2.2.0/gems/power_assert-0.3.0/benchmarks/helper.rb +8 -0
- data/vendor/bundle/ruby/2.2.0/gems/power_assert-0.3.0/lib/power_assert.rb +338 -0
- data/vendor/bundle/ruby/2.2.0/gems/power_assert-0.3.0/lib/power_assert/enable_tracepoint_events.rb +82 -0
- data/vendor/bundle/ruby/2.2.0/gems/power_assert-0.3.0/lib/power_assert/version.rb +3 -0
- data/vendor/bundle/ruby/2.2.0/gems/power_assert-0.3.0/power_assert.gemspec +23 -0
- data/vendor/bundle/ruby/2.2.0/gems/power_assert-0.3.0/test/helper.rb +10 -0
- data/vendor/bundle/ruby/2.2.0/gems/power_assert-0.3.0/test/test_power_assert.rb +512 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/CONTRIBUTING.rdoc +38 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/History.rdoc +719 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/MIT-LICENSE +21 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/Manifest.txt +154 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/README.rdoc +157 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/Rakefile +82 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/bin/rake +33 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/command_line_usage.rdoc +158 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/example/Rakefile1 +38 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/example/Rakefile2 +35 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/example/a.c +6 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/example/b.c +6 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/example/main.c +11 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/glossary.rdoc +42 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/jamis.rb +591 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/proto_rake.rdoc +127 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/rake.1 +141 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/rakefile.rdoc +624 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/rational.rdoc +151 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.4.14.rdoc +23 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.4.15.rdoc +35 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.5.0.rdoc +53 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.5.3.rdoc +78 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.5.4.rdoc +46 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.6.0.rdoc +141 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.7.0.rdoc +119 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.7.1.rdoc +59 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.7.2.rdoc +121 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.7.3.rdoc +47 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.8.0.rdoc +114 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.8.2.rdoc +165 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.8.3.rdoc +112 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.8.4.rdoc +147 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.8.5.rdoc +53 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.8.6.rdoc +37 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.8.7.rdoc +55 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.9.0.rdoc +112 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.9.1.rdoc +52 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.9.2.2.rdoc +55 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.9.2.rdoc +49 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.9.3.rdoc +102 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.9.4.rdoc +60 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.9.5.rdoc +55 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-0.9.6.rdoc +64 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-10.0.0.rdoc +178 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-10.0.1.rdoc +58 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-10.0.2.rdoc +53 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-10.0.3.rdoc +191 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/doc/release_notes/rake-10.1.0.rdoc +61 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake.rb +73 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/application.rb +787 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/backtrace.rb +23 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/clean.rb +76 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/cloneable.rb +16 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/contrib/compositepublisher.rb +21 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/contrib/ftptools.rb +137 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/contrib/sshpublisher.rb +60 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/cpu_counter.rb +120 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/default_loader.rb +14 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/dsl_definition.rb +194 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/early_time.rb +21 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/file_creation_task.rb +24 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/file_list.rb +436 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/file_task.rb +46 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/file_utils.rb +123 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/invocation_chain.rb +56 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/invocation_exception_mixin.rb +16 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/late_time.rb +17 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/linked_list.rb +111 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/loaders/makefile.rb +53 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/multi_task.rb +13 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/name_space.rb +38 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/packagetask.rb +199 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/phony.rb +15 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/private_reader.rb +20 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/promise.rb +99 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/pseudo_status.rb +29 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/rake_module.rb +38 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/rake_test_loader.rb +22 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/rule_recursion_overflow_error.rb +20 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/scope.rb +42 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/task.rb +391 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/task_argument_error.rb +7 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/task_arguments.rb +102 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/task_manager.rb +316 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/tasklib.rb +11 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/testtask.rb +204 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/thread_history_display.rb +48 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/thread_pool.rb +163 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/trace_output.rb +22 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/version.rb +7 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/lib/rake/win32.rb +50 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/rakelib/test_times.rake +25 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/file_creation.rb +34 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/helper.rb +134 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/support/rakefile_definitions.rb +476 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/support/ruby_runner.rb +34 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_private_reader.rb +42 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake.rb +40 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_application.rb +659 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_application_options.rb +468 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_backtrace.rb +119 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_clean.rb +61 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_cpu_counter.rb +68 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_definitions.rb +84 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_directory_task.rb +76 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_dsl.rb +40 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_early_time.rb +31 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_file_creation_task.rb +56 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_file_list.rb +687 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_file_list_path_map.rb +15 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_file_task.rb +197 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_file_utils.rb +318 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_ftp_file.rb +74 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_functional.rb +484 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_invocation_chain.rb +64 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_late_time.rb +18 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_linked_list.rb +84 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_makefile_loader.rb +46 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_multi_task.rb +64 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_name_space.rb +57 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_package_task.rb +79 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_path_map.rb +168 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_path_map_explode.rb +34 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_path_map_partial.rb +18 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_pseudo_status.rb +21 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_rake_test_loader.rb +20 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_reduce_compat.rb +26 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_require.rb +40 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_rules.rb +388 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_scope.rb +44 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_task.rb +430 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_task_argument_parsing.rb +119 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_task_arguments.rb +134 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_task_manager.rb +178 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_task_manager_argument_resolution.rb +19 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_task_with_arguments.rb +172 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_test_task.rb +130 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_thread_pool.rb +145 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_top_level_functions.rb +71 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_rake_win32.rb +72 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_thread_history_display.rb +101 -0
- data/vendor/bundle/ruby/2.2.0/gems/rake-11.1.2/test/test_trace_output.rb +52 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/COPYING +64 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/GPL +339 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/LGPL +502 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/PSFL +271 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/README.md +101 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/Rakefile +71 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test-unit.rb +34 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit.rb +505 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/assertion-failed-error.rb +25 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/assertions.rb +2218 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/attribute-matcher.rb +26 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/attribute.rb +158 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/auto-runner-loader.rb +17 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/autorunner.rb +536 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/code-snippet-fetcher.rb +58 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/collector.rb +73 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/collector/descendant.rb +19 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/collector/dir.rb +108 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/collector/load.rb +202 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/collector/objectspace.rb +34 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/collector/xml.rb +249 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/color-scheme.rb +198 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/color.rb +134 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/data.rb +262 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/diff.rb +746 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/error.rb +158 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/exception-handler.rb +82 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/failure.rb +169 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/fault-location-detector.rb +100 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/fixture.rb +295 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/notification.rb +136 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/omission.rb +195 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/pending.rb +154 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/priority.rb +192 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/runner/console.rb +59 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/runner/emacs.rb +8 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/runner/xml.rb +15 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/test-suite-creator.rb +89 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/testcase.rb +811 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/testresult.rb +132 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/testsuite.rb +175 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/ui/console/outputlevel.rb +15 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/ui/console/testrunner.rb +693 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/ui/emacs/testrunner.rb +49 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/ui/testrunner.rb +53 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/ui/testrunnermediator.rb +114 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/ui/testrunnerutilities.rb +41 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/ui/xml/testrunner.rb +224 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/util/backtracefilter.rb +59 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/util/method-owner-finder.rb +28 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/util/observable.rb +90 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/util/output.rb +31 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/util/procwrapper.rb +48 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/lib/test/unit/version.rb +5 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/sample/adder.rb +13 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/sample/subtracter.rb +12 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/sample/test_adder.rb +20 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/sample/test_subtracter.rb +20 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/sample/test_user.rb +23 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/collector/test-descendant.rb +178 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/collector/test-load.rb +442 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/collector/test_dir.rb +406 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/collector/test_objectspace.rb +100 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/fixtures/header-label.csv +3 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/fixtures/header-label.tsv +3 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/fixtures/header.csv +3 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/fixtures/header.tsv +3 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/fixtures/no-header.csv +2 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/fixtures/no-header.tsv +2 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/fixtures/plus.csv +3 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/run-test.rb +22 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-assertions.rb +2160 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-attribute-matcher.rb +38 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-attribute.rb +123 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-code-snippet.rb +37 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-color-scheme.rb +82 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-color.rb +47 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-data.rb +303 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-diff.rb +518 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-emacs-runner.rb +60 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-error.rb +26 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-failure.rb +33 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-fault-location-detector.rb +163 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-fixture.rb +713 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-notification.rb +33 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-omission.rb +81 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-pending.rb +70 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-priority.rb +173 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-test-case.rb +1171 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-test-result.rb +113 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-test-suite-creator.rb +97 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/test-test-suite.rb +150 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/testunit-test-util.rb +31 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/ui/test_testrunmediator.rb +20 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/util/test-method-owner-finder.rb +38 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/util/test-output.rb +11 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/util/test_backtracefilter.rb +52 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/util/test_observable.rb +102 -0
- data/vendor/bundle/ruby/2.2.0/gems/test-unit-3.1.9/test/util/test_procwrapper.rb +36 -0
- data/vendor/bundle/ruby/2.2.0/specifications/colorize-0.7.7.gemspec +38 -0
- data/vendor/bundle/ruby/2.2.0/specifications/devkit-0.1.0.gemspec +46 -0
- data/vendor/bundle/ruby/2.2.0/specifications/highline-1.7.8.gemspec +37 -0
- data/vendor/bundle/ruby/2.2.0/specifications/power_assert-0.3.0.gemspec +41 -0
- data/vendor/bundle/ruby/2.2.0/specifications/rake-11.1.2.gemspec +43 -0
- data/vendor/bundle/ruby/2.2.0/specifications/test-unit-3.1.9.gemspec +47 -0
- data/win32-api.gemspec +27 -27
- metadata +345 -5
- data/lib/win32/ruby18/win32/api.so +0 -0
- data/lib/win32/ruby19/win32/api.so +0 -0
| @@ -0,0 +1,134 @@ | |
| 1 | 
            +
            module Test
         | 
| 2 | 
            +
              module Unit
         | 
| 3 | 
            +
                class Color
         | 
| 4 | 
            +
                  class Error < StandardError
         | 
| 5 | 
            +
                  end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  class ParseError < Error
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  class << self
         | 
| 11 | 
            +
                    def parse_256_color(string)
         | 
| 12 | 
            +
                      case string
         | 
| 13 | 
            +
                      when /\A([0-5])([0-5])([0-5])\z/
         | 
| 14 | 
            +
                        red, green, blue = $1, $2, $3
         | 
| 15 | 
            +
                        red.to_i * 36 + green.to_i * 6 + blue.to_i + 16
         | 
| 16 | 
            +
                      else
         | 
| 17 | 
            +
                        message = "must be 'RGB' format and R, G and B " +
         | 
| 18 | 
            +
                          "are in 0-5: #{string.inspect}"
         | 
| 19 | 
            +
                        raise ParseError, message
         | 
| 20 | 
            +
                      end
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  NAMES = ["black", "red", "green", "yellow",
         | 
| 25 | 
            +
                           "blue", "magenta", "cyan", "white"]
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  attr_reader :name
         | 
| 28 | 
            +
                  def initialize(name, options={})
         | 
| 29 | 
            +
                    @name = name
         | 
| 30 | 
            +
                    if options.has_key?(:foreground)
         | 
| 31 | 
            +
                      if options[:foreground].nil?
         | 
| 32 | 
            +
                        @background = false
         | 
| 33 | 
            +
                      else
         | 
| 34 | 
            +
                        @background = !options[:foreground]
         | 
| 35 | 
            +
                      end
         | 
| 36 | 
            +
                    else
         | 
| 37 | 
            +
                      @background = options[:background]
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                    @intensity = options[:intensity]
         | 
| 40 | 
            +
                    @bold = options[:bold]
         | 
| 41 | 
            +
                    @italic = options[:italic]
         | 
| 42 | 
            +
                    @underline = options[:underline]
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  def foreground?
         | 
| 46 | 
            +
                    not background?
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  def background?
         | 
| 50 | 
            +
                    @background
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  def intensity?
         | 
| 54 | 
            +
                    @intensity
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  def bold?
         | 
| 58 | 
            +
                    @bold
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  def italic?
         | 
| 62 | 
            +
                    @italic
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  def underline?
         | 
| 66 | 
            +
                    @underline
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                  def ==(other)
         | 
| 70 | 
            +
                    self.class === other and
         | 
| 71 | 
            +
                      [name, background?, intensity?,
         | 
| 72 | 
            +
                       bold?, italic?, underline?] ==
         | 
| 73 | 
            +
                      [other.name, other.background?, other.intensity?,
         | 
| 74 | 
            +
                       other.bold?, other.italic?, other.underline?]
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  def sequence
         | 
| 78 | 
            +
                    sequence = []
         | 
| 79 | 
            +
                    if @name == "none"
         | 
| 80 | 
            +
                    elsif @name == "reset"
         | 
| 81 | 
            +
                      sequence << "0"
         | 
| 82 | 
            +
                    else
         | 
| 83 | 
            +
                      if NAMES.include?(@name)
         | 
| 84 | 
            +
                        color_parameter = foreground? ? 3 : 4
         | 
| 85 | 
            +
                        color_parameter += 6 if intensity?
         | 
| 86 | 
            +
                        color = NAMES.index(@name)
         | 
| 87 | 
            +
                        sequence << "#{color_parameter}#{color}"
         | 
| 88 | 
            +
                      else
         | 
| 89 | 
            +
                        sequence << (foreground? ? "38" : "48")
         | 
| 90 | 
            +
                        sequence << "5"
         | 
| 91 | 
            +
                        sequence << self.class.parse_256_color(@name).to_s
         | 
| 92 | 
            +
                      end
         | 
| 93 | 
            +
                    end
         | 
| 94 | 
            +
                    sequence << "1" if bold?
         | 
| 95 | 
            +
                    sequence << "3" if italic?
         | 
| 96 | 
            +
                    sequence << "4" if underline?
         | 
| 97 | 
            +
                    sequence
         | 
| 98 | 
            +
                  end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                  def escape_sequence
         | 
| 101 | 
            +
                    "\e[#{sequence.join(';')}m"
         | 
| 102 | 
            +
                  end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                  def +(other)
         | 
| 105 | 
            +
                    MixColor.new([self, other])
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
                end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                class MixColor
         | 
| 110 | 
            +
                  attr_reader :colors
         | 
| 111 | 
            +
                  def initialize(colors)
         | 
| 112 | 
            +
                    @colors = colors
         | 
| 113 | 
            +
                  end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                  def sequence
         | 
| 116 | 
            +
                    @colors.inject([]) do |result, color|
         | 
| 117 | 
            +
                      result + color.sequence
         | 
| 118 | 
            +
                    end
         | 
| 119 | 
            +
                  end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                  def escape_sequence
         | 
| 122 | 
            +
                    "\e[#{sequence.join(';')}m"
         | 
| 123 | 
            +
                  end
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                  def +(other)
         | 
| 126 | 
            +
                    self.class.new([self, other])
         | 
| 127 | 
            +
                  end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                  def ==(other)
         | 
| 130 | 
            +
                    self.class === other and colors == other.colors
         | 
| 131 | 
            +
                  end
         | 
| 132 | 
            +
                end
         | 
| 133 | 
            +
              end
         | 
| 134 | 
            +
            end
         | 
| @@ -0,0 +1,262 @@ | |
| 1 | 
            +
            module Test
         | 
| 2 | 
            +
              module Unit
         | 
| 3 | 
            +
                module Data
         | 
| 4 | 
            +
                  class << self
         | 
| 5 | 
            +
                    def included(base)
         | 
| 6 | 
            +
                      base.extend(ClassMethods)
         | 
| 7 | 
            +
                    end
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  module ClassMethods
         | 
| 11 | 
            +
                    # This method provides Data-Driven-Test functionality.
         | 
| 12 | 
            +
                    #
         | 
| 13 | 
            +
                    # Define test data in the test code.
         | 
| 14 | 
            +
                    #
         | 
| 15 | 
            +
                    # @overload data(label, data)
         | 
| 16 | 
            +
                    #   @param [String] label specify test case name.
         | 
| 17 | 
            +
                    #   @param data specify test data.
         | 
| 18 | 
            +
                    #
         | 
| 19 | 
            +
                    #   @example data(label, data)
         | 
| 20 | 
            +
                    #     data("empty string", [true, ""])
         | 
| 21 | 
            +
                    #     data("plain string", [false, "hello"])
         | 
| 22 | 
            +
                    #     def test_empty?(data)
         | 
| 23 | 
            +
                    #       expected, target = data
         | 
| 24 | 
            +
                    #       assert_equal(expected, target.empty?)
         | 
| 25 | 
            +
                    #     end
         | 
| 26 | 
            +
                    #
         | 
| 27 | 
            +
                    # @overload data(data_set)
         | 
| 28 | 
            +
                    #   @param [Hash] data_set specify test data as a Hash that
         | 
| 29 | 
            +
                    #     key is test label and value is test data.
         | 
| 30 | 
            +
                    #
         | 
| 31 | 
            +
                    #   @example data(data_set)
         | 
| 32 | 
            +
                    #     data("empty string" => [true, ""],
         | 
| 33 | 
            +
                    #          "plain string" => [false, "hello"])
         | 
| 34 | 
            +
                    #     def test_empty?(data)
         | 
| 35 | 
            +
                    #       expected, target = data
         | 
| 36 | 
            +
                    #       assert_equal(expected, target.empty?)
         | 
| 37 | 
            +
                    #     end
         | 
| 38 | 
            +
                    #
         | 
| 39 | 
            +
                    # @overload data(&block)
         | 
| 40 | 
            +
                    #   @yieldreturn [Hash] return test data set as a Hash that
         | 
| 41 | 
            +
                    #     key is test label and value is test data.
         | 
| 42 | 
            +
                    #
         | 
| 43 | 
            +
                    #   @example data(&block)
         | 
| 44 | 
            +
                    #     data do
         | 
| 45 | 
            +
                    #       data_set = {}
         | 
| 46 | 
            +
                    #       data_set["empty string"] = [true, ""]
         | 
| 47 | 
            +
                    #       data_set["plain string"] = [false, "hello"]
         | 
| 48 | 
            +
                    #       data_set
         | 
| 49 | 
            +
                    #     end
         | 
| 50 | 
            +
                    #     def test_empty?(data)
         | 
| 51 | 
            +
                    #       expected, target = data
         | 
| 52 | 
            +
                    #       assert_equal(expected, target.empty?)
         | 
| 53 | 
            +
                    #     end
         | 
| 54 | 
            +
                    #
         | 
| 55 | 
            +
                    def data(*arguments, &block)
         | 
| 56 | 
            +
                      n_arguments = arguments.size
         | 
| 57 | 
            +
                      case n_arguments
         | 
| 58 | 
            +
                      when 0
         | 
| 59 | 
            +
                        raise ArgumentError, "no block is given" unless block_given?
         | 
| 60 | 
            +
                        data_set = block
         | 
| 61 | 
            +
                      when 1
         | 
| 62 | 
            +
                        data_set = arguments[0]
         | 
| 63 | 
            +
                      when 2
         | 
| 64 | 
            +
                        data_set = {arguments[0] => arguments[1]}
         | 
| 65 | 
            +
                      else
         | 
| 66 | 
            +
                        message = "wrong number arguments(#{n_arguments} for 1..2)"
         | 
| 67 | 
            +
                        raise ArgumentError, message
         | 
| 68 | 
            +
                      end
         | 
| 69 | 
            +
                      current_data = current_attribute(:data)[:value] || []
         | 
| 70 | 
            +
                      attribute(:data, current_data + [data_set])
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                    # This method provides Data-Driven-Test functionality.
         | 
| 74 | 
            +
                    #
         | 
| 75 | 
            +
                    # Load test data from the file. This is shorthand to load
         | 
| 76 | 
            +
                    # test data from file.  If you want to load complex file, you
         | 
| 77 | 
            +
                    # can use {#data} with block.
         | 
| 78 | 
            +
                    #
         | 
| 79 | 
            +
                    # @param [String] file_name full path to test data file.
         | 
| 80 | 
            +
                    #   File format is automatically detected from filename extension.
         | 
| 81 | 
            +
                    # @raise [ArgumentError] if +file_name+ is not supported file format.
         | 
| 82 | 
            +
                    # @see Loader#load
         | 
| 83 | 
            +
                    #
         | 
| 84 | 
            +
                    # @example Load data from CSV file
         | 
| 85 | 
            +
                    #   load_data("/path/to/test-data.csv")
         | 
| 86 | 
            +
                    #   def test_empty?(data)
         | 
| 87 | 
            +
                    #     assert_equal(data["expected"], data["target"].empty?)
         | 
| 88 | 
            +
                    #   end
         | 
| 89 | 
            +
                    #
         | 
| 90 | 
            +
                    def load_data(file_name)
         | 
| 91 | 
            +
                      loader = Loader.new(self)
         | 
| 92 | 
            +
                      loader.load(file_name)
         | 
| 93 | 
            +
                    end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                    class Loader
         | 
| 96 | 
            +
                      # @api private
         | 
| 97 | 
            +
                      def initialize(test_case)
         | 
| 98 | 
            +
                        @test_case = test_case
         | 
| 99 | 
            +
                      end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                      # Load data from file.
         | 
| 102 | 
            +
                      #
         | 
| 103 | 
            +
                      # @param [String] file_name full path to test data file.
         | 
| 104 | 
            +
                      #   File format is automatically detected from filename extension.
         | 
| 105 | 
            +
                      # @raise [ArgumentError] if +file_name+ is not supported file format.
         | 
| 106 | 
            +
                      # @see #load_csv
         | 
| 107 | 
            +
                      # @see #load_tsv
         | 
| 108 | 
            +
                      # @api private
         | 
| 109 | 
            +
                      def load(file_name)
         | 
| 110 | 
            +
                        case File.extname(file_name).downcase
         | 
| 111 | 
            +
                        when ".csv"
         | 
| 112 | 
            +
                          load_csv(file_name)
         | 
| 113 | 
            +
                        when ".tsv"
         | 
| 114 | 
            +
                          load_tsv(file_name)
         | 
| 115 | 
            +
                        else
         | 
| 116 | 
            +
                          raise ArgumentError, "unsupported file format: <#{file_name}>"
         | 
| 117 | 
            +
                        end
         | 
| 118 | 
            +
                      end
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                      # Load data from CSV file.
         | 
| 121 | 
            +
                      #
         | 
| 122 | 
            +
                      # There are 2 types of CSV file as following examples.
         | 
| 123 | 
            +
                      # First, there is a header on first row and it's first column is "label".
         | 
| 124 | 
            +
                      # Another, there is no header in the file.
         | 
| 125 | 
            +
                      #
         | 
| 126 | 
            +
                      # @example Load data from CSV file with header
         | 
| 127 | 
            +
                      #   # test-data.csv:
         | 
| 128 | 
            +
                      #   #  label,expected,target
         | 
| 129 | 
            +
                      #   #  empty string,true,""
         | 
| 130 | 
            +
                      #   #  plain string,false,hello
         | 
| 131 | 
            +
                      #   #
         | 
| 132 | 
            +
                      #   load_data("/path/to/test-data.csv")
         | 
| 133 | 
            +
                      #   def test_empty?(data)
         | 
| 134 | 
            +
                      #     assert_equal(data["expected"], data["target"].empty?)
         | 
| 135 | 
            +
                      #   end
         | 
| 136 | 
            +
                      #
         | 
| 137 | 
            +
                      # @example Load data from CSV file without header
         | 
| 138 | 
            +
                      #   # test-data-without-header.csv:
         | 
| 139 | 
            +
                      #   #  empty string,true,""
         | 
| 140 | 
            +
                      #   #  plain string,false,hello
         | 
| 141 | 
            +
                      #   #
         | 
| 142 | 
            +
                      #   load_data("/path/to/test-data-without-header.csv")
         | 
| 143 | 
            +
                      #   def test_empty?(data)
         | 
| 144 | 
            +
                      #     expected, target = data
         | 
| 145 | 
            +
                      #     assert_equal(expected, target.empty?)
         | 
| 146 | 
            +
                      #   end
         | 
| 147 | 
            +
                      #
         | 
| 148 | 
            +
                      # @api private
         | 
| 149 | 
            +
                      def load_csv(file_name)
         | 
| 150 | 
            +
                        require 'csv'
         | 
| 151 | 
            +
                        first_row = true
         | 
| 152 | 
            +
                        header = nil
         | 
| 153 | 
            +
                        CSV.foreach(file_name) do |row|
         | 
| 154 | 
            +
                          if first_row
         | 
| 155 | 
            +
                            first_row = false
         | 
| 156 | 
            +
                            if row.first == "label"
         | 
| 157 | 
            +
                              header = row[1..-1]
         | 
| 158 | 
            +
                              next
         | 
| 159 | 
            +
                            end
         | 
| 160 | 
            +
                          end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                          set_test_data(header, row)
         | 
| 163 | 
            +
                        end
         | 
| 164 | 
            +
                      end
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                      # Load data from TSV file.
         | 
| 167 | 
            +
                      #
         | 
| 168 | 
            +
                      # There are 2 types of TSV file as following examples.
         | 
| 169 | 
            +
                      # First, there is a header on first row and it's first column is "label".
         | 
| 170 | 
            +
                      # Another, there is no header in the file.
         | 
| 171 | 
            +
                      #
         | 
| 172 | 
            +
                      # @example Load data from TSV file with header
         | 
| 173 | 
            +
                      #   # test-data.tsv:
         | 
| 174 | 
            +
                      #   #  label	expected	target
         | 
| 175 | 
            +
                      #   #  empty string	true	""
         | 
| 176 | 
            +
                      #   #  plain string	false	hello
         | 
| 177 | 
            +
                      #   #
         | 
| 178 | 
            +
                      #   load_data("/path/to/test-data.tsv")
         | 
| 179 | 
            +
                      #   def test_empty?(data)
         | 
| 180 | 
            +
                      #     assert_equal(data["expected"], data["target"].empty?)
         | 
| 181 | 
            +
                      #   end
         | 
| 182 | 
            +
                      #
         | 
| 183 | 
            +
                      # @example Load data from TSV file without header
         | 
| 184 | 
            +
                      #   # test-data-without-header.tsv:
         | 
| 185 | 
            +
                      #   #  empty string	true	""
         | 
| 186 | 
            +
                      #   #  plain string	false	hello
         | 
| 187 | 
            +
                      #   #
         | 
| 188 | 
            +
                      #   load_data("/path/to/test-data-without-header.tsv")
         | 
| 189 | 
            +
                      #   def test_empty?(data)
         | 
| 190 | 
            +
                      #     expected, target = data
         | 
| 191 | 
            +
                      #     assert_equal(expected, target.empty?)
         | 
| 192 | 
            +
                      #   end
         | 
| 193 | 
            +
                      #
         | 
| 194 | 
            +
                      # @api private
         | 
| 195 | 
            +
                      def load_tsv(file_name)
         | 
| 196 | 
            +
                        require "csv"
         | 
| 197 | 
            +
                        if CSV.const_defined?(:VERSION)
         | 
| 198 | 
            +
                          first_row = true
         | 
| 199 | 
            +
                          header = nil
         | 
| 200 | 
            +
                          CSV.foreach(file_name, :col_sep => "\t") do |row|
         | 
| 201 | 
            +
                            if first_row
         | 
| 202 | 
            +
                              first_row = false
         | 
| 203 | 
            +
                              if row.first == "label"
         | 
| 204 | 
            +
                                header = row[1..-1]
         | 
| 205 | 
            +
                                next
         | 
| 206 | 
            +
                              end
         | 
| 207 | 
            +
                            end
         | 
| 208 | 
            +
             | 
| 209 | 
            +
                            set_test_data(header, row)
         | 
| 210 | 
            +
                          end
         | 
| 211 | 
            +
                        else
         | 
| 212 | 
            +
                          # for old CSV library
         | 
| 213 | 
            +
                          first_row = true
         | 
| 214 | 
            +
                          header = nil
         | 
| 215 | 
            +
                          CSV.open(file_name, "r", "\t") do |row|
         | 
| 216 | 
            +
                            if first_row
         | 
| 217 | 
            +
                              first_row = false
         | 
| 218 | 
            +
                              if row.first == "label"
         | 
| 219 | 
            +
                                header = row[1..-1]
         | 
| 220 | 
            +
                                next
         | 
| 221 | 
            +
                              end
         | 
| 222 | 
            +
                            end
         | 
| 223 | 
            +
             | 
| 224 | 
            +
                            set_test_data(header, row)
         | 
| 225 | 
            +
                          end
         | 
| 226 | 
            +
                        end
         | 
| 227 | 
            +
                      end
         | 
| 228 | 
            +
             | 
| 229 | 
            +
                      private
         | 
| 230 | 
            +
                      def normalize_value(value)
         | 
| 231 | 
            +
                        return true if value == "true"
         | 
| 232 | 
            +
                        return false if value == "false"
         | 
| 233 | 
            +
                        begin
         | 
| 234 | 
            +
                          Integer(value)
         | 
| 235 | 
            +
                        rescue ArgumentError
         | 
| 236 | 
            +
                          begin
         | 
| 237 | 
            +
                            Float(value)
         | 
| 238 | 
            +
                          rescue ArgumentError
         | 
| 239 | 
            +
                            value
         | 
| 240 | 
            +
                          end
         | 
| 241 | 
            +
                        end
         | 
| 242 | 
            +
                      end
         | 
| 243 | 
            +
             | 
| 244 | 
            +
                      def set_test_data(header, row)
         | 
| 245 | 
            +
                        label = row.shift
         | 
| 246 | 
            +
                        if header
         | 
| 247 | 
            +
                          data = {}
         | 
| 248 | 
            +
                          header.each_with_index do |key, i|
         | 
| 249 | 
            +
                            data[key] = normalize_value(row[i])
         | 
| 250 | 
            +
                          end
         | 
| 251 | 
            +
                        else
         | 
| 252 | 
            +
                          data = row.collect do |cell|
         | 
| 253 | 
            +
                            normalize_value(cell)
         | 
| 254 | 
            +
                          end
         | 
| 255 | 
            +
                        end
         | 
| 256 | 
            +
                        @test_case.data(label, data)
         | 
| 257 | 
            +
                      end
         | 
| 258 | 
            +
                    end
         | 
| 259 | 
            +
                  end
         | 
| 260 | 
            +
                end
         | 
| 261 | 
            +
              end
         | 
| 262 | 
            +
            end
         | 
| @@ -0,0 +1,746 @@ | |
| 1 | 
            +
            # port of Python's difflib.
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # Copyright (c) 2001-2008 Python Software Foundation; All Rights Reserved
         | 
| 4 | 
            +
            # Copyright (c) 2008-2011 Kouhei Sutou; All Rights Reserved
         | 
| 5 | 
            +
            #
         | 
| 6 | 
            +
            # It is free software, and is distributed under the Ruby
         | 
| 7 | 
            +
            # license and/or the PSF license. See the COPYING file and
         | 
| 8 | 
            +
            # PSFL file.
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            module Test
         | 
| 11 | 
            +
              module Unit
         | 
| 12 | 
            +
                module Diff
         | 
| 13 | 
            +
                  class SequenceMatcher
         | 
| 14 | 
            +
                    def initialize(from, to, &junk_predicate)
         | 
| 15 | 
            +
                      @from = from
         | 
| 16 | 
            +
                      @to = to
         | 
| 17 | 
            +
                      @junk_predicate = junk_predicate
         | 
| 18 | 
            +
                      update_to_indexes
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    def longest_match(from_start, from_end, to_start, to_end)
         | 
| 22 | 
            +
                      best_info = find_best_match_position(from_start, from_end,
         | 
| 23 | 
            +
                                                           to_start, to_end)
         | 
| 24 | 
            +
                      unless @junks.empty?
         | 
| 25 | 
            +
                        args = [from_start, from_end, to_start, to_end]
         | 
| 26 | 
            +
                        best_info = adjust_best_info_with_junk_predicate(false, best_info,
         | 
| 27 | 
            +
                                                                         *args)
         | 
| 28 | 
            +
                        best_info = adjust_best_info_with_junk_predicate(true, best_info,
         | 
| 29 | 
            +
                                                                         *args)
         | 
| 30 | 
            +
                      end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                      best_info
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    def blocks
         | 
| 36 | 
            +
                      @blocks ||= compute_blocks
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    def operations
         | 
| 40 | 
            +
                      @operations ||= compute_operations
         | 
| 41 | 
            +
                    end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                    def grouped_operations(context_size=nil)
         | 
| 44 | 
            +
                      context_size ||= 3
         | 
| 45 | 
            +
                      _operations = operations.dup
         | 
| 46 | 
            +
                      _operations = [[:equal, 0, 0, 0, 0]] if _operations.empty?
         | 
| 47 | 
            +
                      expand_edge_equal_operations!(_operations, context_size)
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                      group_window = context_size * 2
         | 
| 50 | 
            +
                      groups = []
         | 
| 51 | 
            +
                      group = []
         | 
| 52 | 
            +
                      _operations.each do |tag, from_start, from_end, to_start, to_end|
         | 
| 53 | 
            +
                        if tag == :equal and from_end - from_start > group_window
         | 
| 54 | 
            +
                          group << [tag,
         | 
| 55 | 
            +
                                    from_start,
         | 
| 56 | 
            +
                                    [from_end, from_start + context_size].min,
         | 
| 57 | 
            +
                                    to_start,
         | 
| 58 | 
            +
                                    [to_end, to_start + context_size].min]
         | 
| 59 | 
            +
                          groups << group
         | 
| 60 | 
            +
                          group = []
         | 
| 61 | 
            +
                          from_start = [from_start, from_end - context_size].max
         | 
| 62 | 
            +
                          to_start = [to_start, to_end - context_size].max
         | 
| 63 | 
            +
                        end
         | 
| 64 | 
            +
                        group << [tag, from_start, from_end, to_start, to_end]
         | 
| 65 | 
            +
                      end
         | 
| 66 | 
            +
                      groups << group unless group.empty?
         | 
| 67 | 
            +
                      groups
         | 
| 68 | 
            +
                    end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                    def ratio
         | 
| 71 | 
            +
                      @ratio ||= compute_ratio
         | 
| 72 | 
            +
                    end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                    private
         | 
| 75 | 
            +
                    def update_to_indexes
         | 
| 76 | 
            +
                      @to_indexes = {}
         | 
| 77 | 
            +
                      @junks = {}
         | 
| 78 | 
            +
                      if @to.is_a?(String)
         | 
| 79 | 
            +
                        each = " "[0].is_a?(Integer) ? :each_byte : :each_char
         | 
| 80 | 
            +
                      else
         | 
| 81 | 
            +
                        each = :each
         | 
| 82 | 
            +
                      end
         | 
| 83 | 
            +
                      i = 0
         | 
| 84 | 
            +
                      @to.__send__(each) do |item|
         | 
| 85 | 
            +
                        @to_indexes[item] ||= []
         | 
| 86 | 
            +
                        @to_indexes[item] << i
         | 
| 87 | 
            +
                        i += 1
         | 
| 88 | 
            +
                      end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                      return if @junk_predicate.nil?
         | 
| 91 | 
            +
                      @to_indexes = @to_indexes.reject do |key, value|
         | 
| 92 | 
            +
                        junk = @junk_predicate.call(key)
         | 
| 93 | 
            +
                        @junks[key] = true if junk
         | 
| 94 | 
            +
                        junk
         | 
| 95 | 
            +
                      end
         | 
| 96 | 
            +
                    end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                    def find_best_match_position(from_start, from_end, to_start, to_end)
         | 
| 99 | 
            +
                      best_from, best_to, best_size = from_start, to_start, 0
         | 
| 100 | 
            +
                      sizes = {}
         | 
| 101 | 
            +
                      from_start.upto(from_end) do |from_index|
         | 
| 102 | 
            +
                        _sizes = {}
         | 
| 103 | 
            +
                        (@to_indexes[@from[from_index]] || []).each do |to_index|
         | 
| 104 | 
            +
                          next if to_index < to_start
         | 
| 105 | 
            +
                          break if to_index > to_end
         | 
| 106 | 
            +
                          size = _sizes[to_index] = (sizes[to_index - 1] || 0) + 1
         | 
| 107 | 
            +
                          if size > best_size
         | 
| 108 | 
            +
                            best_from = from_index - size + 1
         | 
| 109 | 
            +
                            best_to = to_index - size + 1
         | 
| 110 | 
            +
                            best_size = size
         | 
| 111 | 
            +
                          end
         | 
| 112 | 
            +
                        end
         | 
| 113 | 
            +
                        sizes = _sizes
         | 
| 114 | 
            +
                      end
         | 
| 115 | 
            +
                      [best_from, best_to, best_size]
         | 
| 116 | 
            +
                    end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                    def adjust_best_info_with_junk_predicate(should_junk, best_info,
         | 
| 119 | 
            +
                                                             from_start, from_end,
         | 
| 120 | 
            +
                                                             to_start, to_end)
         | 
| 121 | 
            +
                      best_from, best_to, best_size = best_info
         | 
| 122 | 
            +
                      while best_from > from_start and best_to > to_start and
         | 
| 123 | 
            +
                          (should_junk ?
         | 
| 124 | 
            +
                           @junks.has_key?(@to[best_to - 1]) :
         | 
| 125 | 
            +
                           !@junks.has_key?(@to[best_to - 1])) and
         | 
| 126 | 
            +
                          @from[best_from - 1] == @to[best_to - 1]
         | 
| 127 | 
            +
                        best_from -= 1
         | 
| 128 | 
            +
                        best_to -= 1
         | 
| 129 | 
            +
                        best_size += 1
         | 
| 130 | 
            +
                      end
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                      while best_from + best_size < from_end and
         | 
| 133 | 
            +
                          best_to + best_size < to_end and
         | 
| 134 | 
            +
                          (should_junk ?
         | 
| 135 | 
            +
                           @junks.has_key?(@to[best_to + best_size]) :
         | 
| 136 | 
            +
                           !@junks.has_key?(@to[best_to + best_size])) and
         | 
| 137 | 
            +
                          @from[best_from + best_size] == @to[best_to + best_size]
         | 
| 138 | 
            +
                        best_size += 1
         | 
| 139 | 
            +
                      end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                      [best_from, best_to, best_size]
         | 
| 142 | 
            +
                    end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                    def matches
         | 
| 145 | 
            +
                      @matches ||= compute_matches
         | 
| 146 | 
            +
                    end
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                    def compute_matches
         | 
| 149 | 
            +
                      matches = []
         | 
| 150 | 
            +
                      queue = [[0, @from.size, 0, @to.size]]
         | 
| 151 | 
            +
                      until queue.empty?
         | 
| 152 | 
            +
                        from_start, from_end, to_start, to_end = queue.pop
         | 
| 153 | 
            +
                        match = longest_match(from_start, from_end - 1, to_start, to_end - 1)
         | 
| 154 | 
            +
                        match_from_index, match_to_index, size = match
         | 
| 155 | 
            +
                        unless size.zero?
         | 
| 156 | 
            +
                          if from_start < match_from_index and
         | 
| 157 | 
            +
                              to_start < match_to_index
         | 
| 158 | 
            +
                            queue.push([from_start, match_from_index,
         | 
| 159 | 
            +
                                        to_start, match_to_index])
         | 
| 160 | 
            +
                          end
         | 
| 161 | 
            +
                          matches << match
         | 
| 162 | 
            +
                          if match_from_index + size < from_end and
         | 
| 163 | 
            +
                              match_to_index + size < to_end
         | 
| 164 | 
            +
                            queue.push([match_from_index + size, from_end,
         | 
| 165 | 
            +
                                        match_to_index + size, to_end])
         | 
| 166 | 
            +
                          end
         | 
| 167 | 
            +
                        end
         | 
| 168 | 
            +
                      end
         | 
| 169 | 
            +
                      matches.sort_by do |(from_index, _, _)|
         | 
| 170 | 
            +
                        from_index
         | 
| 171 | 
            +
                      end
         | 
| 172 | 
            +
                    end
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                    def compute_blocks
         | 
| 175 | 
            +
                      blocks = []
         | 
| 176 | 
            +
                      current_from_index = current_to_index = current_size = 0
         | 
| 177 | 
            +
                      matches.each do |from_index, to_index, size|
         | 
| 178 | 
            +
                        if current_from_index + current_size == from_index and
         | 
| 179 | 
            +
                            current_to_index + current_size == to_index
         | 
| 180 | 
            +
                          current_size += size
         | 
| 181 | 
            +
                        else
         | 
| 182 | 
            +
                          unless current_size.zero?
         | 
| 183 | 
            +
                            blocks << [current_from_index, current_to_index, current_size]
         | 
| 184 | 
            +
                          end
         | 
| 185 | 
            +
                          current_from_index = from_index
         | 
| 186 | 
            +
                          current_to_index = to_index
         | 
| 187 | 
            +
                          current_size = size
         | 
| 188 | 
            +
                        end
         | 
| 189 | 
            +
                      end
         | 
| 190 | 
            +
                      unless current_size.zero?
         | 
| 191 | 
            +
                        blocks << [current_from_index, current_to_index, current_size]
         | 
| 192 | 
            +
                      end
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                      blocks << [@from.size, @to.size, 0]
         | 
| 195 | 
            +
                      blocks
         | 
| 196 | 
            +
                    end
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                    def compute_operations
         | 
| 199 | 
            +
                      from_index = to_index = 0
         | 
| 200 | 
            +
                      operations = []
         | 
| 201 | 
            +
                      blocks.each do |match_from_index, match_to_index, size|
         | 
| 202 | 
            +
                        tag = determine_tag(from_index, to_index,
         | 
| 203 | 
            +
                                            match_from_index, match_to_index)
         | 
| 204 | 
            +
                        if tag != :equal
         | 
| 205 | 
            +
                          operations << [tag,
         | 
| 206 | 
            +
                                         from_index, match_from_index,
         | 
| 207 | 
            +
                                         to_index, match_to_index]
         | 
| 208 | 
            +
                        end
         | 
| 209 | 
            +
             | 
| 210 | 
            +
                        from_index, to_index = match_from_index + size, match_to_index + size
         | 
| 211 | 
            +
                        if size > 0
         | 
| 212 | 
            +
                          operations << [:equal,
         | 
| 213 | 
            +
                                         match_from_index, from_index,
         | 
| 214 | 
            +
                                         match_to_index, to_index]
         | 
| 215 | 
            +
                        end
         | 
| 216 | 
            +
                      end
         | 
| 217 | 
            +
                      operations
         | 
| 218 | 
            +
                    end
         | 
| 219 | 
            +
             | 
| 220 | 
            +
                    def compute_ratio
         | 
| 221 | 
            +
                      matches = blocks.inject(0) {|result, block| result + block[-1]}
         | 
| 222 | 
            +
                      length = @from.length + @to.length
         | 
| 223 | 
            +
                      if length.zero?
         | 
| 224 | 
            +
                        1.0
         | 
| 225 | 
            +
                      else
         | 
| 226 | 
            +
                        2.0 * matches / length
         | 
| 227 | 
            +
                      end
         | 
| 228 | 
            +
                    end
         | 
| 229 | 
            +
             | 
| 230 | 
            +
                    def determine_tag(from_index, to_index,
         | 
| 231 | 
            +
                                      match_from_index, match_to_index)
         | 
| 232 | 
            +
                      if from_index < match_from_index and to_index < match_to_index
         | 
| 233 | 
            +
                        :replace
         | 
| 234 | 
            +
                      elsif from_index < match_from_index
         | 
| 235 | 
            +
                        :delete
         | 
| 236 | 
            +
                      elsif to_index < match_to_index
         | 
| 237 | 
            +
                        :insert
         | 
| 238 | 
            +
                      else
         | 
| 239 | 
            +
                        :equal
         | 
| 240 | 
            +
                      end
         | 
| 241 | 
            +
                    end
         | 
| 242 | 
            +
             | 
| 243 | 
            +
                    def expand_edge_equal_operations!(_operations, context_size)
         | 
| 244 | 
            +
                      tag, from_start, from_end, to_start, to_end = _operations[0]
         | 
| 245 | 
            +
                      if tag == :equal
         | 
| 246 | 
            +
                        _operations[0] = [tag,
         | 
| 247 | 
            +
                                          [from_start, from_end - context_size].max,
         | 
| 248 | 
            +
                                          from_end,
         | 
| 249 | 
            +
                                          [to_start, to_end - context_size].max,
         | 
| 250 | 
            +
                                          to_end]
         | 
| 251 | 
            +
                      end
         | 
| 252 | 
            +
             | 
| 253 | 
            +
                      tag, from_start, from_end, to_start, to_end = _operations[-1]
         | 
| 254 | 
            +
                      if tag == :equal
         | 
| 255 | 
            +
                        _operations[-1] = [tag,
         | 
| 256 | 
            +
                                           from_start,
         | 
| 257 | 
            +
                                           [from_end, from_start + context_size].min,
         | 
| 258 | 
            +
                                           to_start,
         | 
| 259 | 
            +
                                           [to_end, to_start + context_size].min]
         | 
| 260 | 
            +
                      end
         | 
| 261 | 
            +
                    end
         | 
| 262 | 
            +
                  end
         | 
| 263 | 
            +
             | 
| 264 | 
            +
                  class Differ
         | 
| 265 | 
            +
                    def initialize(from, to)
         | 
| 266 | 
            +
                      @from = from
         | 
| 267 | 
            +
                      @to = to
         | 
| 268 | 
            +
                    end
         | 
| 269 | 
            +
             | 
| 270 | 
            +
                    private
         | 
| 271 | 
            +
                    def tag(mark, contents)
         | 
| 272 | 
            +
                      contents.collect {|content| "#{mark}#{content}"}
         | 
| 273 | 
            +
                    end
         | 
| 274 | 
            +
                  end
         | 
| 275 | 
            +
             | 
| 276 | 
            +
                  class UTF8Line
         | 
| 277 | 
            +
                    class << self
         | 
| 278 | 
            +
                      # from http://unicode.org/reports/tr11/
         | 
| 279 | 
            +
                      WIDE_CHARACTERS =
         | 
| 280 | 
            +
                        [0x1100..0x1159, 0x115F..0x115F, 0x2329..0x232A,
         | 
| 281 | 
            +
                         0x2E80..0x2E99, 0x2E9B..0x2EF3, 0x2F00..0x2FD5,
         | 
| 282 | 
            +
                         0x2FF0..0x2FFB, 0x3000..0x303E, 0x3041..0x3096,
         | 
| 283 | 
            +
                         0x3099..0x30FF, 0x3105..0x312D, 0x3131..0x318E,
         | 
| 284 | 
            +
                         0x3190..0x31B7, 0x31C0..0x31E3, 0x31F0..0x321E,
         | 
| 285 | 
            +
                         0x3220..0x3243, 0x3250..0x32FE, 0x3300..0x4DB5,
         | 
| 286 | 
            +
                         0x4E00..0x9FC3, 0xA000..0xA48C, 0xA490..0xA4C6,
         | 
| 287 | 
            +
                         0xAC00..0xD7A3, 0xF900..0xFA2D, 0xFA30..0xFA6A,
         | 
| 288 | 
            +
                         0xFA70..0xFAD9, 0xFE10..0xFE19, 0xFE30..0xFE52,
         | 
| 289 | 
            +
                         0xFE54..0xFE66, 0xFE68..0xFE6B, 0xFF01..0xFF60,
         | 
| 290 | 
            +
                         0xFFE0..0xFFE6, 0x20000..0x2FFFD, 0x30000..0x3FFFD,
         | 
| 291 | 
            +
                        ]
         | 
| 292 | 
            +
             | 
| 293 | 
            +
                      AMBIGUOUS =
         | 
| 294 | 
            +
                        [0x00A1..0x00A1, 0x00A4..0x00A4, 0x00A7..0x00A8,
         | 
| 295 | 
            +
                         0x00AA..0x00AA, 0x00AD..0x00AE, 0x00B0..0x00B4,
         | 
| 296 | 
            +
                         0x00B6..0x00BA, 0x00BC..0x00BF, 0x00C6..0x00C6,
         | 
| 297 | 
            +
                         0x00D0..0x00D0, 0x00D7..0x00D8, 0x00DE..0x00E1,
         | 
| 298 | 
            +
                         0x00E6..0x00E6, 0x00E8..0x00EA, 0x00EC..0x00ED,
         | 
| 299 | 
            +
                         0x00F0..0x00F0, 0x00F2..0x00F3, 0x00F7..0x00FA,
         | 
| 300 | 
            +
                         0x00FC..0x00FC, 0x00FE..0x00FE, 0x0101..0x0101,
         | 
| 301 | 
            +
                         0x0111..0x0111, 0x0113..0x0113, 0x011B..0x011B,
         | 
| 302 | 
            +
                         0x0126..0x0127, 0x012B..0x012B, 0x0131..0x0133,
         | 
| 303 | 
            +
                         0x0138..0x0138, 0x013F..0x0142, 0x0144..0x0144,
         | 
| 304 | 
            +
                         0x0148..0x014B, 0x014D..0x014D, 0x0152..0x0153,
         | 
| 305 | 
            +
                         0x0166..0x0167, 0x016B..0x016B, 0x01CE..0x01CE,
         | 
| 306 | 
            +
                         0x01D0..0x01D0, 0x01D2..0x01D2, 0x01D4..0x01D4,
         | 
| 307 | 
            +
                         0x01D6..0x01D6, 0x01D8..0x01D8, 0x01DA..0x01DA,
         | 
| 308 | 
            +
                         0x01DC..0x01DC, 0x0251..0x0251, 0x0261..0x0261,
         | 
| 309 | 
            +
                         0x02C4..0x02C4, 0x02C7..0x02C7, 0x02C9..0x02CB,
         | 
| 310 | 
            +
                         0x02CD..0x02CD, 0x02D0..0x02D0, 0x02D8..0x02DB,
         | 
| 311 | 
            +
                         0x02DD..0x02DD, 0x02DF..0x02DF, 0x0300..0x036F,
         | 
| 312 | 
            +
                         0x0391..0x03A1, 0x03A3..0x03A9, 0x03B1..0x03C1,
         | 
| 313 | 
            +
                         0x03C3..0x03C9, 0x0401..0x0401, 0x0410..0x044F,
         | 
| 314 | 
            +
                         0x0451..0x0451, 0x2010..0x2010, 0x2013..0x2016,
         | 
| 315 | 
            +
                         0x2018..0x2019, 0x201C..0x201D, 0x2020..0x2022,
         | 
| 316 | 
            +
                         0x2024..0x2027, 0x2030..0x2030, 0x2032..0x2033,
         | 
| 317 | 
            +
                         0x2035..0x2035, 0x203B..0x203B, 0x203E..0x203E,
         | 
| 318 | 
            +
                         0x2074..0x2074, 0x207F..0x207F, 0x2081..0x2084,
         | 
| 319 | 
            +
                         0x20AC..0x20AC, 0x2103..0x2103, 0x2105..0x2105,
         | 
| 320 | 
            +
                         0x2109..0x2109, 0x2113..0x2113, 0x2116..0x2116,
         | 
| 321 | 
            +
                         0x2121..0x2122, 0x2126..0x2126, 0x212B..0x212B,
         | 
| 322 | 
            +
                         0x2153..0x2154, 0x215B..0x215E, 0x2160..0x216B,
         | 
| 323 | 
            +
                         0x2170..0x2179, 0x2190..0x2199, 0x21B8..0x21B9,
         | 
| 324 | 
            +
                         0x21D2..0x21D2, 0x21D4..0x21D4, 0x21E7..0x21E7,
         | 
| 325 | 
            +
                         0x2200..0x2200, 0x2202..0x2203, 0x2207..0x2208,
         | 
| 326 | 
            +
                         0x220B..0x220B, 0x220F..0x220F, 0x2211..0x2211,
         | 
| 327 | 
            +
                         0x2215..0x2215, 0x221A..0x221A, 0x221D..0x2220,
         | 
| 328 | 
            +
                         0x2223..0x2223, 0x2225..0x2225, 0x2227..0x222C,
         | 
| 329 | 
            +
                         0x222E..0x222E, 0x2234..0x2237, 0x223C..0x223D,
         | 
| 330 | 
            +
                         0x2248..0x2248, 0x224C..0x224C, 0x2252..0x2252,
         | 
| 331 | 
            +
                         0x2260..0x2261, 0x2264..0x2267, 0x226A..0x226B,
         | 
| 332 | 
            +
                         0x226E..0x226F, 0x2282..0x2283, 0x2286..0x2287,
         | 
| 333 | 
            +
                         0x2295..0x2295, 0x2299..0x2299, 0x22A5..0x22A5,
         | 
| 334 | 
            +
                         0x22BF..0x22BF, 0x2312..0x2312, 0x2460..0x24E9,
         | 
| 335 | 
            +
                         0x24EB..0x254B, 0x2550..0x2573, 0x2580..0x258F,
         | 
| 336 | 
            +
                         0x2592..0x2595, 0x25A0..0x25A1, 0x25A3..0x25A9,
         | 
| 337 | 
            +
                         0x25B2..0x25B3, 0x25B6..0x25B7, 0x25BC..0x25BD,
         | 
| 338 | 
            +
                         0x25C0..0x25C1, 0x25C6..0x25C8, 0x25CB..0x25CB,
         | 
| 339 | 
            +
                         0x25CE..0x25D1, 0x25E2..0x25E5, 0x25EF..0x25EF,
         | 
| 340 | 
            +
                         0x2605..0x2606, 0x2609..0x2609, 0x260E..0x260F,
         | 
| 341 | 
            +
                         0x2614..0x2615, 0x261C..0x261C, 0x261E..0x261E,
         | 
| 342 | 
            +
                         0x2640..0x2640, 0x2642..0x2642, 0x2660..0x2661,
         | 
| 343 | 
            +
                         0x2663..0x2665, 0x2667..0x266A, 0x266C..0x266D,
         | 
| 344 | 
            +
                         0x266F..0x266F, 0x273D..0x273D, 0x2776..0x277F,
         | 
| 345 | 
            +
                         0xE000..0xF8FF, 0xFE00..0xFE0F, 0xFFFD..0xFFFD,
         | 
| 346 | 
            +
                         0xE0100..0xE01EF, 0xF0000..0xFFFFD, 0x100000..0x10FFFD,
         | 
| 347 | 
            +
                        ]
         | 
| 348 | 
            +
             | 
| 349 | 
            +
                      def wide_character?(character)
         | 
| 350 | 
            +
                        binary_search_ranges(character, WIDE_CHARACTERS) or
         | 
| 351 | 
            +
                          binary_search_ranges(character, AMBIGUOUS)
         | 
| 352 | 
            +
                      end
         | 
| 353 | 
            +
             | 
| 354 | 
            +
                      private
         | 
| 355 | 
            +
                      def binary_search_ranges(character, ranges)
         | 
| 356 | 
            +
                        if ranges.size.zero?
         | 
| 357 | 
            +
                          false
         | 
| 358 | 
            +
                        elsif ranges.size == 1
         | 
| 359 | 
            +
                          ranges[0].include?(character)
         | 
| 360 | 
            +
                        else
         | 
| 361 | 
            +
                          half = ranges.size / 2
         | 
| 362 | 
            +
                          range = ranges[half]
         | 
| 363 | 
            +
                          if range.include?(character)
         | 
| 364 | 
            +
                            true
         | 
| 365 | 
            +
                          elsif character < range.begin
         | 
| 366 | 
            +
                            binary_search_ranges(character, ranges[0...half])
         | 
| 367 | 
            +
                          else
         | 
| 368 | 
            +
                            binary_search_ranges(character, ranges[(half + 1)..-1])
         | 
| 369 | 
            +
                          end
         | 
| 370 | 
            +
                        end
         | 
| 371 | 
            +
                      end
         | 
| 372 | 
            +
                    end
         | 
| 373 | 
            +
             | 
| 374 | 
            +
                    def initialize(line)
         | 
| 375 | 
            +
                      @line = line
         | 
| 376 | 
            +
                      @characters = @line.unpack("U*")
         | 
| 377 | 
            +
                    end
         | 
| 378 | 
            +
             | 
| 379 | 
            +
                    def [](*args)
         | 
| 380 | 
            +
                      result = @characters[*args]
         | 
| 381 | 
            +
                      if result.respond_to?(:pack)
         | 
| 382 | 
            +
                        result.pack("U*")
         | 
| 383 | 
            +
                      else
         | 
| 384 | 
            +
                        result
         | 
| 385 | 
            +
                      end
         | 
| 386 | 
            +
                    end
         | 
| 387 | 
            +
             | 
| 388 | 
            +
                    def each(&block)
         | 
| 389 | 
            +
                      @characters.each(&block)
         | 
| 390 | 
            +
                    end
         | 
| 391 | 
            +
             | 
| 392 | 
            +
                    def size
         | 
| 393 | 
            +
                      @characters.size
         | 
| 394 | 
            +
                    end
         | 
| 395 | 
            +
             | 
| 396 | 
            +
                    def to_s
         | 
| 397 | 
            +
                      @line
         | 
| 398 | 
            +
                    end
         | 
| 399 | 
            +
             | 
| 400 | 
            +
                    def compute_width(start, _end)
         | 
| 401 | 
            +
                      width = 0
         | 
| 402 | 
            +
                      start.upto(_end - 1) do |i|
         | 
| 403 | 
            +
                        if self.class.wide_character?(@characters[i])
         | 
| 404 | 
            +
                          width += 2
         | 
| 405 | 
            +
                        else
         | 
| 406 | 
            +
                          width += 1
         | 
| 407 | 
            +
                        end
         | 
| 408 | 
            +
                      end
         | 
| 409 | 
            +
                      width
         | 
| 410 | 
            +
                    end
         | 
| 411 | 
            +
                  end
         | 
| 412 | 
            +
             | 
| 413 | 
            +
                  class ReadableDiffer < Differ
         | 
| 414 | 
            +
                    def diff(options={})
         | 
| 415 | 
            +
                      @result = []
         | 
| 416 | 
            +
                      operations.each do |tag, from_start, from_end, to_start, to_end|
         | 
| 417 | 
            +
                        case tag
         | 
| 418 | 
            +
                        when :replace
         | 
| 419 | 
            +
                          diff_lines(from_start, from_end, to_start, to_end)
         | 
| 420 | 
            +
                        when :delete
         | 
| 421 | 
            +
                          tag_deleted(@from[from_start...from_end])
         | 
| 422 | 
            +
                        when :insert
         | 
| 423 | 
            +
                          tag_inserted(@to[to_start...to_end])
         | 
| 424 | 
            +
                        when :equal
         | 
| 425 | 
            +
                          tag_equal(@from[from_start...from_end])
         | 
| 426 | 
            +
                        else
         | 
| 427 | 
            +
                          raise "unknown tag: #{tag}"
         | 
| 428 | 
            +
                        end
         | 
| 429 | 
            +
                      end
         | 
| 430 | 
            +
                      @result
         | 
| 431 | 
            +
                    end
         | 
| 432 | 
            +
             | 
| 433 | 
            +
                    private
         | 
| 434 | 
            +
                    def operations
         | 
| 435 | 
            +
                      @operations ||= nil
         | 
| 436 | 
            +
                      if @operations.nil?
         | 
| 437 | 
            +
                        matcher = SequenceMatcher.new(@from, @to)
         | 
| 438 | 
            +
                        @operations = matcher.operations
         | 
| 439 | 
            +
                      end
         | 
| 440 | 
            +
                      @operations
         | 
| 441 | 
            +
                    end
         | 
| 442 | 
            +
             | 
| 443 | 
            +
                    def default_ratio
         | 
| 444 | 
            +
                      0.74
         | 
| 445 | 
            +
                    end
         | 
| 446 | 
            +
             | 
| 447 | 
            +
                    def cut_off_ratio
         | 
| 448 | 
            +
                      0.75
         | 
| 449 | 
            +
                    end
         | 
| 450 | 
            +
             | 
| 451 | 
            +
                    def tag(mark, contents)
         | 
| 452 | 
            +
                      contents.each do |content|
         | 
| 453 | 
            +
                        @result << "#{mark}#{content}"
         | 
| 454 | 
            +
                      end
         | 
| 455 | 
            +
                    end
         | 
| 456 | 
            +
             | 
| 457 | 
            +
                    def tag_deleted(contents)
         | 
| 458 | 
            +
                      tag("- ", contents)
         | 
| 459 | 
            +
                    end
         | 
| 460 | 
            +
             | 
| 461 | 
            +
                    def tag_inserted(contents)
         | 
| 462 | 
            +
                      tag("+ ", contents)
         | 
| 463 | 
            +
                    end
         | 
| 464 | 
            +
             | 
| 465 | 
            +
                    def tag_equal(contents)
         | 
| 466 | 
            +
                      tag("  ", contents)
         | 
| 467 | 
            +
                    end
         | 
| 468 | 
            +
             | 
| 469 | 
            +
                    def tag_difference(contents)
         | 
| 470 | 
            +
                      tag("? ", contents)
         | 
| 471 | 
            +
                    end
         | 
| 472 | 
            +
             | 
| 473 | 
            +
                    def find_diff_line_info(from_start, from_end, to_start, to_end)
         | 
| 474 | 
            +
                      best_ratio = default_ratio
         | 
| 475 | 
            +
                      from_equal_index = to_equal_index = nil
         | 
| 476 | 
            +
                      from_best_index = to_best_index = nil
         | 
| 477 | 
            +
             | 
| 478 | 
            +
                      to_start.upto(to_end - 1) do |to_index|
         | 
| 479 | 
            +
                        from_start.upto(from_end - 1) do |from_index|
         | 
| 480 | 
            +
                          if @from[from_index] == @to[to_index]
         | 
| 481 | 
            +
                            from_equal_index ||= from_index
         | 
| 482 | 
            +
                            to_equal_index ||= to_index
         | 
| 483 | 
            +
                            next
         | 
| 484 | 
            +
                          end
         | 
| 485 | 
            +
             | 
| 486 | 
            +
                          matcher = SequenceMatcher.new(@from[from_index], @to[to_index],
         | 
| 487 | 
            +
                                                        &method(:space_character?))
         | 
| 488 | 
            +
                          if matcher.ratio > best_ratio
         | 
| 489 | 
            +
                            best_ratio = matcher.ratio
         | 
| 490 | 
            +
                            from_best_index = from_index
         | 
| 491 | 
            +
                            to_best_index = to_index
         | 
| 492 | 
            +
                          end
         | 
| 493 | 
            +
                        end
         | 
| 494 | 
            +
                      end
         | 
| 495 | 
            +
             | 
| 496 | 
            +
                      [best_ratio,
         | 
| 497 | 
            +
                       from_equal_index, to_equal_index,
         | 
| 498 | 
            +
                       from_best_index,  to_best_index]
         | 
| 499 | 
            +
                    end
         | 
| 500 | 
            +
             | 
| 501 | 
            +
                    def diff_lines(from_start, from_end, to_start, to_end)
         | 
| 502 | 
            +
                      info = find_diff_line_info(from_start, from_end, to_start, to_end)
         | 
| 503 | 
            +
                      best_ratio, from_equal_index, to_equal_index, *info = info
         | 
| 504 | 
            +
                      from_best_index, to_best_index = info
         | 
| 505 | 
            +
                      from_best_index ||= from_start
         | 
| 506 | 
            +
                      to_best_index ||= to_start
         | 
| 507 | 
            +
             | 
| 508 | 
            +
                      if best_ratio < cut_off_ratio
         | 
| 509 | 
            +
                        if from_equal_index.nil?
         | 
| 510 | 
            +
                          if to_end - to_start < from_end - from_start
         | 
| 511 | 
            +
                            tag_inserted(@to[to_start...to_end])
         | 
| 512 | 
            +
                            tag_deleted(@from[from_start...from_end])
         | 
| 513 | 
            +
                          else
         | 
| 514 | 
            +
                            tag_deleted(@from[from_start...from_end])
         | 
| 515 | 
            +
                            tag_inserted(@to[to_start...to_end])
         | 
| 516 | 
            +
                          end
         | 
| 517 | 
            +
                          return
         | 
| 518 | 
            +
                        end
         | 
| 519 | 
            +
                        from_best_index = from_equal_index
         | 
| 520 | 
            +
                        to_best_index = to_equal_index
         | 
| 521 | 
            +
                        best_ratio = 1.0
         | 
| 522 | 
            +
                      end
         | 
| 523 | 
            +
             | 
| 524 | 
            +
                      _diff_lines(from_start, from_best_index, to_start, to_best_index)
         | 
| 525 | 
            +
                      diff_line(@from[from_best_index], @to[to_best_index])
         | 
| 526 | 
            +
                      _diff_lines(from_best_index + 1, from_end, to_best_index + 1, to_end)
         | 
| 527 | 
            +
                    end
         | 
| 528 | 
            +
             | 
| 529 | 
            +
                    def _diff_lines(from_start, from_end, to_start, to_end)
         | 
| 530 | 
            +
                      if from_start < from_end
         | 
| 531 | 
            +
                        if to_start < to_end
         | 
| 532 | 
            +
                          diff_lines(from_start, from_end, to_start, to_end)
         | 
| 533 | 
            +
                        else
         | 
| 534 | 
            +
                          tag_deleted(@from[from_start...from_end])
         | 
| 535 | 
            +
                        end
         | 
| 536 | 
            +
                      else
         | 
| 537 | 
            +
                        tag_inserted(@to[to_start...to_end])
         | 
| 538 | 
            +
                      end
         | 
| 539 | 
            +
                    end
         | 
| 540 | 
            +
             | 
| 541 | 
            +
                    def line_operations(from_line, to_line)
         | 
| 542 | 
            +
                      if !from_line.respond_to?(:force_encoding) and $KCODE == "UTF8"
         | 
| 543 | 
            +
                        from_line = UTF8Line.new(from_line)
         | 
| 544 | 
            +
                        to_line = UTF8Line.new(to_line)
         | 
| 545 | 
            +
                      end
         | 
| 546 | 
            +
                      matcher = SequenceMatcher.new(from_line, to_line,
         | 
| 547 | 
            +
                                                    &method(:space_character?))
         | 
| 548 | 
            +
                      [from_line, to_line, matcher.operations]
         | 
| 549 | 
            +
                    end
         | 
| 550 | 
            +
             | 
| 551 | 
            +
                    def compute_width(line, start, _end)
         | 
| 552 | 
            +
                      if line.respond_to?(:encoding) and
         | 
| 553 | 
            +
                          Encoding.compatible?(Encoding::UTF_8, line.encoding)
         | 
| 554 | 
            +
                        utf8_line = line[start..._end].encode(Encoding::UTF_8)
         | 
| 555 | 
            +
                        width = 0
         | 
| 556 | 
            +
                        utf8_line.each_codepoint do |unicode_codepoint|
         | 
| 557 | 
            +
                          if UTF8Line.wide_character?(unicode_codepoint)
         | 
| 558 | 
            +
                            width += 2
         | 
| 559 | 
            +
                          else
         | 
| 560 | 
            +
                            width += 1
         | 
| 561 | 
            +
                          end
         | 
| 562 | 
            +
                        end
         | 
| 563 | 
            +
                        width
         | 
| 564 | 
            +
                      elsif line.is_a?(UTF8Line)
         | 
| 565 | 
            +
                        line.compute_width(start, _end)
         | 
| 566 | 
            +
                      else
         | 
| 567 | 
            +
                        _end - start
         | 
| 568 | 
            +
                      end
         | 
| 569 | 
            +
                    end
         | 
| 570 | 
            +
             | 
| 571 | 
            +
                    def diff_line(from_line, to_line)
         | 
| 572 | 
            +
                      from_tags = ""
         | 
| 573 | 
            +
                      to_tags = ""
         | 
| 574 | 
            +
                      from_line, to_line, _operations = line_operations(from_line, to_line)
         | 
| 575 | 
            +
                      _operations.each do |tag, from_start, from_end, to_start, to_end|
         | 
| 576 | 
            +
                        from_width = compute_width(from_line, from_start, from_end)
         | 
| 577 | 
            +
                        to_width = compute_width(to_line, to_start, to_end)
         | 
| 578 | 
            +
                        case tag
         | 
| 579 | 
            +
                        when :replace
         | 
| 580 | 
            +
                          from_tags << "^" * from_width
         | 
| 581 | 
            +
                          to_tags << "^" * to_width
         | 
| 582 | 
            +
                        when :delete
         | 
| 583 | 
            +
                          from_tags << "-" * from_width
         | 
| 584 | 
            +
                        when :insert
         | 
| 585 | 
            +
                          to_tags << "+" * to_width
         | 
| 586 | 
            +
                        when :equal
         | 
| 587 | 
            +
                          from_tags << " " * from_width
         | 
| 588 | 
            +
                          to_tags << " " * to_width
         | 
| 589 | 
            +
                        else
         | 
| 590 | 
            +
                          raise "unknown tag: #{tag}"
         | 
| 591 | 
            +
                        end
         | 
| 592 | 
            +
                      end
         | 
| 593 | 
            +
                      format_diff_point(from_line, to_line, from_tags, to_tags)
         | 
| 594 | 
            +
                    end
         | 
| 595 | 
            +
             | 
| 596 | 
            +
                    def format_diff_point(from_line, to_line, from_tags, to_tags)
         | 
| 597 | 
            +
                      common = [n_leading_characters(from_line, ?\t),
         | 
| 598 | 
            +
                                n_leading_characters(to_line, ?\t)].min
         | 
| 599 | 
            +
                      common = [common,
         | 
| 600 | 
            +
                                n_leading_characters(from_tags[0, common], " "[0])].min
         | 
| 601 | 
            +
                      from_tags = from_tags[common..-1].rstrip
         | 
| 602 | 
            +
                      to_tags = to_tags[common..-1].rstrip
         | 
| 603 | 
            +
             | 
| 604 | 
            +
                      tag_deleted([from_line])
         | 
| 605 | 
            +
                      unless from_tags.empty?
         | 
| 606 | 
            +
                        tag_difference(["#{"\t" * common}#{from_tags}"])
         | 
| 607 | 
            +
                      end
         | 
| 608 | 
            +
                      tag_inserted([to_line])
         | 
| 609 | 
            +
                      unless to_tags.empty?
         | 
| 610 | 
            +
                        tag_difference(["#{"\t" * common}#{to_tags}"])
         | 
| 611 | 
            +
                      end
         | 
| 612 | 
            +
                    end
         | 
| 613 | 
            +
             | 
| 614 | 
            +
                    def n_leading_characters(string, character)
         | 
| 615 | 
            +
                      n = 0
         | 
| 616 | 
            +
                      while string[n] == character
         | 
| 617 | 
            +
                        n += 1
         | 
| 618 | 
            +
                      end
         | 
| 619 | 
            +
                      n
         | 
| 620 | 
            +
                    end
         | 
| 621 | 
            +
             | 
| 622 | 
            +
                    def space_character?(character)
         | 
| 623 | 
            +
                      [" "[0], "\t"[0]].include?(character)
         | 
| 624 | 
            +
                    end
         | 
| 625 | 
            +
                  end
         | 
| 626 | 
            +
             | 
| 627 | 
            +
                  class UnifiedDiffer < Differ
         | 
| 628 | 
            +
                    def diff(options={})
         | 
| 629 | 
            +
                      groups = SequenceMatcher.new(@from, @to).grouped_operations
         | 
| 630 | 
            +
                      return [] if groups.empty?
         | 
| 631 | 
            +
                      return [] if same_content?(groups)
         | 
| 632 | 
            +
             | 
| 633 | 
            +
                      show_context = options[:show_context]
         | 
| 634 | 
            +
                      show_context = true if show_context.nil?
         | 
| 635 | 
            +
                      result = ["--- #{options[:from_label]}".rstrip,
         | 
| 636 | 
            +
                                "+++ #{options[:to_label]}".rstrip]
         | 
| 637 | 
            +
                      groups.each do |operations|
         | 
| 638 | 
            +
                        result << format_summary(operations, show_context)
         | 
| 639 | 
            +
                        operations.each do |args|
         | 
| 640 | 
            +
                          operation_tag, from_start, from_end, to_start, to_end = args
         | 
| 641 | 
            +
                          case operation_tag
         | 
| 642 | 
            +
                          when :replace
         | 
| 643 | 
            +
                            result.concat(tag("-", @from[from_start...from_end]))
         | 
| 644 | 
            +
                            result.concat(tag("+", @to[to_start...to_end]))
         | 
| 645 | 
            +
                          when :delete
         | 
| 646 | 
            +
                            result.concat(tag("-", @from[from_start...from_end]))
         | 
| 647 | 
            +
                          when :insert
         | 
| 648 | 
            +
                            result.concat(tag("+", @to[to_start...to_end]))
         | 
| 649 | 
            +
                          when :equal
         | 
| 650 | 
            +
                            result.concat(tag(" ", @from[from_start...from_end]))
         | 
| 651 | 
            +
                          end
         | 
| 652 | 
            +
                        end
         | 
| 653 | 
            +
                      end
         | 
| 654 | 
            +
                      result
         | 
| 655 | 
            +
                    end
         | 
| 656 | 
            +
             | 
| 657 | 
            +
                    private
         | 
| 658 | 
            +
                    def same_content?(groups)
         | 
| 659 | 
            +
                      return false if groups.size != 1
         | 
| 660 | 
            +
                      group = groups[0]
         | 
| 661 | 
            +
                      return false if group.size != 1
         | 
| 662 | 
            +
                      tag, from_start, from_end, to_start, to_end = group[0]
         | 
| 663 | 
            +
             | 
| 664 | 
            +
                      tag == :equal and [from_start, from_end] == [to_start, to_end]
         | 
| 665 | 
            +
                    end
         | 
| 666 | 
            +
             | 
| 667 | 
            +
                    def format_summary(operations, show_context)
         | 
| 668 | 
            +
                      _, first_from_start, _, first_to_start, _ = operations[0]
         | 
| 669 | 
            +
                      _, _, last_from_end, _, last_to_end = operations[-1]
         | 
| 670 | 
            +
                      summary = "@@ -%d,%d +%d,%d @@" % [first_from_start + 1,
         | 
| 671 | 
            +
                                                         last_from_end - first_from_start,
         | 
| 672 | 
            +
                                                         first_to_start + 1,
         | 
| 673 | 
            +
                                                         last_to_end - first_to_start,]
         | 
| 674 | 
            +
                      if show_context
         | 
| 675 | 
            +
                        interesting_line = find_interesting_line(first_from_start,
         | 
| 676 | 
            +
                                                                 first_to_start,
         | 
| 677 | 
            +
                                                                 :define_line?)
         | 
| 678 | 
            +
                        summary << " #{interesting_line}" if interesting_line
         | 
| 679 | 
            +
                      end
         | 
| 680 | 
            +
                      summary
         | 
| 681 | 
            +
                    end
         | 
| 682 | 
            +
             | 
| 683 | 
            +
                    def find_interesting_line(from_start, to_start, predicate)
         | 
| 684 | 
            +
                      from_index = from_start
         | 
| 685 | 
            +
                      to_index = to_start
         | 
| 686 | 
            +
                      while from_index >= 0 or to_index >= 0
         | 
| 687 | 
            +
                        [@from[from_index], @to[to_index]].each do |line|
         | 
| 688 | 
            +
                          return line if line and __send__(predicate, line)
         | 
| 689 | 
            +
                        end
         | 
| 690 | 
            +
             | 
| 691 | 
            +
                        from_index -= 1
         | 
| 692 | 
            +
                        to_index -= 1
         | 
| 693 | 
            +
                      end
         | 
| 694 | 
            +
                      nil
         | 
| 695 | 
            +
                    end
         | 
| 696 | 
            +
             | 
| 697 | 
            +
                    def define_line?(line)
         | 
| 698 | 
            +
                      /\A(?:[_a-zA-Z$]|\s*(?:class|module|def)\b)/ =~ line
         | 
| 699 | 
            +
                    end
         | 
| 700 | 
            +
                  end
         | 
| 701 | 
            +
             | 
| 702 | 
            +
                  module_function
         | 
| 703 | 
            +
                  def need_fold?(diff)
         | 
| 704 | 
            +
                    /^[-+].{79}/ =~ diff
         | 
| 705 | 
            +
                  end
         | 
| 706 | 
            +
             | 
| 707 | 
            +
                  def fold(string)
         | 
| 708 | 
            +
                    string.split(/\r?\n/).collect do |line|
         | 
| 709 | 
            +
                      line.gsub(/(.{78})/, "\\1\n")
         | 
| 710 | 
            +
                    end.join("\n")
         | 
| 711 | 
            +
                  end
         | 
| 712 | 
            +
             | 
| 713 | 
            +
                  def folded_readable(from, to, options={})
         | 
| 714 | 
            +
                    readable(fold(from), fold(to), options)
         | 
| 715 | 
            +
                  end
         | 
| 716 | 
            +
             | 
| 717 | 
            +
                  def readable(from, to, options={})
         | 
| 718 | 
            +
                    diff(ReadableDiffer, from, to, options)
         | 
| 719 | 
            +
                  end
         | 
| 720 | 
            +
             | 
| 721 | 
            +
                  def unified(from, to, options={})
         | 
| 722 | 
            +
                    diff(UnifiedDiffer, from, to, options)
         | 
| 723 | 
            +
                  end
         | 
| 724 | 
            +
             | 
| 725 | 
            +
                  def diff(differ_class, from, to, options={})
         | 
| 726 | 
            +
                    if from.respond_to?(:valid_encoding?) and not from.valid_encoding?
         | 
| 727 | 
            +
                      from = from.dup.force_encoding("ASCII-8BIT")
         | 
| 728 | 
            +
                    end
         | 
| 729 | 
            +
                    if to.respond_to?(:valid_encoding?) and not to.valid_encoding?
         | 
| 730 | 
            +
                      to = to.dup.force_encoding("ASCII-8BIT")
         | 
| 731 | 
            +
                    end
         | 
| 732 | 
            +
                    differ = differ_class.new(from.split(/\r?\n/), to.split(/\r?\n/))
         | 
| 733 | 
            +
                    lines = differ.diff(options)
         | 
| 734 | 
            +
                    if Object.const_defined?(:EncodingError)
         | 
| 735 | 
            +
                      begin
         | 
| 736 | 
            +
                        lines.join("\n")
         | 
| 737 | 
            +
                      rescue EncodingError
         | 
| 738 | 
            +
                        lines.collect {|line| line.force_encoding("ASCII-8BIT")}.join("\n")
         | 
| 739 | 
            +
                      end
         | 
| 740 | 
            +
                    else
         | 
| 741 | 
            +
                      lines.join("\n")
         | 
| 742 | 
            +
                    end
         | 
| 743 | 
            +
                  end
         | 
| 744 | 
            +
                end
         | 
| 745 | 
            +
              end
         | 
| 746 | 
            +
            end
         |