diff --git a/bundles/CoffeeScriptBundle.tmbundle/.gitignore b/bundles/CoffeeScriptBundle.tmbundle/.gitignore
new file mode 100644
index 000000000..f05fcdc11
--- /dev/null
+++ b/bundles/CoffeeScriptBundle.tmbundle/.gitignore
@@ -0,0 +1 @@
+*.cache
\ No newline at end of file
diff --git a/bundles/CoffeeScriptBundle.tmbundle/Commands/Align Assignments.tmCommand b/bundles/CoffeeScriptBundle.tmbundle/Commands/Align Assignments.tmCommand
new file mode 100644
index 000000000..8c625724e
--- /dev/null
+++ b/bundles/CoffeeScriptBundle.tmbundle/Commands/Align Assignments.tmCommand
@@ -0,0 +1,159 @@
+
+
+
RakeMate v#{RAKEMATE_VERSION} running on Ruby v#{RUBY_VERSION} (#{ENV["TM_RUBY"].strip})
+>>> #{RAKEFILE_DIR}/Rakefile
+
+HTML
+
+rake = ENV["TM_RAKE"]
+if rake.nil? or not File.exist? rake
+ html_error("Rake not found. Please set TM_RAKE.")
+end
+
+prefs = PStore.new( File.expand_path( "~/Library/Preferences/" +
+ "com.macromates.textmate.run_rake" ) )
+
+Dir.chdir(RAKEFILE_DIR)
+tasks = fetch_rake_tasks
+
+unless $?.exited?
+ html_error("Could not fetch task list.")
+end
+if tasks.include? "No Rakefile found"
+ html_error("Could not locate a Rakefile in #{RAKEFILE_DIR}.")
+end
+
+tasks = [DEFAULT_TASK] + tasks.grep(/^rake\s+(\S+)/) { |t| t.split[1] }
+if last_task = tasks.index(prefs.transaction(true) { prefs[RAKEFILE_DIR] })
+ tasks.unshift(tasks.slice!(last_task))
+end
+
+if task = TextMate::UI.request_item( :title => "Rake Tasks",
+ :prompt => "Select a task to execute:",
+ :items => tasks,
+ :button1 => "Run Task")
+ prefs.transaction { prefs[RAKEFILE_DIR] = task }
+
+ testing = task =~ /test/i || task == DEFAULT_TASK
+ run_rake_task(task == DEFAULT_TASK ? nil : task) do |line, mode|
+ if testing and line =~ /^\d+ tests, \d+ assertions, (\d+) failures, (\d+) errors/
+ print "#{line.chomp}
"
+ elsif testing and line =~ /^(\s+)(\S.*?):(\d+)(?::in\s*`(.*?)')?/ and File.exist? $2
+ indent, file, line, method = $1, $2, $3, $4
+
+ url, display_name = '', 'untitled document';
+ unless file == "-"
+ url = '&url=file://' + e_url(File.expand_path(file))
+ display_name = File.basename(file)
+ end
+
+ print "#{indent}" +
+ (method ? "method #{h method}" : 'at top level') +
+ " in #{h display_name} at line #{line}
"
+ elsif mode == :char_by_char
+ if %w[. E F].include? line
+ print line.sub(/^[EF]$/, "\\&"),
+ "
"
+ else
+ print htmlize(line)
+ $stdout.flush
+ next :line_by_line
+ end
+ else
+ print htmlize(line)
+ end
+ $stdout.flush
+ if mode == :char_by_char or (testing and line =~ /^Started\s*/)
+ :char_by_char
+ else
+ :line_by_line
+ end
+ end
+end
+
+puts ""
+html_footer
diff --git a/bundles/ruby.tmbundle/Support/RakeMate/run_rake_task.rb b/bundles/ruby.tmbundle/Support/RakeMate/run_rake_task.rb
new file mode 100644
index 000000000..04c6efcfd
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/RakeMate/run_rake_task.rb
@@ -0,0 +1,47 @@
+#!/usr/bin/env ruby -w
+
+require "#{ENV["TM_SUPPORT_PATH"]}/lib/escape"
+
+class RakeTaskRunner
+ def initialize
+ @mode = :line_by_line
+ end
+
+ def run(task = nil, *options, &block)
+ build_rake_command(task, *options)
+
+ open(@command) do |rake_task|
+ if block.nil?
+ rake_task.read
+ else
+ loop do
+ break if rake_task.eof?
+ new_content = @mode == :char_by_char ? rake_task.getc.chr :
+ rake_task.gets
+ @mode = block.arity == 2 ? block[new_content, @mode] :
+ block[new_content]
+ end
+ end
+ end
+ end
+
+ private
+
+ def build_rake_command(task, *options)
+ @command = "|"
+ @command << ENV["TM_RAKE"] || "rake"
+ @command << " " << e_sh(task) unless task.nil?
+ unless options.empty?
+ @command << " " << options.map { |arg| e_sh(arg) }.join(" ")
+ end
+ @command << " 2>&1"
+ end
+end
+
+def run_rake_task(*args, &block)
+ RakeTaskRunner.new.run(*args, &block)
+end
+
+def fetch_rake_tasks(*args, &block)
+ RakeTaskRunner.new.run("--tasks", *args, &block)
+end
diff --git a/bundles/ruby.tmbundle/Support/RubyMate/catch_exception.rb b/bundles/ruby.tmbundle/Support/RubyMate/catch_exception.rb
new file mode 100644
index 000000000..84e377eda
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/RubyMate/catch_exception.rb
@@ -0,0 +1,41 @@
+# encoding: utf-8
+
+STDOUT.sync = true
+STDERR.sync = true
+
+require 'pathname'
+
+at_exit do
+ if (e = $!) && !e.instance_of?(SystemExit)
+ require "#{ENV['TM_SUPPORT_PATH']}/lib/escape"
+ require "cgi"
+ io = IO.for_fd(ENV['TM_ERROR_FD'].to_i)
+
+ io.write "#{e.class.name}: #{CGI.escapeHTML e.message.sub(/`(\w+)'/, '‘\1’').sub(/ -- /, ' — ')}
\n" + + io.write "\n" + + e.backtrace.each do |b| + if b =~ /(.*?):(\d+)(?::in\s*`(.*?)')?/ then + file, line, method = $1, $2, $3 + + url, display_name = '', 'untitled document'; + if file != '-' && File.exists?(file) && !ENV['TM_SCRIPT_IS_UNTITLED'] then + file = Pathname.new(file).realpath.to_s + url = '&url=file://' + e_url(file) + display_name = File.basename(file) + end + + io << "
\n" + end + end + + io.write " " + io << (method ? "method #{CGI::escapeHTML method}" : 'at top level') + io << " \nin #{CGI::escapeHTML display_name} at line #{line}
"
+ end
+
+ text.sub!(/\A(-+\s+)(([A-Z_]\w*::)*[A-Z_]\w*)((#|::|\.).*)$/) do
+ method = $4
+ namespace = $2.split("::")
+ linked = (0...namespace.size).map do |i|
+ "#{namespace[i]}"
+ end
+ "#{linked.join("::")}#{method}
\n"
+ end
+
+ text.sub!(/^(Includes:\s+-+\s+)(.+?)([ \t]*\n[ \t]*\n|\s*\Z)/m) do
+ head, meths, foot = $1, $2, $3
+ head + meths.gsub(/([A-Z_]\w*)\(([^)]*)\)/) do |match|
+ "#{$1}(" +
+ link_methods("#{$1}#", $2) + ")"
+ end + foot
+ end
+
+ text.sub!(/^(Class methods:\s+-+\s+)(.+?)([ \t]*\n[ \t]*\n|\s*\Z)/m) do
+ $1 + link_methods("#{term}::", $2) + $3
+ end
+
+ text.sub!(/^(Instance methods:\s+-+\s+)(.+?)([ \t]*\n[ \t]*\n|\s*\Z)/m) do
+ $1 + link_methods("#{term}#", $2) + $3
+ end
+
+ text.gsub!(/(?:\n+-+$)?\n+([\w\s]+)[:.]$\n-+\n+/, "\n\n\\1
\n")
+ text.gsub!(/^-+$/, '
')
+
+ text.chomp + "
"
+end
+
+def ri(term)
+ documentation = `#{e_sh LINKED_RI} '#{term}' 'js' 2>&1` \
+ rescue "ri Command Error.
"
+ if documentation =~ /\ACouldn't open the index/
+ TextMate.exit_show_tool_tip(
+ "Index needed by #{RI_EXE} not found.\n" +
+ "You may need to run:\n\n" +
+ " fastri-server -b"
+ )
+ elsif documentation =~ /\ACouldn't initialize DRb and locate the Ring server./
+ TextMate.exit_show_tool_tip("Your fastri-server is not running.")
+ elsif documentation =~ /Nothing known about /
+ TextMate.exit_show_tool_tip(documentation)
+ elsif documentation.sub!(/\A>>\s*/, "")
+ choices = documentation.split
+ choice = TextMate::UI.menu(choices)
+ exit if choice.nil?
+ ri(choices[choice])
+ else
+ [term, documentation]
+ end
+end
+
+mode = ARGV.shift
+if mode.nil? then
+
+ term = STDIN.read.strip
+
+ if term.empty?
+ term = TextMate::UI.request_string( :title => "Ruby Documentation Search",
+ :prompt => "Enter a term to search for:",
+ :button1 => "search")
+ end
+
+ TextMate.exit_show_tool_tip("Please select a term to look up.") if term.empty?
+
+ term, documentation = ri(term)
+
+ html_header("Documentation for ‘#{term}’", "RDoc", <<-HTML)
+
+HTML
+ puts <<-HTML
+
+
+#{documentation}
+HTML
+ html_footer
+ TextMate.exit_show_html
+elsif mode == 'js' then
+ documentation = `#{e_sh RI_EXE} -T -f plain #{e_sh term}` \
+ rescue "ri Command Error.
"
+
+ if documentation =~ /\A(?:\s*More than one method matched|-+\s+Multiple choices)/
+ methods = documentation.split(/\n[ \t]*\n/).last.
+ strip.split(/(?:,\s*|\n)/).map { |m| m[/\S+/] }.compact
+ documentation = ">> #{methods.join(' ')}"
+ else
+ documentation = htmlize_ri_output(documentation, term)
+ end
+
+ puts documentation
+end
diff --git a/bundles/ruby.tmbundle/Support/bin/make_destructive.rb b/bundles/ruby.tmbundle/Support/bin/make_destructive.rb
new file mode 100644
index 000000000..153f20876
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/bin/make_destructive.rb
@@ -0,0 +1,18 @@
+#!/usr/bin/env ruby
+
+require "escape"
+
+CURSOR = [0xFFFC].pack("U").freeze
+line = STDIN.read
+begin
+ line[ENV["TM_LINE_INDEX"].to_i, 0] = CURSOR
+rescue
+ exit
+end
+
+line.sub!(/\b(chomp|chop|collect|compact|delete|downcase|exit|flatten|gsub|lstrip|map|next|reject|reverse|rstrip|slice|sort|squeeze|strip|sub|succs|swapcase|tr|tr_s|uniq|upcase)\b(?!\!)/, "\\1!")
+
+line = e_sn(line)
+line.sub!(CURSOR, "$0")
+
+print line
diff --git a/bundles/ruby.tmbundle/Support/bin/snippet_paren.rb b/bundles/ruby.tmbundle/Support/bin/snippet_paren.rb
new file mode 100755
index 000000000..6b4bbbd39
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/bin/snippet_paren.rb
@@ -0,0 +1,10 @@
+#!/usr/bin/env ruby -wKU
+
+minimize = ENV["TM_MINIMIZE_PARENS"].to_s =~ /\byes\b/i
+
+case ARGV.shift.to_s =~ /\bend\b/i ? :end : :start
+when :start
+ print(minimize ? " " : "(")
+when :end
+ print ")" unless minimize
+end
diff --git a/bundles/ruby.tmbundle/Support/lib/ruby_requires.rb b/bundles/ruby.tmbundle/Support/lib/ruby_requires.rb
new file mode 100644
index 000000000..c589000a6
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/lib/ruby_requires.rb
@@ -0,0 +1,26 @@
+#!/usr/bin/env ruby
+
+$: << "#{ENV['TM_SUPPORT_PATH']}/lib" if ENV.has_key?('TM_SUPPORT_PATH')
+require "escape"
+
+module RubyRequires
+ module_function
+
+ def build_requires( code, libs )
+ libs.reject { |lib| code =~ /require\s*(['"])#{lib}\1/ }.
+ map { |lib| "require \"#{lib}\"\n" }.join
+ end
+
+ def place_requires( code, new_reqs )
+ return code unless new_reqs =~ /\S/
+
+ code.dup.sub!(/(?:^[ \t]*require\s*(['"]).+?\1.*\n)+/, "\\{new_reqs}") ||
+ code.sub(/\A(?:\s*(?:#.*)?\n)*/, "\\{new_reqs}\n")
+ end
+
+ def add_requires( code, reqs )
+ new_reqs = build_requires(code, reqs)
+ code = place_requires(code, new_reqs)
+ e_sn(code)
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/README b/bundles/ruby.tmbundle/Support/vendor/README
new file mode 100644
index 000000000..8f9654a7c
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/README
@@ -0,0 +1,3 @@
+Please remember that anything in this directory has a license of its own.
+
+These projects need to be chosen carefully, after ensuring that there license allows them to be bundled with TextMate, and all changes must comply with the project license.
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/CHANGES b/bundles/ruby.tmbundle/Support/vendor/rcodetools/CHANGES
new file mode 100644
index 000000000..0b102fece
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/CHANGES
@@ -0,0 +1,70 @@
+rcodetools history
+==================
+User-visible changes since 0.8.5
+--------------------------------
+* Fix DATA and __END__ handling in xmpfilter --tempfile (windows)
+
+User-visible changes since 0.8.4
+--------------------------------
+* OOPS, added missing files.
+
+User-visible changes since 0.8.0
+--------------------------------
+* xmpfilter: fixed multi-line annotation bugs
+
+User-visible changes since 0.7.0
+--------------------------------
+* Support Ruby 1.9!
+* xmpfilter: multi-line annotation
+* xmpfilter --expectations generates expectations by Jay Fields
+* anything-rcodetools.el: new elisp
+* --tmpfile, --tempfile: use temporary file instead of open3 on un*x
+* rcodetools.el: smarter xmpfilter-command
+* rcodetools.el: rct-fork interface
+* rct-fork: require 'rubygems' initially
+* rct-fork: more stable
+
+User-visible changes since 0.5.0
+--------------------------------
+* "test-driven completion" (TDC) support for Emacs and vim (see README.TDC)
+* --test (-t), --filename options for rct-complete and rct-doc, allowing to
+ specify the test to be run for 100% accurate completion/documentation in the
+ corresponding implementation
+* ruby-toggle-file: finds the test file corresponding to a given
+ implementation and vice versa
+* rct-fork, rct-fork-client: allow to eliminate the overhead due to library
+ loading (esp. useful for Rails)
+* rbtest: executes unit tests in a single Ruby script
+* --fork, --rbtest, --detect-rbtest supported by several commands
+* xmpfilter's --spec now autodetects the RSpec version and generates
+ specifications with the appropriate syntax
+
+User-visible changes since 0.4.1
+--------------------------------
+* --dev: adds project directories to $:
+* --completion-class-info: list completion candidates and class info
+* display completion candidates with description, both in emacs
+ and vim (using the menu+preview window).
+
+User-visible changes since 0.4.0
+--------------------------------
+* rct-meth-args: implemented -I
+* many bug fixes
+
+xmpfilter was integrated into rcodetools as of 0.4.0.
+
+xmpfilter history
+=================
+User-visible changes since 0.3.1 (2006-10-17)
+* implemented --debug
+* --[no]-warnings
+* --cd working_dir
+* --rails
+* --no-poetry
+* more intelligent assertions: try to find which local variables hold the
+ values compared against in assertions/expectations
+* editor-independent completion (-C, --completion-emacs, --completion-vim)
+* quick method/class reference with -D (--refe, --ri*)
+
+User-visible changes since 0.3.0 (2006-10-16)
+* xmpfilter.rb --spec works on win32 too
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/README b/bundles/ruby.tmbundle/Support/vendor/rcodetools/README
new file mode 100644
index 000000000..036373fc4
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/README
@@ -0,0 +1,98 @@
+
+ rcodetools http://eigenclass.org/hiki.rb?rcodetools
+ Copyright (c) 2005-2007 Mauricio Fernandez http://eigenclass.org
+ Copyright (c) 2006-2008 rubikitch http://www.rubyist.net/~rubikitch/
+Use and distribution subject to the terms of the Ruby license.
+
+= Overview
+rcodetools is a collection of Ruby code manipulation tools.
+It includes xmpfilter and editor-independent Ruby development helper tools,
+as well as emacs and vim interfaces.
+
+Currently, rcodetools comprises:
+* xmpfilter: Automagic Test::Unit assertions/RSpec expectations and code annotations
+* rct-complete: Accurate method/class/constant etc. completions
+* rct-doc: Document browsing and code navigator
+* rct-meth-args: Precise method info (meta-prog. aware) and TAGS generation
+* rct-fork: Pre-load heavy library(Rails etc) and speed up rct-complete/rct-doc (server)
+* rct-fork-client: Run Ruby programs from state the rct-fork server has
+* ruby-toggle-file: Toggle implementation file and test file
+* rbtest: Embedded Test::Unit for small scripts
+
+See also README.xmpfilter.
+
+Originally rct-complete and rct-doc were subcommands of xmpfilter.
+Actually they use xmpfilter's code heavily.
+But the relationship between xmpfilter (annotation) and completion/doc is not
+intuitive, so I (rubikitch) split it into separate executables.
+
+= Usage
+xmpfilter, rct-complete and rct-doc take its input from stdin and write to
+stdout. They can run in several modes; see
+ xmpfilter -h
+ rct-complete -h
+ rct-doc -h
+ rct-meth-args -h
+ rct-fork -h
+ rct-fork-client -h
+ ruby-toggle-file -h
+ rbtest -h
+README.emacs and README.vim describe how to use rcodetools from your editor.
+
+= Accurate Completion Internal and Caveat
+rct-complete and rct-doc use xmpfilter engine, ie they get runtime information by executing code.
+In Ruby (dynamic languages), type of any expressions except literals cannot be known without actually executing code.
+Moreover Ruby has open classes and singleton methods.
+Rcodetools asks `ruby' run-time informations, so we can get very accurate informations.
+Completion and document browsing are essentially identical operations,
+they both need the object value in question.
+Therefore we discuss completion.
+
+rct-complete does:
+(1) replaces target line with completion magic
+ (it calculates methods the target object has).
+(2) executes modified script.
+(3) once the control reaches completion magic, modified script exits.
+(4) outputs in specified format. (list candidates, EmacsLisp...)
+
+But this methodology has two big drawbacks, side-effects and inability to get any informations of uncovered code!
+
+An extreme side-effect example:
+ File.unlink a_file
+ File. <-
+
+If you call rct-complete, it removes a_file (sends a mail, accesses DB ...).
+So you must be careful to use, especially at TOPLEVEL.
+I (rubikitch) often experiment at TOPLEVEL with rcodetools, I NEVER use irb(sh) since rcodetools!
+
+An uncovered code example:
+ def foo
+ 1. <-
+ end
+
+If the code does not call foo, we cannot do any completions.
+
+Useless eh? But we already have a way to elude the drawbacks, test scripts (unit tests)!
+Test scripts are self-enclosed and expected to be executed, so side-effects are not problem.
+Moreover tests call methods we write.
+Because Ruby's Test::Unit has an ability to test only one test method, we can do lightning-fast completion.
+Let's call it Test-Driven Completion (TDC).
+
+To support TDC, rct-complete has -t option.
+With -t, it concatenate modified script and test/unit code.
+If the control does not reach target line, test/unit code calls the line.
+
+How do we select test script and test method?
+The editor selects recently selected buffer of test script as test script of TDC,
+because the test-infected tend to go and return between test script and implementation script.
+It considers files matching /test.*\.rb/ as test script.
+It selects test method at the cursor position.
+
+TDC adds roles of test scripts.
+Enjoy TDC magic!
+
+See also README.TDC.
+
+
+= License
+rcodetools is licensed under the same terms as Ruby.
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.TDC b/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.TDC
new file mode 100644
index 000000000..5a413dab0
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.TDC
@@ -0,0 +1,158 @@
+
+= Overview
+
+Ruby is very dynamic language, therefore it is impossible to do
+accurate completion without executing script. While executing script
+from start to cursor point is often dangerous, executing unit test
+script covering current point is SAFE. I call this methodology
+`Test-Driven Completion' (TDC).
+
+As I have already stated in README, browsing documentation of method
+(rct-doc) is almost identical operation to completion. This
+discussion is applicable to rct-doc.
+
+= Why TDD Is Needed
+
+In the following code snippet:
+
+ File.unlink a_file
+ File. <-
+
+If you complete after `File.', rct-complete actually deletes a_file.
+Normally it is unpleasant.
+In real-life development, side-effect is inevitable.
+
+In the foo method which are not called:
+
+ def foo
+ 1. <-
+ end
+
+If the code does not call foo, rct-complete cannot do any completions.
+Before TDC, if you want to do completion in methods, you have to write
+method call and remove it after completion. Too useless!!
+
+= Messianic Unit Test Script
+
+Recently Test-Driven Development (TDD) is widespread. Many developers
+write unit tests. Fortunately Ruby's unit tester, Test::Unit, is
+sophisticated enough to test one test method. Unit tests are
+self-enclosed: they must tear down resources, so executing unit tests
+are SAFE. TDC uses unit test to do completion.
+
+= TDC Methodology
+
+(1) Switch to unit test script.
+(2) Write a test for target method.
+(3) Switch to implementation script.
+(4) You can write target method WITH COMPLETION!
+(5) Back to (1)
+
+TDC methodology is almost identical to TDD. TDC is very easy for TDDers.
+
+= TDC With Example
+
+For simplicity, suppose that you are unfamiliar with Time class and
+you want to write a method to format date string.
+
+The directory structure and file contents is following:
+
+ /tmp/mylib0/
+ /tmp/mylib0/lib/
+ mylib0.rb
+ /tmp/mylib0/test/
+ test_mylib0.rb
+
+ List: mylib0.rb
+ # contrived example of long-runtime method
+ def mysleep(x)
+ sleep x
+ end
+
+ def mytime(tm)
+
+ end
+
+
+ List: test_mylib0.rb
+ require 'test/unit'
+ require 'mylib0'
+ class TestMylib0 < Test::Unit::TestCase
+ def test_0_mysleep
+ s = Time.now
+ mysleep 3.0
+ e = Time.now
+ assert_in_delta 3.0, e-s, 0.01
+ end
+
+ def test_1_mytime
+
+ end
+ end
+
+These sample files are in demo/ directory.
+
+
+== Switch to unit test script.
+
+TDC starts with writing unit test as TDD does.
+Open test_mylib0.rb.
+
+== Write a test for target method.
+
+Suppose that you want to write mytime method and test_1_mytime test
+method, and that you want to experiment Time class first (before
+forming an assertion).
+
+In TDC, you do not have to write an assertion first: just write only a
+method call. If you are familiar with Time class, you are free to
+write an assertion, of course.
+
+ def test_1_mytime
+ mytime(Time.now)
+ end
+
+At this time, the cursor position is in test_1_mytime test method.
+
+== Switch to implementation script.
+
+Open mylib0.rb with the `ruby-toggle-file' script. For example, in Emacs use
+the `ruby-toggle-buffer' command, and in vim the t (by default
+\t) binding. Since in TDD/TDC you often switch between the test and the
+implementation, it is much handier than typing the filename manually.
+
+The rct-complete uses latest-selected test script as TDC test script
+and test method at cursor position as TDC test method. In this case,
+test_mylib0.rb is TDC test script and test_1_mytime is TDC test
+method. If the cursor position of test_mylib0.rb is at the top,
+rct-complete executes whole test methods in test_mylib0.rb. Therefore
+latency of completion is longer.
+
+== You can write target method WITH COMPLETION!
+
+Fill mytime method.
+
+ def mytime(tm)
+ tm.
+ end
+
+Do completion after `tm.'. Here! Your editor is listing methods `tm'
+accepts!! If your editor has help-on-candidate mechanism (eg. Emacs +
+Icicles), you would see documentation of each listed method.
+
+Then you find `Time#strftime' method. Type `str' and do completion.
+
+ def mytime(tm)
+ tm.strftime
+ end
+
+Usage is... use `rct-doc' (in Emacs, `rct-ri') after `strftime'.
+
+After you are familiar with Time class, switch to test script and write assertions.
+
+= When Modifying Another Method
+
+If you want to modify already-written method, setting cursor position
+of corresponding test script to corresponding test method is better.
+It tells rct-complete new test script and test method, so you can do
+completion in the new method.
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.emacs b/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.emacs
new file mode 100644
index 000000000..c3acff5d3
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.emacs
@@ -0,0 +1,75 @@
+
+rcodetools.el allows you to run rcodetools on a buffer.
+
+To eval the sexp, type C-e C-x C-e; `end-of-line' and `eval-last-sexp'.
+
+installation
+============
+
+If you use RI document feature, you must install ri-emacs first.
+ http://rubyforge.org/projects/ri-emacs/
+
+If you feel RI and ri-emacs.rb startup is SLOW, you want to install FastRI.
+FastRI offers ri-emacs compatible layer, so you can use it with ri-ruby.el.
+ http://eigenclass.org/hiki.rb?fastri
+
+Copy rcodetools.el to the appropriate directory, which is in load-path.
+Then require it.
+ (require 'rcodetools)
+
+If you use icicles copy icicles-rcodetools.el too.
+Then require it.
+ (require 'icicles-rcodetools)
+It provides wonderful `help on candidate' feature, RI document on each candidate during completion.
+
+If you use anything.el copy anything-rcodetools.el too.
+Then require it.
+ (require 'anything-rcodetools)
+RI document on each candidate during completion.
+
+anything-show-completion.el shows selection (mehod) in buffer for completion.
+It is available in:
+ http://www.emacswiki.org/cgi-bin/wiki/download/anything-show-completion.el
+
+I think anything-rcodetools is more convenient than icicles-rcodetools.
+I'm addicted to anything!
+ http://www.emacswiki.org/cgi-bin/wiki/Anything
+
+xmpfilter on buffer
+===================
+
+# [EVAL IT] (describe-function 'xmp)
+
+If you want to add => marks, call comment-dwim twice.
+
+# [EVAL IT] (describe-function 'comment-dwim)
+
+method/class/constant completion
+================================
+
+# [EVAL IT] (describe-function 'rct-complete-symbol)
+
+If you use icicles-rcodetools or anything-rcodetools, you can browse RI document
+for selected candidate by typing C-M-RET (icicles) or C-z (anything.
+It is wonderful icicles and anything feature!!
+
+show RI document / jump to the definition
+=========================================
+
+# [EVAL IT] (describe-function 'rct-ri)
+
+By default rct-ri asks for a TAGS file, which is generated by tag generator like rtags.
+If there is a TAGS file, this command jumps to the definition of current method.
+If use do not use this feature, evaluate:
+ (setq rct-find-tag-if-available nil)
+
+# [EVAL IT] (describe-variable 'rct-find-tag-if-available)
+
+speed-up xmpfilter and completion
+=================================
+
+# [EVAL IT] (describe-function 'rct-fork)
+# [EVAL IT] (describe-function 'rct-fork-kill)
+
+M-x rct-fork pre-loads heavy libraries (like rails).
+You need not every time wait for loading them anymore!
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.ja b/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.ja
new file mode 100644
index 000000000..7a321169f
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.ja
@@ -0,0 +1,84 @@
+
+ rcodetools http://eigenclass.org/hiki.rb?rcodetools
+ Copyright (c) 2005-2007 Mauricio Fernandez http://eigenclass.org
+ Copyright (c) 2006-2008 rubikitch http://www.rubyist.net/~rubikitch/
+Use and distribution subject to the terms of the Ruby license.
+
+=
+rcodetools Ruby Υɤġ뷲Ǥ
+rcodetools ˤ xmpfilter ȥǥ˰¸ʤȯٱġ뤬ޤޤƤޤ
+Emacs Vim ΥեѰդƤޤ
+
+* xmpfilter: Test::Unit assert* / RSpec should* ư
+* rct-complete: ٥å̾饹̾̾䴰
+* rct-doc: ɥȻȡɥʥӥ
+* rct-meth-args: ٥åɾꥹȡTAGS ե
+* rct-fork: Rails Ť饤֥ͽɤ䴰®ʥС
+* rct-fork-client: rct-fork Фݻ֤ Ruby ץȤ¹Ԥ
+* ruby-toggle-file: ƥȥץȤȼץȤڤ괹
+* rbtest: ϥץȤΤ Test::Unit
+
+
+= Ȥ
+
+==
+ͤɽԤ # => äޤ
+
+ a, b = "foo", "baz"
+ a + b # =>
+ a.size # =>
+
+xmpfilter ̤ȲΤ褦˼ͤɽƤޤ
+
+ a, b = "foo", "baz"
+ a + b # => "foobaz"
+ a.size # => 3
+
+
+== Test::Unit assert ʸ
+
+ǤˤǤäƤץΥƥȥץȤΤݤǤ͡
+
+ def test_insertion
+ @o.insert "bar"
+ @o.insert "baz"
+ @o.size # =>
+ @o.last # =>
+ @o.first # =>
+ @o.complex_computation # =>
+ @o.last(2) # =>
+ end
+
+xmpfilter-u ץˤ֤ڸƤޤ
+
+ def test_insertion
+ @o.insert "bar"
+ @o.insert "baz"
+ assert_equal(2, @o.size)
+ assert_equal("baz", @o.last)
+ assert_equal("bar", @o.first)
+ assert_in_delta(3.14159265358979, @o.complex_computation, 0.0001)
+ assert_equal(["baz", "bar"], @o.last(2))
+ end
+
+RSpec ˤĤƤƱͤΤȤǤޤ-s ץ
+
+== 䴰ɥȻ
+
+ưˤ륹åȤƤ
+
+http://eigenclass.org/hiki.rb?rcodetools-screenshots
+
+== ܤȤ
+-h ץĤȻѲǽʥץɽޤ
+
+ xmpfilter -h
+ rct-complete -h
+ rct-doc -h
+ rct-meth-args -h
+ rct-fork -h
+ rct-fork-client -h
+ ruby-toggle-file -h
+ rbtest -h
+
+README.emacs README.vim ˥ǥǤλȤܤƤޤ
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.method_analysis b/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.method_analysis
new file mode 100644
index 000000000..53a482d05
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.method_analysis
@@ -0,0 +1,13 @@
+
+method_analyzer.rb can be used to gather precise information about the exact
+methods called in your code, allowing you to explore it better with rct-doc
+(see README.emacs and README.vim for more information). This requires high
+code coverage, since it can only record such data when the code is executed.
+
+rct-meth-args can be used to generate fairly complete TAGS files. It operates
+by loading the specified files and tracking method definitions; therefore, it
+is meta-programming aware, unlike other implementations.
+
+You can use them conveniently by adding the code shown in
+Rakefile.method_analysis to your Rakefile.
+
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.vim b/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.vim
new file mode 100644
index 000000000..ea7c7c59f
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.vim
@@ -0,0 +1,111 @@
+
+Copy rcodetools.vim to your plugin directory (typically $HOME/.vim/plugin) in
+order to enable accurate code completion, quick RI execution and exact tag
+jumping.
+
+Switching between implementation and test files
+===============================================
+The t binding (by default \t) will call ruby-toggle-file to
+switch from test to implementation and vice versa. Moreover, when you switch
+from the test to the implementation, rcodetools will remember which test
+you were editing (based on the cursor position), and call it as needed for
+advanced code completion or precise RI documentation, as documented below.
+
+The actual binding can be changed in your .vimrc as follows:
+ let g:RCT_toggle_binding="" " use ^X^T to go test <=> implementation
+
+Code completion
+===============
+rcodetools.vim redefines user-defined completion for Ruby programs, so you can
+use the intelligent, 100%-accurate completion with in insert mode.
+Note that this runs the code to obtain the exact candidate list.
+
+If you've set completeopt to menu,preview then rcodetools.vim can display
+information about the completion candidates. The menu will show the synopsis
+as given in the RI documentation, and the preview window will contain the full
+RI documentation.
+
+This functionality relies on fri for quick lookups. It can be enabled by setting
+
+ let g:rct_completion_use_fri = 1 " 0 by default (disabled)
+
+in your .vimrc (don't forget to run fastri-server too).
+Obtaining the documentation for many candidates can be slow, so you can set
+the threshold above which additional documentation will not be shown with
+
+ " 20 by default, about a couple secs max wait on a normal machine
+ let g:rct_completion_info_max_len = 20
+
+Quick RI documentation and exact tag jumping
+============================================
+When you're editing a Ruby file, will jump to the definition of the
+chosen element if found in the TAGS file; otherwise, it will call RI and show
+the documentation in a new window.
+You can specify the RI executable to use by adding something like
+ let g:RCT_ri_cmd = "ri -T -f plain "
+to your .vimrc. (rcodetools.vim also honors b:RCT_RI_cmd and w:RCT_RI_cmd if set).
+By default, "fri -f plain " will be used. fri (FastRI) is an improved RI
+documentation browser, which features more intelligent search modes, gem
+integration, vastly better performance... You can find it at
+http://eigenclass.org/hiki.rb?fastri and it's also available in gem format
+gem install fastri
+
+If you want to call RI for the word the cursor is on (instead of jumping to
+the definition if found), you can use this binding:
+ r (\r by default if you haven't changed your localleader)
+You can specify another binding in your .vimrc as follows:
+ let g:RCT_ri_binding="" " use ^X^R to call vim on current word
+
+Using xmpfilter
+===============
+xmpfilter takes code from stdin and outputs to stdout so you can filter
+your code with ! as usual.
+
+If you use xmpfilter often, you might want to use mappings like the
+following, which allow you to:
+* add annotations
+* expand assertions
+* insert/remove # => markers
+
+
+
+" plain annotations
+map !xmpfilter -a
+nmap V
+imap a
+
+" Test::Unit assertions; use -s to generate RSpec expectations instead
+map !xmpfilter -u
+nmap V
+imap a
+
+" Annotate the full buffer
+" I actually prefer ggVG to %; it's a sort of poor man's visual bell
+nmap mzggVG!xmpfilter -a'z
+imap
+
+" assertions
+nmap mzggVG!xmpfilter -u'z
+imap a
+
+" Add # => markers
+vmap !xmpfilter -m
+nmap V
+imap a
+
+" Remove # => markers
+vmap ms:call RemoveRubyEval()
+nmap V
+imap a
+
+
+function! RemoveRubyEval() range
+ let begv = a:firstline
+ let endv = a:lastline
+ normal Hmt
+ set lz
+ execute ":" . begv . "," . endv . 's/\s*# \(=>\|!!\).*$//e'
+ normal 'tzt`s
+ set nolz
+ redraw
+endfunction
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.xmpfilter b/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.xmpfilter
new file mode 100644
index 000000000..1ea49dcb9
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/README.xmpfilter
@@ -0,0 +1,287 @@
+
+xmpfilter http://eigenclass.org/hiki.rb?xmpfilter
+Copyright (c) 2005-2008 Mauricio Fernandez http://eigenclass.org
+ rubikitch
+Use and distribution subject to the terms of the Ruby license.
+
+Overview
+========
+xmpfilter is a small tool that can be used to
+* generate Test::Unit assertions, RSpec expectations and
+ expectations blocks semi-automatically
+* annotate source code with intermediate results (a bit like irb
+ --simple-prompt but only for the lines explicitly marked with # =>)
+ Very useful for example code (such as postings to ruby-talk).
+
+Usage
+=====
+xmpfilter takes its input from stdin and writes to stdout. It can run in
+several modes (annotation, Test::Unit assertion expansion, RSpec expectation
+generation, expectations expectations generation, marker insertion); see
+ xmpfilter -h
+README.emacs and README.vim describe how to use xmpfilter from your editor.
+
+Example: code annotation
+========================
+Just add "# =>" markers to the lines whose values you want to be shown:
+
+ a, b = "foo", "baz"
+ a + b # =>
+ a.size # =>
+
+will be expanded to (in one keypress in a decent editor, see README.emacs and
+README.vim)
+
+ a, b = "foo", "baz"
+ a + b # => "foobaz"
+ a.size # => 3
+
+This saves much cut&pasting when you're posting to ruby-list/ruby-talk/ruby-core
+(We use it all the time).
+
+
+Example: multi-line code annotation
+===================================
+Just add "# =>" markers to the next lines whose values you want to be shown with pp:
+
+a = ["1111111111111111111111111111111111111111111111111111", 123334324234242342,
+ 1332333333,6,8 ]
+1 # =>
+a
+# =>
+
+will be expanded to (in one keypress in a decent editor, see README.emacs and
+README.vim)
+
+a = ["1111111111111111111111111111111111111111111111111111", 123334324234242342,
+ 1332333333,6,8 ]
+1 # => 1
+a
+# => ["1111111111111111111111111111111111111111111111111111",
+# 123334324234242342,
+# 1332333333,
+# 6,
+# 8]
+
+
+Example: assertion generation
+=============================
+
+xmpfilter can generate assertions based on the current behavior of the code
+to be tested (iow. the current behavior is assumed to be correct and is used
+to generate assertions which won't be modified by further runs of
+xmpfilter), making it quite useful for regression testing.
+
+Imagine you have a ComplexClass you want to test. You might start with
+
+ class TestComplexClass < Test::Unit::TestCase
+ def setup; @o = ComplexClass.new("foo", false) end
+ end
+
+and then want to add some tests:
+
+ def test_insertion
+ @o.insert "bar"
+ @o.insert "baz"
+ # ... assertions here
+ end
+
+At this point, you want to add several assertions to verify that the values
+returned by @o.size, @o.last, @o.first, @o.complex_computation and @o.last(2)
+are correct. You can just write the following and feed the file to
+xmpfilter in -u mode (the # => markers can also be inserted by
+xmpfilter, see README.vim for more information:
+
+ def test_insertion
+ @o.insert "bar"
+ @o.insert "baz"
+ @o.size # =>
+ @o.last # =>
+ @o.first # =>
+ @o.complex_computation # =>
+ @o.last(2) # =>
+ end
+
+xmpfilter will run the test and remember what happened in each marked line,
+and then rewrite the code so that it looks for instance like
+
+ def test_insertion
+ @o.insert "bar"
+ @o.insert "baz"
+ assert_equal(2, @o.size)
+ assert_equal("baz", @o.last)
+ assert_equal("bar", @o.first)
+ assert_in_delta(3.14159265358979, @o.complex_computation, 0.0001)
+ assert_equal(["baz", "bar"], @o.last(2))
+ end
+
+As you can see, it can save some typing.
+
+You can edit the generated assertions as you want: xmpfilter will not
+modify lines without the "# =>" marker. xmpfilter can be used repeatedly as
+you add more assertions. Imagine you want to verify that @o.last(3) raises an
+ArgumentError. You can simply add one line marked with # => :
+
+ ...
+ assert_in_delta(3.14159265358979, @o.complex_computation, 0.0001)
+ assert_equal(["baz", "bar"], @o.last(2))
+ @o.last(3) # =>
+ end
+
+and have it expanded by xmpfilter:
+
+ ...
+ assert_in_delta(3.14159265358979, @o.complex_computation, 0.0001)
+ assert_equal(["baz", "bar"], @o.last(2))
+ assert_raise(ArgumentError){ @o.last(3) }
+ end
+
+
+Example: RSpec expectations
+===========================
+Here's some code before and after filtering it with xmpfilter:
+
+ class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1
+ end
+
+ context "Testing xmpfilter's expectation expansion" do
+ setup do
+ @o = X.new
+ end
+
+ specify "Should expand should_equal expectations" do
+ @o.foo(true) # =>
+ @o.foo(true).a # =>
+ @o.foo(false) # =>
+ end
+
+ specify "Should expand should_raise expectations" do
+ @o.bar # =>
+ end
+
+ specify "Should expand should_be_nil expectations" do
+ @o.baz # =>
+ end
+
+ specify "Should expand correct expectations for complex values" do
+ @o.babar # =>
+ end
+
+ specify "Should expand should_be_close expectations" do
+ @o.fubar(10) # =>
+ end
+ end
+
+
+after piping it to xmpfilter -s:
+
+ class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1 # !> already initialized constant A
+ end
+
+ context "Testing xmpfilter's expectation expansion" do
+ setup do
+ @o = X.new
+ end
+
+ specify "Should expand should_equal expectations" do
+ (@o.foo(true)).should_be_a_kind_of X::Y
+ (@o.foo(true).inspect).should_equal "#"
+ (@o.foo(true).a).should_equal 2
+ (@o.foo(false)).should_equal 2
+ end
+
+ specify "Should expand should_raise expectations" do
+ lambda{(@o.bar)}.should_raise RuntimeError
+ end
+
+ specify "Should expand should_be_nil expectations" do
+ (@o.baz).should_be_nil
+ end
+
+ specify "Should expand correct expectations for complex values" do
+ (@o.babar).should_equal [1, 2]
+ end
+
+ specify "Should expand should_be_close expectations" do
+ (@o.fubar(10)).should_be_close(101.0, 0.0001)
+ end
+ end
+
+
+Example: expectations expectations
+==================================
+Expectations is a light-weight unit testing framework by Jay Fields.
+(http://expectations.rubyforge.org)
+
+Here's some code before and after filtering it with xmpfilter:
+
+ require 'rubygems'
+ require 'expectations'
+
+ S = Struct.new :a
+ Expectations do
+ 1 + 1 # =>
+ "a".length # =>
+ [][1] # =>
+ 1.hoge # =>
+ 1.1 + 1.0 # =>
+ S.new(1) # =>
+ end
+
+after piping it to xmpfilter --expectations:
+
+ require 'rubygems'
+ require 'expectations'
+
+ S = Struct.new :a
+ Expectations do
+ expect 2 do
+ 1 + 1
+ end
+
+ expect 1 do
+ "a".length
+ end
+
+ expect nil do
+ [][1]
+ end
+
+ expect NoMethodError do
+ 1.hoge
+ end
+
+ expect 2.0999..2.1001 do
+ 1.1 + 1.0
+ end
+
+ expect S do
+ S.new(1)
+ end
+
+ expect "#" do
+ S.new(1).inspect
+ end
+
+ end
+
+
+License
+=======
+xmpfilter is licensed under the same terms as Ruby.
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/Rakefile b/bundles/ruby.tmbundle/Support/vendor/rcodetools/Rakefile
new file mode 100644
index 000000000..7d2c227f8
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/Rakefile
@@ -0,0 +1,121 @@
+
+PKG_REVISION = ".0"
+
+$:.unshift "lib" if File.directory? "lib"
+require 'rcodetools/xmpfilter'
+require 'rake/testtask'
+include Rcodetools
+RCT_VERSION = XMPFilter::VERSION
+
+desc "Run the unit tests in pure-Ruby mode ."
+Rake::TestTask.new(:test) do |t|
+ t.test_files = FileList['test/test*.rb']
+ t.verbose = true
+end
+
+begin
+ require 'rcov/rcovtask'
+ desc "Run rcov."
+ Rcov::RcovTask.new do |t|
+ t.rcov_opts << "--xrefs" # comment to disable cross-references
+ t.test_files = FileList['test/test_*.rb'].to_a - ["test/test_functional.rb"]
+ t.verbose = true
+ end
+
+ desc "Save current coverage state for later comparisons."
+ Rcov::RcovTask.new(:rcovsave) do |t|
+ t.rcov_opts << "--save"
+ t.test_files = FileList['test/test_*.rb'].to_a - ["test/test_functional.rb"]
+ t.verbose = true
+ end
+rescue LoadError
+ # rcov is not installed
+end
+task :default => :test
+
+
+#{{{ Package tasks
+PKG_FILES = FileList[
+ "bin/xmpfilter", "bin/rct-*", "bin/ruby-toggle-file", "bin/rbtest",
+"lib/**/*.rb",
+"CHANGES", "rcodetools.*", "icicles-rcodetools.el", "anything-rcodetools.el",
+"README", "README.*", "THANKS",
+"Rakefile", "Rakefile.method_analysis",
+"setup.rb",
+"test/**/*.rb","test/**/*.taf"
+]
+
+begin
+ require 'rake/gempackagetask'
+ Spec = Gem::Specification.new do |s|
+ s.name = "rcodetools"
+ s.version = RCT_VERSION + PKG_REVISION
+ s.summary = "rcodetools is a collection of Ruby code manipulation tools"
+ s.description = <, "Mauricio Fernandez" }
+ s.homepage = "http://eigenclass.org/hiki.rb?rcodetools"
+ s.bindir = "bin"
+ s.executables = %w[rct-complete rct-doc xmpfilter rct-meth-args]
+ s.has_rdoc = true
+ s.extra_rdoc_files = %w[README]
+ s.rdoc_options << "--main" << "README" << "--title" << 'rcodetools'
+ s.test_files = Dir["test/test_*.rb"]
+ s.post_install_message = < [:test]
+ Rake::GemPackageTask.new(Spec) do |p|
+ p.need_tar_gz = true
+ end
+
+rescue LoadError
+ # RubyGems not installed
+end
+
+desc "install by setup.rb"
+task :install do
+ sh "sudo ruby setup.rb install"
+end
+
+desc "release in rubyforge (package is created)"
+task :release_only do
+ sh "rubyforge login"
+ sh "rubyforge add_release rcodetools rcodetools #{RCT_VERSION} pkg/rcodetools-#{RCT_VERSION}.0.tar.gz "
+ sh "rubyforge add_file rcodetools rcodetools #{RCT_VERSION} pkg/rcodetools-#{RCT_VERSION}.0.gem "
+end
+
+desc "release in rubyforge"
+task :release => [:package, :release_only]
+
+# vim: set sw=2 ft=ruby:
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/Rakefile.method_analysis b/bundles/ruby.tmbundle/Support/vendor/rcodetools/Rakefile.method_analysis
new file mode 100644
index 000000000..1dc8e0414
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/Rakefile.method_analysis
@@ -0,0 +1,30 @@
+
+# Rake tasks to generate TAGS and gather method analysis information.
+# See README.method_analysis for more information.
+
+## my standard Rakefile
+task :tags => "TAGS"
+
+desc "Generate method_analysis by ruby -rmethod_analyzer."
+task :analyze => [:_prepare_method_analyze, :tags] do
+ at_exit { sh "ls -l method_analysis" }
+end
+
+task :_prepare_method_analyze do
+ ENV['METHOD_ANALYZER_FORMAT']="marshal"
+ sh "rm -f method_analysis"
+ puts "generating method_analysis"
+end
+
+## application-specific Rakefile (RTtool)
+task :analyze do
+ sh "ruby -Ilib -rmethod_analyzer test/test.rb"
+ sh "ruby -Ilib -rmethod_analyzer test/test-rt2html-lib.rb"
+ sh "ruby -Ilib -rmethod_analyzer test/test-rtparser.rb"
+end
+
+file "TAGS" => FileList["lib/rt/*.rb"] do
+ sh "rct-meth-args -t lib/rt/*.rb > TAGS"
+end
+
+
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/THANKS b/bundles/ruby.tmbundle/Support/vendor/rcodetools/THANKS
new file mode 100644
index 000000000..0ed1e3763
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/THANKS
@@ -0,0 +1,11 @@
+Some names forgotten, tell me if you care :) -- mfp
+
+rubikitch
+* expanded xmp3.rb (a previous version of xmpfilter.rb) to support RSpec expectations
+* wrote the elisp magic to use xmpfilter.rb with emacs
+* made the 100% accurate, editor-independent completion system
+[rubikitch took xmpfilter and turned it into the much more powerful
+rcodetools, so there are way too many things to list them here :)]
+
+Adagios
+* found & fixed problem with rcodetools.vim plugin on win32
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/anything-rcodetools.el b/bundles/ruby.tmbundle/Support/vendor/rcodetools/anything-rcodetools.el
new file mode 100644
index 000000000..e21a743de
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/anything-rcodetools.el
@@ -0,0 +1,151 @@
+;;; anything-rcodetools.el --- accurate Ruby method completion with anything
+;; $Id: anything-rcodetools.el,v 1.13 2009/04/20 16:25:37 rubikitch Exp $
+
+;;; Copyright (c) 2007 rubikitch
+
+;; Author: rubikitch
+;; URL: http://www.emacswiki.org/cgi-bin/wiki/download/anything-rcodetools.el
+
+;;; Use and distribution subject to the terms of the Ruby license.
+
+;;; Commentary:
+
+;; (0) You need rcodetools, anything.el and FastRI. Note that you do not have to
+;; configure anything.el if you use anything.el for this package.
+;; (1) You need to add to .emacs:
+;; (require 'anything)
+;; (require 'anything-rcodetools)
+;; ;; Command to get all RI entries.
+;; (setq rct-get-all-methods-command "PAGER=cat fri -l")
+;; ;; See docs
+;; (define-key anything-map "\C-z" 'anything-execute-persistent-action)
+
+;;; Commands:
+;;
+;; Below are complete command list:
+;;
+;;
+;;; Customizable Options:
+;;
+;; Below are customizable option list:
+;;
+
+;;; History:
+
+;; $Log: anything-rcodetools.el,v $
+;; Revision 1.13 2009/04/20 16:25:37 rubikitch
+;; Set anything-samewindow to nil
+;;
+;; Revision 1.12 2009/04/18 10:12:02 rubikitch
+;; Adjust to change of `use-anything-show-completion'
+;;
+;; Revision 1.11 2009/04/17 20:21:47 rubikitch
+;; * require anything
+;; * require anything-show-completion.el if available
+;;
+;; Revision 1.10 2009/04/17 20:11:03 rubikitch
+;; removed old code
+;;
+;; Revision 1.9 2009/04/17 20:07:52 rubikitch
+;; * use --completion-emacs-anything option
+;; * New implementation of `anything-c-source-complete-ruby-all'
+;;
+;; Revision 1.8 2009/04/15 10:25:25 rubikitch
+;; Set `anything-execute-action-at-once-if-one' t
+;;
+;; Revision 1.7 2009/04/15 10:24:23 rubikitch
+;; regexp bug fix
+;;
+;; Revision 1.6 2008/01/14 17:59:34 rubikitch
+;; * uniform format (anything-c-source-complete-ruby, anything-c-source-complete-ruby-all)
+;; * rename command: anything-c-ri -> anything-rct-ri
+;;
+;; Revision 1.5 2008/01/13 17:54:04 rubikitch
+;; anything-current-buffer advice.
+;;
+;; Revision 1.4 2008/01/08 14:47:34 rubikitch
+;; Added (require 'rcodetools).
+;; Revised commentary.
+;;
+;; Revision 1.3 2008/01/04 09:32:29 rubikitch
+;; *** empty log message ***
+;;
+;; Revision 1.2 2008/01/04 09:21:23 rubikitch
+;; fixed typo
+;;
+;; Revision 1.1 2008/01/04 09:21:05 rubikitch
+;; Initial revision
+;;
+
+;;; Code:
+
+(require 'anything)
+(require 'rcodetools)
+(when (require 'anything-show-completion nil t)
+ (use-anything-show-completion 'rct-complete-symbol--anything
+ '(length pattern)))
+
+(defun anything-rct-ri (meth)
+ (ri (get-text-property 0 'desc meth)))
+
+(defun anything-rct-complete (meth)
+ (save-excursion
+ (set-buffer anything-current-buffer)
+ (search-backward pattern)
+ (delete-char (length pattern)))
+ (insert meth))
+
+(setq rct-complete-symbol-function 'rct-complete-symbol--anything)
+(defvar anything-c-source-complete-ruby
+ '((name . "Ruby Method Completion")
+ (candidates . rct-method-completion-table)
+ (init
+ . (lambda ()
+ (condition-case x
+ (rct-exec-and-eval rct-complete-command-name "--completion-emacs-anything")
+ ((error) (setq rct-method-completion-table nil)))))
+ (action
+ ("Completion" . anything-rct-complete)
+ ("RI" . anything-rct-ri))
+ (volatile)
+ (persistent-action . anything-rct-ri)))
+
+(defvar rct-get-all-methods-command "PAGER=cat fri -l")
+(defvar anything-c-source-complete-ruby-all
+ '((name . "Ruby Method Completion (ALL)")
+ (init
+ . (lambda ()
+ (unless (anything-candidate-buffer)
+ (with-current-buffer (anything-candidate-buffer 'global)
+ (call-process-shell-command rct-get-all-methods-command nil t)
+ (goto-char 1)
+ (while (re-search-forward "^.+[:#.]\\([^:#.]+\\)$" nil t)
+ (replace-match "\\1\t[\\&]"))))))
+ (candidates-in-buffer
+ . (lambda ()
+ (let ((anything-pattern (format "^%s.*%s" (regexp-quote pattern) anything-pattern)))
+ (anything-candidates-in-buffer))))
+ (display-to-real
+ . (lambda (line)
+ (if (string-match "\t\\[\\(.+\\)\\]$" line)
+ (propertize (substring line 0 (match-beginning 0))
+ 'desc (match-string 1 line))
+ line)))
+ (action
+ ("Completion" . anything-rct-complete)
+ ("RI" . anything-rct-ri))
+ (persistent-action . anything-rct-ri)))
+
+
+(defun rct-complete-symbol--anything ()
+ (interactive)
+ (let ((anything-execute-action-at-once-if-one t)
+ anything-samewindow)
+ (anything '(anything-c-source-complete-ruby
+ anything-c-source-complete-ruby-all))))
+
+(provide 'anything-rcodetools)
+
+;; How to save (DO NOT REMOVE!!)
+;; (emacswiki-post "anything-rcodetools.el")
+;;; install-elisp.el ends here
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/bin/rbtest b/bundles/ruby.tmbundle/Support/vendor/rcodetools/bin/rbtest
new file mode 100755
index 000000000..ab51c9425
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/bin/rbtest
@@ -0,0 +1,266 @@
+#! /usr/local/bin/ruby18
+# Copyright (c) 2006-2007 rubikitch
+#
+# Use and distribution subject to the terms of the Ruby license.
+
+USAGE = <<'XXX'
+Usage: rbtest SCRIPT [-S RUBY_INTERPRETER] [Test::Unit OPTIONS]
+Usage: rbtest [-h] [--help] [--example]
+
+I am rbtest, embedded Test::Unit executor for one-file scripts.
+Splitting a small script into many files (executables, libraries and tests) is cumbersome.
+And it is handy to put unit tests near implementations like D language, which has
+built-in unittest keyword.
+
+Embedded Test::Unit is simpler than vanilla Test::Unit.
+You do not have to define a Test::Unit::TestCase subclass,
+it is automagically defined and executed by me.
+Embedded Test::Unit uses =begin/=end comment blocks.
+
+"=begin TEST_METHOD_NAME" blocks define test methods, eg. "=begin test_foo".
+"=begin rbtest" blocks define utility methods and setup/teardown methods.
+
+Of course, you MUST use "if __FILE__ ==$0" idiom to split executable and class/method/function.
+
+I am also an real-life example of rbtest usage.
+Issue:
+ rbtest --example
+to show me.
+
+
+options:
+ -h, --help Print usage.
+ -S RUBY_INTERPRETER Use Ruby interpreter RUBY_INTERPRETER.
+ --example Print this file.
+ --output Print internally-generated test script (for debug).
+XXX
+
+
+def first_test(script_filename)
+ "require 'test/unit';" +
+ "load '#{script_filename}';" +
+ "class TestByRbtest < Test::Unit::TestCase;"
+end
+
+=begin rbtest
+def setup
+end
+
+def unindent(s)
+ s.lines.map{|x| x[1..-1]}.join
+end
+=end
+
+=begin test_script_to_test_script
+# indent is needed to avoid syntax error.
+script = < http://eigenclass.org
+# 2006-2007 rubikitch http://www.rubyist.net/~rubikitch/
+#
+# Use and distribution subject to the same conditions as Ruby.
+
+require 'rcodetools/options'
+include Rcodetools
+$VERBOSE = nil
+$__method_args_off = true
+
+if ARGV.empty? or ARGV.include? '-h' or ARGV.include? '--help'
+ puts < [ ...]
+
+-Idirectory specify $LOAD_PATH directory (same as ruby)
+--dev Add this project's bin/ and lib/ to $LOAD_PATH.
+ A directory that has Rakefile is considered as project base direcotry.
+-i omit instance methods defined in classes
+-m omit instance methods defined in modules
+-c omit class methods
+
+-n print the filename and line number with output lines
+-t generate TAGS output
+--summarize summary output sorted by method name
+
+The given files will be #require()d in order.
+Examples:
+ rct-meth-args complex
+ rct-meth-args thread
+ rct-meth-args -c rubygems
+EOF
+ exit # '
+end
+
+def debugprint(*args)
+ $stderr.puts(*args) if $DEBUG
+end
+
+module MethodArgs
+ MAX_ARGS = 20
+
+ private
+ def needed_args(arity)
+ arity >= 0 ? arity : arity.abs - 1
+ end
+
+ def with_tracer
+ begin
+ set_trace_func @__trace_func
+ yield
+ ensure
+ set_trace_func nil
+ end
+ end
+
+ module LineContents
+ # usage: Contents[filename][lineno]
+ Contents = Hash.new{ |h,k|
+ sum = 0
+ # Unshift is needed because lineno starts with 1.
+ h[k] = File.readlines(k).map{ |line| [line.chomp, sum+=line.length] }.unshift nil
+ }
+ def content
+ Contents[filename][lineno.to_i][0] rescue ""
+ end
+
+ def byte
+ Contents[filename][lineno.to_i-1][1] rescue 0
+ end
+
+ def arg_desc
+ # TODO
+ desc = content[ /\((.+)\)/]
+ desc.gsub!(/(\S),(\S)/, '\1, \2')
+ desc.gsub!(/(\S)=(\S)/, '\1 = \2')
+ desc
+ end
+
+ FileNameCache = Hash.new{ |h,k| h[k] = File.expand_path(k) }
+ def full_filename
+ FileNameCache[filename]
+ end
+ end
+
+ class Location < Struct.new(:filename, :lineno)
+ include LineContents
+ end
+
+ class Printer
+ def method_info(io, x)
+ prefix = x[:location] ? "#{x[:location].filename}:#{x[:location].lineno}:" : ""
+ io.puts "#{prefix}#{x[:fullname]}#{x[:arg_desc]}" unless x[:klass].to_s == ""
+ end
+
+ def included_location(io, x)
+ x[:callsite] and io.print "#{x[:callsite].filename}:#{x[:callsite].lineno}:"
+ io.puts([ x[:comment], x[:mod], x[:flag], x[:self] ].join(" "))
+ end
+ end
+
+ class SummarizePrinter
+ def initialize
+ @hash = Hash.new
+ at_exit { print_result }
+ end
+
+ def method_info(io, x)
+ @io = io
+ prefix = x[:location] ? "#{x[:location].filename}:#{x[:location].lineno}:" : ""
+ (@hash[x[:meth]]||=[]) << "#{prefix}#{x[:fullname]}#{x[:arg_desc]}" unless x[:klass].to_s == ""
+ end
+
+ def included_location(io, x)
+ # not implemented
+ end
+
+ def print_result
+ @hash.keys.sort.each do |meth|
+ @io.puts meth
+ @hash[meth].each do |line|
+ @io.puts line
+ end
+ @io.puts
+ end
+ end
+ end
+
+ class TagsPrinter
+ def initialize
+ @previous_filename = ""
+ end
+
+ def output_filename(filename)
+ if @previous_filename != filename
+ @previous_filename = filename
+ puts "\cl"
+ puts "#{filename},0"
+ end
+ end
+
+ def method_info(io, x)
+ return unless x[:location]
+ output_filename x[:location].full_filename
+ io.puts "#{x[:location].content}::#{x[:fullname]}#{x[:location].lineno},#{x[:location].byte}"
+ end
+
+ def included_location(io, x)
+ return unless x[:callsite]
+ output_filename x[:callsite].full_filename
+ io.puts "#{x[:callsite].content}::#{x[:mod]}#{x[:callsite].lineno},#{x[:callsite].byte}"
+ end
+ end
+
+ def _print_method_info(klass, is_singleton, meth, arg_desc=nil, location=nil, with_location=$__with_location, printer=$__printer)
+ arg_desc ||= "(...)"
+ arg_desc = " " + arg_desc unless arg_desc.empty?
+ flag = is_singleton ? "." : "#"
+ x = { :arg_desc => arg_desc, :klass => klass,
+ :meth => meth.to_s,
+ :fullname => [klass, flag, meth].join,
+ :location => with_location && location,
+ }
+ printer.method_info $>, x
+ end
+
+ def output_attr_info(klass, object, meth, is_singleton, location)
+ arg_desc = meth.to_s =~ /=$/ ? "(value)" : ""
+ _print_method_info klass, is_singleton, meth, arg_desc, location
+ end
+
+ def output_method_info(klass, object, meth, is_singleton = false, by_attr = nil, by_define_method = nil)
+ return if $__method_args_off
+ file = line = params = values = nil
+ location = nil
+ begin
+ unless %w[initialize].include?(meth.to_s)
+ if is_singleton
+ return if class << klass; private_instance_methods(true) end.include?(meth.to_s)
+ else
+ return if class << object; private_instance_methods(true) end.include?(meth.to_s)
+ end
+ end
+ rescue TypeError # no virtual class
+ end
+
+ arity = is_singleton ? object.method(meth).arity : klass.instance_method(meth).arity
+ @__trace_func = lambda{|event, file, line, id, binding, classname|
+ begin
+ debugprint "!EVENT: #{event} #{classname}##{id}, #{file} #{line}"
+ debugprint "(#{self} #{meth})"
+ if event[/call/] && classname == self && id == meth
+ location = Location.new(file, line) if event == 'call'
+ debugprint "EVENT: #{event} #{classname}##{id}"
+ throw :done
+ end
+ rescue Exception
+ nil # rcov workaround
+ end
+ }
+ if by_define_method
+ _print_method_info klass, is_singleton, meth, nil, by_define_method
+ return
+ end
+
+ if by_attr
+ output_attr_info klass, object, meth, is_singleton, by_attr
+ return
+ end
+
+ catch(:done) do
+ begin
+ with_tracer { object.send(meth, *(0...needed_args(arity))) }
+ rescue Exception
+ nil # rcov workaround
+ end
+ end
+
+ arg_desc = location.arg_desc
+
+ _print_method_info klass, is_singleton, meth, arg_desc, location
+ rescue Exception
+ debugprint "GOT EXCEPTION while processing #{klass} #{meth}"
+ debugprint $!.class
+ debugprint $!.message
+ debugprint $!.backtrace
+ _print_method_info klass, is_singleton, meth, nil, location
+ ensure
+ set_trace_func(nil)
+ end
+end
+
+class Object
+ include MethodArgs
+end
+
+class Module
+ class CallSite # compatible with Location
+ include MethodArgs::LineContents
+ def initialize(caller_string)
+ @filename, @lineno, @in = caller_string.split(/:/)
+ end
+ attr_reader :filename, :lineno
+ end
+
+ def _method_defined_with(ivar, caller, &block)
+ begin
+ instance_variable_set(ivar, caller)
+ yield
+ ensure
+ instance_variable_set(ivar, false)
+ end
+ end
+
+ def with_attr(caller, &block)
+ _method_defined_with :@by_attr, caller, &block
+ end
+
+ def with_define_method(caller, &block)
+ _method_defined_with :@by_define_method, caller, &block
+ end
+
+ [ :attr, :attr_reader, :attr_writer, :attr_accessor ].each do |meth|
+ attr = instance_method(meth)
+ define_method(meth) do |*args|
+ with_attr(CallSite.new(caller(1)[0])){ attr.bind(self).call(*args) }
+ end
+ end
+
+ alias :__define_method_orig :define_method
+ def define_method(*args, &body)
+ with_define_method(CallSite.new(caller(1)[0])){ __define_method_orig(*args, &body) }
+ end
+
+end
+
+new_args = []
+omissions = {}
+$__with_location = false
+$__printer = Printer.new
+i_opt_p = false
+
+ARGV.each do |arg|
+ case arg
+ when "-n"; $__with_location = true
+ when "-t"; $__printer = TagsPrinter.new; $__with_location = true
+ when "--summarize"; $__printer = SummarizePrinter.new
+ when /-I(.+)$/; $:.unshift $1
+ when "-I"; i_opt_p = true
+ when "--dev"; OptionHandler.auto_include_paths($:, Dir.pwd)
+ when /^-.$/; omissions[$&] = true
+ else
+ if i_opt_p
+ $:.unshift arg
+ i_opt_p = false
+ else
+ new_args << arg
+ end
+ end
+end
+
+ARGV.replace new_args
+
+class Object
+ ALLOCATOR = Hash.new{|h,k| h[k] = k.allocate }.merge(Fixnum=>1,
+ Bignum=>10000000000000000,
+ Float=>1.1,
+ Symbol=>:method_args_tmp,
+ Binding=>binding,
+ UnboundMethod=>instance_method(:object_id),
+ Method=>method(:object_id),
+ Proc=>lambda{},
+ Continuation=>callcc{|c|c},
+ Thread=>Thread.new{},
+ FalseClass=>false,
+ TrueClass=>true,
+ NilClass=>nil,
+ Struct=>Struct.new(:a).new(1))
+
+# ABSTRACT_CLASSES = %w[Digest::Base ]
+ def self.method_added(meth)
+# if ABSTRACT_CLASSES.include? self.to_s
+# _print_method_info self, false, meth
+# return
+# end
+ begin
+ o = ALLOCATOR[self]
+ rescue Exception # for abstract classes
+ nil
+ end
+ output_method_info(self, o, meth, false, @by_attr, @by_define_method)
+ end
+end unless omissions["-i"]
+
+class Module
+ method_added = instance_method(:method_added)
+ define_method(:method_added) do |meth|
+ begin
+ if instance_of? Module
+ o = Object.new
+ o.extend(self)
+ output_method_info(self, o, meth, false, @by_attr, @by_define_method)
+ end
+ method_added.bind(self).call(meth)
+ rescue Exception
+ _print_method_info self, false, meth
+ end
+ end
+end unless omissions["-m"]
+
+
+class Class
+ def singleton_method_added(meth)
+ by_attr = class << self; @by_attr; end
+ by_define_method = class << self; @by_define_method; end
+ output_method_info(self, self, meth, true, by_attr, by_define_method)
+ rescue Exception
+ _print_method_info self, true, meth
+ end
+end unless omissions["-c"]
+
+#### include / extend
+class Module
+ def _print_included_location(mod, caller_string, comment, flag, with_location=$__with_location, printer=$__printer)
+ if caller_string # nil when the class is defined by C
+ x = { :comment => comment, :mod => mod, :flag => flag, :self => self,
+ :callsite => with_location && CallSite.new(caller_string)
+ }
+ printer.included_location $>, x
+ end
+ end
+
+ undef_method :included
+ def included(mod)
+ _print_included_location mod, caller(0)[1], "include", "<="
+ end
+
+ undef_method :extended
+ def extended(mod)
+ _print_included_location mod, caller(0)[1], "extend", "<-" if Module === mod
+ end
+end
+
+#### inheritance
+class Class
+ undef :inherited
+ def inherited(klass, caller_level=0)
+ _print_included_location klass, caller(caller_level)[1], "class", "<" unless self == Object
+ end
+end
+
+#### Struct inspection
+class << Struct
+ def to_s
+ orig = super
+ if orig =~ /" : ""
+ else
+ orig
+ end
+ end
+
+ def inherited(klass)
+ if self == Struct
+ @inherited_delay = lambda{ super(klass, 3) }
+ else
+ super(klass, 1)
+ end
+ end
+
+ @@struct_initializing = false
+ def method_added(meth)
+ super unless @@struct_initializing
+ end
+
+ orig_new = instance_method(:new)
+ define_method(:new) do |*args|
+ begin
+ @@struct_initializing = true
+ orig_new.bind(self).call(*args)
+ ensure
+ @@struct_initializing = false
+ @inherited_delay[]
+ end
+ end
+
+end
+
+$__method_args_off = false
+
+ARGV.each{|x|
+ begin
+ require x
+ rescue LoadError
+ load x
+ end
+}
+
+$__method_args_off = true
+# END { puts "zzzz OK" }
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/bin/ruby-toggle-file b/bundles/ruby.tmbundle/Support/vendor/rcodetools/bin/ruby-toggle-file
new file mode 100644
index 000000000..9adccc929
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/bin/ruby-toggle-file
@@ -0,0 +1,26 @@
+#! /usr/local/bin/ruby18
+require 'ruby_toggle_file'
+require 'optparse'
+
+USAGE = < markers.") do
+ klass = XMPAddMarkers
+ end
+
+ opts.handle_interpreter options
+
+ opts.separator ""
+ opts.separator "Specific options:"
+ opts.on("-l N", "--min-line-length N", Integer, "Align markers to N spaces.") do |min_codeline_size|
+ options[:min_codeline_size] = min_codeline_size
+ end
+ opts.on("--rails", "Setting appropriate for Rails.",
+ "(no warnings, find working directory,",
+ " Test::Unit assertions)") do
+ require 'rcodetools/xmptestunitfilter'
+ options[:warnings] = false
+ klass = XMPTestUnitFilter
+ rails_settings = true
+ end
+ opts.on("--[no-]poetry", "Whether to use extra parentheses.",
+ "(default: use them)") do |poetry_p|
+ options[:use_parentheses] = !poetry_p
+ end
+ opts.on("--[no-]warnings", "Whether to add warnings (# !>).",
+ "(default: enabled)") {|warnings_p| options[:warnings] = warnings_p }
+ opts.on("-q", "--quiet", "Supress standard output.") do
+ options[:output_stdout] = false
+ end
+
+ opts.handle_misc options
+end
+
+set_extra_opts options
+opts.parse!(ARGV)
+
+if rails_settings && !options[:wd]
+ if File.exist? ARGF.path
+ options[:wd] = File.dirname(ARGF.path)
+ elsif File.exist? "test/unit"
+ options[:wd] = "test/unit"
+ elsif File.exist? "unit"
+ options[:wd] = "unit"
+ end
+end
+targetcode = ARGF.read
+Dir.chdir options[:wd] if options[:wd]
+
+if XMPFilter.detect_rbtest(targetcode, options)
+ require 'rcodetools/xmptestunitfilter'
+ klass = XMPTestUnitFilter
+end
+
+# Do the job. dispatched by klass.
+puts klass.run(targetcode, options)
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/icicles-rcodetools.el b/bundles/ruby.tmbundle/Support/vendor/rcodetools/icicles-rcodetools.el
new file mode 100644
index 000000000..a6de2ca6e
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/icicles-rcodetools.el
@@ -0,0 +1,35 @@
+;;; icicles-rcodetools.el -- accurate completion with icicles
+
+;;; Copyright (c) 2006-2007 rubikitch
+;;;
+;;; Use and distribution subject to the terms of the Ruby license.
+
+(require 'icicles)
+(require 'rcodetools)
+
+(setq rct-complete-symbol-function 'rct-complete-symbol--icicles)
+(icicle-define-command rct-complete-symbol--icicles
+ "Perform ruby method and class completion on the text around point with icicles.
+C-M-RET shows RI documentation on each candidate.
+See also `rct-interactive'."
+
+ (lambda (result)
+ (save-excursion
+ (search-backward pattern)
+ (setq beg (point)))
+ (delete-region beg end)
+ (insert result)) ;/function
+ "rct-complete: " ;prompt
+ rct-method-completion-table
+ nil nil pattern nil nil nil
+ ((end (point)) beg
+ (icicle-list-join-string "\t")
+ (icicle-list-use-nth-parts '(1))
+ (icicle-point-position-in-candidate 'input-end)
+ pattern klass alist
+ (icicle-candidate-help-fn
+ (lambda (result)
+ (ri (cdr (assoc result alist)))))) ;bindings
+ (rct-exec-and-eval rct-complete-command-name "--completion-emacs-icicles"))
+
+(provide 'icicles-rcodetools)
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/method_analyzer.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/method_analyzer.rb
new file mode 100644
index 000000000..4f71cc274
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/method_analyzer.rb
@@ -0,0 +1,107 @@
+class Module
+ remove_method :attr_reader
+ def attr_reader(*names)
+ names.each do |name|
+ module_eval "def #{name}() @#{name} end"
+ end
+ end
+ remove_method :attr_writer
+ def attr_writer(*names)
+ names.each do |name|
+ module_eval "def #{name}=(x) @#{name}=x end"
+ end
+ end
+ remove_method :attr_accessor
+ def attr_accessor(*names)
+ attr_reader(*names)
+ attr_writer(*names)
+ end
+ remove_method :attr
+ def attr(name, writer=false)
+ attr_reader name
+ attr_writer name if writer
+ end
+end
+
+
+module MethodAnalyzer
+ @@methods = Hash.new{ |h,k| h[k] = Hash.new{ |h,k| h[k] = []} }
+ @@whereis = []
+ @@expand_path = Hash.new{ |h,k| h[k] = File.expand_path(k)}
+
+ def self.trace_func(event, file, line, id, binding, klass, *rest)
+ return if file == __FILE__
+ return if (event != 'call' and event != 'c-call')
+ return if klass == Class and id == :inherited
+ return if klass == Module and id == :method_added
+ return if klass == Kernel and id == :singleton_method_added
+ saved_crit = Thread.critical
+ Thread.critical = true
+
+ the_self = eval("self",binding)
+ flag = Class === the_self ? "." : "#"
+ #klass = klass == Kernel ? Object : klass
+ fullname = "#{klass}#{flag}#{id}"
+ file.replace @@expand_path[file]
+ if event == 'call'
+ @@whereis << [file, line, fullname] if file !~ /\(eval\)$/
+ file, line, rest = caller(4)[0].split(/:/)
+ file.replace @@expand_path[file] # DRY
+ p caller(0) if $DEBUG
+ line = line.to_i
+ end
+ @@methods[file][line] << fullname if event =~ /call/
+
+ Thread.critical = saved_crit
+ end
+
+ def self.at_exit__output_marshal
+ at_exit do
+ set_trace_func nil
+ dbfile = "method_analysis"
+ old = Marshal.load(File.read(dbfile)) rescue {}
+ open(dbfile, "wb") do |io|
+ # Because Marshal.dump cannot handle hashes with default_proc
+ @@methods.default = nil
+ @@methods.each_value{ |v| v.default=nil; v.each_value{ |vv| vv.uniq! } }
+ Marshal.dump(@@methods.merge(old), io)
+ end
+ end
+ end
+
+
+ def self.at_exit__output_text
+ at_exit do
+ set_trace_func nil
+ puts "method fullnames"
+ @@methods.sort.each do |file, lines|
+ lines.sort.each do |line, methods|
+ printf "%s:%s:%s\n", file, line, methods.uniq.join(" ")
+ end
+ end
+
+ puts
+ puts "method definitions"
+ @@whereis.sort.uniq.each do |file, line, fullname |
+ printf "%s:%s:%s\n", file, line, fullname
+ end
+
+ end
+ end
+
+ def self.set_at_exit
+ case ENV['METHOD_ANALYZER_FORMAT']
+ when 'marshal'
+ at_exit__output_marshal
+ else
+ at_exit__output_text
+ end
+ end
+
+ set_at_exit
+ set_trace_func method(:trace_func).to_proc
+end
+
+if __FILE__ == $0
+ load "./test/data/method_analyzer-data.rb"
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/compat.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/compat.rb
new file mode 100644
index 000000000..13e50832b
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/compat.rb
@@ -0,0 +1,14 @@
+if RUBY_VERSION >= "1.9"
+ class String
+ alias :each :each_line
+ include Enumerable
+ end
+
+ module Enumerable
+ alias :enum_with_index :each_with_index
+ end
+
+ class Array
+ alias :to_s :join
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/completion.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/completion.rb
new file mode 100644
index 000000000..ccc936a3c
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/completion.rb
@@ -0,0 +1,406 @@
+# Nearly 100% accurate completion for any editors!!
+# by rubikitch
+
+require 'rcodetools/xmpfilter'
+require 'enumerator'
+
+module Rcodetools
+
+# Common routines for XMPCompletionFilter/XMPDocFilter
+module ProcessParticularLine
+ def fill_literal!(expr)
+ [ "\"", "'", "`" ].each do |q|
+ expr.gsub!(/#{q}(.+)#{q}/){ '"' + "x"*$1.length + '"' }
+ end
+ expr.gsub!(/(%([wWqQxrs])?(\W))(.+?)\3/){
+ percent = $2 == 'x' ? '%'+$3 : $1 # avoid executing shell command
+ percent + "x"*$4.length + $3
+ }
+ [ %w[( )], %w[{ }], %w![ ]!, %w[< >] ].each do |b,e|
+ rb, re = [b,e].map{ |x| Regexp.quote(x)}
+ expr.gsub!(/(%([wWqQxrs])?(#{rb}))(.+)#{re}/){
+ percent = $2 == 'x' ? '%'+$3 : $1 # avoid executing shell command
+ percent + "x"*$4.length + e
+ }
+ end
+ end
+
+ module ExpressionExtension
+ attr_accessor :eval_string
+ attr_accessor :meth
+ end
+ OPERATOR_CHARS = '\|^&<>=~\+\-\*\/%\['
+ def set_expr_and_postfix!(expr, column, ®exp)
+ expr.extend ExpressionExtension
+
+ @postfix = ""
+ expr_orig = expr.clone
+ column ||= expr.length
+ last_char = expr[column-1]
+ expr.replace expr[ regexp[column] ]
+ debugprint "expr_orig=#{expr_orig}", "expr(sliced)=#{expr}"
+ right_stripped = Regexp.last_match.post_match
+ _handle_do_end right_stripped
+ aref_or_aset = aref_or_aset? right_stripped, last_char
+ debugprint "aref_or_aset=#{aref_or_aset.inspect}"
+ set_last_word! expr, aref_or_aset
+ fill_literal! expr_orig
+ _handle_brackets expr_orig, expr
+ expr << aref_or_aset if aref_or_aset
+ _handle_keywords expr_orig, column
+ debugprint "expr(processed)=#{expr}"
+ expr
+ end
+
+ def _handle_do_end(right_stripped)
+ right_stripped << "\n"
+ n_do = right_stripped.scan(/[\s\)]do\s/).length
+ n_end = right_stripped.scan(/\bend\b/).length
+ @postfix = ";begin" * (n_do - n_end)
+ end
+
+ def _handle_brackets(expr_orig, expr)
+ [ %w[{ }], %w[( )], %w![ ]! ].each do |left, right|
+ n_left = expr_orig.count(left) - expr.count(left)
+ n_right = expr_orig.count(right) - expr.count(right)
+ n = n_left - n_right
+ @postfix << ";#{left}" * n if n >= 0
+ end
+ end
+
+ def _handle_keywords(expr_orig, column)
+ %w[if unless while until for].each do |keyw|
+ pos = expr_orig.index(/\b#{keyw}\b/)
+ @postfix << ";begin" if pos and pos < column # if * xxx
+
+ pos = expr_orig.index(/;\s*#{keyw}\b/)
+ @postfix << ";begin" if pos and column < pos # * ; if xxx
+ end
+ end
+
+ def aref_or_aset?(right_stripped, last_char)
+ if last_char == ?[
+ case right_stripped
+ when /\]\s*=/ then "[]="
+ when /\]/ then "[]"
+ end
+ end
+ end
+
+ def set_last_word!(expr, aref_or_aset=nil)
+ debugprint "expr(before set_last_word)=#{expr}"
+ if aref_or_aset
+ opchars = ""
+ else
+ opchars = expr.slice!(/\s*[#{OPERATOR_CHARS}]+$/)
+ debugprint "expr(strip opchars)=#{expr}"
+ end
+
+ expr.replace(if expr =~ /[\"\'\`]$/ # String operations
+ "''"
+ else
+ fill_literal! expr
+ phrase = current_phrase(expr)
+ if aref_or_aset
+ expr.eval_string = expr[0..-2]
+ expr.meth = aref_or_aset
+ elsif phrase.match( /^(.+)\.(.*)$/ )
+ expr.eval_string, expr.meth = $1, $2
+ elsif opchars != ''
+ expr
+ end
+ debugprint "expr.eval_string=#{expr.eval_string}", "expr.meth=#{expr.meth}"
+ phrase
+ end << (opchars || '')) # ` font-lock hack
+ debugprint "expr(after set_last_word)=#{expr}"
+ end
+
+ def current_phrase(expr)
+ paren_level = 0
+ start = 0
+ (expr.length-1).downto(0) do |i|
+ c = expr[i,1]
+ if c =~ /[\)\}\]]/
+ paren_level += 1
+ next
+ end
+ if paren_level > 0
+ next if c =~ /[, ]/
+ else
+ break (start = i+1) if c =~ /[ ,\(\{\[]/
+ end
+ if c =~ /[\(\{\[]/
+ paren_level -= 1
+ break (start = i+1) if paren_level < 0
+ end
+ end
+ expr[start..-1]
+ end
+
+ def add_BEGIN
+ <\\Z] )[1].sub(/\\A.*?\\((.*?)\\)(.*)\\Z/){ "\#{$1}\#{$2}" }.sub(/##/) { "\#{$1}." }
+ #{result} = #{v}.to_s + ".new" if #{result} == 'Class#new' and #{v}.private_method_defined?(:initialize)
+ #{result} = "Object#" + #{meth} if #{result} =~ /^Kernel#/ and Kernel.instance_methods(false).map{|x| x.to_s}.include? #{meth}
+ #{result}
+EOC
+ end
+
+end
+
+# Nearly 100% accurate completion for any editors!!
+# by rubikitch
+class XMPCompletionFilter < XMPFilter
+ include ProcessParticularLine
+
+ class << self
+ attr_accessor :candidates_with_description_flag
+ end
+ @candidates_with_description_flag = false
+
+ # String completion begins with this.
+ attr :prefix
+
+ def self.run(code, opts)
+ new(opts).completion_code(code, opts[:lineno], opts[:column])
+ end
+
+ def magic_help_code(recv, meth)
+ oneline_ize __magic_help_code("#{VAR}_result", recv, meth)
+ end
+
+ def methods_map_code(recv)
+ # delimiter is \0
+ m = "#{VAR}_m"
+ mhc = magic_help_code((recv), m)
+ %Q[map{|%s| "\#{%s}\\0" + %s}] % [m, m, mhc]
+ end
+
+ def split_method_info(minfo)
+ minfo.split(/\0/,2)
+ end
+
+ def prepare_line(expr, column)
+ set_expr_and_postfix!(expr, column){|c| /^.{#{c}}/ }
+ @prefix = expr
+ case expr
+ when /^\$\w*$/ # global variable
+ __prepare_line 'nil', 'global_variables', '%n'
+ when /^@@\w*$/ # class variable
+ __prepare_line 'nil', 'Module === self ? class_variables : self.class.class_variables', '%n'
+ when /^@\w*$/ # instance variable
+ __prepare_line 'nil', 'instance_variables', '%n'
+ when /^([A-Z].*)::([^.]*)$/ # nested constants / class methods
+ @prefix = $2
+ __prepare_line $1, "#$1.constants | #$1.methods(true)",
+ %Q[#$1.constants + #$1.methods(true).#{methods_map_code($1)}]
+ when /^[A-Z]\w*$/ # normal constants
+ __prepare_line 'nil', 'Module.constants', '%n'
+ when /^(.*::.+)\.(.*)$/ # toplevel class methods
+ @prefix = $2
+ __prepare_line $1, "#$1.methods",
+ %Q[%n.#{methods_map_code($1)}]
+ when /^(::.+)::(.*)$/ # toplevel nested constants
+ @prefix = $2
+ __prepare_line $1, "#$1.constants | #$1.methods",
+ %Q[#$1.constants + #$1.methods.#{methods_map_code($1)}]
+ when /^::(.*)/ # toplevel constant
+ @prefix = $1
+ __prepare_line 'nil', 'Object.constants', '%n'
+ when /^(:[^:.]*)$/ # symbol
+ __prepare_line 'nil', 'Symbol.all_symbols.map{|s| ":" + s.id2name}', '%n'
+ when /\.([^.]*)$/ # method call
+ @prefix = $1
+ recv = Regexp.last_match.pre_match
+ __prepare_line recv, "(#{recv}).methods(true)",
+ %Q[%n.#{methods_map_code(recv)}]
+ else # bare words
+ __prepare_line 'self', "methods | private_methods | local_variables | self.class.constants",
+ %Q[(methods | private_methods).#{methods_map_code('self')} + local_variables | self.class.constants]
+ end
+ end
+
+ def __prepare_line(recv, all_completion_expr, all_completion_expr_verbose)
+ if self.class.candidates_with_description_flag
+ ___prepare_line(recv, all_completion_expr_verbose.gsub(/%n/, '('+all_completion_expr+')'))
+ else
+ ___prepare_line(recv, all_completion_expr)
+ end
+
+ end
+
+ def ___prepare_line(recv, all_completion_expr)
+ v = "#{VAR}"
+ rcv = "#{VAR}_recv"
+ idx = 1
+ oneline_ize(< " + #{rcv}.to_s + " " + #{v}.join(" ")) || #{v}
+exit
+EOC
+ end
+
+ def candidates_with_class(code, lineno, column=nil)
+ klass, methods = runtime_data_with_class(code, lineno, column) rescue ["", ""]
+ raise NoCandidates, "No candidates." if methods.nil? or methods.empty?
+ [klass, methods.split(/ /).sort]
+ end
+
+ # Array of completion candidates.
+ class NoCandidates < RuntimeError; end
+ def candidates(code, lineno, column=nil)
+ candidates_with_class(code, lineno, column)[1]
+ end
+
+ # Completion code for editors.
+ def completion_code(code, lineno, column=nil)
+ candidates(code, lineno, column).join("\n") rescue "\n"
+ end
+end
+
+# for debugging XMPCompletionEmacsFilter
+class XMPCompletionVerboseFilter < XMPCompletionFilter
+ @candidates_with_description_flag = true
+end
+
+class XMPCompletionClassInfoFilter < XMPCompletionFilter
+ @candidates_with_description_flag = true
+
+ def completion_code(code, lineno, column=nil)
+ candidates(code, lineno, column).join("\n").tr("\0", "\t")
+ rescue NoCandidates
+ ""
+ end
+end
+
+class XMPCompletionEmacsFilter < XMPCompletionFilter
+ @candidates_with_description_flag = true
+
+ def completion_code(code, lineno, column=nil)
+ elisp = "(progn\n"
+ table = "(setq rct-method-completion-table '("
+ alist = "(setq alist '("
+ begin
+ candidates(code, lineno, column).sort.each do |minfo|
+ meth, description = split_method_info(minfo)
+ table << format('("%s") ', meth)
+ alist << format('("%s\\t[%s]") ', meth, description)
+ end
+ table << "))\n"
+ alist << "))\n"
+ rescue Exception => err
+ return error_code(err)
+ end
+ elisp << table << alist
+ elisp << %Q[(setq pattern "#{prefix}")\n]
+ elisp << %Q[(try-completion pattern rct-method-completion-table nil)\n]
+ elisp << ")" # /progn
+ end
+
+ def error_code(err)
+ case err
+ when NoCandidates
+ %Q[(error "#{err.message}")]
+ else
+ %Q[(error "#{err.message}\n#{err.backtrace.join("\n")}")]
+ end
+
+ end
+end
+
+class XMPCompletionEmacsIciclesFilter < XMPCompletionEmacsFilter
+ @candidates_with_description_flag = true
+
+ def completion_code(code, lineno, column=nil)
+ elisp = "(progn\n"
+ table = "(setq rct-method-completion-table '("
+ help_alist = "(setq alist '("
+
+ begin
+ klass, cands = candidates_with_class(code, lineno, column)
+ cands.sort.each do |minfo|
+ meth, description = split_method_info(minfo)
+ table << format('("%s\\t[%s]") ', meth, description)
+ help_alist << format('("%s" . "%s")', meth, description)
+ end
+ table << "))\n"
+ help_alist << "))\n"
+ rescue Exception => err
+ return error_code(err)
+ end
+ elisp << table << help_alist
+ elisp << %Q[(setq pattern "#{prefix}")\n]
+ elisp << %Q[(setq klass "#{klass}")\n]
+ elisp << ")" # /progn
+ end
+end
+
+class XMPCompletionEmacsAnythingFilter < XMPCompletionEmacsFilter
+ @candidates_with_description_flag = true
+
+ def completion_code(code, lineno, column=nil)
+ elisp = "(progn\n"
+ table = "(setq rct-method-completion-table `("
+
+ begin
+ klass, cands = candidates_with_class(code, lineno, column)
+ cands.sort.each do |minfo|
+ meth, description = split_method_info(minfo)
+ table << format('("%s\\t[%s]" . ,(propertize "%s" \'desc "%s")) ',
+ meth, description, meth, description)
+ end
+ table << "))\n"
+ rescue Exception => err
+ return error_code(err)
+ end
+ elisp << table
+ elisp << %Q[(setq pattern "#{prefix}")\n]
+ elisp << %Q[(setq klass "#{klass}")\n]
+ elisp << ")" # /progn
+ end
+end
+
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/doc.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/doc.rb
new file mode 100644
index 000000000..9a3e752db
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/doc.rb
@@ -0,0 +1,168 @@
+require 'rcodetools/completion'
+# Call Ri for any editors!!
+# by rubikitch
+module Rcodetools
+
+class XMPDocFilter < XMPFilter
+ include ProcessParticularLine
+
+ def initialize(opts = {})
+ super
+ @filename = opts[:filename]
+ extend UseMethodAnalyzer if opts[:use_method_analyzer]
+ end
+
+ def self.run(code, opts)
+ new(opts).doc(code, opts[:lineno], opts[:column])
+ end
+
+ def prepare_line(expr, column)
+ set_expr_and_postfix!(expr, column){|c|
+ withop_re = /^.{#{c-1}}[#{OPERATOR_CHARS}]+/
+ if expr =~ withop_re
+ withop_re
+ else
+ /^.{#{c}}[\w#{OPERATOR_CHARS}]*/
+ end
+ }
+ recv = expr
+
+ # When expr already knows receiver and method,
+ return(__prepare_line :recv => expr.eval_string, :meth => expr.meth) if expr.eval_string
+
+ case expr
+ when /^(?:::)?([A-Z].*)(?:::|\.)(.*)$/ # nested constants / class methods
+ __prepare_line :klass => $1, :meth_or_constant => $2
+ when /^(?:::)?[A-Z]/ # normal constants
+ __prepare_line :klass => expr
+ when /\.([^.]*)$/ # method call
+ __prepare_line :recv => Regexp.last_match.pre_match, :meth => $1
+ when /^(.+)(\[\]=?)$/ # [], []=
+ __prepare_line :recv => $1, :meth => $2
+ when /[#{OPERATOR_CHARS}]+$/ # operator
+ __prepare_line :recv => Regexp.last_match.pre_match, :meth => $&
+ else # bare words
+ __prepare_line :recv => "self", :meth => expr
+ end
+ end
+
+ def __prepare_line(x)
+ v = "#{VAR}"
+ result = "#{VAR}_result"
+ klass = "#{VAR}_klass"
+ flag = "#{VAR}_flag"
+ which_methods = "#{VAR}_methods"
+ ancestor_class = "#{VAR}_ancestor_class"
+ idx = 1
+ recv = x[:recv] || x[:klass] || raise(ArgumentError, "need :recv or :klass")
+ meth = x[:meth_or_constant] || x[:meth]
+ debugprint "recv=#{recv}", "meth=#{meth}"
+ if meth
+ # imported from fastri/MagicHelp
+ code = <<-EOC
+#{v} = (#{recv})
+$stderr.print("#{MARKER}[#{idx}] => " + #{v}.class.to_s + " ")
+
+if Module === #{v} and '#{meth}' =~ /^[A-Z]/ and #{v}.const_defined?('#{meth}')
+ #{result} = #{v}.to_s + "::#{meth}"
+else
+ #{__magic_help_code result, v, meth.dump}
+end
+
+$stderr.puts(#{result})
+exit
+ EOC
+ else
+ code = <<-EOC
+#{v} = (#{recv})
+$stderr.print("#{MARKER}[#{idx}] => " + #{v}.class.to_s + " ")
+$stderr.puts(#{v}.to_s)
+exit
+ EOC
+ end
+ oneline_ize(code)
+ end
+
+ # overridable by module
+ def _doc(code, lineno, column)
+ end
+
+ def doc(code, lineno, column=nil)
+ _doc(code, lineno, column) or runtime_data(code, lineno, column).to_s
+ end
+
+ module UseMethodAnalyzer
+ METHOD_ANALYSIS = "method_analysis"
+ def have_method_analysis
+ File.file? METHOD_ANALYSIS
+ end
+
+ def find_method_analysis
+ here = Dir.pwd
+ oldpwd = here
+ begin
+ while ! have_method_analysis
+ Dir.chdir("..")
+ if Dir.pwd == here
+ return nil # not found
+ end
+ here = Dir.pwd
+ end
+ ensure
+ Dir.chdir oldpwd
+ end
+ yield(File.join(here, METHOD_ANALYSIS))
+ end
+
+ def _doc(code, lineno, column=nil)
+ find_method_analysis do |ma_file|
+ methods = open(ma_file, "rb"){ |f| Marshal.load(f)}
+ line = File.readlines(@filename)[lineno-1]
+ current_method = line[ /^.{#{column}}\w*/][ /\w+[\?!]?$/ ].sub(/:+/,'')
+ filename = @filename # FIXME
+ begin
+ methods[filename][lineno].grep(Regexp.new(Regexp.quote(current_method)))[0]
+ rescue NoMethodError
+ raise "doc/method_analyzer:cannot find #{current_method}"
+ end
+
+ end
+ end
+ end
+
+end
+
+# ReFe is so-called `Japanese Ri'.
+class XMPReFeFilter < XMPDocFilter
+ def doc(code, lineno, column=nil)
+ "refe '#{super}'"
+ end
+end
+
+class XMPRiFilter < XMPDocFilter
+ def doc(code, lineno, column=nil)
+ "ri '#{super.sub(/\./, '::')}'"
+ end
+end
+
+class XMPRiEmacsFilter < XMPDocFilter
+ def doc(code, lineno, column=nil)
+ begin
+ %!(rct-find-tag-or-ri "#{super}")!
+ rescue Exception => err
+ return %Q[(error "#{err.message}")]
+ end
+ end
+end
+
+class XMPRiVimFilter < XMPDocFilter
+ def doc(code, lineno, column=nil)
+ begin
+ %{call RCT_find_tag_or_ri("#{super}")}
+ rescue Exception => err
+ return %Q[echo #{err.message.inspect}]
+ end
+ end
+end
+
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/fork.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/fork.rb
new file mode 100644
index 000000000..87fc2645c
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/fork.rb
@@ -0,0 +1,210 @@
+## Rcodetools version of ruby_fork
+#
+# Based on ruby_fork.rb by Ryan Davis, Eric Hodel, Zen Spider Software
+#
+# (The MIT License)
+#
+# Copyright (c) 2006 Ryan Davis, Eric Hodel, Zen Spider Software
+# 2007 rubikitch
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+require 'optparse'
+require 'socket'
+require 'rcodetools/fork_config'
+
+module Rcodetools
+module Fork
+
+ USAGE_HELP = < [],
+ :code => [],
+ :extra_paths => [],
+ :port => PORT,
+ }
+
+ def self.add_env_args(opts, settings)
+ opts.separator ''
+ opts.separator 'Process environment options:'
+
+ opts.separator ''
+ opts.on('-e CODE', 'Execute CODE in parent process.',
+ 'May be specified multiple times.') do |code|
+ settings[:code] << code
+ end
+
+ opts.separator ''
+ opts.on('-I DIRECTORY', 'Adds DIRECTORY to $LOAD_PATH.',
+ 'May be specified multiple times.') do |dir|
+ settings[:extra_paths] << dir
+ end
+
+ opts.separator ''
+ opts.on('-r LIBRARY', 'Require LIBRARY in the parent process.',
+ 'May be specified multiple times.') do |lib|
+ settings[:requires] << lib
+ end
+ end
+
+ def self.parse_client_args(args)
+ settings = Marshal.load Marshal.dump(DEFAULT_SETTINGS)
+
+ opts = OptionParser.new do |opts|
+ opts.banner = "Usage: #{$0} [options]\n#{USAGE_HELP}"
+
+ opts.separator ''
+ opts.on('-p', '--port PORT',
+ 'Listen for connections on PORT.',
+ "Default: #{settings[:port]}") do |port|
+ settings[:port] = port.to_i
+ end
+
+ opts.separator ''
+ opts.on('-h', '--help', 'You\'re looking at it.') do
+ $stderr.puts opts
+ exit 1
+ end
+
+ add_env_args opts, settings
+ end
+
+ opts.parse! args
+
+ return settings
+ end
+
+ def self.parse_server_args(args)
+ settings = Marshal.load Marshal.dump(DEFAULT_SETTINGS)
+
+ opts = OptionParser.new do |opts|
+ opts.banner = "Usage: #{$0} [options]\n#{USAGE_HELP}"
+
+ opts.separator ''
+ opts.on('-p', '--port PORT',
+ 'Listen for connections on PORT.',
+ "Default: #{settings[:port]}") do |port|
+ settings[:port] = port.to_i
+ end
+
+ opts.separator ''
+ opts.on('-h', '--help', 'You\'re looking at it.') do
+ $stderr.puts opts
+ exit 1
+ end
+
+ add_env_args opts, settings
+ end
+
+ opts.parse! args
+
+ return settings
+ end
+
+ def self.start_client(args = ARGV)
+ trap 'INT' do exit 1 end # Exit gracefully
+
+ settings = parse_client_args args
+
+ args = Marshal.dump [settings, ARGV]
+
+ socket = TCPSocket.new 'localhost', settings[:port]
+
+ socket.puts args.length
+ socket.write args
+ socket.close_write
+ end
+
+ def self.start_server(args = ARGV)
+ begin
+ require 'rubygems'
+ rescue LoadError
+ end
+ write_pwd
+ settings = parse_server_args args
+ setup_environment settings
+
+ server = TCPServer.new 'localhost', settings[:port]
+
+ $stderr.puts "#{$0} Running as PID #{$$} on #{settings[:port]}"
+
+ loop do
+ Thread.new server.accept do |socket|
+ begin
+ args_length = socket.gets.to_i
+ args = socket.read args_length
+ settings, argv = Marshal.load args
+ fork do
+ ARGV.replace argv
+ setup_environment settings
+ socket.close
+ end
+ socket.close # close my copy.
+ rescue => e
+ socket.close if socket
+ end
+ end
+ end
+ rescue Interrupt, SystemExit
+ File.unlink PWD_FILE
+ rescue Exception => e
+ File.unlink PWD_FILE
+ puts "Failed to catch #{e.class}:#{e.message}"
+ puts "\t#{e.backtrace.join "\n\t"}"
+ end
+
+ def self.setup_environment(settings)
+ settings[:extra_paths].map! { |dir| dir.split ':' }
+ settings[:extra_paths].flatten!
+ settings[:extra_paths].each { |dir| $:.unshift dir }
+
+ begin
+ settings[:requires].each { |file| require file }
+ settings[:code].each { |code| eval code, TOPLEVEL_BINDING }
+ rescue Exception
+ $@.reject! {|s| s =~ %r!rcodetools/fork\.rb!}
+ raise
+ end
+ end
+
+end
+
+end
+
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/fork_config.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/fork_config.rb
new file mode 100644
index 000000000..e22b4cd1f
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/fork_config.rb
@@ -0,0 +1,26 @@
+
+module Rcodetools
+
+module Fork
+ PORT = 9085
+ # Contains $PWD of rct-fork server. Exists only while running.
+ PWD_FILE = File.expand_path "~/.rct-fork.pwd"
+
+ def self.chdir_fork_directory
+ if run?
+ Dir.chdir File.read(PWD_FILE)
+ else
+ raise "rct-fork is not running."
+ end
+ end
+
+ def self.write_pwd
+ open(PWD_FILE, "w"){|f| f.print Dir.pwd }
+ end
+
+ def self.run?
+ File.file? PWD_FILE
+ end
+end
+
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/options.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/options.rb
new file mode 100644
index 000000000..8ba920986
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/options.rb
@@ -0,0 +1,136 @@
+require 'optparse'
+
+module Rcodetools
+# Domain specific OptionParser extensions
+module OptionHandler
+ def set_banner
+ self.banner = "Usage: #{$0} [options] [inputfile] [-- cmdline args]"
+ end
+
+ def handle_position(options)
+ separator ""
+ separator "Position options:"
+ on("--line=LINE", "Current line number.") do |n|
+ options[:lineno] = n.to_i
+ end
+ on("--column=COLUMN", "Current column number in BYTE.") do |n|
+ options[:column] = n.to_i
+ end
+ on("-t TEST", "--test=TEST",
+ "Execute test script. ",
+ "TEST is TESTSCRIPT, TESTSCRIPT@TESTMETHOD, or TESTSCRIPT@LINENO.",
+ "You must specify --filename option.") do |t|
+ options[:test_script], options[:test_method] = t.split(/@/)
+ end
+ on("--filename=FILENAME", "Filename of standard input.") do |f|
+ options[:filename] = f
+ end
+ end
+
+ def handle_interpreter(options)
+ separator ""
+ separator "Interpreter options:"
+ on("-S FILE", "--interpreter FILE", "Use interpreter FILE.") do |interpreter|
+ options[:interpreter] = interpreter
+ end
+ on("-I PATH", "Add PATH to $LOAD_PATH") do |path|
+ options[:include_paths] << path
+ end
+ on("--dev", "Add this project's bin/ and lib/ to $LOAD_PATH.",
+ "A directory with a Rakefile is considered a project base directory.") do
+ auto_include_paths(options[:include_paths], Dir.pwd)
+ end
+ on("-r LIB", "Require LIB before execution.") do |lib|
+ options[:libs] << lib
+ end
+ on("-e EXPR", "--eval=EXPR", "--stub=EXPR", "Evaluate EXPR after execution.") do |expr|
+ options[:evals] << expr
+ end
+ on("--fork", "Use rct-fork-client if rct-fork is running.") do
+ options[:detect_rct_fork] = true
+ end
+ on("--rbtest", "Use rbtest.") do
+ options[:use_rbtest] = true
+ end
+ on("--detect-rbtest", "Use rbtest if '=begin test_*' blocks exist.") do
+ options[:detect_rbtest] = true
+ end
+ end
+
+ def handle_misc(options)
+ separator ""
+ separator "Misc options:"
+ on("--cd DIR", "Change working directory to DIR.") do |dir|
+ options[:wd] = dir
+ end
+ on("--debug", "Write transformed source code to xmp-tmp.PID.rb.") do
+ options[:dump] = "xmp-tmp.#{Process.pid}.rb"
+ end
+ on("--tmpfile", "--tempfile", "Use tmpfile instead of open3. (non-windows)") do
+ options[:execute_ruby_tmpfile] = true
+ end
+ on("-w N", "--width N", Integer, "Set width of multi-line annotation. (xmpfilter only)") do |width|
+ options[:width] = width
+ end
+ separator ""
+ on("-h", "--help", "Show this message") do
+ puts self
+ exit
+ end
+ on("-v", "--version", "Show version information") do
+ puts "#{File.basename($0)} #{XMPFilter::VERSION}"
+ exit
+ end
+ end
+
+ def auto_include_paths(include_paths, pwd)
+ if pwd =~ %r!^(.+)/(lib|bin)!
+ include_paths.unshift("#$1/lib").unshift("#$1/bin")
+ elsif File.file? "#{pwd}/Rakefile" or File.file? "#{pwd}/rakefile"
+ include_paths.unshift("#{pwd}/lib").unshift("#{pwd}/bin")
+ end
+ end
+ module_function :auto_include_paths
+
+end
+
+def set_extra_opts(options)
+ if idx = ARGV.index("--")
+ options[:options] = ARGV[idx+1..-1]
+ ARGV.replace ARGV[0...idx]
+ else
+ options[:options] = []
+ end
+end
+
+def check_opts(options)
+ if options[:test_script]
+ unless options[:filename]
+ $stderr.puts "You must specify --filename as well as -t(--test)."
+ exit 1
+ end
+ end
+end
+
+DEFAULT_OPTIONS = {
+ :interpreter => "ruby",
+ :options => ["hoge"],
+ :min_codeline_size => 50,
+ :width => 79,
+ :libs => [],
+ :evals => [],
+ :include_paths => [],
+ :dump => nil,
+ :wd => nil,
+ :warnings => true,
+ :use_parentheses => true,
+ :column => nil,
+ :output_stdout => true,
+ :test_script => nil,
+ :test_method => nil,
+ :detect_rct_fork => false,
+ :use_rbtest => false,
+ :detect_rbtest => false,
+ :execute_ruby_tmpfile => false,
+ }
+end # /Rcodetools
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/xmpfilter.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/xmpfilter.rb
new file mode 100755
index 000000000..a174b5180
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/xmpfilter.rb
@@ -0,0 +1,379 @@
+#!/usr/bin/env ruby
+# Copyright (c) 2005-2008 Mauricio Fernandez http://eigenclass.org
+# rubikitch
+# Use and distribution subject to the terms of the Ruby license.
+
+# This is needed regexps cannot match with invalid-encoding strings.
+# xmpfilter is unaware of script encoding.
+Encoding.default_external = "ASCII-8BIT" if RUBY_VERSION >= "1.9"
+
+ENV['HOME'] ||= "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}"
+require 'rcodetools/fork_config'
+require 'rcodetools/compat'
+require 'tmpdir'
+
+module Rcodetools
+
+class XMPFilter
+ VERSION = "0.8.7"
+
+ MARKER = "!XMP#{Time.new.to_i}_#{Process.pid}_#{rand(1000000)}!"
+ XMP_RE = Regexp.new("^" + Regexp.escape(MARKER) + '\[([0-9]+)\] (=>|~>|==>) (.*)')
+ VAR = "_xmp_#{Time.new.to_i}_#{Process.pid}_#{rand(1000000)}"
+ WARNING_RE = /.*:([0-9]+): warning: (.*)/
+
+ RuntimeData = Struct.new(:results, :exceptions, :bindings)
+
+ INITIALIZE_OPTS = {:interpreter => "ruby", :options => [], :libs => [],
+ :include_paths => [], :warnings => true,
+ :use_parentheses => true}
+
+ def windows?
+ /win|mingw/ =~ RUBY_PLATFORM && /darwin/ !~ RUBY_PLATFORM
+ end
+
+ Interpreter = Struct.new(:options, :execute_method, :accept_debug, :accept_include_paths, :chdir_proc)
+ INTERPRETER_RUBY = Interpreter.new(["-w"],
+ :execute_ruby, true, true, nil)
+ INTERPRETER_RBTEST = Interpreter.new(["-S", "rbtest"],
+ :execute_script, false, false, nil)
+ INTERPRETER_FORK = Interpreter.new(["-S", "rct-fork-client"],
+ :execute_tmpfile, false, true,
+ lambda { Fork::chdir_fork_directory })
+
+ def self.detect_rbtest(code, opts)
+ opts[:use_rbtest] ||= (opts[:detect_rbtest] and code =~ /^=begin test./) ? true : false
+ end
+
+ # The processor (overridable)
+ def self.run(code, opts)
+ new(opts).annotate(code)
+ end
+
+ def initialize(opts = {})
+ options = INITIALIZE_OPTS.merge opts
+ @interpreter_info = INTERPRETER_RUBY
+ @interpreter = options[:interpreter]
+ @options = options[:options]
+ @libs = options[:libs]
+ @evals = options[:evals] || []
+ @include_paths = options[:include_paths]
+ @output_stdout = options[:output_stdout]
+ @dump = options[:dump]
+ @warnings = options[:warnings]
+ @parentheses = options[:use_parentheses]
+ @ignore_NoMethodError = options[:ignore_NoMethodError]
+ test_script = options[:test_script]
+ test_method = options[:test_method]
+ filename = options[:filename]
+ @execute_ruby_tmpfile = options[:execute_ruby_tmpfile]
+ @postfix = ""
+ @stdin_path = nil
+ @width = options[:width]
+
+ initialize_rct_fork if options[:detect_rct_fork]
+ initialize_rbtest if options[:use_rbtest]
+ initialize_for_test_script test_script, test_method, filename if test_script and !options[:use_rbtest]
+ end
+
+ def initialize_rct_fork
+ if Fork::run?
+ @interpreter_info = INTERPRETER_FORK
+ end
+ end
+
+ def initialize_rbtest
+ @interpreter_info = INTERPRETER_RBTEST
+ end
+
+ def initialize_for_test_script(test_script, test_method, filename)
+ test_script.replace File.expand_path(test_script)
+ filename.replace File.expand_path(filename)
+ unless test_script == filename
+ basedir = common_path(test_script, filename)
+ relative_filename = filename[basedir.length+1 .. -1].sub(%r!^lib/!, '')
+ @evals << %Q!$LOADED_FEATURES << #{relative_filename.dump}!
+ @evals << safe_require_code('test/unit')
+ @evals << %Q!load #{test_script.dump}!
+ end
+ test_method = get_test_method_from_lineno(test_script, test_method.to_i) if test_method =~ /^\d/
+ @evals << %Q!Test::Unit::AutoRunner.run(false, nil, ["-n", #{test_method.dump}])! if test_method
+ end
+
+ def get_test_method_from_lineno(filename, lineno)
+ lines = File.readlines(filename)
+ (lineno-1).downto(0) do |i|
+ if lines[i] =~ /^ *def *(test_[A-Za-z0-9?!_]+)$/
+ return $1
+ end
+ end
+ nil
+ end
+
+ def common_path(a, b)
+ (a.split(File::Separator) & b.split(File::Separator)).join(File::Separator)
+ end
+
+ def add_markers(code, min_codeline_size = 50)
+ maxlen = code.map{|x| x.size}.max
+ maxlen = [min_codeline_size, maxlen + 2].max
+ ret = ""
+ code.each do |l|
+ l = l.chomp.gsub(/ # (=>|!>).*/, "").gsub(/\s*$/, "")
+ ret << (l + " " * (maxlen - l.size) + " # =>\n")
+ end
+ ret
+ end
+
+ SINGLE_LINE_RE = /^(?!(?:\s+|(?:\s*#.+)?)# ?=>)(.*) # ?=>.*/
+ MULTI_LINE_RE = /^(.*)\n(( *)# ?=>.*(?:\n|\z))(?: *# .*\n)*/
+ def annotate(code)
+ idx = 0
+ code = code.gsub(/ # !>.*/, '')
+ newcode = code.gsub(SINGLE_LINE_RE){ prepare_line($1, idx += 1) }
+ newcode.gsub!(MULTI_LINE_RE){ prepare_line($1, idx += 1, true)}
+ File.open(@dump, "w"){|f| f.puts newcode} if @dump
+ execute(newcode) do |stdout, stderr|
+ output = stderr.readlines
+ runtime_data = extract_data(output)
+ idx = 0
+ annotated = code.gsub(SINGLE_LINE_RE) { |l|
+ expr = $1
+ if /^\s*#/ =~ l
+ l
+ else
+ annotated_line(l, expr, runtime_data, idx += 1)
+ end
+ }
+ annotated.gsub!(/ # !>.*/, '')
+ annotated.gsub!(/# (>>|~>)[^\n]*\n/m, "");
+ annotated.gsub!(MULTI_LINE_RE) { |l|
+ annotated_multi_line(l, $1, $3, runtime_data, idx += 1)
+ }
+ ret = final_decoration(annotated, output)
+ if @output_stdout and (s = stdout.read) != ""
+ ret << s.inject(""){|s,line| s + "# >> #{line}".chomp + "\n" }
+ end
+ ret
+ end
+ end
+
+ def annotated_line(line, expression, runtime_data, idx)
+ "#{expression} # => " + (runtime_data.results[idx].map{|x| x[1]} || []).join(", ")
+ end
+
+ def annotated_multi_line(line, expression, indent, runtime_data, idx)
+ pretty = (runtime_data.results[idx].map{|x| x[1]} || []).join(", ")
+ first, *rest = pretty.to_a
+ rest.inject("#{expression}\n#{indent}# => #{first || "\n"}") {|s, l| s << "#{indent}# " << l }
+ end
+
+ def prepare_line_annotation(expr, idx, multi_line=false)
+ v = "#{VAR}"
+ blocal = "__#{VAR}"
+ blocal2 = "___#{VAR}"
+ lastmatch = "____#{VAR}"
+ if multi_line
+ pp = safe_require_code "pp"
+ result = "((begin; #{lastmatch} = $~; PP.pp(#{v}, '', #{@width-5}).gsub(/\\r?\\n/, 'PPPROTECT'); ensure; $~ = #{lastmatch} end))"
+ else
+ pp = ''
+ result = "#{v}.inspect"
+ end
+ oneline_ize(<<-EOF).chomp
+#{pp}
+#{v} = (#{expr})
+$stderr.puts("#{MARKER}[#{idx}] => " + #{v}.class.to_s + " " + #{result}) || begin
+ $stderr.puts local_variables
+ local_variables.each{|#{blocal}|
+ #{blocal2} = eval(#{blocal})
+ if #{v} == #{blocal2} && #{blocal} != %#{expr}.strip
+ $stderr.puts("#{MARKER}[#{idx}] ==> " + #{blocal})
+ elsif [#{blocal2}] == #{v}
+ $stderr.puts("#{MARKER}[#{idx}] ==> [" + #{blocal} + "]")
+ end
+ }
+ nil
+rescue Exception
+ nil
+end || #{v}
+ EOF
+
+ end
+ alias_method :prepare_line, :prepare_line_annotation
+
+ def safe_require_code(lib)
+ oldverbose = "$#{VAR}_old_verbose"
+ "#{oldverbose} = $VERBOSE; $VERBOSE = false; require '#{lib}'; $VERBOSE = #{oldverbose}"
+ end
+ private :safe_require_code
+
+ def execute_ruby(code)
+ meth = (windows? or @execute_ruby_tmpfile) ? :execute_tmpfile : :execute_popen
+ __send__ meth, code
+ end
+
+ def split_shbang(script)
+ ary = script.each_line.to_a
+ if ary[0] =~ /^#!/ and ary[1] =~ /^#.*coding/
+ [ary[0..1], ary[2..-1]]
+ elsif ary[0] =~ /^#!|^#.*coding/
+ [[ary[0]], ary[1..-1]]
+ else
+ [[], ary]
+ end
+ end
+ private :split_shbang
+
+ def execute_tmpfile(code)
+ ios = %w[_ stdin stdout stderr]
+ stdin, stdout, stderr = (1..3).map do |i|
+ fname = if $DEBUG
+ "xmpfilter.tmpfile_#{ios[i]}.rb"
+ else
+ "xmpfilter.tmpfile_#{Process.pid}-#{i}.rb"
+ end
+ f = File.open(fname, "w+")
+ f
+ end
+ # stdin.puts code
+ # stdin.close
+ shbang_magic_comment, rest = split_shbang(code)
+ @stdin_path = File.expand_path stdin.path
+ stdin.print shbang_magic_comment
+ stdin.print <<-EOF.map{|l| l.strip}.join(";")
+ $stdout.reopen('#{File.expand_path(stdout.path)}', 'w')
+ $stderr.reopen('#{File.expand_path(stderr.path)}', 'w')
+ $0 = '#{File.expand_path(stdin.path)}'
+ ARGV.replace(#{@options.inspect})
+ END { #{@evals.join(";")} }
+ EOF
+ stdin.print ";#{rest}"
+
+ debugprint "execute command = #{(interpreter_command << stdin.path).join ' '}"
+ stdin.close
+ oldpwd = Dir.pwd
+ @interpreter_info.chdir_proc and @interpreter_info.chdir_proc.call
+ system(*(interpreter_command << stdin.path))
+ Dir.chdir oldpwd
+ [stdout, stderr]
+ end
+
+ def execute_popen(code)
+ require 'open3'
+ stdin, stdout, stderr = Open3::popen3(*interpreter_command)
+ stdin.puts code
+ @evals.each{|x| stdin.puts x } unless @evals.empty?
+ stdin.close
+ [stdout, stderr]
+ end
+
+ def execute_script(code)
+ path = File.expand_path("xmpfilter.tmpfile_#{Process.pid}.rb", Dir.tmpdir)
+ File.open(path, "w"){|f| f.puts code}
+ at_exit { File.unlink path if File.exist? path}
+ stdout_path, stderr_path = (1..2).map do |i|
+ fname = "xmpfilter.tmpfile_#{Process.pid}-#{i}.rb"
+ File.expand_path(fname, Dir.tmpdir)
+ end
+ args = *(interpreter_command << %["#{path}"] << "2>" <<
+ %["#{stderr_path}"] << ">" << %["#{stdout_path}"])
+ system(args.join(" "))
+
+ [stdout_path, stderr_path].map do |fullname|
+ f = File.open(fullname, "r")
+ # at_exit {
+ # f.close unless f.closed?
+ # File.unlink fullname if File.exist? fullname
+ # }
+ f
+ end
+ end
+
+ def execute(code)
+ stdout, stderr = __send__ @interpreter_info.execute_method, code
+ if block_given?
+ begin
+ yield stdout, stderr
+ ensure
+ for out in [stdout, stderr]
+ path = out.path rescue nil
+ out.close
+# File.unlink path if path
+ end
+ end
+ else
+ [stdout, stderr]
+ end
+ end
+
+ def interpreter_command
+ # BUG interpreter option arguments containing space are not
+ # accepted. But it seems to be rare case.
+ r = @interpreter.split + @interpreter_info.options
+ r << "-d" if $DEBUG and @interpreter_info.accept_debug
+ r << "-I#{@include_paths.join(":")}" if @interpreter_info.accept_include_paths and !@include_paths.empty?
+ @libs.each{|x| r << "-r#{x}" } unless @libs.empty?
+ (r << "-").concat @options unless @options.empty?
+ r
+ end
+
+ def extract_data(output)
+ results = Hash.new{|h,k| h[k] = []}
+ exceptions = Hash.new{|h,k| h[k] = []}
+ bindings = Hash.new{|h,k| h[k] = []}
+ output.grep(XMP_RE).each do |line|
+ result_id, op, result = XMP_RE.match(line).captures
+ case op
+ when "=>"
+ klass, value = /(\S+)\s+(.*)/.match(result).captures
+ results[result_id.to_i] << [klass, value.gsub(/PPPROTECT/, "\n")]
+ when "~>"
+ exceptions[result_id.to_i] << result
+ when "==>"
+ bindings[result_id.to_i] << result unless result.index(VAR)
+ end
+ end
+ RuntimeData.new(results, exceptions, bindings)
+ end
+
+ def final_decoration(code, output)
+ warnings = {}
+ output.join.grep(WARNING_RE).map do |x|
+ md = WARNING_RE.match(x)
+ warnings[md[1].to_i] = md[2]
+ end
+ idx = 0
+ ret = code.map do |line|
+ w = warnings[idx+=1]
+ if @warnings
+ w ? (line.chomp + " # !> #{w}") : line
+ else
+ line
+ end
+ end
+ output = output.reject{|x| /^-:[0-9]+: warning/.match(x)}
+ if exception = /^-e?:[0-9]+:.*|^(?!!XMP)[^\n]+:[0-9]+:in .*/m.match(output.join)
+ err = exception[0]
+ err.gsub!(Regexp.union(@stdin_path), '-') if @stdin_path
+ ret << err.map{|line| "# ~> " + line }
+ end
+ ret
+ end
+
+ def oneline_ize(code)
+ "((" + code.gsub(/\r?\n|\r/, ';') + "));#{@postfix}\n"
+ end
+
+ def debugprint(*args)
+ $stderr.puts(*args) if $DEBUG
+ end
+end # clas XMPFilter
+
+class XMPAddMarkers < XMPFilter
+ def self.run(code, opts)
+ new(opts).add_markers(code, opts[:min_codeline_size])
+ end
+end
+
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/xmptestunitfilter.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/xmptestunitfilter.rb
new file mode 100644
index 000000000..e3fe395f2
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/lib/rcodetools/xmptestunitfilter.rb
@@ -0,0 +1,314 @@
+require 'rcodetools/xmpfilter'
+
+module Rcodetools
+
+FLOAT_TOLERANCE = 0.0001
+class XMPTestUnitFilter < XMPFilter
+ def initialize(opts = {})
+ super
+ @output_stdout = false
+ mod = @parentheses ? :WithParentheses : :Poetry
+ extend self.class.const_get(mod) unless opts[:_no_extend_module]
+ end
+
+ private
+ def annotated_line(line, expression, runtime_data, idx)
+ indent = /^\s*/.match(line)[0]
+ assertions(expression.strip, runtime_data, idx).map{|x| indent + x}.join("\n")
+ end
+
+ def prepare_line(expr, idx)
+ basic_eval = prepare_line_annotation(expr, idx)
+ %|begin; #{basic_eval}; rescue Exception; $stderr.puts("#{MARKER}[#{idx}] ~> " + $!.class.to_s); end|
+ end
+
+ def assertions(expression, runtime_data, index)
+ exceptions = runtime_data.exceptions
+ ret = []
+
+ unless (vars = runtime_data.bindings[index]).empty?
+ vars.each{|var| ret << equal_assertion(var, expression) }
+ end
+ if !(wanted = runtime_data.results[index]).empty? || !exceptions[index]
+ case (wanted[0][1] rescue 1)
+ when "nil"
+ ret.concat nil_assertion(expression)
+ else
+ case wanted.size
+ when 1
+ ret.concat _value_assertions(wanted[0], expression)
+ else
+ # discard values from multiple runs
+ ret.concat(["#xmpfilter: WARNING!! extra values ignored"] +
+ _value_assertions(wanted[0], expression))
+ end
+ end
+ else
+ ret.concat raise_assertion(expression, exceptions, index)
+ end
+
+ ret
+ end
+
+ OTHER = Class.new
+ def _value_assertions(klass_value_txt_pair, expression)
+ klass_txt, value_txt = klass_value_txt_pair
+ value = eval(value_txt) || OTHER.new
+ # special cases
+ value = nil if value_txt.strip == "nil"
+ value = false if value_txt.strip == "false"
+ value_assertions klass_txt, value_txt, value, expression
+ rescue Exception
+ return object_assertions(klass_txt, value_txt, expression)
+ end
+
+ def raise_assertion(expression, exceptions, index)
+ ["assert_raise(#{exceptions[index][0]}){#{expression}}"]
+ end
+
+ module WithParentheses
+ def nil_assertion(expression)
+ ["assert_nil(#{expression})"]
+ end
+
+ def value_assertions(klass_txt, value_txt, value, expression)
+ case value
+ when Float
+ ["assert_in_delta(#{value.inspect}, #{expression}, #{FLOAT_TOLERANCE})"]
+ when Numeric, String, Hash, Array, Regexp, TrueClass, FalseClass, Symbol, NilClass
+ ["assert_equal(#{value_txt}, #{expression})"]
+ else
+ object_assertions(klass_txt, value_txt, expression)
+ end
+ end
+
+ def object_assertions(klass_txt, value_txt, expression)
+ [ "assert_kind_of(#{klass_txt}, #{expression})",
+ "assert_equal(#{value_txt.inspect}, #{expression}.inspect)" ]
+ end
+
+ def equal_assertion(expected, actual)
+ "assert_equal(#{expected}, #{actual})"
+ end
+ end
+
+ module Poetry
+ def nil_assertion(expression)
+ ["assert_nil #{expression}"]
+ end
+
+ def value_assertions(klass_txt, value_txt, value, expression)
+ case value
+ when Float
+ ["assert_in_delta #{value.inspect}, #{expression}, #{FLOAT_TOLERANCE}"]
+ when Numeric, String, Hash, Array, Regexp, TrueClass, FalseClass, Symbol, NilClass
+ ["assert_equal #{value_txt}, #{expression}"]
+ else
+ object_assertions klass_txt, value_txt, expression
+ end
+ end
+
+ def object_assertions(klass_txt, value_txt, expression)
+ [ "assert_kind_of #{klass_txt}, #{expression} ",
+ "assert_equal #{value_txt.inspect}, #{expression}.inspect" ]
+ end
+
+ def equal_assertion(expected, actual)
+ "assert_equal #{expected}, #{actual}"
+ end
+ end
+end
+
+class XMPRSpecFilter < XMPTestUnitFilter
+ def initialize(x={})
+ super(x.merge(:_no_extend_module => true))
+ load_rspec
+ specver = (Spec::VERSION::STRING rescue "1.0.0")
+ api_module = specver >= "0.8.0" ? NewAPI : OldAPI
+ @interpreter_info.execute_method = :execute_script
+ mod = @parentheses ? :WithParentheses : :Poetry
+ extend api_module.const_get(mod)
+ extend api_module
+ end
+
+ private
+ def load_rspec
+ begin
+ require 'spec/version'
+ rescue LoadError
+ require 'rubygems'
+ begin
+ require 'spec/version'
+ rescue LoadError # if rspec isn't available, use most recent conventions
+ end
+ end
+ end
+
+# alias :execute :execute_script
+
+ def interpreter_command
+ [@interpreter] + @libs.map{|x| "-r#{x}"}
+ end
+
+ module NewAPI
+ def raise_assertion(expression, exceptions, index)
+ ["lambda{#{expression}}.should raise_error(#{exceptions[index][0]})"]
+ end
+
+ module WithParentheses
+ def nil_assertion(expression)
+ ["(#{expression}).should be_nil"]
+ end
+
+ def value_assertions(klass_txt, value_txt, value, expression)
+ case value
+ when Float
+ ["(#{expression}).should be_close(#{value.inspect}, #{FLOAT_TOLERANCE})"]
+ when Numeric, String, Hash, Array, Regexp, TrueClass, FalseClass, Symbol, NilClass
+ ["(#{expression}).should == (#{value_txt})"]
+ else
+ object_assertions klass_txt, value_txt, expression
+ end
+ end
+
+ def object_assertions(klass_txt, value_txt, expression)
+ [ "(#{expression}).should be_a_kind_of(#{klass_txt})",
+ "(#{expression}.inspect).should == (#{value_txt.inspect})" ]
+ end
+
+ def equal_assertion(expected, actual)
+ "(#{actual}).should == (#{expected})"
+ end
+ end
+
+ module Poetry
+ def nil_assertion(expression)
+ ["#{expression}.should be_nil"]
+ end
+
+ def value_assertions(klass_txt, value_txt, value, expression)
+ case value
+ when Float
+ ["#{expression}.should be_close(#{value.inspect}, #{FLOAT_TOLERANCE})"]
+ when Numeric, String, Hash, Array, Regexp, TrueClass, FalseClass, Symbol, NilClass
+ ["#{expression}.should == #{value_txt}"]
+ else
+ object_assertions klass_txt, value_txt, expression
+ end
+ end
+
+ def object_assertions(klass_txt, value_txt, expression)
+ [ "#{expression}.should be_a_kind_of(#{klass_txt})",
+ "#{expression}.inspect.should == #{value_txt.inspect}" ]
+ end
+
+ def equal_assertion(expected, actual)
+ "#{actual}.should == #{expected}"
+ end
+ end
+ end
+
+ module OldAPI
+ # old rspec, use deprecated syntax
+ def raise_assertion(expression, exceptions, index)
+ ["lambda{#{expression}}.should_raise_error(#{exceptions[index][0]})"]
+ end
+
+ module WithParentheses
+ def nil_assertion(expression)
+ ["(#{expression}).should_be_nil"]
+ end
+
+ def value_assertions(klass_txt, value_txt, value, expression)
+ case value
+ when Float
+ ["(#{expression}).should_be_close(#{value.inspect}, #{FLOAT_TOLERANCE})"]
+ when Numeric, String, Hash, Array, Regexp, TrueClass, FalseClass, Symbol, NilClass
+ ["(#{expression}).should_equal(#{value_txt})"]
+ else
+ object_assertions klass_txt, value_txt, expression
+ end
+ end
+
+ def object_assertions(klass_txt, value_txt, expression)
+ [ "(#{expression}).should_be_a_kind_of(#{klass_txt})",
+ "(#{expression}.inspect).should_equal(#{value_txt.inspect})" ]
+ end
+
+ def equal_assertion(expected, actual)
+ "(#{actual}).should_equal(#{expected})"
+ end
+ end
+
+ module Poetry
+ def nil_assertion(expression)
+ ["#{expression}.should_be_nil"]
+ end
+
+ def value_assertions(klass_txt, value_txt, value, expression)
+ case value
+ when Float
+ ["#{expression}.should_be_close #{value.inspect}, #{FLOAT_TOLERANCE}"]
+ when Numeric, String, Hash, Array, Regexp, TrueClass, FalseClass, Symbol, NilClass
+ ["#{expression}.should_equal #{value_txt}"]
+ else
+ object_assertions klass_txt, value_txt, expression
+ end
+ end
+
+ def object_assertions(klass_txt, value_txt, expression)
+ [ "#{expression}.should_be_a_kind_of #{klass_txt}",
+ "#{expression}.inspect.should_equal #{value_txt.inspect}" ]
+ end
+
+ def equal_assertion(expected, actual)
+ "#{actual}.should_equal #{expected}"
+ end
+ end
+ end
+
+
+end
+
+class XMPExpectationsFilter < XMPTestUnitFilter
+ def initialize(x={})
+ super(x.merge(:_no_extend_module => true))
+ @warnings = false
+ end
+
+ def expectation(expected, actual)
+ < 'unit', 'controllers' => 'functional' }
+ RAILS_TESTNAME2MVC = RAILS_MVC2TESTNAME.invert
+ def test_file_00_rails(implementation, basedir, dir, node) # rails
+ if m = %r!app/(models|controllers)/(.+)\.rb$!.match(implementation)
+ "%stest/%s/%s_test.rb" % [ m.pre_match, RAILS_MVC2TESTNAME[m[1]], m[2] ]
+ end
+ end
+
+ def test_file_05_rails_lib(implementation, basedir, dir, node)
+ if basedir and File.directory?( File.join(basedir, "app") )
+ "#{basedir}test/unit/test_#{node}.rb"
+ end
+ end
+
+ def test_file_10_no_match(implementation, basedir, dir, node)
+ if [basedir, dir, node].all?{|x| x.nil?}
+ "#{File.dirname(implementation)}/test_#{File.basename(implementation)}"
+ end
+ end
+
+ def test_file_20_simple(implementation, basedir, dir, node) # test/test_NODE.rb
+ exist "#{basedir}test/test_#{node}.rb"
+ end
+
+ def test_file_30_flat(implementation, basedir, dir, node) # lib/XXX/NODE.rb -> test/test_NODE.rb
+ exist "#{basedir}test/test_#{node}.rb" if dir
+ end
+
+ def test_file_99_autotest_default(implementation, basedir, dir, node) # lib/XXX/NODE.rb -> test/XXX/test_NODE.rb
+ "#{basedir}test/#{dir}test_#{node}.rb"
+ end
+
+ def implementation_file_00_rails(test, basedir, dir, node)
+ if m = %r!test/(unit|functional)/(.+)_test.rb$!.match(test)
+ "%sapp/%s/%s.rb" % [ m.pre_match, RAILS_TESTNAME2MVC[m[1]], m[2] ]
+ end
+ end
+
+ def implementation_file_10_no_match(test, basename, dir, node)
+ if dir == nil and node == nil and test =~ %r!/test_(.+)\.rb$!
+ test.sub("/test_", "/")
+ end
+ end
+
+ def implementation_file_20(test, basedir, dir, node)
+ exist("#{basedir}lib/#{dir}#{node}.rb")
+ end
+
+ def implementation_file_30_flat(test, basedir, dir, node)
+ Dir[ "#{basedir}lib/**/#{node}.rb" ].first
+ end
+
+ def implementation_file_99_default(test, basedir, dir, node)
+ "#{basedir}lib/#{dir}#{node}.rb"
+ end
+
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/license.txt b/bundles/ruby.tmbundle/Support/vendor/rcodetools/license.txt
new file mode 100644
index 000000000..e2eb45cde
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/license.txt
@@ -0,0 +1,8 @@
+
+ rcodetools http://eigenclass.org/hiki.rb?rcodetools
+ Copyright (c) 2005-2007 Mauricio Fernandez http://eigenclass.org
+ Copyright (c) 2006-2008 rubikitch http://www.rubyist.net/~rubikitch/
+Use and distribution subject to the terms of the Ruby license.
+
+= License
+rcodetools is licensed under the same terms as Ruby.
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/rcodetools.el b/bundles/ruby.tmbundle/Support/vendor/rcodetools/rcodetools.el
new file mode 100644
index 000000000..e5c90af96
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/rcodetools.el
@@ -0,0 +1,430 @@
+;;; rcodetools.el -- annotation / accurate completion / browsing documentation
+
+;;; Copyright (c) 2006-2008 rubikitch
+;;;
+;;; Use and distribution subject to the terms of the Ruby license.
+
+(defvar xmpfilter-command-name "ruby -S xmpfilter --dev --fork --detect-rbtest"
+ "The xmpfilter command name.")
+(defvar rct-doc-command-name "ruby -S rct-doc --dev --fork --detect-rbtest"
+ "The rct-doc command name.")
+(defvar rct-complete-command-name "ruby -S rct-complete --dev --fork --detect-rbtest"
+ "The rct-complete command name.")
+(defvar ruby-toggle-file-command-name "ruby -S ruby-toggle-file"
+ "The ruby-toggle-file command name.")
+(defvar rct-fork-command-name "ruby -S rct-fork")
+(defvar rct-option-history nil) ;internal
+(defvar rct-option-local nil) ;internal
+(make-variable-buffer-local 'rct-option-local)
+(defvar rct-debug nil
+ "If non-nil, output debug message into *Messages*.")
+;; (setq rct-debug t)
+
+(defadvice comment-dwim (around rct-hack activate)
+ "If comment-dwim is successively called, add => mark."
+ (if (and (eq major-mode 'ruby-mode)
+ (eq last-command 'comment-dwim)
+ ;; TODO =>check
+ )
+ (insert "=>")
+ ad-do-it))
+;; To remove this advice.
+;; (progn (ad-disable-advice 'comment-dwim 'around 'rct-hack) (ad-update 'comment-dwim))
+
+(defun rct-current-line ()
+ "Return the vertical position of point..."
+ (+ (count-lines (point-min) (point))
+ (if (= (current-column) 0) 1 0)))
+
+(defun rct-save-position (proc)
+ "Evaluate proc with saving current-line/current-column/window-start."
+ (let ((line (rct-current-line))
+ (col (current-column))
+ (wstart (window-start)))
+ (funcall proc)
+ (goto-char (point-min))
+ (forward-line (1- line))
+ (move-to-column col)
+ (set-window-start (selected-window) wstart)))
+
+(defun rct-interactive ()
+ "All the rcodetools-related commands with prefix args read rcodetools' common option. And store option into buffer-local variable."
+ (list
+ (let ((option (or rct-option-local "")))
+ (if current-prefix-arg
+ (setq rct-option-local
+ (read-from-minibuffer "rcodetools option: " option nil nil 'rct-option-history))
+ option))))
+
+(defun rct-shell-command (command &optional buffer)
+ "Replacement for `(shell-command-on-region (point-min) (point-max) command buffer t' because of encoding problem."
+ (let ((input-rb (concat (make-temp-name "xmptmp-in") ".rb"))
+ (output-rb (concat (make-temp-name "xmptmp-out") ".rb"))
+ (coding-system-for-read buffer-file-coding-system))
+ (write-region (point-min) (point-max) input-rb nil 'nodisp)
+ (shell-command
+ (rct-debuglog (format "%s %s > %s" command input-rb output-rb))
+ t " *rct-error*")
+ (with-current-buffer (or buffer (current-buffer))
+ (insert-file-contents output-rb nil nil nil t))
+ (delete-file input-rb)
+ (delete-file output-rb)))
+
+(defvar xmpfilter-command-function 'xmpfilter-command)
+(defun xmp (&optional option)
+ "Run xmpfilter for annotation/test/spec on whole buffer.
+See also `rct-interactive'. "
+ (interactive (rct-interactive))
+ (rct-save-position
+ (lambda ()
+ (rct-shell-command (funcall xmpfilter-command-function option)))))
+
+(defun xmpfilter-command (&optional option)
+ "The xmpfilter command line, DWIM."
+ (setq option (or option ""))
+ (flet ((in-block (beg-re)
+ (save-excursion
+ (goto-char (point-min))
+ (when (re-search-forward beg-re nil t)
+ (let ((s (point)) e)
+ (when (re-search-forward "^end\n" nil t)
+ (setq e (point))
+ (goto-char s)
+ (re-search-forward "# => *$" e t)))))))
+ (cond ((in-block "^class.+< Test::Unit::TestCase$")
+ (format "%s --unittest %s" xmpfilter-command-name option))
+ ((in-block "^\\(describe\\|context\\).+do$")
+ (format "%s --spec %s" xmpfilter-command-name option))
+ (t
+ (format "%s %s" xmpfilter-command-name option)))))
+
+;;;; Completion
+(defvar rct-method-completion-table nil) ;internal
+(defvar rct-complete-symbol-function 'rct-complete-symbol--normal
+ "Function to use rct-complete-symbol.")
+;; (setq rct-complete-symbol-function 'rct-complete-symbol--icicles)
+(defvar rct-use-test-script t
+ "Whether rct-complete/rct-doc use test scripts.")
+
+(defun rct-complete-symbol (&optional option)
+ "Perform ruby method and class completion on the text around point.
+This command only calls a function according to `rct-complete-symbol-function'.
+See also `rct-interactive', `rct-complete-symbol--normal', and `rct-complete-symbol--icicles'."
+ (interactive (rct-interactive))
+ (call-interactively rct-complete-symbol-function))
+
+(defun rct-complete-symbol--normal (&optional option)
+ "Perform ruby method and class completion on the text around point.
+See also `rct-interactive'."
+ (interactive (rct-interactive))
+ (let ((end (point)) beg
+ pattern alist
+ completion)
+ (setq completion (rct-try-completion)) ; set also pattern / completion
+ (save-excursion
+ (search-backward pattern)
+ (setq beg (point)))
+ (cond ((eq completion t) ;sole completion
+ (message "%s" "Sole completion"))
+ ((null completion) ;no completions
+ (message "Can't find completion for \"%s\"" pattern)
+ (ding))
+ ((not (string= pattern completion)) ;partial completion
+ (delete-region beg end) ;delete word
+ (insert completion)
+ (message ""))
+ (t
+ (message "Making completion list...")
+ (with-output-to-temp-buffer "*Completions*"
+ (display-completion-list
+ (all-completions pattern alist)))
+ (message "Making completion list...%s" "done")))))
+
+;; (define-key ruby-mode-map "\M-\C-i" 'rct-complete-symbol)
+
+(defun rct-debuglog (logmsg)
+ "if `rct-debug' is non-nil, output LOGMSG into *Messages*. Returns LOGMSG."
+ (if rct-debug
+ (message "%s" logmsg))
+ logmsg)
+
+(defun rct-exec-and-eval (command opt)
+ "Execute rct-complete/rct-doc and evaluate the output."
+ (let ((eval-buffer (get-buffer-create " *rct-eval*")))
+ ;; copy to temporary buffer to do completion at non-EOL.
+ (rct-shell-command
+ (format "%s %s %s --line=%d --column=%d %s"
+ command opt (or rct-option-local "")
+ (rct-current-line)
+ ;; specify column in BYTE
+ (string-bytes
+ (encode-coding-string
+ (buffer-substring (point-at-bol) (point))
+ buffer-file-coding-system))
+ (if rct-use-test-script (rct-test-script-option-string) ""))
+ eval-buffer)
+ (message "")
+ (eval (with-current-buffer eval-buffer
+ (goto-char 1)
+ (unwind-protect
+ (read (current-buffer))
+ (unless rct-debug (kill-buffer eval-buffer)))))))
+
+(defun rct-test-script-option-string ()
+ (if (null buffer-file-name)
+ ""
+ (let ((test-buf (rct-find-test-script-buffer))
+ (bfn buffer-file-name)
+ bfn2 t-opt test-filename)
+ (if (and test-buf
+ (setq bfn2 (buffer-local-value 'buffer-file-name test-buf))
+ (file-exists-p bfn2))
+ ;; pass test script's filename and lineno
+ (with-current-buffer test-buf
+ (setq t-opt (format "%s@%s" buffer-file-name (rct-current-line)))
+ (format "-t %s --filename=%s" t-opt bfn))
+ ""))))
+
+(require 'cl)
+
+(defun rct-find-test-script-buffer (&optional buffer-list)
+ "Find the latest used Ruby test script buffer."
+ (setq buffer-list (or buffer-list (buffer-list)))
+ (dolist (buf buffer-list)
+ (with-current-buffer buf
+ (if (and buffer-file-name (string-match "test.*\.rb$" buffer-file-name))
+ (return buf)))))
+
+;; (defun rct-find-test-method (buffer)
+;; "Find test method on point on BUFFER."
+;; (with-current-buffer buffer
+;; (save-excursion
+;; (forward-line 1)
+;; (if (re-search-backward "^ *def *\\(test_[A-Za-z0-9?!_]+\\)" nil t)
+;; (match-string 1)))))
+
+(defun rct-try-completion ()
+ "Evaluate the output of rct-complete."
+ (rct-exec-and-eval rct-complete-command-name "--completion-emacs"))
+
+;;;; TAGS or Ri
+(autoload 'ri "ri-ruby" nil t)
+(defvar rct-find-tag-if-available t
+ "If non-nil and the method location is in TAGS, go to the location instead of show documentation.")
+(defun rct-ri (&optional option)
+ "Browse Ri document at the point.
+If `rct-find-tag-if-available' is non-nil, search the definition using TAGS.
+
+See also `rct-interactive'. "
+ (interactive (rct-interactive))
+ (rct-exec-and-eval
+ rct-doc-command-name
+ (concat "--ri-emacs --use-method-analyzer "
+ (if (buffer-file-name)
+ (concat "--filename=" (buffer-file-name))
+ ""))))
+
+(defun rct-find-tag-or-ri (fullname)
+ (if (not rct-find-tag-if-available)
+ (ri fullname)
+ (condition-case err
+ (let ()
+ (visit-tags-table-buffer)
+ (find-tag-in-order (concat "::" fullname) 'search-forward '(tag-exact-match-p) nil "containing" t))
+ (error
+ (ri fullname)))))
+
+;;;;
+(defun ruby-toggle-buffer ()
+ "Open a related file to the current buffer. test<=>impl."
+ (interactive)
+ (find-file (shell-command-to-string
+ (format "%s %s" ruby-toggle-file-command-name buffer-file-name))))
+
+;;;; rct-fork support
+(defun rct-fork (options)
+ "Run rct-fork.
+Rct-fork makes xmpfilter and completion MUCH FASTER because it pre-loads heavy libraries.
+When rct-fork is running, the mode-line indicates it to avoid unnecessary run.
+To kill rct-fork process, use \\[rct-fork-kill].
+"
+ (interactive (list
+ (read-string "rct-fork options (-e CODE -I LIBDIR -r LIB): "
+ (rct-fork-default-options))))
+ (rct-fork-kill)
+ (rct-fork-minor-mode 1)
+ (start-process-shell-command
+ "rct-fork" "*rct-fork*" rct-fork-command-name options))
+
+(defun rct-fork-default-options ()
+ "Default options for rct-fork by collecting requires."
+ (mapconcat
+ (lambda (lib) (format "-r %s" lib))
+ (save-excursion
+ (goto-char (point-min))
+ (loop while (re-search-forward "\\ ['\"]\\([^'\"]+\\)['\"]" nil t)
+ collect (match-string-no-properties 1)))
+ " "))
+
+(defun rct-fork-kill ()
+ "Kill rct-fork process invoked by \\[rct-fork]."
+ (interactive)
+ (when rct-fork-minor-mode
+ (rct-fork-minor-mode -1)
+ (interrupt-process "rct-fork")))
+(define-minor-mode rct-fork-minor-mode
+ "This minor mode is turned on when rct-fork is run.
+It is nothing but an indicator."
+ :lighter " " :global t)
+
+;;;; unit tests
+(when (and (fboundp 'expectations))
+ (require 'ruby-mode)
+ (require 'el-mock nil t)
+ (expectations
+ (desc "comment-dwim advice")
+ (expect "# =>"
+ (with-temp-buffer
+ (ruby-mode)
+ (setq last-command nil)
+ (call-interactively 'comment-dwim)
+ (setq last-command 'comment-dwim)
+ (call-interactively 'comment-dwim)
+ (buffer-string)))
+ (expect (regexp "^1 +# =>")
+ (with-temp-buffer
+ (ruby-mode)
+ (insert "1")
+ (setq last-command nil)
+ (call-interactively 'comment-dwim)
+ (setq last-command 'comment-dwim)
+ (call-interactively 'comment-dwim)
+ (buffer-string)))
+
+ (desc "rct-current-line")
+ (expect 1
+ (with-temp-buffer
+ (rct-current-line)))
+ (expect 1
+ (with-temp-buffer
+ (insert "1")
+ (rct-current-line)))
+ (expect 2
+ (with-temp-buffer
+ (insert "1\n")
+ (rct-current-line)))
+ (expect 2
+ (with-temp-buffer
+ (insert "1\n2")
+ (rct-current-line)))
+
+ (desc "rct-save-position")
+ (expect (mock (set-window-start * 7) => nil)
+ (stub window-start => 7)
+ (with-temp-buffer
+ (insert "abcdef\nghi")
+ (rct-save-position #'ignore)))
+ (expect 2
+ (with-temp-buffer
+ (stub window-start => 1)
+ (stub set-window-start => nil)
+ (insert "abcdef\nghi")
+ (rct-save-position #'ignore)
+ (rct-current-line)))
+ (expect 3
+ (with-temp-buffer
+ (stub window-start => 1)
+ (stub set-window-start => nil)
+ (insert "abcdef\nghi")
+ (rct-save-position #'ignore)
+ (current-column)))
+
+ (desc "rct-interactive")
+ (expect '("read")
+ (let ((current-prefix-arg t))
+ (stub read-from-minibuffer => "read")
+ (rct-interactive)))
+ (expect '("-S ruby19")
+ (let ((current-prefix-arg nil)
+ (rct-option-local "-S ruby19"))
+ (stub read-from-minibuffer => "read")
+ (rct-interactive)))
+ (expect '("")
+ (let ((current-prefix-arg nil)
+ (rct-option-local))
+ (stub read-from-minibuffer => "read")
+ (rct-interactive)))
+
+ (desc "rct-shell-command")
+ (expect "1+1 # => 2\n"
+ (with-temp-buffer
+ (insert "1+1 # =>\n")
+ (rct-shell-command "xmpfilter")
+ (buffer-string)))
+
+ (desc "xmp")
+
+ (desc "xmpfilter-command")
+ (expect "xmpfilter --rails"
+ (let ((xmpfilter-command-name "xmpfilter"))
+ (with-temp-buffer
+ (insert "class TestFoo < Test::Unit::TestCase\n")
+ (xmpfilter-command "--rails"))))
+ (expect "xmpfilter "
+ (let ((xmpfilter-command-name "xmpfilter"))
+ (with-temp-buffer
+ (insert "context 'foo' do\n")
+ (xmpfilter-command))))
+ (expect "xmpfilter "
+ (let ((xmpfilter-command-name "xmpfilter"))
+ (with-temp-buffer
+ (insert "describe Array do\n")
+ (xmpfilter-command))))
+ (expect "xmpfilter --unittest --rails"
+ (let ((xmpfilter-command-name "xmpfilter"))
+ (with-temp-buffer
+ (insert "class TestFoo < Test::Unit::TestCase\n"
+ " def test_0\n"
+ " 1 + 1 # =>\n"
+ " end\n"
+ "end\n")
+ (xmpfilter-command "--rails"))))
+ (expect "xmpfilter --spec "
+ (let ((xmpfilter-command-name "xmpfilter"))
+ (with-temp-buffer
+ (insert "context 'foo' do\n"
+ " specify \"foo\" do\n"
+ " 1 + 1 # =>\n"
+ " end\n"
+ "end\n")
+ (xmpfilter-command))))
+ (expect "xmpfilter --spec "
+ (let ((xmpfilter-command-name "xmpfilter"))
+ (with-temp-buffer
+ (insert "describe Array do\n"
+ " it \"foo\" do\n"
+ " [1] + [1] # =>\n"
+ " end\n"
+ "end\n")
+ (xmpfilter-command))))
+ (expect "xmpfilter "
+ (let ((xmpfilter-command-name "xmpfilter"))
+ (with-temp-buffer
+ (insert "1 + 2\n")
+ (xmpfilter-command))))
+
+ (desc "rct-fork")
+ (expect t
+ (stub start-process-shell-command => t)
+ (stub interrupt-process => t)
+ (rct-fork "-r activesupport")
+ rct-fork-minor-mode)
+ (expect nil
+ (stub start-process-shell-command => t)
+ (stub interrupt-process => t)
+ (rct-fork "-r activesupport")
+ (rct-fork-kill)
+ rct-fork-minor-mode)
+ ))
+
+(provide 'rcodetools)
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/rcodetools.elc b/bundles/ruby.tmbundle/Support/vendor/rcodetools/rcodetools.elc
new file mode 100644
index 000000000..a5c67c0ed
Binary files /dev/null and b/bundles/ruby.tmbundle/Support/vendor/rcodetools/rcodetools.elc differ
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/rcodetools.gif b/bundles/ruby.tmbundle/Support/vendor/rcodetools/rcodetools.gif
new file mode 100644
index 000000000..7c35fe78d
Binary files /dev/null and b/bundles/ruby.tmbundle/Support/vendor/rcodetools/rcodetools.gif differ
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/rcodetools.sxmp b/bundles/ruby.tmbundle/Support/vendor/rcodetools/rcodetools.sxmp
new file mode 100644
index 000000000..a81418acd
Binary files /dev/null and b/bundles/ruby.tmbundle/Support/vendor/rcodetools/rcodetools.sxmp differ
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/rcodetools.vim b/bundles/ruby.tmbundle/Support/vendor/rcodetools/rcodetools.vim
new file mode 100644
index 000000000..0796f007d
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/rcodetools.vim
@@ -0,0 +1,173 @@
+" Copyright (C) 2006 Mauricio Fernandez
+" rcodetools support plugin
+"
+
+if exists("loaded_rcodetools")
+ finish
+endif
+
+let loaded_rcodetools = 1
+let s:save_cpo = &cpo
+set cpo&vim
+
+"{{{ set s:sid
+
+map xx xx
+let s:sid = maparg("xx")
+unmap xx
+let s:sid = substitute(s:sid, 'xx', '', '')
+
+"{{{ function: s:spellgetoption(name, default)
+" grab a user-specified option to override the default provided. options are
+" searched in the window, buffer, then global spaces.
+function! s:GetOption(name, default)
+ if exists("w:{&filetype}_" . a:name)
+ execute "return w:{&filetype}_".a:name
+ elseif exists("w:" . a:name)
+ execute "return w:".a:name
+ elseif exists("b:{&filetype}_" . a:name)
+ execute "return b:{&filetype}_".a:name
+ elseif exists("b:" . a:name)
+ execute "return b:".a:name
+ elseif exists("g:{&filetype}_" . a:name)
+ execute "return g:{&filetype}_".a:name
+ elseif exists("g:" . a:name)
+ execute "return g:".a:name
+ else
+ return a:default
+ endif
+endfunction
+
+"{{{ IsOptionSet
+function! s:IsOptionSet(name)
+ let bogus_val = "df hdsoi3y98 hjsdfhdkj"
+ return s:GetOption(a:name, bogus_val) == bogus_val ? 0 : 1
+endfunction
+
+
+"{{{ RCT_completion function
+
+let s:last_test_file = ""
+let s:last_test_lineno = 0
+
+let s:rct_completion_col = 0
+let s:rct_tmpfile = ""
+
+function! RCT_command_with_test_options(cmd)
+ if s:last_test_file != ""
+ return a:cmd .
+ \ "-" . "-filename='" . expand("%:p") . "' " .
+ \ "-t '" . s:last_test_file . "@" . s:last_test_lineno . "' "
+ endif
+ return a:cmd
+endfunction
+
+function! RCT_completion(findstart, base)
+ if a:findstart
+ let s:rct_completion_col = col('.') - 1
+ let s:rct_tmpfile = "tmp-rcodetools" . strftime("Y-%m-%d-%H-%M-%S.rb")
+ silent exec ":w " . s:rct_tmpfile
+ return strridx(getline('.'), '.', col('.')) + 1
+ else
+ let line = line('.')
+ let column = s:rct_completion_col
+
+ let command = "rct-complete --completion-class-info --dev --fork --line=" .
+ \ line . " --column=" . column . " "
+ let command = RCT_command_with_test_options(command) . s:rct_tmpfile
+
+ let data = split(system(command), '\n')
+
+ for dline in data
+ let parts = split(dline, "\t")
+ let name = get(parts, 0)
+ let selector = get(parts, 1)
+ echo name
+ echo selector
+ if s:GetOption('rct_completion_use_fri', 0) && s:GetOption('rct_completion_info_max_len', 20) >= len(data)
+ let fri_data = system('fri -f plain ' . "'" . selector . "'" . ' 2>/dev/null')
+ call complete_add({'word': name,
+ \ 'menu': get(split(fri_data), 2, ''),
+ \ 'info': fri_data } )
+ else
+ call complete_add(name)
+ endif
+ if complete_check()
+ break
+ endif
+ endfor
+
+ call delete(s:rct_tmpfile)
+ return []
+ endif
+endfunction
+
+"{{{ ri functions
+
+function! RCT_new_ri_window()
+ execute "new"
+ execute "set bufhidden=delete buftype=nofile noswapfile nobuflisted"
+ execute 'nmap 2u'
+ execute 'nmap :call' . s:sid . 'RCT_execute_ri(expand(""))'
+endfunction
+
+function! RCT_execute_ri(query_term)
+ silent %delete _
+ let term = matchstr(a:query_term, '\v[^,.;]+')
+ let cmd = s:GetOption("RCT_ri_cmd", "fri -f plain ")
+ let text = system(cmd . "'" . term . "'")
+ call append(0, split(text, "\n"))
+ normal gg
+endfunction
+
+function! RCT_find_tag_or_ri(fullname)
+ " rubikitch: modified for rtags-compatible tags
+ let tagname = '::' . a:fullname
+ let tagresults = taglist(tagname)
+ if len(tagresults) != 0
+ execute "tjump " . tagname
+ else
+ call RCT_new_ri_window()
+ call RCT_execute_ri(a:fullname)
+ endif
+endfunction
+
+function! RCT_smart_ri()
+ let tmpfile = "tmp-rcodetools" . strftime("Y-%m-%d-%H-%M-%S.rb")
+ silent exec ":w " . tmpfile
+
+ let line = line('.')
+ let column = col('.') - 1
+ let command = "rct-doc --ri-vim --line=" . line . " --column=" . column . " "
+ let command = RCT_command_with_test_options(command) . tmpfile
+ "let term = matchstr(system(command), "\\v[^\n]+")
+ exec system(command)
+ call delete(tmpfile)
+ "call RCT_find_tag_or_ri(term)
+endfunction
+
+function! RCT_ruby_toggle()
+ let curr_file = expand("%:p")
+ let cmd = "ruby -S ruby-toggle-file " . curr_file
+ if match(curr_file, '\v_test|test_') != -1
+ let s:last_test_file = curr_file
+ let s:last_test_lineno = line(".")
+ endif
+ let dest = system(cmd)
+ silent exec ":w"
+ exec ("edit " . dest)
+ silent! normal g;
+endfunction
+
+"{{{ bindings and au
+
+if v:version >= 700
+ execute "au Filetype ruby setlocal completefunc=" . s:sid . "RCT_completion"
+endif
+execute 'au Filetype ruby nmap :exec "call ' .
+ \ 'RCT_find_tag_or_ri(''" . expand("") . "'')"'
+execute 'au Filetype ruby nmap ' . s:GetOption("RCT_ri_binding", "r") .
+ \ ' :call ' . s:sid . 'RCT_smart_ri()'
+execute 'au Filetype ruby nmap ' . s:GetOption("RCT_toggle_binding", "t") .
+ \ ' :call ' . s:sid . 'RCT_ruby_toggle()'
+let &cpo = s:save_cpo
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/setup.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/setup.rb
new file mode 100644
index 000000000..424a5f37c
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/setup.rb
@@ -0,0 +1,1585 @@
+#
+# setup.rb
+#
+# Copyright (c) 2000-2005 Minero Aoki
+#
+# This program is free software.
+# You can distribute/modify this program under the terms of
+# the GNU LGPL, Lesser General Public License version 2.1.
+#
+
+unless Enumerable.method_defined?(:map) # Ruby 1.4.6
+ module Enumerable
+ alias map collect
+ end
+end
+
+unless File.respond_to?(:read) # Ruby 1.6
+ def File.read(fname)
+ open(fname) {|f|
+ return f.read
+ }
+ end
+end
+
+unless Errno.const_defined?(:ENOTEMPTY) # Windows?
+ module Errno
+ class ENOTEMPTY
+ # We do not raise this exception, implementation is not needed.
+ end
+ end
+end
+
+def File.binread(fname)
+ open(fname, 'rb') {|f|
+ return f.read
+ }
+end
+
+# for corrupted Windows' stat(2)
+def File.dir?(path)
+ File.directory?((path[-1,1] == '/') ? path : path + '/')
+end
+
+
+class ConfigTable
+
+ include Enumerable
+
+ def initialize(rbconfig)
+ @rbconfig = rbconfig
+ @items = []
+ @table = {}
+ # options
+ @install_prefix = nil
+ @config_opt = nil
+ @verbose = true
+ @no_harm = false
+ end
+
+ attr_accessor :install_prefix
+ attr_accessor :config_opt
+
+ attr_writer :verbose
+
+ def verbose?
+ @verbose
+ end
+
+ attr_writer :no_harm
+
+ def no_harm?
+ @no_harm
+ end
+
+ def [](key)
+ lookup(key).resolve(self)
+ end
+
+ def []=(key, val)
+ lookup(key).set val
+ end
+
+ def names
+ @items.map {|i| i.name }
+ end
+
+ def each(&block)
+ @items.each(&block)
+ end
+
+ def key?(name)
+ @table.key?(name)
+ end
+
+ def lookup(name)
+ @table[name] or setup_rb_error "no such config item: #{name}"
+ end
+
+ def add(item)
+ @items.push item
+ @table[item.name] = item
+ end
+
+ def remove(name)
+ item = lookup(name)
+ @items.delete_if {|i| i.name == name }
+ @table.delete_if {|name, i| i.name == name }
+ item
+ end
+
+ def load_script(path, inst = nil)
+ if File.file?(path)
+ MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path
+ end
+ end
+
+ def savefile
+ '.config'
+ end
+
+ def load_savefile
+ begin
+ File.foreach(savefile()) do |line|
+ k, v = *line.split(/=/, 2)
+ self[k] = v.strip
+ end
+ rescue Errno::ENOENT
+ setup_rb_error $!.message + "\n#{File.basename($0)} config first"
+ end
+ end
+
+ def save
+ @items.each {|i| i.value }
+ File.open(savefile(), 'w') {|f|
+ @items.each do |i|
+ f.printf "%s=%s\n", i.name, i.value if i.value? and i.value
+ end
+ }
+ end
+
+ def load_standard_entries
+ standard_entries(@rbconfig).each do |ent|
+ add ent
+ end
+ end
+
+ def standard_entries(rbconfig)
+ c = rbconfig
+
+ rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT'])
+
+ major = c['MAJOR'].to_i
+ minor = c['MINOR'].to_i
+ teeny = c['TEENY'].to_i
+ version = "#{major}.#{minor}"
+
+ # ruby ver. >= 1.4.4?
+ newpath_p = ((major >= 2) or
+ ((major == 1) and
+ ((minor >= 5) or
+ ((minor == 4) and (teeny >= 4)))))
+
+ if c['rubylibdir']
+ # V > 1.6.3
+ libruby = "#{c['prefix']}/lib/ruby"
+ librubyver = c['rubylibdir']
+ librubyverarch = c['archdir']
+ siteruby = c['sitedir']
+ siterubyver = c['sitelibdir']
+ siterubyverarch = c['sitearchdir']
+ elsif newpath_p
+ # 1.4.4 <= V <= 1.6.3
+ libruby = "#{c['prefix']}/lib/ruby"
+ librubyver = "#{c['prefix']}/lib/ruby/#{version}"
+ librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
+ siteruby = c['sitedir']
+ siterubyver = "$siteruby/#{version}"
+ siterubyverarch = "$siterubyver/#{c['arch']}"
+ else
+ # V < 1.4.4
+ libruby = "#{c['prefix']}/lib/ruby"
+ librubyver = "#{c['prefix']}/lib/ruby/#{version}"
+ librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
+ siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby"
+ siterubyver = siteruby
+ siterubyverarch = "$siterubyver/#{c['arch']}"
+ end
+ parameterize = lambda {|path|
+ path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')
+ }
+
+ if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
+ makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
+ else
+ makeprog = 'make'
+ end
+
+ [
+ ExecItem.new('installdirs', 'std/site/home',
+ 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\
+ {|val, table|
+ case val
+ when 'std'
+ table['rbdir'] = '$librubyver'
+ table['sodir'] = '$librubyverarch'
+ when 'site'
+ table['rbdir'] = '$siterubyver'
+ table['sodir'] = '$siterubyverarch'
+ when 'home'
+ setup_rb_error '$HOME was not set' unless ENV['HOME']
+ table['prefix'] = ENV['HOME']
+ table['rbdir'] = '$libdir/ruby'
+ table['sodir'] = '$libdir/ruby'
+ end
+ },
+ PathItem.new('prefix', 'path', c['prefix'],
+ 'path prefix of target environment'),
+ PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
+ 'the directory for commands'),
+ PathItem.new('libdir', 'path', parameterize.call(c['libdir']),
+ 'the directory for libraries'),
+ PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
+ 'the directory for shared data'),
+ PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
+ 'the directory for man pages'),
+ PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
+ 'the directory for system configuration files'),
+ PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']),
+ 'the directory for local state data'),
+ PathItem.new('libruby', 'path', libruby,
+ 'the directory for ruby libraries'),
+ PathItem.new('librubyver', 'path', librubyver,
+ 'the directory for standard ruby libraries'),
+ PathItem.new('librubyverarch', 'path', librubyverarch,
+ 'the directory for standard ruby extensions'),
+ PathItem.new('siteruby', 'path', siteruby,
+ 'the directory for version-independent aux ruby libraries'),
+ PathItem.new('siterubyver', 'path', siterubyver,
+ 'the directory for aux ruby libraries'),
+ PathItem.new('siterubyverarch', 'path', siterubyverarch,
+ 'the directory for aux ruby binaries'),
+ PathItem.new('rbdir', 'path', '$siterubyver',
+ 'the directory for ruby scripts'),
+ PathItem.new('sodir', 'path', '$siterubyverarch',
+ 'the directory for ruby extentions'),
+ PathItem.new('rubypath', 'path', rubypath,
+ 'the path to set to #! line'),
+ ProgramItem.new('rubyprog', 'name', rubypath,
+ 'the ruby program using for installation'),
+ ProgramItem.new('makeprog', 'name', makeprog,
+ 'the make program to compile ruby extentions'),
+ SelectItem.new('shebang', 'all/ruby/never', 'ruby',
+ 'shebang line (#!) editing mode'),
+ BoolItem.new('without-ext', 'yes/no', 'no',
+ 'does not compile/install ruby extentions')
+ ]
+ end
+ private :standard_entries
+
+ def load_multipackage_entries
+ multipackage_entries().each do |ent|
+ add ent
+ end
+ end
+
+ def multipackage_entries
+ [
+ PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
+ 'package names that you want to install'),
+ PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
+ 'package names that you do not want to install')
+ ]
+ end
+ private :multipackage_entries
+
+ ALIASES = {
+ 'std-ruby' => 'librubyver',
+ 'stdruby' => 'librubyver',
+ 'rubylibdir' => 'librubyver',
+ 'archdir' => 'librubyverarch',
+ 'site-ruby-common' => 'siteruby', # For backward compatibility
+ 'site-ruby' => 'siterubyver', # For backward compatibility
+ 'bin-dir' => 'bindir',
+ 'bin-dir' => 'bindir',
+ 'rb-dir' => 'rbdir',
+ 'so-dir' => 'sodir',
+ 'data-dir' => 'datadir',
+ 'ruby-path' => 'rubypath',
+ 'ruby-prog' => 'rubyprog',
+ 'ruby' => 'rubyprog',
+ 'make-prog' => 'makeprog',
+ 'make' => 'makeprog'
+ }
+
+ def fixup
+ ALIASES.each do |ali, name|
+ @table[ali] = @table[name]
+ end
+ @items.freeze
+ @table.freeze
+ @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/
+ end
+
+ def parse_opt(opt)
+ m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}"
+ m.to_a[1,2]
+ end
+
+ def dllext
+ @rbconfig['DLEXT']
+ end
+
+ def value_config?(name)
+ lookup(name).value?
+ end
+
+ class Item
+ def initialize(name, template, default, desc)
+ @name = name.freeze
+ @template = template
+ @value = default
+ @default = default
+ @description = desc
+ end
+
+ attr_reader :name
+ attr_reader :description
+
+ attr_accessor :default
+ alias help_default default
+
+ def help_opt
+ "--#{@name}=#{@template}"
+ end
+
+ def value?
+ true
+ end
+
+ def value
+ @value
+ end
+
+ def resolve(table)
+ @value.gsub(%r<\$([^/]+)>) { table[$1] }
+ end
+
+ def set(val)
+ @value = check(val)
+ end
+
+ private
+
+ def check(val)
+ setup_rb_error "config: --#{name} requires argument" unless val
+ val
+ end
+ end
+
+ class BoolItem < Item
+ def config_type
+ 'bool'
+ end
+
+ def help_opt
+ "--#{@name}"
+ end
+
+ private
+
+ def check(val)
+ return 'yes' unless val
+ case val
+ when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes'
+ when /\An(o)?\z/i, /\Af(alse)\z/i then 'no'
+ else
+ setup_rb_error "config: --#{@name} accepts only yes/no for argument"
+ end
+ end
+ end
+
+ class PathItem < Item
+ def config_type
+ 'path'
+ end
+
+ private
+
+ def check(path)
+ setup_rb_error "config: --#{@name} requires argument" unless path
+ path[0,1] == '$' ? path : File.expand_path(path)
+ end
+ end
+
+ class ProgramItem < Item
+ def config_type
+ 'program'
+ end
+ end
+
+ class SelectItem < Item
+ def initialize(name, selection, default, desc)
+ super
+ @ok = selection.split('/')
+ end
+
+ def config_type
+ 'select'
+ end
+
+ private
+
+ def check(val)
+ unless @ok.include?(val.strip)
+ setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
+ end
+ val.strip
+ end
+ end
+
+ class ExecItem < Item
+ def initialize(name, selection, desc, &block)
+ super name, selection, nil, desc
+ @ok = selection.split('/')
+ @action = block
+ end
+
+ def config_type
+ 'exec'
+ end
+
+ def value?
+ false
+ end
+
+ def resolve(table)
+ setup_rb_error "$#{name()} wrongly used as option value"
+ end
+
+ undef set
+
+ def evaluate(val, table)
+ v = val.strip.downcase
+ unless @ok.include?(v)
+ setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})"
+ end
+ @action.call v, table
+ end
+ end
+
+ class PackageSelectionItem < Item
+ def initialize(name, template, default, help_default, desc)
+ super name, template, default, desc
+ @help_default = help_default
+ end
+
+ attr_reader :help_default
+
+ def config_type
+ 'package'
+ end
+
+ private
+
+ def check(val)
+ unless File.dir?("packages/#{val}")
+ setup_rb_error "config: no such package: #{val}"
+ end
+ val
+ end
+ end
+
+ class MetaConfigEnvironment
+ def initialize(config, installer)
+ @config = config
+ @installer = installer
+ end
+
+ def config_names
+ @config.names
+ end
+
+ def config?(name)
+ @config.key?(name)
+ end
+
+ def bool_config?(name)
+ @config.lookup(name).config_type == 'bool'
+ end
+
+ def path_config?(name)
+ @config.lookup(name).config_type == 'path'
+ end
+
+ def value_config?(name)
+ @config.lookup(name).config_type != 'exec'
+ end
+
+ def add_config(item)
+ @config.add item
+ end
+
+ def add_bool_config(name, default, desc)
+ @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
+ end
+
+ def add_path_config(name, default, desc)
+ @config.add PathItem.new(name, 'path', default, desc)
+ end
+
+ def set_config_default(name, default)
+ @config.lookup(name).default = default
+ end
+
+ def remove_config(name)
+ @config.remove(name)
+ end
+
+ # For only multipackage
+ def packages
+ raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer
+ @installer.packages
+ end
+
+ # For only multipackage
+ def declare_packages(list)
+ raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer
+ @installer.packages = list
+ end
+ end
+
+end # class ConfigTable
+
+
+# This module requires: #verbose?, #no_harm?
+module FileOperations
+
+ def mkdir_p(dirname, prefix = nil)
+ dirname = prefix + File.expand_path(dirname) if prefix
+ $stderr.puts "mkdir -p #{dirname}" if verbose?
+ return if no_harm?
+
+ # Does not check '/', it's too abnormal.
+ dirs = File.expand_path(dirname).split(%r<(?=/)>)
+ if /\A[a-z]:\z/i =~ dirs[0]
+ disk = dirs.shift
+ dirs[0] = disk + dirs[0]
+ end
+ dirs.each_index do |idx|
+ path = dirs[0..idx].join('')
+ Dir.mkdir path unless File.dir?(path)
+ end
+ end
+
+ def rm_f(path)
+ $stderr.puts "rm -f #{path}" if verbose?
+ return if no_harm?
+ force_remove_file path
+ end
+
+ def rm_rf(path)
+ $stderr.puts "rm -rf #{path}" if verbose?
+ return if no_harm?
+ remove_tree path
+ end
+
+ def remove_tree(path)
+ if File.symlink?(path)
+ remove_file path
+ elsif File.dir?(path)
+ remove_tree0 path
+ else
+ force_remove_file path
+ end
+ end
+
+ def remove_tree0(path)
+ Dir.foreach(path) do |ent|
+ next if ent == '.'
+ next if ent == '..'
+ entpath = "#{path}/#{ent}"
+ if File.symlink?(entpath)
+ remove_file entpath
+ elsif File.dir?(entpath)
+ remove_tree0 entpath
+ else
+ force_remove_file entpath
+ end
+ end
+ begin
+ Dir.rmdir path
+ rescue Errno::ENOTEMPTY
+ # directory may not be empty
+ end
+ end
+
+ def move_file(src, dest)
+ force_remove_file dest
+ begin
+ File.rename src, dest
+ rescue
+ File.open(dest, 'wb') {|f|
+ f.write File.binread(src)
+ }
+ File.chmod File.stat(src).mode, dest
+ File.unlink src
+ end
+ end
+
+ def force_remove_file(path)
+ begin
+ remove_file path
+ rescue
+ end
+ end
+
+ def remove_file(path)
+ File.chmod 0777, path
+ File.unlink path
+ end
+
+ def install(from, dest, mode, prefix = nil)
+ $stderr.puts "install #{from} #{dest}" if verbose?
+ return if no_harm?
+
+ realdest = prefix ? prefix + File.expand_path(dest) : dest
+ realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
+ str = File.binread(from)
+ if diff?(str, realdest)
+ verbose_off {
+ rm_f realdest if File.exist?(realdest)
+ }
+ File.open(realdest, 'wb') {|f|
+ f.write str
+ }
+ File.chmod mode, realdest
+
+ File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
+ if prefix
+ f.puts realdest.sub(prefix, '')
+ else
+ f.puts realdest
+ end
+ }
+ end
+ end
+
+ def diff?(new_content, path)
+ return true unless File.exist?(path)
+ new_content != File.binread(path)
+ end
+
+ def command(*args)
+ $stderr.puts args.join(' ') if verbose?
+ system(*args) or raise RuntimeError,
+ "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
+ end
+
+ def ruby(*args)
+ command config('rubyprog'), *args
+ end
+
+ def make(task = nil)
+ command(*[config('makeprog'), task].compact)
+ end
+
+ def extdir?(dir)
+ File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
+ end
+
+ def files_of(dir)
+ Dir.open(dir) {|d|
+ return d.select {|ent| File.file?("#{dir}/#{ent}") }
+ }
+ end
+
+ DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
+
+ def directories_of(dir)
+ Dir.open(dir) {|d|
+ return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
+ }
+ end
+
+end
+
+
+# This module requires: #srcdir_root, #objdir_root, #relpath
+module HookScriptAPI
+
+ def get_config(key)
+ @config[key]
+ end
+
+ alias config get_config
+
+ # obsolete: use metaconfig to change configuration
+ def set_config(key, val)
+ @config[key] = val
+ end
+
+ #
+ # srcdir/objdir (works only in the package directory)
+ #
+
+ def curr_srcdir
+ "#{srcdir_root()}/#{relpath()}"
+ end
+
+ def curr_objdir
+ "#{objdir_root()}/#{relpath()}"
+ end
+
+ def srcfile(path)
+ "#{curr_srcdir()}/#{path}"
+ end
+
+ def srcexist?(path)
+ File.exist?(srcfile(path))
+ end
+
+ def srcdirectory?(path)
+ File.dir?(srcfile(path))
+ end
+
+ def srcfile?(path)
+ File.file?(srcfile(path))
+ end
+
+ def srcentries(path = '.')
+ Dir.open("#{curr_srcdir()}/#{path}") {|d|
+ return d.to_a - %w(. ..)
+ }
+ end
+
+ def srcfiles(path = '.')
+ srcentries(path).select {|fname|
+ File.file?(File.join(curr_srcdir(), path, fname))
+ }
+ end
+
+ def srcdirectories(path = '.')
+ srcentries(path).select {|fname|
+ File.dir?(File.join(curr_srcdir(), path, fname))
+ }
+ end
+
+end
+
+
+class ToplevelInstaller
+
+ Version = '3.4.1'
+ Copyright = 'Copyright (c) 2000-2005 Minero Aoki'
+
+ TASKS = [
+ [ 'all', 'do config, setup, then install' ],
+ [ 'config', 'saves your configurations' ],
+ [ 'show', 'shows current configuration' ],
+ [ 'setup', 'compiles ruby extentions and others' ],
+ [ 'install', 'installs files' ],
+ [ 'test', 'run all tests in test/' ],
+ [ 'clean', "does `make clean' for each extention" ],
+ [ 'distclean',"does `make distclean' for each extention" ]
+ ]
+
+ def ToplevelInstaller.invoke
+ config = ConfigTable.new(load_rbconfig())
+ config.load_standard_entries
+ config.load_multipackage_entries if multipackage?
+ config.fixup
+ klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller)
+ klass.new(File.dirname($0), config).invoke
+ end
+
+ def ToplevelInstaller.multipackage?
+ File.dir?(File.dirname($0) + '/packages')
+ end
+
+ def ToplevelInstaller.load_rbconfig
+ if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
+ ARGV.delete(arg)
+ load File.expand_path(arg.split(/=/, 2)[1])
+ $".push 'rbconfig.rb'
+ else
+ require 'rbconfig'
+ end
+ ::Config::CONFIG
+ end
+
+ def initialize(ardir_root, config)
+ @ardir = File.expand_path(ardir_root)
+ @config = config
+ # cache
+ @valid_task_re = nil
+ end
+
+ def config(key)
+ @config[key]
+ end
+
+ def inspect
+ "#<#{self.class} #{__id__()}>"
+ end
+
+ def invoke
+ run_metaconfigs
+ case task = parsearg_global()
+ when nil, 'all'
+ parsearg_config
+ init_installers
+ exec_config
+ exec_setup
+ exec_install
+ else
+ case task
+ when 'config', 'test'
+ ;
+ when 'clean', 'distclean'
+ @config.load_savefile if File.exist?(@config.savefile)
+ else
+ @config.load_savefile
+ end
+ __send__ "parsearg_#{task}"
+ init_installers
+ __send__ "exec_#{task}"
+ end
+ end
+
+ def run_metaconfigs
+ @config.load_script "#{@ardir}/metaconfig"
+ end
+
+ def init_installers
+ @installer = Installer.new(@config, @ardir, File.expand_path('.'))
+ end
+
+ #
+ # Hook Script API bases
+ #
+
+ def srcdir_root
+ @ardir
+ end
+
+ def objdir_root
+ '.'
+ end
+
+ def relpath
+ '.'
+ end
+
+ #
+ # Option Parsing
+ #
+
+ def parsearg_global
+ while arg = ARGV.shift
+ case arg
+ when /\A\w+\z/
+ setup_rb_error "invalid task: #{arg}" unless valid_task?(arg)
+ return arg
+ when '-q', '--quiet'
+ @config.verbose = false
+ when '--verbose'
+ @config.verbose = true
+ when '--help'
+ print_usage $stdout
+ exit 0
+ when '--version'
+ puts "#{File.basename($0)} version #{Version}"
+ exit 0
+ when '--copyright'
+ puts Copyright
+ exit 0
+ else
+ setup_rb_error "unknown global option '#{arg}'"
+ end
+ end
+ nil
+ end
+
+ def valid_task?(t)
+ valid_task_re() =~ t
+ end
+
+ def valid_task_re
+ @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/
+ end
+
+ def parsearg_no_options
+ unless ARGV.empty?
+ task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1)
+ setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}"
+ end
+ end
+
+ alias parsearg_show parsearg_no_options
+ alias parsearg_setup parsearg_no_options
+ alias parsearg_test parsearg_no_options
+ alias parsearg_clean parsearg_no_options
+ alias parsearg_distclean parsearg_no_options
+
+ def parsearg_config
+ evalopt = []
+ set = []
+ @config.config_opt = []
+ while i = ARGV.shift
+ if /\A--?\z/ =~ i
+ @config.config_opt = ARGV.dup
+ break
+ end
+ name, value = *@config.parse_opt(i)
+ if @config.value_config?(name)
+ @config[name] = value
+ else
+ evalopt.push [name, value]
+ end
+ set.push name
+ end
+ evalopt.each do |name, value|
+ @config.lookup(name).evaluate value, @config
+ end
+ # Check if configuration is valid
+ set.each do |n|
+ @config[n] if @config.value_config?(n)
+ end
+ end
+
+ def parsearg_install
+ @config.no_harm = false
+ @config.install_prefix = ''
+ while a = ARGV.shift
+ case a
+ when '--no-harm'
+ @config.no_harm = true
+ when /\A--prefix=/
+ path = a.split(/=/, 2)[1]
+ path = File.expand_path(path) unless path[0,1] == '/'
+ @config.install_prefix = path
+ else
+ setup_rb_error "install: unknown option #{a}"
+ end
+ end
+ end
+
+ def print_usage(out)
+ out.puts 'Typical Installation Procedure:'
+ out.puts " $ ruby #{File.basename $0} config"
+ out.puts " $ ruby #{File.basename $0} setup"
+ out.puts " # ruby #{File.basename $0} install (may require root privilege)"
+ out.puts
+ out.puts 'Detailed Usage:'
+ out.puts " ruby #{File.basename $0} "
+ out.puts " ruby #{File.basename $0} [] []"
+
+ fmt = " %-24s %s\n"
+ out.puts
+ out.puts 'Global options:'
+ out.printf fmt, '-q,--quiet', 'suppress message outputs'
+ out.printf fmt, ' --verbose', 'output messages verbosely'
+ out.printf fmt, ' --help', 'print this message'
+ out.printf fmt, ' --version', 'print version and quit'
+ out.printf fmt, ' --copyright', 'print copyright and quit'
+ out.puts
+ out.puts 'Tasks:'
+ TASKS.each do |name, desc|
+ out.printf fmt, name, desc
+ end
+
+ fmt = " %-24s %s [%s]\n"
+ out.puts
+ out.puts 'Options for CONFIG or ALL:'
+ @config.each do |item|
+ out.printf fmt, item.help_opt, item.description, item.help_default
+ end
+ out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
+ out.puts
+ out.puts 'Options for INSTALL:'
+ out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
+ out.printf fmt, '--prefix=path', 'install path prefix', ''
+ out.puts
+ end
+
+ #
+ # Task Handlers
+ #
+
+ def exec_config
+ @installer.exec_config
+ @config.save # must be final
+ end
+
+ def exec_setup
+ @installer.exec_setup
+ end
+
+ def exec_install
+ @installer.exec_install
+ end
+
+ def exec_test
+ @installer.exec_test
+ end
+
+ def exec_show
+ @config.each do |i|
+ printf "%-20s %s\n", i.name, i.value if i.value?
+ end
+ end
+
+ def exec_clean
+ @installer.exec_clean
+ end
+
+ def exec_distclean
+ @installer.exec_distclean
+ end
+
+end # class ToplevelInstaller
+
+
+class ToplevelInstallerMulti < ToplevelInstaller
+
+ include FileOperations
+
+ def initialize(ardir_root, config)
+ super
+ @packages = directories_of("#{@ardir}/packages")
+ raise 'no package exists' if @packages.empty?
+ @root_installer = Installer.new(@config, @ardir, File.expand_path('.'))
+ end
+
+ def run_metaconfigs
+ @config.load_script "#{@ardir}/metaconfig", self
+ @packages.each do |name|
+ @config.load_script "#{@ardir}/packages/#{name}/metaconfig"
+ end
+ end
+
+ attr_reader :packages
+
+ def packages=(list)
+ raise 'package list is empty' if list.empty?
+ list.each do |name|
+ raise "directory packages/#{name} does not exist"\
+ unless File.dir?("#{@ardir}/packages/#{name}")
+ end
+ @packages = list
+ end
+
+ def init_installers
+ @installers = {}
+ @packages.each do |pack|
+ @installers[pack] = Installer.new(@config,
+ "#{@ardir}/packages/#{pack}",
+ "packages/#{pack}")
+ end
+ with = extract_selection(config('with'))
+ without = extract_selection(config('without'))
+ @selected = @installers.keys.select {|name|
+ (with.empty? or with.include?(name)) \
+ and not without.include?(name)
+ }
+ end
+
+ def extract_selection(list)
+ a = list.split(/,/)
+ a.each do |name|
+ setup_rb_error "no such package: #{name}" unless @installers.key?(name)
+ end
+ a
+ end
+
+ def print_usage(f)
+ super
+ f.puts 'Inluded packages:'
+ f.puts ' ' + @packages.sort.join(' ')
+ f.puts
+ end
+
+ #
+ # Task Handlers
+ #
+
+ def exec_config
+ run_hook 'pre-config'
+ each_selected_installers {|inst| inst.exec_config }
+ run_hook 'post-config'
+ @config.save # must be final
+ end
+
+ def exec_setup
+ run_hook 'pre-setup'
+ each_selected_installers {|inst| inst.exec_setup }
+ run_hook 'post-setup'
+ end
+
+ def exec_install
+ run_hook 'pre-install'
+ each_selected_installers {|inst| inst.exec_install }
+ run_hook 'post-install'
+ end
+
+ def exec_test
+ run_hook 'pre-test'
+ each_selected_installers {|inst| inst.exec_test }
+ run_hook 'post-test'
+ end
+
+ def exec_clean
+ rm_f @config.savefile
+ run_hook 'pre-clean'
+ each_selected_installers {|inst| inst.exec_clean }
+ run_hook 'post-clean'
+ end
+
+ def exec_distclean
+ rm_f @config.savefile
+ run_hook 'pre-distclean'
+ each_selected_installers {|inst| inst.exec_distclean }
+ run_hook 'post-distclean'
+ end
+
+ #
+ # lib
+ #
+
+ def each_selected_installers
+ Dir.mkdir 'packages' unless File.dir?('packages')
+ @selected.each do |pack|
+ $stderr.puts "Processing the package `#{pack}' ..." if verbose?
+ Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
+ Dir.chdir "packages/#{pack}"
+ yield @installers[pack]
+ Dir.chdir '../..'
+ end
+ end
+
+ def run_hook(id)
+ @root_installer.run_hook id
+ end
+
+ # module FileOperations requires this
+ def verbose?
+ @config.verbose?
+ end
+
+ # module FileOperations requires this
+ def no_harm?
+ @config.no_harm?
+ end
+
+end # class ToplevelInstallerMulti
+
+
+class Installer
+
+ FILETYPES = %w( bin lib ext data conf man )
+
+ include FileOperations
+ include HookScriptAPI
+
+ def initialize(config, srcroot, objroot)
+ @config = config
+ @srcdir = File.expand_path(srcroot)
+ @objdir = File.expand_path(objroot)
+ @currdir = '.'
+ end
+
+ def inspect
+ "#<#{self.class} #{File.basename(@srcdir)}>"
+ end
+
+ def noop(rel)
+ end
+
+ #
+ # Hook Script API base methods
+ #
+
+ def srcdir_root
+ @srcdir
+ end
+
+ def objdir_root
+ @objdir
+ end
+
+ def relpath
+ @currdir
+ end
+
+ #
+ # Config Access
+ #
+
+ # module FileOperations requires this
+ def verbose?
+ @config.verbose?
+ end
+
+ # module FileOperations requires this
+ def no_harm?
+ @config.no_harm?
+ end
+
+ def verbose_off
+ begin
+ save, @config.verbose = @config.verbose?, false
+ yield
+ ensure
+ @config.verbose = save
+ end
+ end
+
+ #
+ # TASK config
+ #
+
+ def exec_config
+ exec_task_traverse 'config'
+ end
+
+ alias config_dir_bin noop
+ alias config_dir_lib noop
+
+ def config_dir_ext(rel)
+ extconf if extdir?(curr_srcdir())
+ end
+
+ alias config_dir_data noop
+ alias config_dir_conf noop
+ alias config_dir_man noop
+
+ def extconf
+ ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt
+ end
+
+ #
+ # TASK setup
+ #
+
+ def exec_setup
+ exec_task_traverse 'setup'
+ end
+
+ def setup_dir_bin(rel)
+ files_of(curr_srcdir()).each do |fname|
+ update_shebang_line "#{curr_srcdir()}/#{fname}"
+ end
+ end
+
+ alias setup_dir_lib noop
+
+ def setup_dir_ext(rel)
+ make if extdir?(curr_srcdir())
+ end
+
+ alias setup_dir_data noop
+ alias setup_dir_conf noop
+ alias setup_dir_man noop
+
+ def update_shebang_line(path)
+ return if no_harm?
+ return if config('shebang') == 'never'
+ old = Shebang.load(path)
+ if old
+ $stderr.puts "warning: #{path}: Shebang line includes too many args. It is not portable and your program may not work." if old.args.size > 1
+ new = new_shebang(old)
+ return if new.to_s == old.to_s
+ else
+ return unless config('shebang') == 'all'
+ new = Shebang.new(config('rubypath'))
+ end
+ $stderr.puts "updating shebang: #{File.basename(path)}" if verbose?
+ open_atomic_writer(path) {|output|
+ File.open(path, 'rb') {|f|
+ f.gets if old # discard
+ output.puts new.to_s
+ output.print f.read
+ }
+ }
+ end
+
+ def new_shebang(old)
+ if /\Aruby/ =~ File.basename(old.cmd)
+ Shebang.new(config('rubypath'), old.args)
+ elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
+ Shebang.new(config('rubypath'), old.args[1..-1])
+ else
+ return old unless config('shebang') == 'all'
+ Shebang.new(config('rubypath'))
+ end
+ end
+
+ def open_atomic_writer(path, &block)
+ tmpfile = File.basename(path) + '.tmp'
+ begin
+ File.open(tmpfile, 'wb', &block)
+ File.rename tmpfile, File.basename(path)
+ ensure
+ File.unlink tmpfile if File.exist?(tmpfile)
+ end
+ end
+
+ class Shebang
+ def Shebang.load(path)
+ line = nil
+ File.open(path) {|f|
+ line = f.gets
+ }
+ return nil unless /\A#!/ =~ line
+ parse(line)
+ end
+
+ def Shebang.parse(line)
+ cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
+ new(cmd, args)
+ end
+
+ def initialize(cmd, args = [])
+ @cmd = cmd
+ @args = args
+ end
+
+ attr_reader :cmd
+ attr_reader :args
+
+ def to_s
+ "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
+ end
+ end
+
+ #
+ # TASK install
+ #
+
+ def exec_install
+ rm_f 'InstalledFiles'
+ exec_task_traverse 'install'
+ end
+
+ def install_dir_bin(rel)
+ install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755
+ end
+
+ def install_dir_lib(rel)
+ install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644
+ end
+
+ def install_dir_ext(rel)
+ return unless extdir?(curr_srcdir())
+ install_files rubyextentions('.'),
+ "#{config('sodir')}/#{File.dirname(rel)}",
+ 0555
+ end
+
+ def install_dir_data(rel)
+ install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644
+ end
+
+ def install_dir_conf(rel)
+ # FIXME: should not remove current config files
+ # (rename previous file to .old/.org)
+ install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644
+ end
+
+ def install_dir_man(rel)
+ install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644
+ end
+
+ def install_files(list, dest, mode)
+ mkdir_p dest, @config.install_prefix
+ list.each do |fname|
+ install fname, dest, mode, @config.install_prefix
+ end
+ end
+
+ def libfiles
+ glob_reject(%w(*.y *.output), targetfiles())
+ end
+
+ def rubyextentions(dir)
+ ents = glob_select("*.#{@config.dllext}", targetfiles())
+ if ents.empty?
+ setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
+ end
+ ents
+ end
+
+ def targetfiles
+ mapdir(existfiles() - hookfiles())
+ end
+
+ def mapdir(ents)
+ ents.map {|ent|
+ if File.exist?(ent)
+ then ent # objdir
+ else "#{curr_srcdir()}/#{ent}" # srcdir
+ end
+ }
+ end
+
+ # picked up many entries from cvs-1.11.1/src/ignore.c
+ JUNK_FILES = %w(
+ core RCSLOG tags TAGS .make.state
+ .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
+ *~ *.old *.bak *.BAK *.orig *.rej _$* *$
+
+ *.org *.in .*
+ )
+
+ def existfiles
+ glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
+ end
+
+ def hookfiles
+ %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
+ %w( config setup install clean ).map {|t| sprintf(fmt, t) }
+ }.flatten
+ end
+
+ def glob_select(pat, ents)
+ re = globs2re([pat])
+ ents.select {|ent| re =~ ent }
+ end
+
+ def glob_reject(pats, ents)
+ re = globs2re(pats)
+ ents.reject {|ent| re =~ ent }
+ end
+
+ GLOB2REGEX = {
+ '.' => '\.',
+ '$' => '\$',
+ '#' => '\#',
+ '*' => '.*'
+ }
+
+ def globs2re(pats)
+ /\A(?:#{
+ pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
+ })\z/
+ end
+
+ #
+ # TASK test
+ #
+
+ TESTDIR = 'test'
+
+ def exec_test
+ unless File.directory?('test')
+ $stderr.puts 'no test in this package' if verbose?
+ return
+ end
+ $stderr.puts 'Running tests...' if verbose?
+ begin
+ require 'test/unit'
+ rescue LoadError
+ setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.'
+ end
+ runner = Test::Unit::AutoRunner.new(true)
+ runner.to_run << TESTDIR
+ runner.run
+ end
+
+ #
+ # TASK clean
+ #
+
+ def exec_clean
+ exec_task_traverse 'clean'
+ rm_f @config.savefile
+ rm_f 'InstalledFiles'
+ end
+
+ alias clean_dir_bin noop
+ alias clean_dir_lib noop
+ alias clean_dir_data noop
+ alias clean_dir_conf noop
+ alias clean_dir_man noop
+
+ def clean_dir_ext(rel)
+ return unless extdir?(curr_srcdir())
+ make 'clean' if File.file?('Makefile')
+ end
+
+ #
+ # TASK distclean
+ #
+
+ def exec_distclean
+ exec_task_traverse 'distclean'
+ rm_f @config.savefile
+ rm_f 'InstalledFiles'
+ end
+
+ alias distclean_dir_bin noop
+ alias distclean_dir_lib noop
+
+ def distclean_dir_ext(rel)
+ return unless extdir?(curr_srcdir())
+ make 'distclean' if File.file?('Makefile')
+ end
+
+ alias distclean_dir_data noop
+ alias distclean_dir_conf noop
+ alias distclean_dir_man noop
+
+ #
+ # Traversing
+ #
+
+ def exec_task_traverse(task)
+ run_hook "pre-#{task}"
+ FILETYPES.each do |type|
+ if type == 'ext' and config('without-ext') == 'yes'
+ $stderr.puts 'skipping ext/* by user option' if verbose?
+ next
+ end
+ traverse task, type, "#{task}_dir_#{type}"
+ end
+ run_hook "post-#{task}"
+ end
+
+ def traverse(task, rel, mid)
+ dive_into(rel) {
+ run_hook "pre-#{task}"
+ __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
+ directories_of(curr_srcdir()).each do |d|
+ traverse task, "#{rel}/#{d}", mid
+ end
+ run_hook "post-#{task}"
+ }
+ end
+
+ def dive_into(rel)
+ return unless File.dir?("#{@srcdir}/#{rel}")
+
+ dir = File.basename(rel)
+ Dir.mkdir dir unless File.dir?(dir)
+ prevdir = Dir.pwd
+ Dir.chdir dir
+ $stderr.puts '---> ' + rel if verbose?
+ @currdir = rel
+ yield
+ Dir.chdir prevdir
+ $stderr.puts '<--- ' + rel if verbose?
+ @currdir = File.dirname(rel)
+ end
+
+ def run_hook(id)
+ path = [ "#{curr_srcdir()}/#{id}",
+ "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
+ return unless path
+ begin
+ instance_eval File.read(path), path, 1
+ rescue
+ raise if $DEBUG
+ setup_rb_error "hook #{path} failed:\n" + $!.message
+ end
+ end
+
+end # class Installer
+
+
+class SetupError < StandardError; end
+
+def setup_rb_error(msg)
+ raise SetupError, msg
+end
+
+if $0 == __FILE__
+ begin
+ ToplevelInstaller.invoke
+ rescue SetupError
+ raise if $DEBUG
+ $stderr.puts $!.message
+ $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
+ exit 1
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/attic/test_run.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/attic/test_run.rb
new file mode 100644
index 000000000..37d83d5a5
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/attic/test_run.rb
@@ -0,0 +1,45 @@
+require 'test/unit'
+require 'rcodetools/xmpfilter'
+require 'rcodetools/xmptestunitfilter'
+require 'rcodetools/completion'
+require 'rcodetools/doc'
+require 'rcodetools/options'
+require 'stringio'
+
+class TestRun < Test::Unit::TestCase
+ include Rcodetools
+ DIR = File.expand_path(File.dirname(__FILE__))
+
+ tests = {
+ :simple_annotation => {:klass => XMPFilter},
+ :unit_test => {:klass => XMPTestUnitFilter},
+ :rspec => {:klass => XMPRSpecFilter, :interpreter => "spec"},
+ :rspec_poetry => {:klass => XMPRSpecFilter, :interpreter => "spec", :use_parentheses => false},
+ :no_warnings => {:klass => XMPFilter, :warnings => false},
+ :bindings => {:klass => XMPTestUnitFilter, :use_parentheses => false},
+ :unit_test_poetry => {:klass => XMPTestUnitFilter, :use_parentheses => false},
+ :add_markers => {:klass => XMPAddMarkers},
+
+ :completion => {:klass => XMPCompletionFilter, :lineno => 1},
+ :completion_emacs => {:klass => XMPCompletionEmacsFilter, :lineno => 1},
+ :completion_emacs_icicles => {:klass => XMPCompletionEmacsIciclesFilter, :lineno => 1},
+ :completion_class_info => {:klass => XMPCompletionClassInfoFilter, :lineno => 1},
+ :completion_class_info_no_candidates => {:klass => XMPCompletionClassInfoFilter, :lineno => 1},
+
+ :doc => {:klass => XMPDocFilter, :lineno => 1},
+ :refe => {:klass => XMPReFeFilter, :lineno => 1},
+ :ri => {:klass => XMPRiFilter, :lineno => 1},
+ :ri_emacs => {:klass => XMPRiEmacsFilter, :lineno => 1},
+ :ri_vim => {:klass => XMPRiVimFilter, :lineno => 1},
+
+ }
+ tests.each_pair do |test, opts|
+ define_method("test_#{test}") do
+ inputfile = "#{DIR}/data/#{test}-input.rb"
+ outputfile = "#{DIR}/data/#{test}-output.rb"
+ sio = StringIO.new
+ sio.puts opts[:klass].run(File.read(inputfile), DEFAULT_OPTIONS.merge(opts))
+ assert_equal(File.read(outputfile), sio.string)
+ end
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/add_markers-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/add_markers-input.rb
new file mode 100644
index 000000000..33a508e45
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/add_markers-input.rb
@@ -0,0 +1,2 @@
+1+1
+2+3
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/add_markers-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/add_markers-output.rb
new file mode 100644
index 000000000..fe8fd61b4
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/add_markers-output.rb
@@ -0,0 +1,2 @@
+1+1 # =>
+2+3 # =>
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/bindings-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/bindings-input.rb
new file mode 100644
index 000000000..90e97e27a
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/bindings-input.rb
@@ -0,0 +1,26 @@
+
+require 'test/unit'
+
+class TestFoo < Test::Unit::TestCase
+ def setup
+ @o = []
+ end
+
+ def test_foo
+ a = 1
+ b = a
+ b # =>
+ end
+
+ def test_arr
+ last = 1
+ @o << last
+ @o.last # =>
+ end
+
+ def test_bar
+ a = b = c = 1
+ d = a
+ d # =>
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/bindings-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/bindings-output.rb
new file mode 100644
index 000000000..cbea3c07c
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/bindings-output.rb
@@ -0,0 +1,31 @@
+
+require 'test/unit'
+
+class TestFoo < Test::Unit::TestCase
+ def setup
+ @o = []
+ end
+
+ def test_foo
+ a = 1
+ b = a
+ assert_equal a, b
+ assert_equal 1, b
+ end
+
+ def test_arr
+ last = 1
+ @o << last
+ assert_equal last, @o.last
+ assert_equal 1, @o.last
+ end
+
+ def test_bar
+ a = b = c = 1
+ d = a
+ assert_equal a, d
+ assert_equal b, d
+ assert_equal c, d
+ assert_equal 1, d
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion-input.rb
new file mode 100644
index 000000000..2dcaa3f08
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion-input.rb
@@ -0,0 +1 @@
+Array.new(3).uni
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion-output.rb
new file mode 100644
index 000000000..9546ff3ac
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion-output.rb
@@ -0,0 +1,2 @@
+uniq
+uniq!
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_class_info-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_class_info-input.rb
new file mode 100644
index 000000000..6ea236464
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_class_info-input.rb
@@ -0,0 +1 @@
+Array.new(3).s
\ No newline at end of file
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_class_info-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_class_info-output.rb
new file mode 100644
index 000000000..8c604b3c0
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_class_info-output.rb
@@ -0,0 +1,10 @@
+select Array#select
+send Object#send
+shift Array#shift
+singleton_methods Object#singleton_methods
+size Array#size
+slice Array#slice
+slice! Array#slice!
+sort Array#sort
+sort! Array#sort!
+sort_by Enumerable#sort_by
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_class_info_no_candidates-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_class_info_no_candidates-input.rb
new file mode 100644
index 000000000..4666cc05c
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_class_info_no_candidates-input.rb
@@ -0,0 +1 @@
+Array.new(3).nonexisten
\ No newline at end of file
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_class_info_no_candidates-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_class_info_no_candidates-output.rb
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_class_info_no_candidates-output.rb
@@ -0,0 +1 @@
+
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_detect_rbtest-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_detect_rbtest-input.rb
new file mode 100755
index 000000000..c4d92ca63
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_detect_rbtest-input.rb
@@ -0,0 +1,7 @@
+#!/usr/bin/env ruby
+=begin test_bar
+assert_equal "BAR", bar("bar")
+=end
+def bar(s)
+ s.upca
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_detect_rbtest-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_detect_rbtest-output.rb
new file mode 100644
index 000000000..c3d421a75
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_detect_rbtest-output.rb
@@ -0,0 +1,2 @@
+upcase
+upcase!
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_detect_rbtest2-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_detect_rbtest2-input.rb
new file mode 100644
index 000000000..2dcaa3f08
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_detect_rbtest2-input.rb
@@ -0,0 +1 @@
+Array.new(3).uni
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_detect_rbtest2-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_detect_rbtest2-output.rb
new file mode 100644
index 000000000..9546ff3ac
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_detect_rbtest2-output.rb
@@ -0,0 +1,2 @@
+uniq
+uniq!
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_emacs-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_emacs-input.rb
new file mode 100644
index 000000000..2dcaa3f08
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_emacs-input.rb
@@ -0,0 +1 @@
+Array.new(3).uni
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_emacs-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_emacs-output.rb
new file mode 100644
index 000000000..c83366a11
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_emacs-output.rb
@@ -0,0 +1,6 @@
+(progn
+(setq rct-method-completion-table '(("uniq") ("uniq!") ))
+(setq alist '(("uniq\t[Array#uniq]") ("uniq!\t[Array#uniq!]") ))
+(setq pattern "uni")
+(try-completion pattern rct-method-completion-table nil)
+)
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_emacs_icicles-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_emacs_icicles-input.rb
new file mode 100644
index 000000000..aa062b7f9
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_emacs_icicles-input.rb
@@ -0,0 +1 @@
+1.div
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_emacs_icicles-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_emacs_icicles-output.rb
new file mode 100644
index 000000000..e4747ae36
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_emacs_icicles-output.rb
@@ -0,0 +1,6 @@
+(progn
+(setq rct-method-completion-table '(("div\t[Fixnum#div]") ("divmod\t[Fixnum#divmod]") ))
+(setq alist '(("div" . "Fixnum#div")("divmod" . "Fixnum#divmod")))
+(setq pattern "div")
+(setq klass "Fixnum")
+)
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_in_method-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_in_method-input.rb
new file mode 100644
index 000000000..164408012
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_in_method-input.rb
@@ -0,0 +1,3 @@
+def fooz
+ [].lengt
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_in_method-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_in_method-output.rb
new file mode 100644
index 000000000..7f5e3b64d
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_in_method-output.rb
@@ -0,0 +1 @@
+length
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_in_method-test.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_in_method-test.rb
new file mode 100644
index 000000000..1edef979e
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_in_method-test.rb
@@ -0,0 +1,6 @@
+require 'test/unit'
+class TestFooz < Test::Unit::TestCase
+ def test_fooz
+ assert_equal(0, fooz)
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_rbtest-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_rbtest-input.rb
new file mode 100755
index 000000000..c4d92ca63
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_rbtest-input.rb
@@ -0,0 +1,7 @@
+#!/usr/bin/env ruby
+=begin test_bar
+assert_equal "BAR", bar("bar")
+=end
+def bar(s)
+ s.upca
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_rbtest-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_rbtest-output.rb
new file mode 100644
index 000000000..c3d421a75
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/completion_rbtest-output.rb
@@ -0,0 +1,2 @@
+upcase
+upcase!
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc-input.rb
new file mode 100644
index 000000000..624aca755
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc-input.rb
@@ -0,0 +1 @@
+[].length
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc-output.rb
new file mode 100644
index 000000000..ca542dbcc
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc-output.rb
@@ -0,0 +1 @@
+Array#length
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_detect_rbtest-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_detect_rbtest-input.rb
new file mode 100644
index 000000000..624aca755
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_detect_rbtest-input.rb
@@ -0,0 +1 @@
+[].length
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_detect_rbtest-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_detect_rbtest-output.rb
new file mode 100644
index 000000000..ca542dbcc
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_detect_rbtest-output.rb
@@ -0,0 +1 @@
+Array#length
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_detect_rbtest2-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_detect_rbtest2-input.rb
new file mode 100755
index 000000000..bf97ffe15
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_detect_rbtest2-input.rb
@@ -0,0 +1,7 @@
+#!/usr/bin/env ruby
+=begin test_bar
+assert_equal "BAR", bar("bar")
+=end
+def bar(s)
+ s.upcase
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_detect_rbtest2-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_detect_rbtest2-output.rb
new file mode 100644
index 000000000..579185024
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_detect_rbtest2-output.rb
@@ -0,0 +1 @@
+String#upcase
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_rbtest-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_rbtest-input.rb
new file mode 100755
index 000000000..bf97ffe15
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_rbtest-input.rb
@@ -0,0 +1,7 @@
+#!/usr/bin/env ruby
+=begin test_bar
+assert_equal "BAR", bar("bar")
+=end
+def bar(s)
+ s.upcase
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_rbtest-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_rbtest-output.rb
new file mode 100644
index 000000000..579185024
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/doc_rbtest-output.rb
@@ -0,0 +1 @@
+String#upcase
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/no_warnings-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/no_warnings-input.rb
new file mode 100644
index 000000000..514e18c0d
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/no_warnings-input.rb
@@ -0,0 +1,3 @@
+A = 1
+A = 1
+p (1)
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/no_warnings-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/no_warnings-output.rb
new file mode 100644
index 000000000..27a723858
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/no_warnings-output.rb
@@ -0,0 +1,4 @@
+A = 1
+A = 1
+p (1)
+# >> 1
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/refe-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/refe-input.rb
new file mode 100644
index 000000000..624aca755
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/refe-input.rb
@@ -0,0 +1 @@
+[].length
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/refe-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/refe-output.rb
new file mode 100644
index 000000000..8653c3d4b
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/refe-output.rb
@@ -0,0 +1 @@
+refe 'Array#length'
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri-input.rb
new file mode 100644
index 000000000..624aca755
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri-input.rb
@@ -0,0 +1 @@
+[].length
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri-output.rb
new file mode 100644
index 000000000..f1ba49e61
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri-output.rb
@@ -0,0 +1 @@
+ri 'Array#length'
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri_emacs-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri_emacs-input.rb
new file mode 100644
index 000000000..624aca755
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri_emacs-input.rb
@@ -0,0 +1 @@
+[].length
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri_emacs-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri_emacs-output.rb
new file mode 100644
index 000000000..5f7389fb3
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri_emacs-output.rb
@@ -0,0 +1 @@
+(rct-find-tag-or-ri "Array#length")
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri_vim-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri_vim-input.rb
new file mode 100644
index 000000000..624aca755
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri_vim-input.rb
@@ -0,0 +1 @@
+[].length
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri_vim-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri_vim-output.rb
new file mode 100644
index 000000000..8e71a9a5c
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/ri_vim-output.rb
@@ -0,0 +1 @@
+call RCT_find_tag_or_ri("Array#length")
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/rspec-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/rspec-input.rb
new file mode 100644
index 000000000..c57b23c47
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/rspec-input.rb
@@ -0,0 +1,48 @@
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1
+end
+
+
+describe "xmpfilter's expectation expansion" do
+ before do
+ @o = X.new
+ end
+
+ it "should expand should == expectations" do
+ @o.foo(true) # =>
+ @o.foo(true).a # =>
+ @o.foo(false) # =>
+ end
+
+ it "should expand should raise_error expectations" do
+ @o.bar # =>
+ end
+
+ it "should expand should be_nil expectations" do
+ @o.baz # =>
+ end
+
+ it "should expand correct expectations for complex values" do
+ @o.babar # =>
+ end
+
+ it "should expand should be_close expectations" do
+ @o.fubar(10) # =>
+ end
+end
+
+describe "xmpfilter's automagic binding detection" do
+ it "should expand should == expectations" do
+ a = b = c = 1
+ d = a
+ d # =>
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/rspec-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/rspec-output.rb
new file mode 100644
index 000000000..00abb887b
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/rspec-output.rb
@@ -0,0 +1,52 @@
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1 # !> already initialized constant A
+end
+
+
+describe "xmpfilter's expectation expansion" do
+ before do
+ @o = X.new
+ end
+
+ it "should expand should == expectations" do
+ (@o.foo(true)).should be_a_kind_of(X::Y)
+ (@o.foo(true).inspect).should == ("#")
+ (@o.foo(true).a).should == (2)
+ (@o.foo(false)).should == (2)
+ end
+
+ it "should expand should raise_error expectations" do
+ lambda{@o.bar}.should raise_error(RuntimeError)
+ end
+
+ it "should expand should be_nil expectations" do
+ (@o.baz).should be_nil
+ end
+
+ it "should expand correct expectations for complex values" do
+ (@o.babar).should == ([1, 2])
+ end
+
+ it "should expand should be_close expectations" do
+ (@o.fubar(10)).should be_close(101.0, 0.0001)
+ end
+end
+
+describe "xmpfilter's automagic binding detection" do
+ it "should expand should == expectations" do
+ a = b = c = 1
+ d = a
+ (d).should == (a)
+ (d).should == (b)
+ (d).should == (c)
+ (d).should == (1)
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/rspec_poetry-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/rspec_poetry-input.rb
new file mode 100644
index 000000000..c57b23c47
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/rspec_poetry-input.rb
@@ -0,0 +1,48 @@
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1
+end
+
+
+describe "xmpfilter's expectation expansion" do
+ before do
+ @o = X.new
+ end
+
+ it "should expand should == expectations" do
+ @o.foo(true) # =>
+ @o.foo(true).a # =>
+ @o.foo(false) # =>
+ end
+
+ it "should expand should raise_error expectations" do
+ @o.bar # =>
+ end
+
+ it "should expand should be_nil expectations" do
+ @o.baz # =>
+ end
+
+ it "should expand correct expectations for complex values" do
+ @o.babar # =>
+ end
+
+ it "should expand should be_close expectations" do
+ @o.fubar(10) # =>
+ end
+end
+
+describe "xmpfilter's automagic binding detection" do
+ it "should expand should == expectations" do
+ a = b = c = 1
+ d = a
+ d # =>
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/rspec_poetry-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/rspec_poetry-output.rb
new file mode 100644
index 000000000..907b30535
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/rspec_poetry-output.rb
@@ -0,0 +1,52 @@
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1 # !> already initialized constant A
+end
+
+
+describe "xmpfilter's expectation expansion" do
+ before do
+ @o = X.new
+ end
+
+ it "should expand should == expectations" do
+ @o.foo(true).should be_a_kind_of(X::Y)
+ @o.foo(true).inspect.should == "#"
+ @o.foo(true).a.should == 2
+ @o.foo(false).should == 2
+ end
+
+ it "should expand should raise_error expectations" do
+ lambda{@o.bar}.should raise_error(RuntimeError)
+ end
+
+ it "should expand should be_nil expectations" do
+ @o.baz.should be_nil
+ end
+
+ it "should expand correct expectations for complex values" do
+ @o.babar.should == [1, 2]
+ end
+
+ it "should expand should be_close expectations" do
+ @o.fubar(10).should be_close(101.0, 0.0001)
+ end
+end
+
+describe "xmpfilter's automagic binding detection" do
+ it "should expand should == expectations" do
+ a = b = c = 1
+ d = a
+ d.should == a
+ d.should == b
+ d.should == c
+ d.should == 1
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/simple_annotation-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/simple_annotation-input.rb
new file mode 100644
index 000000000..e4eb38504
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/simple_annotation-input.rb
@@ -0,0 +1,8 @@
+
+a = 1
+10.times do |i|
+ i ** 2 # =>
+ a += i
+end
+A = 1
+A = 1
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/simple_annotation-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/simple_annotation-output.rb
new file mode 100644
index 000000000..41cd4c0cd
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/simple_annotation-output.rb
@@ -0,0 +1,8 @@
+
+a = 1
+10.times do |i|
+ i ** 2 # => 0, 1, 4, 9, 16, 25, 36, 49, 64, 81
+ a += i
+end
+A = 1
+A = 1 # !> already initialized constant A
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test-input.rb
new file mode 100644
index 000000000..d9d02cdcd
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test-input.rb
@@ -0,0 +1,50 @@
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1
+ def difftype() [1, "s"] end
+end
+
+
+require 'test/unit'
+class Test_X < Test::Unit::TestCase
+ def setup
+ @o = X.new
+ end
+
+ def test_foo
+ @o.foo(true) # =>
+ @o.foo(true).a # =>
+ @o.foo(false) # =>
+ end
+
+ def test_bar
+ @o.bar # =>
+ end
+
+ def test_baz
+ @o.baz # =>
+ end
+
+ def test_babar
+ @o.babar # =>
+ end
+
+ def test_fubar
+ @o.fubar(10) # =>
+ end
+
+ def test_difftype
+ for x in @o.difftype
+ x # =>
+ end
+ end
+
+end
+
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test-output.rb
new file mode 100644
index 000000000..49f4e6314
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test-output.rb
@@ -0,0 +1,52 @@
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1 # !> already initialized constant A
+ def difftype() [1, "s"] end
+end
+
+
+require 'test/unit'
+class Test_X < Test::Unit::TestCase
+ def setup
+ @o = X.new
+ end
+
+ def test_foo
+ assert_kind_of(X::Y, @o.foo(true))
+ assert_equal("#", @o.foo(true).inspect)
+ assert_equal(2, @o.foo(true).a)
+ assert_equal(2, @o.foo(false))
+ end
+
+ def test_bar
+ assert_raise(RuntimeError){@o.bar}
+ end
+
+ def test_baz
+ assert_nil(@o.baz)
+ end
+
+ def test_babar
+ assert_equal([1, 2], @o.babar)
+ end
+
+ def test_fubar
+ assert_in_delta(101.0, @o.fubar(10), 0.0001)
+ end
+
+ def test_difftype
+ for x in @o.difftype
+ #xmpfilter: WARNING!! extra values ignored
+ assert_equal(1, x)
+ end
+ end
+
+end
+
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_detect_rbtest-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_detect_rbtest-input.rb
new file mode 100644
index 000000000..d9d02cdcd
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_detect_rbtest-input.rb
@@ -0,0 +1,50 @@
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1
+ def difftype() [1, "s"] end
+end
+
+
+require 'test/unit'
+class Test_X < Test::Unit::TestCase
+ def setup
+ @o = X.new
+ end
+
+ def test_foo
+ @o.foo(true) # =>
+ @o.foo(true).a # =>
+ @o.foo(false) # =>
+ end
+
+ def test_bar
+ @o.bar # =>
+ end
+
+ def test_baz
+ @o.baz # =>
+ end
+
+ def test_babar
+ @o.babar # =>
+ end
+
+ def test_fubar
+ @o.fubar(10) # =>
+ end
+
+ def test_difftype
+ for x in @o.difftype
+ x # =>
+ end
+ end
+
+end
+
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_detect_rbtest-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_detect_rbtest-output.rb
new file mode 100644
index 000000000..49f4e6314
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_detect_rbtest-output.rb
@@ -0,0 +1,52 @@
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1 # !> already initialized constant A
+ def difftype() [1, "s"] end
+end
+
+
+require 'test/unit'
+class Test_X < Test::Unit::TestCase
+ def setup
+ @o = X.new
+ end
+
+ def test_foo
+ assert_kind_of(X::Y, @o.foo(true))
+ assert_equal("#", @o.foo(true).inspect)
+ assert_equal(2, @o.foo(true).a)
+ assert_equal(2, @o.foo(false))
+ end
+
+ def test_bar
+ assert_raise(RuntimeError){@o.bar}
+ end
+
+ def test_baz
+ assert_nil(@o.baz)
+ end
+
+ def test_babar
+ assert_equal([1, 2], @o.babar)
+ end
+
+ def test_fubar
+ assert_in_delta(101.0, @o.fubar(10), 0.0001)
+ end
+
+ def test_difftype
+ for x in @o.difftype
+ #xmpfilter: WARNING!! extra values ignored
+ assert_equal(1, x)
+ end
+ end
+
+end
+
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_detect_rbtest2-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_detect_rbtest2-input.rb
new file mode 100644
index 000000000..afb6ebba2
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_detect_rbtest2-input.rb
@@ -0,0 +1,6 @@
+=begin test_bar
+bar("bar") # =>
+=end
+def bar(s)
+ s.upcase
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_detect_rbtest2-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_detect_rbtest2-output.rb
new file mode 100644
index 000000000..67ac1d924
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_detect_rbtest2-output.rb
@@ -0,0 +1,6 @@
+=begin test_bar
+assert_equal("BAR", bar("bar"))
+=end
+def bar(s)
+ s.upcase
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_poetry-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_poetry-input.rb
new file mode 100644
index 000000000..d9d02cdcd
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_poetry-input.rb
@@ -0,0 +1,50 @@
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1
+ def difftype() [1, "s"] end
+end
+
+
+require 'test/unit'
+class Test_X < Test::Unit::TestCase
+ def setup
+ @o = X.new
+ end
+
+ def test_foo
+ @o.foo(true) # =>
+ @o.foo(true).a # =>
+ @o.foo(false) # =>
+ end
+
+ def test_bar
+ @o.bar # =>
+ end
+
+ def test_baz
+ @o.baz # =>
+ end
+
+ def test_babar
+ @o.babar # =>
+ end
+
+ def test_fubar
+ @o.fubar(10) # =>
+ end
+
+ def test_difftype
+ for x in @o.difftype
+ x # =>
+ end
+ end
+
+end
+
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_poetry-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_poetry-output.rb
new file mode 100644
index 000000000..6278c2553
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_poetry-output.rb
@@ -0,0 +1,52 @@
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1 # !> already initialized constant A
+ def difftype() [1, "s"] end
+end
+
+
+require 'test/unit'
+class Test_X < Test::Unit::TestCase
+ def setup
+ @o = X.new
+ end
+
+ def test_foo
+ assert_kind_of X::Y, @o.foo(true)
+ assert_equal "#", @o.foo(true).inspect
+ assert_equal 2, @o.foo(true).a
+ assert_equal 2, @o.foo(false)
+ end
+
+ def test_bar
+ assert_raise(RuntimeError){@o.bar}
+ end
+
+ def test_baz
+ assert_nil @o.baz
+ end
+
+ def test_babar
+ assert_equal [1, 2], @o.babar
+ end
+
+ def test_fubar
+ assert_in_delta 101.0, @o.fubar(10), 0.0001
+ end
+
+ def test_difftype
+ for x in @o.difftype
+ #xmpfilter: WARNING!! extra values ignored
+ assert_equal 1, x
+ end
+ end
+
+end
+
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_rbtest-input.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_rbtest-input.rb
new file mode 100644
index 000000000..afb6ebba2
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_rbtest-input.rb
@@ -0,0 +1,6 @@
+=begin test_bar
+bar("bar") # =>
+=end
+def bar(s)
+ s.upcase
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_rbtest-output.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_rbtest-output.rb
new file mode 100644
index 000000000..67ac1d924
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/attic/unit_test_rbtest-output.rb
@@ -0,0 +1,6 @@
+=begin test_bar
+assert_equal("BAR", bar("bar"))
+=end
+def bar(s)
+ s.upcase
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/method_analyzer-data.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/method_analyzer-data.rb
new file mode 100644
index 000000000..82fca088e
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/method_analyzer-data.rb
@@ -0,0 +1,33 @@
+
+class A
+ def A.foo
+ 1
+ end
+
+ def a
+ 1+1
+ end
+end
+class B < A
+ def initialize
+ end
+ attr_accessor :bb
+
+ def b
+ "a".length
+ end
+end
+tm = Time.now
+[tm.year, tm.month, tm.day] << 0
+a = A.new
+a.a
+b = B.new
+b.a
+b.b
+[b.a,b.b]
+z = b.a + b.b
+A.foo
+B.foo
+b.bb=1
+b.bb
+
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/method_args.data.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/method_args.data.rb
new file mode 100644
index 000000000..b95fa8337
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/method_args.data.rb
@@ -0,0 +1,106 @@
+# method_args.data.rb
+class FixedArgsMethods
+ def self.singleton(a1) end
+ def initialize(arg) end
+ def f(a1) end
+ def b(a1,&block) end
+ define_method(:defmethod) {|a1|}
+ attr_accessor :by_attr_accessor
+ attr :by_attr_false
+ attr :by_attr_true, true
+ attr_reader :by_attr_reader_1, :by_attr_reader_2
+ attr_writer :by_attr_writer
+ def private_meth(x) end
+ private :private_meth
+ class << self
+ attr_accessor :singleton_attr_accessor
+ define_method(:singleton_defmethod){|a2|}
+ end
+end
+
+module VariableArgsMethods
+ def s(a1,*splat) end
+ def sb(a1,*splat, &block) end
+ def d(a1,default=nil) end
+ def ds(a1,default=nil,*splat) end
+ def dsb(a1,default=nil,*splat,&block) end
+ def db(a1,default=nil,&block) end
+end
+
+class Fixnum
+ def method_in_Fixnum(arg1, arg2) end
+ def self.singleton_method_in_Fixnum(arg1, arg2) end
+end
+class Bignum
+ def method_in_Bignum(arg1, arg2) end
+end
+class Float
+ def method_in_Float(arg1, arg2) end
+end
+class Symbol
+ def method_in_Symbol(arg1, arg2) end
+end
+class Binding
+ def method_in_Binding(arg1, arg2) end
+end
+class UnboundMethod
+ def method_in_UnboundMethod(arg1, arg2) end
+end
+class Method
+ def method_in_Method(arg1, arg2) end
+end
+class Proc
+ def method_in_Proc(arg1, arg2) end
+end
+class Continuation
+ def method_in_Continuation(arg1, arg2) end
+end
+class Thread
+ def method_in_Thread(arg1, arg2) end
+end
+# FIXME mysterious
+# class FalseClass
+# def method_in_FalseClass(arg1, arg2) end
+# end
+class TrueClass
+ def method_in_TrueClass(arg1, arg2) end
+end
+class NilClass
+ def method_in_NilClass(arg1, arg2) end
+end
+class Struct
+ def method_in_Struct(arg1, arg2) end
+end
+
+require 'digest'
+class Digest::Base
+ def method_in_Digest_Base(arg1, arg2) end
+end
+
+class AnAbstractClass
+ $__method_args_off = true
+ def self.allocate
+ raise NotImplementedError, "#{self} is an abstract class."
+ end
+ $__method_args_off = false
+
+ def method_in_AnAbstractClass(arg1, arg2)
+ end
+
+end
+
+class AClass
+ include VariableArgsMethods
+ extend VariableArgsMethods
+end
+
+class ASubClass < AClass
+end
+
+StructA = Struct.new :a, :b
+class SubclassOfStructA < StructA
+ attr :method_in_b
+end
+class StructSubclass < Struct.new(:c)
+ attr :method_in_c
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete-TDC/completion_in_method__testmethod.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete-TDC/completion_in_method__testmethod.taf
new file mode 100644
index 000000000..dfa125677
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete-TDC/completion_in_method__testmethod.taf
@@ -0,0 +1,17 @@
+==========
+completion_in_method__testmethod
+==========
+rct-complete --filename %s --line 2 -t %s@test_fooz
+==========
+def fooz
+ [].lengt
+end
+==========
+length
+==========
+require 'test/unit'
+class TestFooz < Test::Unit::TestCase
+ def test_fooz
+ assert_equal(0, fooz)
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete-TDC/completion_in_method__testscript.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete-TDC/completion_in_method__testscript.taf
new file mode 100644
index 000000000..f2de8add1
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete-TDC/completion_in_method__testscript.taf
@@ -0,0 +1,17 @@
+==========
+completion_in_method__testscript
+==========
+rct-complete --filename %s --line 2 -t %s
+==========
+def fooz
+ [].lengt
+end
+==========
+length
+==========
+require 'test/unit'
+class TestFooz < Test::Unit::TestCase
+ def test_fooz
+ assert_equal(0, fooz)
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete-TDC/completion_in_method__wrong_testmethod.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete-TDC/completion_in_method__wrong_testmethod.taf
new file mode 100644
index 000000000..989c1f492
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete-TDC/completion_in_method__wrong_testmethod.taf
@@ -0,0 +1,17 @@
+==========
+completion_in_method__wrong_testmethod
+==========
+rct-complete --filename %s --line 2 -t %s@test_NOT_FOUND
+==========
+def fooz
+ [].lengt
+end
+==========
+
+==========
+require 'test/unit'
+class TestFooz < Test::Unit::TestCase
+ def test_fooz
+ assert_equal(0, fooz)
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion.taf
new file mode 100644
index 000000000..de08a22cf
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion.taf
@@ -0,0 +1,9 @@
+==========
+completion
+==========
+rct-complete -C --line=1
+==========
+Array.new(3).uni
+==========
+uniq
+uniq!
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_class_info.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_class_info.taf
new file mode 100644
index 000000000..40d82fc9f
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_class_info.taf
@@ -0,0 +1,9 @@
+==========
+completion_class_info
+==========
+rct-complete --completion-class-info --line=1
+==========
+Array.new(3).sl
+==========
+slice Array#slice
+slice! Array#slice!
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_class_info_no_candidates.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_class_info_no_candidates.taf
new file mode 100644
index 000000000..f4e8959bc
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_class_info_no_candidates.taf
@@ -0,0 +1,8 @@
+==========
+completion_class_info_no_candidates
+==========
+rct-complete --completion-class-info --line=1
+==========
+Array.new(3).nonexisten
+==========
+
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_detect_rbtest.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_detect_rbtest.taf
new file mode 100644
index 000000000..e5405568d
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_detect_rbtest.taf
@@ -0,0 +1,15 @@
+==========
+completion_detect_rbtest
+==========
+rct-complete --detect-rbtest --line=6
+==========
+#!/usr/bin/env ruby
+=begin test_bar
+assert_equal "BAR", bar("bar")
+=end
+def bar(s)
+ s.upca
+end
+==========
+upcase
+upcase!
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_detect_rbtest2.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_detect_rbtest2.taf
new file mode 100644
index 000000000..49eaf171c
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_detect_rbtest2.taf
@@ -0,0 +1,9 @@
+==========
+completion_detect_rbtest2
+==========
+rct-complete --detect-rbtest --line=1
+==========
+Array.new(3).uni
+==========
+uniq
+uniq!
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_emacs.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_emacs.taf
new file mode 100644
index 000000000..9282ad09d
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_emacs.taf
@@ -0,0 +1,13 @@
+==========
+completion_emacs
+==========
+rct-complete --completion-emacs --line=1
+==========
+Array.new(3).uni
+==========
+(progn
+(setq rct-method-completion-table '(("uniq") ("uniq!") ))
+(setq alist '(("uniq\t[Array#uniq]") ("uniq!\t[Array#uniq!]") ))
+(setq pattern "uni")
+(try-completion pattern rct-method-completion-table nil)
+)
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_emacs_icicles.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_emacs_icicles.taf
new file mode 100644
index 000000000..324a1cfa8
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_emacs_icicles.taf
@@ -0,0 +1,13 @@
+==========
+completion_emacs_icicles
+==========
+rct-complete --completion-emacs-icicles --line=1
+==========
+1.div
+==========
+(progn
+(setq rct-method-completion-table '(("div\t[Fixnum#div]") ("divmod\t[Fixnum#divmod]") ))
+(setq alist '(("div" . "Fixnum#div")("divmod" . "Fixnum#divmod")))
+(setq pattern "div")
+(setq klass "Fixnum")
+)
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_rbtest.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_rbtest.taf
new file mode 100644
index 000000000..e8c6cbe62
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-complete/completion_rbtest.taf
@@ -0,0 +1,15 @@
+==========
+completion_rbtest
+==========
+rct-complete --rbtest --line=6
+==========
+#!/usr/bin/env ruby
+=begin test_bar
+assert_equal "BAR", bar("bar")
+=end
+def bar(s)
+ s.upca
+end
+==========
+upcase
+upcase!
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/doc.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/doc.taf
new file mode 100644
index 000000000..aa017f636
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/doc.taf
@@ -0,0 +1,8 @@
+==========
+doc
+==========
+rct-doc -D --line=1
+==========
+[].length
+==========
+Array#length
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/doc_detect_rbtest.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/doc_detect_rbtest.taf
new file mode 100644
index 000000000..28ac60836
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/doc_detect_rbtest.taf
@@ -0,0 +1,8 @@
+==========
+doc_detect_rbtest
+==========
+rct-doc --detect-rbtest --line=1
+==========
+[].length
+==========
+Array#length
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/doc_detect_rbtest2.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/doc_detect_rbtest2.taf
new file mode 100644
index 000000000..043bea94d
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/doc_detect_rbtest2.taf
@@ -0,0 +1,14 @@
+==========
+doc_detect_rbtest2
+==========
+rct-doc --detect-rbtest --line=6
+==========
+#!/usr/bin/env ruby
+=begin test_bar
+assert_equal "BAR", bar("bar")
+=end
+def bar(s)
+ s.upcase
+end
+==========
+String#upcase
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/doc_rbtest.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/doc_rbtest.taf
new file mode 100644
index 000000000..7da58ce76
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/doc_rbtest.taf
@@ -0,0 +1,14 @@
+==========
+doc_rbtest
+==========
+rct-doc --rbtest --line=6
+==========
+#!/usr/bin/env ruby
+=begin test_bar
+assert_equal "BAR", bar("bar")
+=end
+def bar(s)
+ s.upcase
+end
+==========
+String#upcase
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/refe.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/refe.taf
new file mode 100644
index 000000000..6f074037d
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/refe.taf
@@ -0,0 +1,8 @@
+==========
+refe
+==========
+rct-doc --refe --line=1
+==========
+[].length
+==========
+refe 'Array#length'
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/ri.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/ri.taf
new file mode 100644
index 000000000..02f27d6a1
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/ri.taf
@@ -0,0 +1,8 @@
+==========
+ri
+==========
+rct-doc --ri --line=1
+==========
+[].length
+==========
+ri 'Array#length'
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/ri_emacs.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/ri_emacs.taf
new file mode 100644
index 000000000..b41c7e373
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/ri_emacs.taf
@@ -0,0 +1,8 @@
+==========
+ri_emacs
+==========
+rct-doc --ri-emacs --line=1
+==========
+[].length
+==========
+(rct-find-tag-or-ri "Array#length")
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/ri_vim.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/ri_vim.taf
new file mode 100644
index 000000000..11413ce40
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/rct-doc/ri_vim.taf
@@ -0,0 +1,8 @@
+==========
+ri_vim
+==========
+rct-doc --ri-vim --line=1
+==========
+[].length
+==========
+call RCT_find_tag_or_ri("Array#length")
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/sample_test_script.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/sample_test_script.rb
new file mode 100644
index 000000000..b368a8ca2
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/sample_test_script.rb
@@ -0,0 +1,9 @@
+require 'test/unit'
+class TestSample < Test::Unit::TestCase
+ def test_sample0
+ assert(true)
+ end
+
+ def test_sample1
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/add_markers.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/add_markers.taf
new file mode 100644
index 000000000..88e846131
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/add_markers.taf
@@ -0,0 +1,10 @@
+==========
+add_markers
+==========
+xmpfilter -m
+==========
+1+1
+2+3
+==========
+1+1 # =>
+2+3 # =>
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/bindings.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/bindings.taf
new file mode 100644
index 000000000..bcd30560d
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/bindings.taf
@@ -0,0 +1,63 @@
+==========
+bindings
+==========
+xmpfilter --poetry -u
+==========
+
+require 'test/unit'
+
+class TestFoo < Test::Unit::TestCase
+ def setup
+ @o = []
+ end
+
+ def test_foo
+ a = 1
+ b = a
+ b # =>
+ end
+
+ def test_arr
+ last = 1
+ @o << last
+ @o.last # =>
+ end
+
+ def test_bar
+ a = b = c = 1
+ d = a
+ d # =>
+ end
+end
+==========
+
+require 'test/unit'
+
+class TestFoo < Test::Unit::TestCase
+ def setup
+ @o = []
+ end
+
+ def test_foo
+ a = 1
+ b = a
+ assert_equal a, b
+ assert_equal 1, b
+ end
+
+ def test_arr
+ last = 1
+ @o << last
+ assert_equal last, @o.last
+ assert_equal 1, @o.last
+ end
+
+ def test_bar
+ a = b = c = 1
+ d = a
+ assert_equal a, d
+ assert_equal b, d
+ assert_equal c, d
+ assert_equal 1, d
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/comment_out.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/comment_out.taf
new file mode 100644
index 000000000..2520e79d7
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/comment_out.taf
@@ -0,0 +1,22 @@
+==========
+comment_out
+==========
+xmpfilter
+==========
+
+# 1 # =>
+# 1 # => 2
+1 # => 12
+1
+# # =>
+# 1
+# # =>
+==========
+
+# 1 # =>
+# 1 # => 2
+1 # => 1
+1
+# # =>
+# 1
+# # =>
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/exception.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/exception.taf
new file mode 100644
index 000000000..3918c2e4d
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/exception.taf
@@ -0,0 +1,14 @@
+==========
+exception
+==========
+xmpfilter
+==========
+def foo
+ raise NameError, "ERR!!" rescue $@ # =>
+end
+foo
+==========
+def foo
+ raise NameError, "ERR!!" rescue $@ # => ["-:2:in `foo'", "-:4"]
+end
+foo
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/expectations.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/expectations.taf
new file mode 100644
index 000000000..ad244d7ea
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/expectations.taf
@@ -0,0 +1,54 @@
+==========
+expectations
+==========
+xmpfilter --expectations
+==========
+
+require 'rubygems'
+require 'expectations'
+
+S = Struct.new :a
+Expectations do
+ 1 + 1 # =>
+ "a".length # =>
+ [][1] # =>
+ 1.hoge # =>
+ 1.1 + 1.0 # =>
+ S.new(1) # =>
+end
+==========
+
+require 'rubygems'
+require 'expectations'
+
+S = Struct.new :a
+Expectations do
+ expect 2 do
+ 1 + 1
+ end
+
+ expect 1 do
+ "a".length
+ end
+
+ expect nil do
+ [][1]
+ end
+
+ expect NoMethodError do
+ 1.hoge
+ end
+
+ expect 2.0999..2.1001 do
+ 1.1 + 1.0
+ end
+
+ expect S do
+ S.new(1)
+ end
+
+ expect "#" do
+ S.new(1).inspect
+ end
+
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/last_match.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/last_match.taf
new file mode 100644
index 000000000..56a086384
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/last_match.taf
@@ -0,0 +1,18 @@
+==========
+last_match
+==========
+xmpfilter
+==========
+
+md = "abc".match(/(.)(.)./)
+1
+# =>
+[$1, $2] # =>
+$1 # =>
+==========
+
+md = "abc".match(/(.)(.)./)
+1
+# => 1
+[$1, $2] # => ["a", "b"]
+$1 # => "a"
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/mult.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/mult.rb
new file mode 100644
index 000000000..fa9025a07
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/mult.rb
@@ -0,0 +1,9 @@
+a = ["1111111111111111111111111111111111111111111111111111", 123334324234242342,
+ 1332333333,6,8 ]
+1 # => 1
+a
+# => ["1111111111111111111111111111111111111111111111111111",
+# 123334324234242342,
+# 1332333333,
+# 6,
+# 8]
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_1.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_1.taf
new file mode 100644
index 000000000..63a0a053d
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_1.taf
@@ -0,0 +1,22 @@
+==========
+multi_line_annotation_1
+==========
+xmpfilter
+==========
+
+1+2 # =>
+a = ["1111111111111111111111111111111111111111111111111111", 123334324234242342,
+ 1332333333 ]
+1+2 # =>
+a
+# =>
+==========
+
+1+2 # => 3
+a = ["1111111111111111111111111111111111111111111111111111", 123334324234242342,
+ 1332333333 ]
+1+2 # => 3
+a
+# => ["1111111111111111111111111111111111111111111111111111",
+# 123334324234242342,
+# 1332333333]
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_2.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_2.taf
new file mode 100644
index 000000000..d5027dbdf
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_2.taf
@@ -0,0 +1,24 @@
+==========
+multi_line_annotation_2
+==========
+xmpfilter
+==========
+
+1+2 # => 32
+a = ["1111111111111111111111111111111111111111111111111111", 123334324234242342,
+ 55555555 ]
+1+2 # => 300
+a
+# => ["1111111111111111111111111111111111111111111111111111",
+# 123334324234242342,
+# 1332333333]
+==========
+
+1+2 # => 3
+a = ["1111111111111111111111111111111111111111111111111111", 123334324234242342,
+ 55555555 ]
+1+2 # => 3
+a
+# => ["1111111111111111111111111111111111111111111111111111",
+# 123334324234242342,
+# 55555555]
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_3.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_3.taf
new file mode 100644
index 000000000..2b5efef34
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_3.taf
@@ -0,0 +1,20 @@
+==========
+multi_line_annotation_3
+==========
+xmpfilter
+==========
+
+a = ["1111111111111111111111111111111111111111111111111111", 123334324234242342,
+ 1332333333 ]
+a
+# =>
+1 # =>
+==========
+
+a = ["1111111111111111111111111111111111111111111111111111", 123334324234242342,
+ 1332333333 ]
+a
+# => ["1111111111111111111111111111111111111111111111111111",
+# 123334324234242342,
+# 1332333333]
+1 # => 1
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_4.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_4.taf
new file mode 100644
index 000000000..e8adac712
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_4.taf
@@ -0,0 +1,22 @@
+==========
+multi_line_annotation_4
+==========
+xmpfilter
+==========
+
+a = ["1111111111111111111111111111111111111111111111111111", 123334324234242342,
+ 55555555 ]
+a
+# => ["1111111111111111111111111111111111111111111111111111",
+# 123334324234242342,
+# 1332333333]
+# not removed
+==========
+
+a = ["1111111111111111111111111111111111111111111111111111", 123334324234242342,
+ 55555555 ]
+a
+# => ["1111111111111111111111111111111111111111111111111111",
+# 123334324234242342,
+# 55555555]
+# not removed
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_5.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_5.taf
new file mode 100644
index 000000000..af0cb8460
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_5.taf
@@ -0,0 +1,34 @@
+==========
+multi_line_annotation_5
+==========
+xmpfilter
+==========
+
+def test
+ a = ["1111111111111111111111111111111111111111111111111111", 123334324234242342,
+ 55555555 ]
+ a
+ # => ["",
+ # 123334324234242342,
+ # 1332333333]
+ a
+ # =>
+ # not removed
+end
+test
+==========
+
+def test
+ a = ["1111111111111111111111111111111111111111111111111111", 123334324234242342,
+ 55555555 ]
+ a
+ # => ["1111111111111111111111111111111111111111111111111111",
+ # 123334324234242342,
+ # 55555555]
+ a
+ # => ["1111111111111111111111111111111111111111111111111111",
+ # 123334324234242342,
+ # 55555555]
+ # not removed
+end
+test
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_6.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_6.taf
new file mode 100644
index 000000000..24c48e2b0
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_6.taf
@@ -0,0 +1,12 @@
+==========
+multi_line_annotation_6
+==========
+xmpfilter
+==========
+
+1 + 2 # !> warning
+# =>
+==========
+
+1 + 2
+# => 3
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_7.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_7.taf
new file mode 100644
index 000000000..21ed1daec
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/multi_line_annotation_7.taf
@@ -0,0 +1,23 @@
+==========
+multi_line_annotation_7
+==========
+xmpfilter
+==========
+
+[1,2]
+# =>
+raise
+[3,4]
+# =>
+[5,6]
+# =>
+==========
+
+[1,2]
+# => [1, 2]
+raise
+[3,4]
+# =>
+[5,6]
+# =>
+# ~> -:2: unhandled exception
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/no_warnings.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/no_warnings.taf
new file mode 100644
index 000000000..76cf8b021
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/no_warnings.taf
@@ -0,0 +1,13 @@
+==========
+no_warnings
+==========
+xmpfilter --no-warnings
+==========
+A = 1
+A = 1
+p (1)
+==========
+A = 1
+A = 1
+p (1)
+# >> 1
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/nospace.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/nospace.taf
new file mode 100644
index 000000000..bb71aeae4
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/nospace.taf
@@ -0,0 +1,16 @@
+==========
+nospace_annotation
+==========
+xmpfilter
+==========
+
+1 #=>
+2 #=> 2
+3
+#=>
+==========
+
+1 # => 1
+2 # => 2
+3
+# => 3
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/rspec.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/rspec.taf
new file mode 100644
index 000000000..6c3a3d666
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/rspec.taf
@@ -0,0 +1,106 @@
+==========
+rspec
+==========
+xmpfilter -s
+==========
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1
+end
+
+
+describe "xmpfilter's expectation expansion" do
+ before do
+ @o = X.new
+ end
+
+ it "should expand should == expectations" do
+ @o.foo(true) # =>
+ @o.foo(true).a # =>
+ @o.foo(false) # =>
+ end
+
+ it "should expand should raise_error expectations" do
+ @o.bar # =>
+ end
+
+ it "should expand should be_nil expectations" do
+ @o.baz # =>
+ end
+
+ it "should expand correct expectations for complex values" do
+ @o.babar # =>
+ end
+
+ it "should expand should be_close expectations" do
+ @o.fubar(10) # =>
+ end
+end
+
+describe "xmpfilter's automagic binding detection" do
+ it "should expand should == expectations" do
+ a = b = c = 1
+ d = a
+ d # =>
+ end
+end
+==========
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1 # !> already initialized constant A
+end
+
+
+describe "xmpfilter's expectation expansion" do
+ before do
+ @o = X.new
+ end
+
+ it "should expand should == expectations" do
+ (@o.foo(true)).should be_a_kind_of(X::Y)
+ (@o.foo(true).inspect).should == ("#")
+ (@o.foo(true).a).should == (2)
+ (@o.foo(false)).should == (2)
+ end
+
+ it "should expand should raise_error expectations" do
+ lambda{@o.bar}.should raise_error(RuntimeError)
+ end
+
+ it "should expand should be_nil expectations" do
+ (@o.baz).should be_nil
+ end
+
+ it "should expand correct expectations for complex values" do
+ (@o.babar).should == ([1, 2])
+ end
+
+ it "should expand should be_close expectations" do
+ (@o.fubar(10)).should be_close(101.0, 0.0001)
+ end
+end
+
+describe "xmpfilter's automagic binding detection" do
+ it "should expand should == expectations" do
+ a = b = c = 1
+ d = a
+ (d).should == (a)
+ (d).should == (b)
+ (d).should == (c)
+ (d).should == (1)
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/rspec_poetry.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/rspec_poetry.taf
new file mode 100644
index 000000000..0bcd6859a
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/rspec_poetry.taf
@@ -0,0 +1,106 @@
+==========
+rspec_poetry
+==========
+xmpfilter -s --poetry
+==========
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1
+end
+
+
+describe "xmpfilter's expectation expansion" do
+ before do
+ @o = X.new
+ end
+
+ it "should expand should == expectations" do
+ @o.foo(true) # =>
+ @o.foo(true).a # =>
+ @o.foo(false) # =>
+ end
+
+ it "should expand should raise_error expectations" do
+ @o.bar # =>
+ end
+
+ it "should expand should be_nil expectations" do
+ @o.baz # =>
+ end
+
+ it "should expand correct expectations for complex values" do
+ @o.babar # =>
+ end
+
+ it "should expand should be_close expectations" do
+ @o.fubar(10) # =>
+ end
+end
+
+describe "xmpfilter's automagic binding detection" do
+ it "should expand should == expectations" do
+ a = b = c = 1
+ d = a
+ d # =>
+ end
+end
+==========
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1 # !> already initialized constant A
+end
+
+
+describe "xmpfilter's expectation expansion" do
+ before do
+ @o = X.new
+ end
+
+ it "should expand should == expectations" do
+ @o.foo(true).should be_a_kind_of(X::Y)
+ @o.foo(true).inspect.should == "#"
+ @o.foo(true).a.should == 2
+ @o.foo(false).should == 2
+ end
+
+ it "should expand should raise_error expectations" do
+ lambda{@o.bar}.should raise_error(RuntimeError)
+ end
+
+ it "should expand should be_nil expectations" do
+ @o.baz.should be_nil
+ end
+
+ it "should expand correct expectations for complex values" do
+ @o.babar.should == [1, 2]
+ end
+
+ it "should expand should be_close expectations" do
+ @o.fubar(10).should be_close(101.0, 0.0001)
+ end
+end
+
+describe "xmpfilter's automagic binding detection" do
+ it "should expand should == expectations" do
+ a = b = c = 1
+ d = a
+ d.should == a
+ d.should == b
+ d.should == c
+ d.should == 1
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/simple_annotation.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/simple_annotation.taf
new file mode 100644
index 000000000..9aa82d54b
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/simple_annotation.taf
@@ -0,0 +1,22 @@
+==========
+simple_annotation
+==========
+xmpfilter
+==========
+
+a = 1
+10.times do |i|
+ i ** 2 # =>
+ a += i
+end
+A = 1
+A = 1
+==========
+
+a = 1
+10.times do |i|
+ i ** 2 # => 0, 1, 4, 9, 16, 25, 36, 49, 64, 81
+ a += i
+end
+A = 1
+A = 1 # !> already initialized constant A
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/unit_test.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/unit_test.taf
new file mode 100644
index 000000000..662ae861b
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/unit_test.taf
@@ -0,0 +1,108 @@
+==========
+unit_test
+==========
+xmpfilter -u
+==========
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1
+ def difftype() [1, "s"] end
+end
+
+
+require 'test/unit'
+class Test_X < Test::Unit::TestCase
+ def setup
+ @o = X.new
+ end
+
+ def test_foo
+ @o.foo(true) # =>
+ @o.foo(true).a # =>
+ @o.foo(false) # =>
+ end
+
+ def test_bar
+ @o.bar # =>
+ end
+
+ def test_baz
+ @o.baz # =>
+ end
+
+ def test_babar
+ @o.babar # =>
+ end
+
+ def test_fubar
+ @o.fubar(10) # =>
+ end
+
+ def test_difftype
+ for x in @o.difftype
+ x # =>
+ end
+ end
+
+end
+
+==========
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1 # !> already initialized constant A
+ def difftype() [1, "s"] end
+end
+
+
+require 'test/unit'
+class Test_X < Test::Unit::TestCase
+ def setup
+ @o = X.new
+ end
+
+ def test_foo
+ assert_kind_of(X::Y, @o.foo(true))
+ assert_equal("#", @o.foo(true).inspect)
+ assert_equal(2, @o.foo(true).a)
+ assert_equal(2, @o.foo(false))
+ end
+
+ def test_bar
+ assert_raise(RuntimeError){@o.bar}
+ end
+
+ def test_baz
+ assert_nil(@o.baz)
+ end
+
+ def test_babar
+ assert_equal([1, 2], @o.babar)
+ end
+
+ def test_fubar
+ assert_in_delta(101.0, @o.fubar(10), 0.0001)
+ end
+
+ def test_difftype
+ for x in @o.difftype
+ #xmpfilter: WARNING!! extra values ignored
+ assert_equal(1, x)
+ end
+ end
+
+end
+
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/unit_test_detect_rbtest.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/unit_test_detect_rbtest.taf
new file mode 100644
index 000000000..7cc5893e7
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/unit_test_detect_rbtest.taf
@@ -0,0 +1,108 @@
+==========
+unit_test_detect_rbtest
+==========
+xmpfilter -u --detect-rbtest
+==========
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1
+ def difftype() [1, "s"] end
+end
+
+
+require 'test/unit'
+class Test_X < Test::Unit::TestCase
+ def setup
+ @o = X.new
+ end
+
+ def test_foo
+ @o.foo(true) # =>
+ @o.foo(true).a # =>
+ @o.foo(false) # =>
+ end
+
+ def test_bar
+ @o.bar # =>
+ end
+
+ def test_baz
+ @o.baz # =>
+ end
+
+ def test_babar
+ @o.babar # =>
+ end
+
+ def test_fubar
+ @o.fubar(10) # =>
+ end
+
+ def test_difftype
+ for x in @o.difftype
+ x # =>
+ end
+ end
+
+end
+
+==========
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1 # !> already initialized constant A
+ def difftype() [1, "s"] end
+end
+
+
+require 'test/unit'
+class Test_X < Test::Unit::TestCase
+ def setup
+ @o = X.new
+ end
+
+ def test_foo
+ assert_kind_of(X::Y, @o.foo(true))
+ assert_equal("#", @o.foo(true).inspect)
+ assert_equal(2, @o.foo(true).a)
+ assert_equal(2, @o.foo(false))
+ end
+
+ def test_bar
+ assert_raise(RuntimeError){@o.bar}
+ end
+
+ def test_baz
+ assert_nil(@o.baz)
+ end
+
+ def test_babar
+ assert_equal([1, 2], @o.babar)
+ end
+
+ def test_fubar
+ assert_in_delta(101.0, @o.fubar(10), 0.0001)
+ end
+
+ def test_difftype
+ for x in @o.difftype
+ #xmpfilter: WARNING!! extra values ignored
+ assert_equal(1, x)
+ end
+ end
+
+end
+
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/unit_test_detect_rbtest2.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/unit_test_detect_rbtest2.taf
new file mode 100644
index 000000000..219b4a996
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/unit_test_detect_rbtest2.taf
@@ -0,0 +1,18 @@
+==========
+unit_test_detect_rbtest2
+==========
+xmpfilter --detect-rbtest
+==========
+=begin test_bar
+bar("bar") # =>
+=end
+def bar(s)
+ s.upcase
+end
+==========
+=begin test_bar
+assert_equal("BAR", bar("bar"))
+=end
+def bar(s)
+ s.upcase
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/unit_test_poetry.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/unit_test_poetry.taf
new file mode 100644
index 000000000..b7c24902f
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/unit_test_poetry.taf
@@ -0,0 +1,108 @@
+==========
+unit_test_poetry
+==========
+xmpfilter -u --poetry
+==========
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1
+ def difftype() [1, "s"] end
+end
+
+
+require 'test/unit'
+class Test_X < Test::Unit::TestCase
+ def setup
+ @o = X.new
+ end
+
+ def test_foo
+ @o.foo(true) # =>
+ @o.foo(true).a # =>
+ @o.foo(false) # =>
+ end
+
+ def test_bar
+ @o.bar # =>
+ end
+
+ def test_baz
+ @o.baz # =>
+ end
+
+ def test_babar
+ @o.babar # =>
+ end
+
+ def test_fubar
+ @o.fubar(10) # =>
+ end
+
+ def test_difftype
+ for x in @o.difftype
+ x # =>
+ end
+ end
+
+end
+
+==========
+
+class X
+ Y = Struct.new(:a)
+ def foo(b); b ? Y.new(2) : 2 end
+ def bar; raise "No good" end
+ def baz; nil end
+ def fubar(x); x ** 2.0 + 1 end
+ def babar; [1,2] end
+ A = 1
+ A = 1 # !> already initialized constant A
+ def difftype() [1, "s"] end
+end
+
+
+require 'test/unit'
+class Test_X < Test::Unit::TestCase
+ def setup
+ @o = X.new
+ end
+
+ def test_foo
+ assert_kind_of X::Y, @o.foo(true)
+ assert_equal "#", @o.foo(true).inspect
+ assert_equal 2, @o.foo(true).a
+ assert_equal 2, @o.foo(false)
+ end
+
+ def test_bar
+ assert_raise(RuntimeError){@o.bar}
+ end
+
+ def test_baz
+ assert_nil @o.baz
+ end
+
+ def test_babar
+ assert_equal [1, 2], @o.babar
+ end
+
+ def test_fubar
+ assert_in_delta 101.0, @o.fubar(10), 0.0001
+ end
+
+ def test_difftype
+ for x in @o.difftype
+ #xmpfilter: WARNING!! extra values ignored
+ assert_equal 1, x
+ end
+ end
+
+end
+
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/unit_test_rbtest.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/unit_test_rbtest.taf
new file mode 100644
index 000000000..622f11828
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/unit_test_rbtest.taf
@@ -0,0 +1,18 @@
+==========
+unit_test_rbtest
+==========
+xmpfilter -u --rbtest
+==========
+=begin test_bar
+bar("bar") # =>
+=end
+def bar(s)
+ s.upcase
+end
+==========
+=begin test_bar
+assert_equal("BAR", bar("bar"))
+=end
+def bar(s)
+ s.upcase
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/width.taf b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/width.taf
new file mode 100644
index 000000000..4fa436e02
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/data/xmpfilter/width.taf
@@ -0,0 +1,16 @@
+==========
+width
+==========
+xmpfilter -w 15
+==========
+
+a = ["abcdefg", 12345, Object]
+a
+# =>
+==========
+
+a = ["abcdefg", 12345, Object]
+a
+# => ["abcdefg",
+# 12345,
+# Object]
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/test_completion.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/test_completion.rb
new file mode 100644
index 000000000..fce0fef1c
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/test_completion.rb
@@ -0,0 +1,674 @@
+$: << ".." << "../lib"
+require 'rcodetools/completion'
+require 'test/unit'
+
+class TestXMPCompletionFilter < Test::Unit::TestCase
+ include Rcodetools
+ def doit(code, lineno, column=nil, options={})
+ xmp = XMPCompletionFilter.new options
+ xmp.candidates(code, lineno, column).sort
+ end
+
+ def test_complete_method__simple
+ assert_equal(["length"], doit('"a".lengt', 1))
+ assert_equal(["length"], doit('`echo a`.lengt', 1))
+ end
+
+ def test_complete_method__in_arg
+ assert_equal(["length"], doit('print("a".lengt)', 1, 15))
+ assert_equal(["length"], doit("print('a'.lengt)", 1, 15))
+ assert_equal(["length"], doit("((a, b = 1 + 'a'.lengt))", 1, 22))
+ end
+
+ def test_complete_method__in_method
+ assert_equal(["length"], doit(<true))
+ module X
+ xx # normally NoMethodError
+ module_funct
+ end
+EOC
+ end
+
+ # drawback of ignore_NoMethodError
+ def test_with_or_without_ignore_NoMethodError
+ code = <true)
+ end
+ end
+
+ def test__syntax_error
+ assert_raise(ProcessParticularLine::NewCodeError) do
+ doit(< == === =~ > >= < <= << >>
+ + - * / % ** ~
+ ].each do |op|
+ ancestors_re = Fixnum.ancestors.map{|x|x.to_s}.join('|')
+ assert_match(/^#{ancestors_re}##{Regexp.quote(op)}$/, doit("1 #{op} 2",1,2))
+ end
+ end
+
+ def test_aref_aset__Array
+ assert_equal("Array#[]", doit("[0][ 0 ]",1,4))
+ assert_equal("Array#[]=", doit("[0][ 0 ]=10",1,4))
+ assert_equal("Array#[]", doit("[0][0]",1,4))
+ assert_equal("Array#[]=", doit("[0][0]=10",1,4))
+ end
+
+ def test_aref_aset__Object
+ assert_equal("Array#[]", doit("Array.new(3)[ 0 ]",1,13))
+ assert_equal("Array#[]=", doit("Array.new(3)[ 0 ]=10",1,13))
+ assert_equal("Array#[]", doit("Array.new(3)[0]",1,13))
+ assert_equal("Array#[]=", doit("Array.new(3)[0]=10",1,13))
+ end
+
+ def test_aref_aset__Fixnum
+ assert_equal("Fixnum#[]", doit("0[ 0 ]",1,2))
+ assert_equal("Fixnum#[]", doit("0[0]",1,2))
+ end
+
+ def test_aref_aset__String
+ assert_equal("String#[]", doit("'a' + '[0]'[ 0 ]",1,12))
+ assert_equal("String#[]", doit("'[0]'[ 0 ]",1,6))
+ assert_equal("String#[]=", doit("'0'[ 0 ]=10",1,4))
+ assert_equal("String#[]", doit("'[0]'[0]",1,6))
+ assert_equal("String#[]=", doit("'0'[0]=10",1,4))
+ end
+
+ def test_phrase
+ assert_equal("Array#uniq", doit('Array.new(3).uniq',1))
+ assert_equal("Array#uniq", doit('Array.new(3).to_a.uniq',1))
+ assert_equal("Array#uniq", doit('Array.new(3).map{|x| x.to_i}.uniq',1))
+ assert_equal("Array#uniq", doit('[][0,(1+1)].uniq',1))
+ end
+
+ def test_percent__String
+ assert_equal("String#length", doit('%!foo!.length',1))
+ assert_equal("String#length", doit('%q!foo!.length',1))
+ assert_equal("String#length", doit('%Q!foo!.length',1))
+ assert_equal("String#length", doit('%x!foo!.length',1))
+
+ assert_equal("String#length", doit('%{foo}.length',1))
+ assert_equal("String#length", doit('%q{foo}.length',1))
+ assert_equal("String#length", doit('%q!(!.length',1))
+ assert_equal("String#length", doit('%Q!(!.length',1))
+ assert_equal("String#length", doit('%x!(!.length',1))
+ assert_equal("String#length", doit('%x{(}.length',1))
+
+ assert_equal("String#length", doit('%{f(o)o}.length',1))
+ assert_equal("String#length", doit('%{f{o}o}.length',1))
+ assert_equal("String#length", doit('(%{f{o}o}+%!}x!).length',1))
+ end
+
+ def test_percent__Array
+ assert_equal("Array#length", doit('%w!foo!.length',1))
+ assert_equal("Array#length", doit('%W!foo!.length',1))
+
+ assert_equal("Array#length", doit('%w{foo}.length',1))
+ assert_equal("Array#length", doit('%W{foo}.length',1))
+ assert_equal("Array#length", doit('%w!(!.length',1))
+ assert_equal("Array#length", doit('%W!(!.length',1))
+ assert_equal("Array#length", doit('%w{(}.length',1))
+
+ assert_equal("Array#length", doit('%w{f(o)o}.length',1))
+ assert_equal("Array#length", doit('%w{f{o}o}.length',1))
+ assert_equal("Array#length", doit('(%W{f{o}o}+%w!}x!).length',1))
+ end
+
+ def test_percent__Regexp
+ assert_equal("Regexp#kcode", doit('%r!foo!.kcode',1))
+ assert_equal("Regexp#kcode", doit('%r{foo}.kcode',1))
+ assert_equal("Regexp#kcode", doit('%r!(!.kcode',1))
+ assert_equal("Regexp#kcode", doit('%r[(].kcode',1))
+ assert_equal("Regexp#kcode", doit('%r.kcode',1))
+ end
+
+ def test_percent__Symbol
+ assert_equal("Symbol#id2name", doit('%s!foo!.id2name',1))
+ assert_equal("Symbol#id2name", doit('%s{foo}.id2name',1))
+ assert_equal("Symbol#id2name", doit('%s!(!.id2name',1))
+ assert_equal("Symbol#id2name", doit('%s{(}.id2name',1))
+ assert_equal("Symbol#id2name", doit('%s(f(o)o).id2name',1))
+ end
+
+ def test_bare_word__with_NoMethodError
+ assert_equal("Module#module_function", doit(<true))
+ module X
+ xx # normally NoMethodError
+ module_function
+ end
+EOC
+ end
+
+ def test__syntax_error
+ assert_raise(ProcessParticularLine::NewCodeError) do
+ doit(< < Struct
+method_args.data.rb:101:class SubclassOfStructA < StructA
+method_args.data.rb:102:SubclassOfStructA#method_in_b
+method_args.data.rb:104:class < Struct
+method_args.data.rb:104:class StructSubclass <
+method_args.data.rb:105:StructSubclass#method_in_c
+XXX
+
+ # To avoid dependency of pwd.
+ module StripDir
+ def strip_dir!
+ slice! %r!^.*/!
+ self
+ end
+ end
+
+ @@expected.each do |line|
+ begin
+ file_lineno_klass_meth, rest = line.split(/\s+/,2)
+ if file_lineno_klass_meth =~ /:/
+ file, lineno, klass_meth = file_lineno_klass_meth.split(/:/)
+ klass_meth = rest if %w[class include extend].include? klass_meth
+ else # filename/lineno is unknown
+ klass_meth = file_lineno_klass_meth
+ end
+
+ test_method_name = "test_" + klass_meth
+ define_method(test_method_name) do
+ actual = @@result.grep(/#{klass_meth}/)[0].extend(StripDir).strip_dir!
+ assert_equal line, actual
+ end
+ rescue Exception
+ end
+ end
+
+ def test_all_tests
+ assert_equal @@expected.length, @@result.length, @@result.join("\n")
+ end
+
+ def test_without_n_option
+ first_line = "FixedArgsMethods.singleton (a1)"
+ command_output = `ruby '#{SCRIPT}' '#{DATAFILE}'`
+ assert_match(/\A#{Regexp.quote(first_line)}\n/, command_output)
+ end
+end
+
+
+class TestTAGS < Test::Unit::TestCase
+ include MethodArgsScriptConfig
+
+ @@TAGS = `ruby '#{SCRIPT}' -t '#{DATAFILE}'`
+ def test_filename
+ # check whether full path is passed.
+ assert_match %r!^\cl\n/.+method_args.data.rb,\d!, @@TAGS
+ end
+
+ def test_singleton_method
+ # including line/byte test
+ assert @@TAGS.include?(" def self.singleton(a1) end::FixedArgsMethods.singleton3,45")
+ end
+
+ def test_instance_method
+ assert @@TAGS.include?(" def initialize(arg) end::FixedArgsMethods#initialize4,74")
+ end
+
+ def test_include
+ assert_match(/^ include VariableArgsMethods::AClass/, @@TAGS)
+ end
+
+ def test_extend
+ assert_match(/^ extend VariableArgsMethods::AClass/, @@TAGS)
+ end
+
+ def test_inheritance
+ assert_match(/^class ASubClass < AClass::ASubClass/, @@TAGS)
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/test_options.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/test_options.rb
new file mode 100644
index 000000000..8751516f2
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/test_options.rb
@@ -0,0 +1,33 @@
+$: << ".." << "../lib"
+require 'rcodetools/options'
+require 'test/unit'
+require 'tmpdir'
+require 'fileutils'
+
+class TestOptionHandler < Test::Unit::TestCase
+ include Rcodetools
+ include OptionHandler
+
+ def include_paths_check
+ options = { :include_paths => [] }
+ auto_include_paths options[:include_paths], Dir.pwd
+ assert options[:include_paths].include?("#{@basedir}/lib")
+ assert options[:include_paths].include?("#{@basedir}/bin")
+ end
+
+ def test_auto_include_paths
+ Dir.chdir(Dir.tmpdir) do
+ begin
+ FileUtils.mkdir_p ["project", "project/lib/project", "project/bin", "project/share"]
+ open("project/Rakefile","w"){}
+ @basedir = File.expand_path "project"
+ Dir.chdir("project/lib/project/") { include_paths_check }
+ Dir.chdir("project/lib/") { include_paths_check }
+ Dir.chdir("project/bin/") { include_paths_check }
+ Dir.chdir("project/") { include_paths_check }
+ ensure
+ FileUtils.rm_rf "project"
+ end
+ end
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/test_ruby_toggle_file.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/test_ruby_toggle_file.rb
new file mode 100644
index 000000000..e7960f9a3
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/test_ruby_toggle_file.rb
@@ -0,0 +1,174 @@
+require 'fileutils'
+require 'test/unit'
+require 'ruby_toggle_file'
+require 'tmpdir'
+
+class TestRubyToggleFile < Test::Unit::TestCase
+ WORK_DIR = "#{Dir.tmpdir}/zdsfwfwejiotest".freeze
+ FileUtils.rm_rf WORK_DIR
+
+ def teardown
+ FileUtils.rm_rf WORK_DIR
+ end
+
+ def create(*files)
+ for file in files.map{|f| _(f) }
+ FileUtils.mkpath(File.dirname(file))
+ open(file,"w"){}
+ end
+ end
+
+ def _(path) # make full path
+ WORK_DIR + "/" + path
+ end
+
+ ###########################################################################
+ # naming convention #
+ # test_METHOD__EXISTP__IMPLEMENTDIR_TESTDIR #
+ ###########################################################################
+ def test_test_file__exist__lib_test
+ create "lib/zero.rb", "test/test_zero.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("test/test_zero.rb"), rtf.ruby_toggle_file(_("lib/zero.rb"))
+ end
+
+ def test_test_file__exist__libone_testone
+ create "lib/one/one.rb", "test/one/test_one.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("test/one/test_one.rb"), rtf.ruby_toggle_file(_("lib/one/one.rb"))
+ end
+
+ def test_test_file__exist__libtwo_test
+ create "lib/two/two.rb", "test/test_two.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("test/test_two.rb"), rtf.ruby_toggle_file(_("lib/two/two.rb"))
+ end
+
+ def test_test_file__exist__top_test
+ create "three.rb", "test_three.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("test_three.rb"), rtf.ruby_toggle_file(_("three.rb"))
+ end
+
+ def test_test_file__not_exist__top
+ create "four.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("test_four.rb"), rtf.ruby_toggle_file(_("four.rb"))
+ end
+
+ def test_test_file__not_exist__lib
+ create "lib/five.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("test/test_five.rb"), rtf.ruby_toggle_file(_("lib/five.rb"))
+ end
+
+ def test_test_file__not_exist__libsixsix
+ create "lib/six/six/six.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("test/six/six/test_six.rb"), rtf.ruby_toggle_file(_("lib/six/six/six.rb"))
+ end
+
+ def test_implementation_file__exist__lib_test
+ create "lib/zero.rb", "test/test_zero.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("lib/zero.rb"), rtf.ruby_toggle_file(_("test/test_zero.rb"))
+ end
+
+ def test_implementation_file__exist__libone_testone
+ create "lib/one/one.rb", "test/one/test_one.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("lib/one/one.rb"), rtf.ruby_toggle_file(_("test/one/test_one.rb"))
+ end
+
+ def test_implementation_file__exist__libtwo_test
+ create "lib/two/two.rb", "test/test_two.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("lib/two/two.rb"), rtf.ruby_toggle_file(_("test/test_two.rb"))
+ end
+
+ def test_implementation_file__exist__top_test
+ create "three.rb", "test_three.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("three.rb"), rtf.ruby_toggle_file(_("test_three.rb"))
+ end
+
+ def test_implementation_file__not_exist__none_top
+ create "test_seven.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("seven.rb"), rtf.ruby_toggle_file(_("test_seven.rb"))
+ end
+
+ def test_implementation_file__not_exist__none_test
+ create "test/test_eight.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("lib/eight.rb"), rtf.ruby_toggle_file(_("test/test_eight.rb"))
+ end
+
+ def test_implementation_file__not_exist__none_testninenine
+ create "test/nine/nine/nine.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("lib/nine/nine/nine.rb"), rtf.ruby_toggle_file(_("test/nine/nine/test_nine.rb"))
+ end
+
+ ###########################################################################
+ # Rails test #
+ ###########################################################################
+ def test_test_file__rails_controllers
+ create "app/controllers/c.rb", "test/functional/c_test.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("test/functional/c_test.rb"), rtf.ruby_toggle_file(_("app/controllers/c.rb"))
+ end
+
+ def test_test_file__rails_models
+ create "app/models/m.rb", "test/unit/m_test.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("test/unit/m_test.rb"), rtf.ruby_toggle_file(_("app/models/m.rb"))
+ end
+
+ def test_test_file__rails_lib
+ create "lib/l.rb", "test/unit/test_l.rb", "app/models/m.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("test/unit/test_l.rb"), rtf.ruby_toggle_file(_("lib/l.rb"))
+ end
+
+
+ def test_implementation_file__rails_controllers
+ create "app/controllers/c.rb", "test/functional/c_test.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("app/controllers/c.rb"), rtf.ruby_toggle_file(_("test/functional/c_test.rb"))
+ end
+
+ def test_implementation_file__rails_models
+ create "app/models/m.rb", "test/unit/m_test.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("app/models/m.rb"), rtf.ruby_toggle_file(_("test/unit/m_test.rb"))
+ end
+
+ def test_implementation_file__rails_lib
+ create "lib/l.rb", "test/unit/test_l.rb", "app/models/m.rb"
+ rtf = RubyToggleFile.new
+ assert_equal _("lib/l.rb"), rtf.ruby_toggle_file(_("test/unit/test_l.rb"))
+ end
+end
+
+
+class TestRunHooksWithArgsUntilSuccess < Test::Unit::TestCase
+ def m001(x) nil end
+ private
+ def m002(x) false end
+ def m003(x) 100*x end
+ def m004(x) 200 end
+
+ public
+ def test_run_hooks_with_args_until_success__m003
+ assert_equal 1000, run_hooks_with_args_until_success(/^m\d+$/, 10)
+ end
+
+ def test_run_hooks_with_args_until_success__m001
+ assert_nil run_hooks_with_args_until_success(/^m001$/, 10)
+ end
+
+ def test_run_hooks_with_args_until_success__m004
+ assert_equal 200, run_hooks_with_args_until_success(/^m004$/, 10)
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/test_xmpfilter.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/test_xmpfilter.rb
new file mode 100644
index 000000000..0ed9aa6b8
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/test_xmpfilter.rb
@@ -0,0 +1,221 @@
+
+require 'test/unit'
+$: << ".." << "../lib"
+require "rcodetools/xmpfilter"
+require 'rubygems'
+require 'mocha'
+
+class TestXMPFilter < Test::Unit::TestCase
+ include Rcodetools
+ def test_extract_data__results
+ marker = XMPFilter::MARKER
+ str = <<-EOF
+#{marker}[1] => Fixnum 42
+#{marker}[1] => Fixnum 0
+#{marker}[1] ==> var
+#{marker}[1] ==> var2
+#{marker}[4] ==> var3
+#{marker}[2] ~> some exception
+#{marker}[10] => Fixnum 42
+ EOF
+ xmp = XMPFilter.new
+ data = xmp.extract_data(str)
+ assert_equal([[1, [["Fixnum", "42"], ["Fixnum", "0"]]], [10, [["Fixnum", "42"]]]], data.results.sort)
+ end
+
+ def test_extract_data__exceptions
+ marker = XMPFilter::MARKER
+ str = <<-EOF
+#{marker}[1] => Fixnum 42
+#{marker}[1] => Fixnum 0
+#{marker}[1] ==> var
+#{marker}[1] ==> var2
+#{marker}[4] ==> var3
+#{marker}[2] ~> some exception
+#{marker}[10] => Fixnum 42
+ EOF
+ xmp = XMPFilter.new
+ data = xmp.extract_data(str)
+ assert_equal([[2, ["some exception"]]], data.exceptions.sort)
+ end
+
+ def test_extract_data__bindings
+ marker = XMPFilter::MARKER
+ str = <<-EOF
+#{marker}[1] => Fixnum 42
+#{marker}[1] => Fixnum 0
+#{marker}[1] ==> var
+#{marker}[1] ==> var2
+#{marker}[4] ==> var3
+#{marker}[2] ~> some exception
+#{marker}[10] => Fixnum 42
+ EOF
+ xmp = XMPFilter.new
+ data = xmp.extract_data(str)
+ assert_equal([[1, ["var", "var2"]], [4, ["var3"]]], data.bindings.sort)
+ end
+
+ def test_interpreter_command
+ xmp = XMPFilter.new(:interpreter=>"ruby", :detect_rct_fork => false)
+ assert_equal(%w[ruby -w], xmp.interpreter_command)
+ end
+
+ def test_interpreter_command_detect_rct_fork
+ Fork.stubs(:run?).returns true
+ xmp = XMPFilter.new(:interpreter=>"ruby", :detect_rct_fork => true)
+ assert_equal(%w[ruby -S rct-fork-client], xmp.interpreter_command)
+ end
+
+ def test_interpreter_command_use_rbtest
+ xmp = XMPFilter.new(:interpreter=>"ruby", :use_rbtest => true)
+ assert_equal(%w[ruby -S rbtest], xmp.interpreter_command)
+ end
+
+ def test_initialize__test_script_1
+ XMPFilter.any_instance.stubs(:safe_require_code).returns("require 'test/unit'")
+ xmp = XMPFilter.new(:test_script=>"/path/to/test/test_ruby_toggle_file.rb",
+ :test_method=>"test_implementation_file_file_exist",
+ :filename=>"/path/to/lib/ruby_toggle_file.rb")
+
+ evals_expected = [
+ %q!$LOADED_FEATURES << "ruby_toggle_file.rb"!,
+ %q!require 'test/unit'!,
+ %q!load "/path/to/test/test_ruby_toggle_file.rb"!,
+ %q!Test::Unit::AutoRunner.run(false, nil, ["-n", "test_implementation_file_file_exist"])!
+ ]
+ assert_equal evals_expected, xmp.instance_variable_get(:@evals)
+ end
+
+ def test_initialize__test_script_2
+ XMPFilter.any_instance.stubs(:safe_require_code).returns("require 'test/unit'")
+ xmp = XMPFilter.new(:test_script=>"/path/to/test_ruby_toggle_file.rb",
+ :test_method=>"test_implementation_file_file_exist",
+ :filename=>"/path/to/ruby_toggle_file.rb")
+
+ evals_expected = [
+ %q!$LOADED_FEATURES << "ruby_toggle_file.rb"!,
+ %q!require 'test/unit'!,
+ %q!load "/path/to/test_ruby_toggle_file.rb"!,
+ %q!Test::Unit::AutoRunner.run(false, nil, ["-n", "test_implementation_file_file_exist"])!
+ ]
+ assert_equal evals_expected, xmp.instance_variable_get(:@evals)
+ end
+
+ def test_initialize__test_script_3
+ test_script = File.join(File.dirname(__FILE__), "data/sample_test_script.rb")
+ filename = File.join(File.dirname(__FILE__), "data/sample.rb")
+ XMPFilter.any_instance.stubs(:safe_require_code).returns("require 'test/unit'")
+ xmp = XMPFilter.new(:test_script=>test_script, :test_method=>"4", :filename=>filename)
+
+ evals_expected = [
+ %q!$LOADED_FEATURES << "sample.rb"!,
+ %q!require 'test/unit'!,
+ %Q!load #{test_script.dump}!,
+ %q!Test::Unit::AutoRunner.run(false, nil, ["-n", "test_sample0"])!
+ ]
+ assert_equal evals_expected, xmp.instance_variable_get(:@evals)
+ end
+
+ def test_initialize__test_script__filename_eq_test_script
+ test_script = File.join(File.dirname(__FILE__), "data/sample_test_script.rb")
+ filename = test_script
+ xmp = XMPFilter.new(:test_script=>test_script, :test_method=>"4", :filename=>filename)
+
+ evals_expected = [
+ %q!Test::Unit::AutoRunner.run(false, nil, ["-n", "test_sample0"])!
+ ]
+ assert_equal evals_expected, xmp.instance_variable_get(:@evals)
+ end
+
+ def test_get_test_method_from_lineno
+ file = File.join(File.dirname(__FILE__), "data/sample_test_script.rb")
+ xmp = XMPFilter.new
+ assert_equal("test_sample0", xmp.get_test_method_from_lineno(file, 4))
+ assert_equal("test_sample1", xmp.get_test_method_from_lineno(file, 7))
+ assert_equal("test_sample1", xmp.get_test_method_from_lineno(file, 8))
+ assert_equal(nil, xmp.get_test_method_from_lineno(file, 1))
+ end
+
+ # Use methods to avoid confusing syntax highlighting
+ def beg() "=begin" end
+ def ed() "=end" end
+
+ def test_s_detect_rbtest_1
+ rbtest_script_1 = < true}
+ assert_equal true, XMPFilter.detect_rbtest(rbtest_script_1, opts)
+ assert_equal true, opts[:use_rbtest]
+ opts = {:detect_rbtest => false}
+ assert_equal false, XMPFilter.detect_rbtest(rbtest_script_1, opts)
+ assert_equal false, opts[:use_rbtest]
+ opts = {:detect_rbtest => false, :use_rbtest => true}
+ assert_equal true, XMPFilter.detect_rbtest(rbtest_script_1, opts)
+ assert_equal true, opts[:use_rbtest]
+ end
+
+ def test_s_detect_rbtest_2
+ rbtest_script_2 = < true}
+ assert_equal true, XMPFilter.detect_rbtest(rbtest_script_2, opts)
+ assert_equal true, opts[:use_rbtest]
+ opts = {:detect_rbtest => false}
+ assert_equal false, XMPFilter.detect_rbtest(rbtest_script_2, opts)
+ assert_equal false, opts[:use_rbtest]
+ end
+
+ def test_s_detect_rbtest_3
+ no_rbtest_script = < true}
+ assert_equal false, XMPFilter.detect_rbtest(no_rbtest_script, opts)
+ assert_equal false, opts[:use_rbtest]
+ opts = {:detect_rbtest => false}
+ assert_equal false, XMPFilter.detect_rbtest(no_rbtest_script, opts)
+ assert_equal false, opts[:use_rbtest]
+ end
+
+end
+
+class TestTempScript < Test::Unit::TestCase
+ def test(script)
+ Rcodetools::XMPFilter.new.__send__(:split_shbang,script)
+ end
+
+ def test_none
+ assert_equal [[], ["1\n"]], test(<
+arr.last # \=>
+EOF
+ ANNOTATION_VAR_INFERENCE_OUTPUT = <]\", arr.inspect)
+assert_equal(x, arr.last)
+assert_kind_of(X, arr.last)
+assert_equal(\"#\", arr.last.inspect)
+EOF
+
+ def test_annotation_var_inference
+ xmp = XMPTestUnitFilter.new
+ assert_equal(ANNOTATION_VAR_INFERENCE_OUTPUT,
+ xmp.annotate(ANNOTATION_VAR_INFERENCE_INPUT).join(""))
+ end
+
+ def test_equality_assertions
+ xmp = XMPTestUnitFilter.new
+ assert_equal(["a = 1\n", "assert_equal(1, a)"], xmp.annotate("a = 1\na # \=>"))
+ assert_equal(["a = {1,2}\n", "assert_equal({1=>2}, a)"],
+ xmp.annotate("a = {1,2}\na # \=>"))
+ assert_equal(["a = [1,2]\n", "assert_equal([1, 2], a)"],
+ xmp.annotate("a = [1,2]\na # \=>"))
+ assert_equal(["a = 'foo'\n", "assert_equal(\"foo\", a)"],
+ xmp.annotate("a = 'foo'\na # \=>"))
+ assert_equal(["a = 1.0\n", "assert_in_delta(1.0, a, 0.0001)"],
+ xmp.annotate("a = 1.0\na # \=>"))
+ end
+
+ def test_raise_assertion
+ code = <
+EOF
+ xmp = XMPTestUnitFilter.new
+ assert_equal(["class NoGood < Exception; end\n",
+ "assert_raise(NoGood){raise NoGood}\n"], xmp.annotate(code))
+ end
+
+ def test_assert_nil
+ xmp = XMPTestUnitFilter.new
+ assert_equal(["a = nil\n", "assert_nil(a)"], xmp.annotate("a = nil\na # \=>"))
+ end
+
+ def test_poetry_mode
+ code = <
+a = 1.0
+a # \=>
+raise "foo" # \=>
+a = nil
+a # \=>
+EOF
+ output = < false)
+ assert_equal(output, xmp.annotate(code).join)
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/tmp_functional.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/tmp_functional.rb
new file mode 100644
index 000000000..339fdfc2b
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/tmp_functional.rb
@@ -0,0 +1,162 @@
+require 'test/unit'
+
+module TestFunctional
+ DIR = File.expand_path(File.dirname(__FILE__))
+ LIBDIR = File.expand_path(DIR + '/../lib')
+
+ module DefineFunctionalTests
+ def define_functional_tests(bin, exec, tests)
+ tests.each_pair do |test, opts|
+ define_method("test_#{test}") do
+
+ output = `ruby -I#{LIBDIR} #{exec} #{opts.join(" ")} #{DIR}/data/#{test}-input.rb`
+ outputfile = "#{DIR}/data/#{test}-output.rb"
+ taffile = "#{DIR}/data/#{bin}/#{test}.taf"
+ open(taffile, "w") do |f|
+ f.puts "=========="
+ f.puts test
+ f.puts "=========="
+ f.puts bin + " " + opts.join(" ")
+ f.puts "=========="
+ f.puts File.read("#{DIR}/data/#{test}-input.rb")
+ f.puts "=========="
+ f.puts File.read("#{DIR}/data/#{test}-output.rb")
+ end
+# assert_equal(File.read(outputfile), output)
+ end
+ end
+ end
+ end
+
+ class TestXmpfilter < Test::Unit::TestCase
+ extend DefineFunctionalTests
+ tests = {
+ :simple_annotation => [], :unit_test => ["-u"], :rspec => ["-s"],
+ :no_warnings => ["--no-warnings"], :bindings => ["--poetry", "-u"],
+ :add_markers => ["-m"], :unit_test_rbtest => ["-u", "--rbtest"],
+ :unit_test_detect_rbtest => ["-u", "--detect-rbtest"],
+ :unit_test_detect_rbtest2 => ["--detect-rbtest"],
+ }
+ define_functional_tests "xmpfilter", File.expand_path(DIR + '/../bin/xmpfilter'), tests
+ end
+
+ class TestRctComplete < Test::Unit::TestCase
+ extend DefineFunctionalTests
+ tests = {
+ :completion_rbtest => [ "--rbtest", "--line=6" ],
+ :completion_detect_rbtest => [ "--detect-rbtest", "--line=6" ],
+ :completion_detect_rbtest2 => [ "--detect-rbtest", "--line=1" ],
+ }
+ define_functional_tests "rct-complete", File.expand_path(DIR + '/../bin/rct-complete'), tests
+ end
+
+ class TestRctDoc < Test::Unit::TestCase
+ extend DefineFunctionalTests
+ tests = {
+ :doc_rbtest => [ "--rbtest", "--line=6" ],
+ :doc_detect_rbtest => [ "--detect-rbtest", "--line=1" ],
+ :doc_detect_rbtest2 => [ "--detect-rbtest", "--line=6" ],
+ }
+ define_functional_tests "rct-doc", File.expand_path(DIR + '/../bin/rct-doc'), tests
+ end
+
+
+ # Other tests are in test_run.rb
+ class TestRctCompleteTDC < Test::Unit::TestCase
+ test = :completion_in_method
+ inputfile = "#{DIR}/data/#{test}-input.rb"
+ outputfile = "#{DIR}/data/#{test}-output.rb"
+ test_script = "#{DIR}/data/#{test}-test.rb"
+ common_opts = ["--filename #{inputfile}", "--line 2"]
+ right_output = File.read(outputfile)
+ wrong_output = "\n"
+
+ tests = {
+ :completion_in_method__testscript =>
+ [ common_opts + ["-t #{test_script}"], right_output ],
+ :completion_in_method__testmethod =>
+ [ common_opts + ["-t #{test_script}@test_fooz"], right_output ],
+ :completion_in_method__wrong_testmethod =>
+ [ common_opts + ["-t #{test_script}@test_NOT_FOUND"], wrong_output ],
+ }
+ exec = File.expand_path(DIR + '/../bin/rct-complete')
+# tests.each_pair do |test, (opts, expected)|
+# define_method("test_#{test}") do
+# output = `ruby -I#{LIBDIR} #{exec} #{opts.join(" ")} #{inputfile}`
+
+# taffile = "#{DIR}/data/#{bin}/#{test}.taf"
+# open(taffile, "w") do |f|
+# f.puts "=========="
+# f.puts test
+# f.puts "=========="
+# f.puts bin + " " + opts.join(" ")
+# f.puts "=========="
+# f.puts File.read("#{DIR}/data/#{test}-input.rb")
+# f.puts "=========="
+# f.puts File.read("#{DIR}/data/#{test}-output.rb")
+# end
+# end
+# end
+
+ test=:completion_in_method__testscript
+ define_method("test_#{test}") do
+ taffile = "#{DIR}/data/rct-complete-TDC/completion_in_method__testscript.taf"
+ open(taffile, "w") do |f|
+ opts = tests[test]
+ f.puts "=========="
+ f.puts test
+ f.puts "=========="
+ f.puts "rct-complete " + opts.join(" ")
+ f.puts "=========="
+ test0 = :completion_in_method
+ f.puts File.read("#{DIR}/data/#{test0}-input.rb")
+ f.puts "=========="
+ f.puts File.read("#{DIR}/data/#{test0}-output.rb")
+ f.puts "=========="
+ f.puts File.read("#{DIR}/data/#{test0}-test.rb")
+ end
+
+ end
+
+ test=:completion_in_method__testmethod
+ define_method("test_#{test}") do
+ taffile = "#{DIR}/data/rct-complete-TDC/completion_in_method__testmethod.taf"
+ open(taffile, "w") do |f|
+ opts = tests[test]
+ f.puts "=========="
+ f.puts test
+ f.puts "=========="
+ f.puts "rct-complete " + opts.join(" ")
+ f.puts "=========="
+ test0 = :completion_in_method
+ f.puts File.read("#{DIR}/data/#{test0}-input.rb")
+ f.puts "=========="
+ f.puts File.read("#{DIR}/data/#{test0}-output.rb")
+ f.puts "=========="
+ f.puts File.read("#{DIR}/data/#{test0}-test.rb")
+ end
+
+ end
+
+ test=:completion_in_method__wrong_testmethod
+ define_method("test_#{test}") do
+ taffile = "#{DIR}/data/rct-complete-TDC/completion_in_method__wrong_testmethod.taf"
+ open(taffile, "w") do |f|
+ opts = tests[test]
+ f.puts "=========="
+ f.puts test
+ f.puts "=========="
+ f.puts "rct-complete " + opts.join(" ")
+ f.puts "=========="
+ test0 = :completion_in_method
+ f.puts File.read("#{DIR}/data/#{test0}-input.rb")
+ f.puts "=========="
+ f.puts
+ f.puts "=========="
+ f.puts File.read("#{DIR}/data/#{test0}-test.rb")
+ end
+
+ end
+
+ end
+end
diff --git a/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/tmp_run.rb b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/tmp_run.rb
new file mode 100644
index 000000000..b3bed0d01
--- /dev/null
+++ b/bundles/ruby.tmbundle/Support/vendor/rcodetools/test/tmp_run.rb
@@ -0,0 +1,66 @@
+require 'test/unit'
+require 'rcodetools/xmpfilter'
+require 'rcodetools/xmptestunitfilter'
+require 'rcodetools/completion'
+require 'rcodetools/doc'
+require 'rcodetools/options'
+require 'stringio'
+
+class TestRun < Test::Unit::TestCase
+ include Rcodetools
+ DIR = File.expand_path(File.dirname(__FILE__))
+
+ tests = {
+# :rspec_poetry => {:klass => XMPRSpecFilter, :interpreter => "spec", :use_parentheses => false},
+ :rspec_poetry => ["xmpfilter", "-s --poetry"],
+# :unit_test_poetry => {:klass => XMPTestUnitFilter, :use_parentheses => false},
+ :unit_test_poetry => ["xmpfilter", "-u --poetry"],
+
+# :completion => {:klass => XMPCompletionFilter, :lineno => 1},
+ :completion => ["rct-complete", "-C --line=1"],
+# :completion_emacs => {:klass => XMPCompletionEmacsFilter, :lineno => 1},
+ :completion_emacs => ["rct-complete", "--completion-emacs --line=1"],
+# :completion_emacs_icicles => {:klass => XMPCompletionEmacsIciclesFilter, :lineno => 1},
+ :completion_emacs_icicles => ["rct-complete","--completion-emacs-icicles --line=1"],
+# :completion_class_info => {:klass => XMPCompletionClassInfoFilter, :lineno => 1},
+ :completion_class_info => ["rct-complete", "--completion-class-info --line=1"],
+# :completion_class_info_no_candidates => {:klass => XMPCompletionClassInfoFilter, :lineno => 1},
+ :completion_class_info_no_candidates => ["rct-complete", "--completion-class-info --line=1"],
+
+# :doc => {:klass => XMPDocFilter, :lineno => 1},
+# :refe => {:klass => XMPReFeFilter, :lineno => 1},
+# :ri => {:klass => XMPRiFilter, :lineno => 1},
+# :ri_emacs => {:klass => XMPRiEmacsFilter, :lineno => 1},
+# :ri_vim => {:klass => XMPRiVimFilter, :lineno => 1},
+ :doc => ["rct-doc", "-D --line=1"],
+ :refe => ["rct-doc", "--refe --line=1"],
+ :ri => ["rct-doc", "--ri --line=1"],
+ :ri_emacs => ["rct-doc", "--ri-emacs --line=1"],
+ :ri_vim => ["rct-doc", "--ri-vim --line=1"],
+
+ }
+ DIR = File.expand_path(File.dirname(__FILE__))
+ LIBDIR = File.expand_path(DIR + '/../lib')
+
+ tests.each_pair do |test, (bin,opts)|
+ define_method("test_#{test}") do
+ inputfile = "#{DIR}/data/#{test}-input.rb"
+ outputfile = "#{DIR}/data/#{test}-output.rb"
+
+# exec = File.expand_path(DIR + '/../bin/xmpfilter')
+# output = `ruby -I#{LIBDIR} #{exec} #{opts} #{DIR}/data/#{test}-input.rb`
+# outputfile = "#{DIR}/data/#{test}-output.rb"
+ taffile = "#{DIR}/data/#{bin}/#{test}.taf"
+ open(taffile, "w") do |f|
+ f.puts "=========="
+ f.puts test
+ f.puts "=========="
+ f.puts bin + " " + opts
+ f.puts "=========="
+ f.puts File.read("#{DIR}/data/#{test}-input.rb")
+ f.puts "=========="
+ f.puts File.read("#{DIR}/data/#{test}-output.rb")
+ end
+ end
+ end
+end
diff --git a/bundles/ruby.tmbundle/Syntaxes/Ruby.plist b/bundles/ruby.tmbundle/Syntaxes/Ruby.plist
new file mode 100644
index 000000000..8070bb973
--- /dev/null
+++ b/bundles/ruby.tmbundle/Syntaxes/Ruby.plist
@@ -0,0 +1,2853 @@
+
+
+
+
+ comment
+
+ TODO: unresolved issues
+
+ text:
+ "p << end
+ print me!
+ end"
+ symptoms:
+ not recognized as a heredoc
+ solution:
+ there is no way to distinguish perfectly between the << operator and the start
+ of a heredoc. Currently, we require assignment to recognize a heredoc. More
+ refinement is possible.
+ • Heredocs with indented terminators (<<-) are always distinguishable, however.
+ • Nested heredocs are not really supportable at present
+
+ text:
+ print <<-'THERE'
+ This is single quoted.
+ The above used #{Time.now}
+ THERE
+ symtoms:
+ From Programming Ruby p306; should be a non-interpolated heredoc.
+
+ text:
+ "a\332a"
+ symptoms:
+ '\332' is not recognized as slash3.. which should be octal 332.
+ solution:
+ plain regexp.. should be easy.
+
+ text:
+ val?(a):p(b)
+ val?'a':'b'
+ symptoms:
+ ':p' is recognized as a symbol.. its 2 things ':' and 'p'.
+ :'b' has same problem.
+ solution:
+ ternary operator rule, precedence stuff, symbol rule.
+ but also consider 'a.b?(:c)' ??
+
+ fileTypes
+
+ rb
+ rbx
+ rjs
+ Rakefile
+ rake
+ cgi
+ fcgi
+ gemspec
+ irbrc
+ capfile
+
+ firstLineMatch
+ ^#!/.*\bruby
+ foldingStartMarker
+ (?x)^
+ (\s*+
+ (module|class|def(?!.*\bend\s*$)
+ |unless|if
+ |case
+ |begin
+ |for|while|until
+ |^=begin
+ |( "(\\.|[^"])*+" # eat a double quoted string
+ | '(\\.|[^'])*+' # eat a single quoted string
+ | [^#"'] # eat all but comments and strings
+ )*
+ ( \s (do|begin|case)
+ | (?<!\$)[-+=&|*/~%^<>~] \s*+ (if|unless)
+ )
+ )\b
+ (?! [^;]*+ ; .*? \bend\b )
+ |( "(\\.|[^"])*+" # eat a double quoted string
+ | '(\\.|[^'])*+' # eat a single quoted string
+ | [^#"'] # eat all but comments and strings
+ )*
+ ( \{ (?! [^}]*+ \} )
+ | \[ (?! [^\]]*+ \] )
+ )
+ ).*$
+ | [#] .*? \(fold\) \s*+ $ # Sune’s special marker
+
+ foldingStopMarker
+ (?x)
+ ( (^|;) \s*+ end \s*+ ([#].*)? $
+ | (^|;) \s*+ end \. .* $
+ | ^ \s*+ [}\]] ,? \s*+ ([#].*)? $
+ | [#] .*? \(end\) \s*+ $ # Sune’s special marker
+ | ^=end
+ )
+ keyEquivalent
+ ^~R
+ name
+ Ruby
+ patterns
+
+
+ captures
+
+ 1
+
+ name
+ keyword.control.class.ruby
+
+ 2
+
+ name
+ entity.name.type.class.ruby
+
+ 4
+
+ name
+ entity.other.inherited-class.ruby
+
+ 5
+
+ name
+ punctuation.separator.inheritance.ruby
+
+ 6
+
+ name
+ variable.other.object.ruby
+
+ 7
+
+ name
+ punctuation.definition.variable.ruby
+
+
+ match
+ ^\s*(class)\s+(([.a-zA-Z0-9_:]+(\s*(<)\s*[.a-zA-Z0-9_:]+)?)|((<<)\s*[.a-zA-Z0-9_:]+))
+ name
+ meta.class.ruby
+
+
+ captures
+
+ 1
+
+ name
+ keyword.control.module.ruby
+
+ 2
+
+ name
+ entity.name.type.module.ruby
+
+ 3
+
+ name
+ entity.other.inherited-class.module.first.ruby
+
+ 4
+
+ name
+ punctuation.separator.inheritance.ruby
+
+ 5
+
+ name
+ entity.other.inherited-class.module.second.ruby
+
+ 6
+
+ name
+ punctuation.separator.inheritance.ruby
+
+ 7
+
+ name
+ entity.other.inherited-class.module.third.ruby
+
+ 8
+
+ name
+ punctuation.separator.inheritance.ruby
+
+
+ match
+ ^\s*(module)\s+(([A-Z]\w*(::))?([A-Z]\w*(::))?([A-Z]\w*(::))*[A-Z]\w*)
+ name
+ meta.module.ruby
+
+
+ comment
+ else if is a common mistake carried over from other languages. it works if you put in a second end, but it’s never what you want.
+ match
+ (?<!\.)\belse(\s)+if\b
+ name
+ invalid.deprecated.ruby
+
+
+ comment
+ everything being a reserved word, not a value and needing a 'end' is a..
+ match
+ (?<!\.)\b(BEGIN|begin|case|class|else|elsif|END|end|ensure|for|if|in|module|rescue|then|unless|until|when|while)\b(?![?!])
+ name
+ keyword.control.ruby
+
+
+ comment
+ contextual smart pair support for block parameters
+ match
+ (?<!\.)\bdo\b\s*
+ name
+ keyword.control.start-block.ruby
+
+
+ comment
+ contextual smart pair support
+ match
+ (?<=\{)(\s+)
+ name
+ meta.syntax.ruby.start-block
+
+
+ comment
+ as above, just doesn't need a 'end' and does a logic operation
+ match
+ (?<!\.)\b(and|not|or)\b
+ name
+ keyword.operator.logical.ruby
+
+
+ comment
+ just as above but being not a logical operation
+ match
+ (?<!\.)\b(alias|alias_method|break|next|redo|retry|return|super|undef|yield)\b(?![?!])|\bdefined\?|\bblock_given\?
+ name
+ keyword.control.pseudo-method.ruby
+
+
+ match
+ \b(nil|true|false)\b(?![?!])
+ name
+ constant.language.ruby
+
+
+ match
+ \b(__(FILE|LINE)__|self)\b(?![?!])
+ name
+ variable.language.ruby
+
+
+ comment
+ everything being a method but having a special function is a..
+ match
+ \b(initialize|new|loop|include|extend|raise|attr_reader|attr_writer|attr_accessor|attr|catch|throw|private|module_function|public|protected)\b(?![?!])
+ name
+ keyword.other.special-method.ruby
+
+
+ begin
+ \b(require|gem)\b
+ captures
+
+ 1
+
+ name
+ keyword.other.special-method.ruby
+
+
+ end
+ $|(?=#)
+ name
+ meta.require.ruby
+ patterns
+
+
+ include
+ $self
+
+
+
+
+ captures
+
+ 1
+
+ name
+ punctuation.definition.variable.ruby
+
+
+ match
+ (@)[a-zA-Z_]\w*
+ name
+ variable.other.readwrite.instance.ruby
+
+
+ captures
+
+ 1
+
+ name
+ punctuation.definition.variable.ruby
+
+
+ match
+ (@@)[a-zA-Z_]\w*
+ name
+ variable.other.readwrite.class.ruby
+
+
+ captures
+
+ 1
+
+ name
+ punctuation.definition.variable.ruby
+
+
+ match
+ (\$)[a-zA-Z_]\w*
+ name
+ variable.other.readwrite.global.ruby
+
+
+ captures
+
+ 1
+
+ name
+ punctuation.definition.variable.ruby
+
+
+ match
+ (\$)(!|@|&|`|'|\+|\d+|~|=|/|\\|,|;|\.|<|>|_|\*|\$|\?|:|"|-[0adFiIlpv])
+ name
+ variable.other.readwrite.global.pre-defined.ruby
+
+
+ begin
+ \b(ENV)\[
+ beginCaptures
+
+ 1
+
+ name
+ variable.other.constant.ruby
+
+
+ end
+ \]
+ name
+ meta.environment-variable.ruby
+ patterns
+
+
+ include
+ $self
+
+
+
+
+ match
+ \b[A-Z]\w*(?=((\.|::)[A-Za-z]|\[))
+ name
+ support.class.ruby
+
+
+ match
+ \b[A-Z]\w*\b
+ name
+ variable.other.constant.ruby
+
+
+ begin
+ (?x)
+ (?=def\b) # an optimization to help Oniguruma fail fast
+ (?<=^|\s)(def)\s+ # the def keyword
+ ( (?>[a-zA-Z_]\w*(?>\.|::))? # a method name prefix
+ (?>[a-zA-Z_]\w*(?>[?!]|=(?!>))? # the method name
+ |===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?) ) # …or an operator method
+ \s*(\() # the openning parenthesis for arguments
+
+ beginCaptures
+
+ 1
+
+ name
+ keyword.control.def.ruby
+
+ 2
+
+ name
+ entity.name.function.ruby
+
+ 3
+
+ name
+ punctuation.definition.parameters.ruby
+
+
+ comment
+ the method pattern comes from the symbol pattern, see there for a explaination
+ contentName
+ variable.parameter.function.ruby
+ end
+ \)
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.parameters.ruby
+
+
+ name
+ meta.function.method.with-arguments.ruby
+ patterns
+
+
+ include
+ $self
+
+
+
+
+ begin
+ (?x)
+ (?=def\b) # an optimization to help Oniguruma fail fast
+ (?<=^|\s)(def)\s+ # the def keyword
+ ( (?>[a-zA-Z_]\w*(?>\.|::))? # a method name prefix
+ (?>[a-zA-Z_]\w*(?>[?!]|=(?!>))? # the method name
+ |===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?) ) # …or an operator method
+ [ \t] # the space separating the arguments
+ (?=[ \t]*[^\s#;]) # make sure arguments and not a comment follow
+
+ beginCaptures
+
+ 1
+
+ name
+ keyword.control.def.ruby
+
+ 2
+
+ name
+ entity.name.function.ruby
+
+
+ comment
+ same as the previous rule, but without parentheses around the arguments
+ contentName
+ variable.parameter.function.ruby
+ end
+ $
+ name
+ meta.function.method.with-arguments.ruby
+ patterns
+
+
+ include
+ $self
+
+
+
+
+ captures
+
+ 1
+
+ name
+ keyword.control.def.ruby
+
+ 3
+
+ name
+ entity.name.function.ruby
+
+
+ comment
+ the optional name is just to catch the def also without a method-name
+ match
+ (?x)
+ (?=def\b) # an optimization to help Oniguruma fail fast
+ (?<=^|\s)(def)\b # the def keyword
+ ( \s+ # an optional group of whitespace followed by…
+ ( (?>[a-zA-Z_]\w*(?>\.|::))? # a method name prefix
+ (?>[a-zA-Z_]\w*(?>[?!]|=(?!>))? # the method name
+ |===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?) ) )? # …or an operator method
+
+ name
+ meta.function.method.without-arguments.ruby
+
+
+ match
+ \b(0[xX]\h(?>_?\h)*|\d(?>_?\d)*(\.(?![^[:space:][:digit:]])(?>_?\d)*)?([eE][-+]?\d(?>_?\d)*)?|0[bB][01]+)\b
+ name
+ constant.numeric.ruby
+
+
+ begin
+ :'
+ captures
+
+ 0
+
+ name
+ punctuation.definition.constant.ruby
+
+
+ end
+ '
+ name
+ constant.other.symbol.single-quoted.ruby
+ patterns
+
+
+ match
+ \\['\\]
+ name
+ constant.character.escape.ruby
+
+
+
+
+ begin
+ :"
+ captures
+
+ 0
+
+ name
+ punctuation.definition.constant.ruby
+
+
+ end
+ "
+ name
+ constant.other.symbol.double-quoted.ruby
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ comment
+ Needs higher precidence than regular expressions.
+ match
+ (?<!\()/=
+ name
+ keyword.operator.assignment.augmented.ruby
+
+
+ begin
+ '
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ single quoted string (does not allow interpolation)
+ end
+ '
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.quoted.single.ruby
+ patterns
+
+
+ match
+ \\'|\\\\
+ name
+ constant.character.escape.ruby
+
+
+
+
+ begin
+ "
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ double quoted string (allows for interpolation)
+ end
+ "
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.quoted.double.ruby
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ `
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ execute string (allows for interpolation)
+ end
+ `
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.interpolated.ruby
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ %x\{
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ execute string (allow for interpolation)
+ end
+ \}
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.interpolated.ruby
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+ include
+ #nest_curly_i
+
+
+
+
+ begin
+ %x\[
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ execute string (allow for interpolation)
+ end
+ \]
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.interpolated.ruby
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+ include
+ #nest_brackets_i
+
+
+
+
+ begin
+ %x\<
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ execute string (allow for interpolation)
+ end
+ \>
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.interpolated.ruby
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+ include
+ #nest_ltgt_i
+
+
+
+
+ begin
+ %x\(
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ execute string (allow for interpolation)
+ end
+ \)
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.interpolated.ruby
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+ include
+ #nest_parens_i
+
+
+
+
+ begin
+ %x([^\w])
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ execute string (allow for interpolation)
+ end
+ \1
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.interpolated.ruby
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ (?x)
+ (?:
+ ^ # beginning of line
+ | (?<= # or look-behind on:
+ [=>~(?:\[,|&;]
+ | [\s;]if\s # keywords
+ | [\s;]elsif\s
+ | [\s;]while\s
+ | [\s;]unless\s
+ | [\s;]when\s
+ | [\s;]assert_match\s
+ | [\s;]or\s # boolean opperators
+ | [\s;]and\s
+ | [\s;]not\s
+ | [\s.]index\s # methods
+ | [\s.]scan\s
+ | [\s.]sub\s
+ | [\s.]sub!\s
+ | [\s.]gsub\s
+ | [\s.]gsub!\s
+ | [\s.]match\s
+ )
+ | (?<= # or a look-behind with line anchor:
+ ^when\s # duplication necessary due to limits of regex
+ | ^if\s
+ | ^elsif\s
+ | ^while\s
+ | ^unless\s
+ )
+ )
+ \s*((/))(?![*+{}?])
+
+ captures
+
+ 1
+
+ name
+ string.regexp.classic.ruby
+
+ 2
+
+ name
+ punctuation.definition.string.ruby
+
+
+ comment
+ regular expressions (normal)
+ we only start a regexp if the character before it (excluding whitespace)
+ is what we think is before a regexp
+
+ contentName
+ string.regexp.classic.ruby
+ end
+ ((/[eimnosux]*))
+ patterns
+
+
+ include
+ #regex_sub
+
+
+
+
+ begin
+ %r\{
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ regular expressions (literal)
+ end
+ \}[eimnosux]*
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.regexp.mod-r.ruby
+ patterns
+
+
+ include
+ #regex_sub
+
+
+ include
+ #nest_curly_r
+
+
+
+
+ begin
+ %r\[
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ regular expressions (literal)
+ end
+ \][eimnosux]*
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.regexp.mod-r.ruby
+ patterns
+
+
+ include
+ #regex_sub
+
+
+ include
+ #nest_brackets_r
+
+
+
+
+ begin
+ %r\(
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ regular expressions (literal)
+ end
+ \)[eimnosux]*
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.regexp.mod-r.ruby
+ patterns
+
+
+ include
+ #regex_sub
+
+
+ include
+ #nest_parens_r
+
+
+
+
+ begin
+ %r\<
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ regular expressions (literal)
+ end
+ \>[eimnosux]*
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.regexp.mod-r.ruby
+ patterns
+
+
+ include
+ #regex_sub
+
+
+ include
+ #nest_ltgt_r
+
+
+
+
+ begin
+ %r([^\w])
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ regular expressions (literal)
+ end
+ \1[eimnosux]*
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.regexp.mod-r.ruby
+ patterns
+
+
+ include
+ #regex_sub
+
+
+
+
+ begin
+ %[QWSR]?\(
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ literal capable of interpolation ()
+ end
+ \)
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.quoted.other.literal.upper.ruby
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+ include
+ #nest_parens_i
+
+
+
+
+ begin
+ %[QWSR]?\[
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ literal capable of interpolation []
+ end
+ \]
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.quoted.other.literal.upper.ruby
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+ include
+ #nest_brackets_i
+
+
+
+
+ begin
+ %[QWSR]?\<
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ literal capable of interpolation <>
+ end
+ \>
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.quoted.other.literal.upper.ruby
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+ include
+ #nest_ltgt_i
+
+
+
+
+ begin
+ %[QWSR]?\{
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ literal capable of interpolation -- {}
+ end
+ \}
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.quoted.double.ruby.mod
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+ include
+ #nest_curly_i
+
+
+
+
+ begin
+ %[QWSR]([^\w])
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ literal capable of interpolation -- wildcard
+ end
+ \1
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.quoted.other.literal.upper.ruby
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ %([^\w\s=])
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ literal capable of interpolation -- wildcard
+ end
+ \1
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.quoted.other.literal.other.ruby
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ %[qws]\(
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ literal incapable of interpolation -- ()
+ end
+ \)
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.quoted.other.literal.lower.ruby
+ patterns
+
+
+ match
+ \\\)|\\\\
+ name
+ constant.character.escape.ruby
+
+
+ include
+ #nest_parens
+
+
+
+
+ begin
+ %[qws]\<
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ literal incapable of interpolation -- <>
+ end
+ \>
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.quoted.other.literal.lower.ruby
+ patterns
+
+
+ match
+ \\\>|\\\\
+ name
+ constant.character.escape.ruby
+
+
+ include
+ #nest_ltgt
+
+
+
+
+ begin
+ %[qws]\[
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ literal incapable of interpolation -- []
+ end
+ \]
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.quoted.other.literal.lower.ruby
+ patterns
+
+
+ match
+ \\\]|\\\\
+ name
+ constant.character.escape.ruby
+
+
+ include
+ #nest_brackets
+
+
+
+
+ begin
+ %[qws]\{
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ literal incapable of interpolation -- {}
+ end
+ \}
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.quoted.other.literal.lower.ruby
+ patterns
+
+
+ match
+ \\\}|\\\\
+ name
+ constant.character.escape.ruby
+
+
+ include
+ #nest_curly
+
+
+
+
+ begin
+ %[qws]([^\w])
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ literal incapable of interpolation -- wildcard
+ end
+ \1
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.quoted.other.literal.lower.ruby
+ patterns
+
+
+ comment
+ Cant be named because its not neccesarily an escape.
+ match
+ \\.
+
+
+
+
+ captures
+
+ 1
+
+ name
+ punctuation.definition.constant.ruby
+
+
+ comment
+ symbols
+ match
+ (?<!:)(:)(?>[a-zA-Z_]\w*(?>[?!]|=(?![>=]))?|===?|>[>=]?|<[<=]?|<=>|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?|@@?[a-zA-Z_]\w*)
+ name
+ constant.other.symbol.ruby
+
+
+ captures
+
+ 1
+
+ name
+ punctuation.definition.constant.ruby
+
+
+ comment
+ symbols
+ match
+ (?>[a-zA-Z_]\w*(?>[?!])?)(:)(?!:)
+ name
+ constant.other.symbol.ruby.19syntax
+
+
+ begin
+ ^=begin
+ captures
+
+ 0
+
+ name
+ punctuation.definition.comment.ruby
+
+
+ comment
+ multiline comments
+ end
+ ^=end
+ name
+ comment.block.documentation.ruby
+
+
+ captures
+
+ 1
+
+ name
+ punctuation.definition.comment.ruby
+
+
+ match
+ (?:^[ \t]+)?(#).*$\n?
+ name
+ comment.line.number-sign.ruby
+
+
+ comment
+
+ matches questionmark-letters.
+
+ examples (1st alternation = hex):
+ ?\x1 ?\x61
+
+ examples (2nd alternation = octal):
+ ?\0 ?\07 ?\017
+
+ examples (3rd alternation = escaped):
+ ?\n ?\b
+
+ examples (4th alternation = meta-ctrl):
+ ?\C-a ?\M-a ?\C-\M-\C-\M-a
+
+ examples (4th alternation = normal):
+ ?a ?A ?0
+ ?* ?" ?(
+ ?. ?#
+
+
+ the negative lookbehind prevents against matching
+ p(42.tainted?)
+
+ match
+ (?<!\w)\?(\\(x\h{1,2}(?!\h)\b|0[0-7]{0,2}(?![0-7])\b|[^x0MC])|(\\[MC]-)+\w|[^\s\\])
+ name
+ constant.numeric.ruby
+
+
+ begin
+ ^__END__\n
+ captures
+
+ 0
+
+ name
+ string.unquoted.program-block.ruby
+
+
+ comment
+ __END__ marker
+ contentName
+ text.plain
+ end
+ (?=not)impossible
+ patterns
+
+
+ begin
+ (?=<?xml|<(?i:html\b)|!DOCTYPE (?i:html\b))
+ end
+ (?=not)impossible
+ name
+ text.html.embedded.ruby
+ patterns
+
+
+ include
+ text.html.basic
+
+
+
+
+
+
+ begin
+ (?><<-("?)((?:[_\w]+_|)HTML)\b\1)
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ heredoc with embedded HTML and indented terminator
+ contentName
+ text.html.embedded.ruby
+ end
+ \s*\2$
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.unquoted.embedded.html.ruby
+ patterns
+
+
+ include
+ #heredoc
+
+
+ include
+ text.html.basic
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ (?><<-("?)((?:[_\w]+_|)SQL)\b\1)
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ heredoc with embedded SQL and indented terminator
+ contentName
+ text.sql.embedded.ruby
+ end
+ \s*\2$
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.unquoted.embedded.sql.ruby
+ patterns
+
+
+ include
+ #heredoc
+
+
+ include
+ source.sql
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ (?><<-("?)((?:[_\w]+_|)CSS)\b\1)
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ heredoc with embedded css and intented terminator
+ contentName
+ text.css.embedded.ruby
+ end
+ \s*\2$
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.unquoted.embedded.css.ruby
+ patterns
+
+
+ include
+ #heredoc
+
+
+ include
+ source.css
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ (?><<-("?)((?:[_\w]+_|)CPP)\b\1)
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ heredoc with embedded c++ and intented terminator
+ contentName
+ text.c++.embedded.ruby
+ end
+ \s*\2$
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.unquoted.embedded.cplusplus.ruby
+ patterns
+
+
+ include
+ #heredoc
+
+
+ include
+ source.c++
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ (?><<-("?)((?:[_\w]+_|)C)\b\1)
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ heredoc with embedded c++ and intented terminator
+ contentName
+ text.c.embedded.ruby
+ end
+ \s*\2$
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.unquoted.embedded.c.ruby
+ patterns
+
+
+ include
+ #heredoc
+
+
+ include
+ source.c
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ (?><<-("?)((?:[_\w]+_|)(?:JS|JAVASCRIPT))\b\1)
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ heredoc with embedded javascript and intented terminator
+ contentName
+ text.js.embedded.ruby
+ end
+ \s*\2$
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.unquoted.embedded.js.ruby
+ patterns
+
+
+ include
+ #heredoc
+
+
+ include
+ source.js
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ (?><<-("?)((?:[_\w]+_|)JQUERY)\b\1)
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ heredoc with embedded javascript and intented terminator
+ contentName
+ text.js.jquery.embedded.ruby
+ end
+ \s*\2$
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.unquoted.embedded.js.jquery.ruby
+ patterns
+
+
+ include
+ #heredoc
+
+
+ include
+ source.js.jquery
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ (?><<-("?)((?:[_\w]+_|)(?:SH|SHELL))\b\1)
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ heredoc with embedded shell and intented terminator
+ contentName
+ text.shell.embedded.ruby
+ end
+ \s*\2$
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.unquoted.embedded.shell.ruby
+ patterns
+
+
+ include
+ #heredoc
+
+
+ include
+ source.shell
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ (?><<-("?)((?:[_\w]+_|)RUBY)\b\1)
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ heredoc with embedded ruby and intented terminator
+ contentName
+ text.ruby.embedded.ruby
+ end
+ \s*\2$
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.unquoted.embedded.ruby.ruby
+ patterns
+
+
+ include
+ #heredoc
+
+
+ include
+ source.ruby
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ (?>\=\s*<<(\w+))
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ end
+ ^\1$
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.unquoted.heredoc.ruby
+ patterns
+
+
+ include
+ #heredoc
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ (?><<-(\w+))
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.begin.ruby
+
+
+ comment
+ heredoc with indented terminator
+ end
+ \s*\1$
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.string.end.ruby
+
+
+ name
+ string.unquoted.heredoc.ruby
+ patterns
+
+
+ include
+ #heredoc
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ (?<=\{|do|\{\s|do\s)(\|)
+ captures
+
+ 1
+
+ name
+ punctuation.separator.variable.ruby
+
+
+ end
+ (\|)
+ patterns
+
+
+ match
+ [_a-zA-Z][_a-zA-Z0-9]*
+ name
+ variable.other.block.ruby
+
+
+ match
+ ,
+ name
+ punctuation.separator.variable.ruby
+
+
+
+
+ match
+ =>
+ name
+ punctuation.separator.key-value
+
+
+ match
+ <<=|%=|&=|\*=|\*\*=|\+=|\-=|\^=|\|{1,2}=|<<
+ name
+ keyword.operator.assignment.augmented.ruby
+
+
+ match
+ <=>|<(?!<|=)|>(?!<|=|>)|<=|>=|===|==|=~|!=|!~|(?<=[ \t])\?
+ name
+ keyword.operator.comparison.ruby
+
+
+ match
+ (?<=[ \t])!+|\bnot\b|&&|\band\b|\|\||\bor\b|\^
+ name
+ keyword.operator.logical.ruby
+
+
+ match
+ (%|&|\*\*|\*|\+|\-|/)
+ name
+ keyword.operator.arithmetic.ruby
+
+
+ match
+ =
+ name
+ keyword.operator.assignment.ruby
+
+
+ match
+ \||~|>>
+ name
+ keyword.operator.other.ruby
+
+
+ match
+ :
+ name
+ punctuation.separator.other.ruby
+
+
+ match
+ \;
+ name
+ punctuation.separator.statement.ruby
+
+
+ match
+ ,
+ name
+ punctuation.separator.object.ruby
+
+
+ match
+ \.|::
+ name
+ punctuation.separator.method.ruby
+
+
+ match
+ \{|\}
+ name
+ punctuation.section.scope.ruby
+
+
+ match
+ \[|\]
+ name
+ punctuation.section.array.ruby
+
+
+ match
+ \(|\)
+ name
+ punctuation.section.function.ruby
+
+
+ repository
+
+ escaped_char
+
+ match
+ \\(?:[0-7]{1,3}|x[\da-fA-F]{1,2}|.)
+ name
+ constant.character.escape.ruby
+
+ heredoc
+
+ begin
+ ^<<-?\w+
+ end
+ $
+ patterns
+
+
+ include
+ $self
+
+
+
+ interpolated_ruby
+
+ patterns
+
+
+ captures
+
+ 0
+
+ name
+ punctuation.section.embedded.ruby
+
+ 1
+
+ name
+ source.ruby.embedded.source.empty
+
+
+ match
+ #\{(\})
+ name
+ source.ruby.embedded.source
+
+
+ begin
+ #\{
+ captures
+
+ 0
+
+ name
+ punctuation.section.embedded.ruby
+
+
+ end
+ \}
+ name
+ source.ruby.embedded.source
+ patterns
+
+
+ include
+ #nest_curly_and_self
+
+
+ include
+ $self
+
+
+
+
+ captures
+
+ 1
+
+ name
+ punctuation.definition.variable.ruby
+
+
+ match
+ (#@)[a-zA-Z_]\w*
+ name
+ variable.other.readwrite.instance.ruby
+
+
+ captures
+
+ 1
+
+ name
+ punctuation.definition.variable.ruby
+
+
+ match
+ (#@@)[a-zA-Z_]\w*
+ name
+ variable.other.readwrite.class.ruby
+
+
+ captures
+
+ 1
+
+ name
+ punctuation.definition.variable.ruby
+
+
+ match
+ (#\$)[a-zA-Z_]\w*
+ name
+ variable.other.readwrite.global.ruby
+
+
+
+ nest_brackets
+
+ begin
+ \[
+ captures
+
+ 0
+
+ name
+ punctuation.section.scope.ruby
+
+
+ end
+ \]
+ patterns
+
+
+ include
+ #nest_brackets
+
+
+
+ nest_brackets_i
+
+ begin
+ \[
+ captures
+
+ 0
+
+ name
+ punctuation.section.scope.ruby
+
+
+ end
+ \]
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+ include
+ #nest_brackets_i
+
+
+
+ nest_brackets_r
+
+ begin
+ \[
+ captures
+
+ 0
+
+ name
+ punctuation.section.scope.ruby
+
+
+ end
+ \]
+ patterns
+
+
+ include
+ #regex_sub
+
+
+ include
+ #nest_brackets_r
+
+
+
+ nest_curly
+
+ begin
+ \{
+ captures
+
+ 0
+
+ name
+ punctuation.section.scope.ruby
+
+
+ end
+ \}
+ patterns
+
+
+ include
+ #nest_curly
+
+
+
+ nest_curly_and_self
+
+ patterns
+
+
+ begin
+ \{
+ captures
+
+ 0
+
+ name
+ punctuation.section.scope.ruby
+
+
+ end
+ \}
+ patterns
+
+
+ include
+ #nest_curly_and_self
+
+
+
+
+ include
+ $self
+
+
+
+ nest_curly_i
+
+ begin
+ \{
+ captures
+
+ 0
+
+ name
+ punctuation.section.scope.ruby
+
+
+ end
+ \}
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+ include
+ #nest_curly_i
+
+
+
+ nest_curly_r
+
+ begin
+ \{
+ captures
+
+ 0
+
+ name
+ punctuation.section.scope.ruby
+
+
+ end
+ \}
+ patterns
+
+
+ include
+ #regex_sub
+
+
+ include
+ #nest_curly_r
+
+
+
+ nest_ltgt
+
+ begin
+ \<
+ captures
+
+ 0
+
+ name
+ punctuation.section.scope.ruby
+
+
+ end
+ \>
+ patterns
+
+
+ include
+ #nest_ltgt
+
+
+
+ nest_ltgt_i
+
+ begin
+ \<
+ captures
+
+ 0
+
+ name
+ punctuation.section.scope.ruby
+
+
+ end
+ \>
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+ include
+ #nest_ltgt_i
+
+
+
+ nest_ltgt_r
+
+ begin
+ \<
+ captures
+
+ 0
+
+ name
+ punctuation.section.scope.ruby
+
+
+ end
+ \>
+ patterns
+
+
+ include
+ #regex_sub
+
+
+ include
+ #nest_ltgt_r
+
+
+
+ nest_parens
+
+ begin
+ \(
+ captures
+
+ 0
+
+ name
+ punctuation.section.scope.ruby
+
+
+ end
+ \)
+ patterns
+
+
+ include
+ #nest_parens
+
+
+
+ nest_parens_i
+
+ begin
+ \(
+ captures
+
+ 0
+
+ name
+ punctuation.section.scope.ruby
+
+
+ end
+ \)
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+ include
+ #nest_parens_i
+
+
+
+ nest_parens_r
+
+ begin
+ \(
+ captures
+
+ 0
+
+ name
+ punctuation.section.scope.ruby
+
+
+ end
+ \)
+ patterns
+
+
+ include
+ #regex_sub
+
+
+ include
+ #nest_parens_r
+
+
+
+ regex_sub
+
+ patterns
+
+
+ include
+ #interpolated_ruby
+
+
+ include
+ #escaped_char
+
+
+ captures
+
+ 1
+
+ name
+ punctuation.definition.arbitrary-repitition.ruby
+
+ 3
+
+ name
+ punctuation.definition.arbitrary-repitition.ruby
+
+
+ match
+ (\{)\d+(,\d+)?(\})
+ name
+ string.regexp.arbitrary-repitition.ruby
+
+
+ begin
+ \[(?:\^?\])?
+ captures
+
+ 0
+
+ name
+ punctuation.definition.character-class.ruby
+
+
+ end
+ \]
+ name
+ string.regexp.character-class.ruby
+ patterns
+
+
+ include
+ #escaped_char
+
+
+
+
+ begin
+ \(
+ captures
+
+ 0
+
+ name
+ punctuation.definition.group.ruby
+
+
+ end
+ \)
+ name
+ string.regexp.group.ruby
+ patterns
+
+
+ include
+ #regex_sub
+
+
+
+
+ captures
+
+ 1
+
+ name
+ punctuation.definition.comment.ruby
+
+
+ comment
+ We are restrictive in what we allow to go after the comment character to avoid false positives, since the availability of comments depend on regexp flags.
+ match
+ (?<=^|\s)(#)\s[[a-zA-Z0-9,. \t?!-][^\x{00}-\x{7F}]]*$
+ name
+ comment.line.number-sign.ruby
+
+
+
+
+ scopeName
+ source.ruby
+ uuid
+ E00B62AC-6B1C-11D9-9B1F-000D93589AF6
+
+
diff --git a/bundles/ruby.tmbundle/Tests/division_ambiguity.rb b/bundles/ruby.tmbundle/Tests/division_ambiguity.rb
new file mode 100644
index 000000000..a20e52a46
--- /dev/null
+++ b/bundles/ruby.tmbundle/Tests/division_ambiguity.rb
@@ -0,0 +1,88 @@
+# purpose:
+# exercise constructs with division
+#
+# division itself 84 / 2
+# regexp /pattern/
+#
+#
+#
+
+def test(*obj)
+ p(*obj)
+end
+a, b = 4, 2
+
+# -------------------------------------------
+#
+# Testarea for division
+#
+# -------------------------------------------
+
+# singleline numbers
+test(84 / 2)
+
+# singleline symbols
+test(a / b)
+
+# singleline symbols
+test(a / b / 3)
+
+
+test(Float(42) / Float(5))
+
+# multiline with symbols
+=begin # invalid
+test(a
+/ b)
+=end
+
+# multiline with symbols
+test(a /
+b)
+
+
+# -------------------------------------------
+#
+# Testarea for regexp
+#
+# -------------------------------------------
+
+# singleline
+test( // )
+test( /abc/ )
+test( /a\/bc/ )
+test [/^F../]
+p 'Foobar'[/^F../]
+p '42' =~ /42/
+test(nil && /\\/ =~ '\\')
+test(nil || /\\/ =~ '\\')
+test(nil and /\\/ =~ '\\')
+test(nil or /\\/ =~ '\\')
+test(/a/x)
+test(/x/.match('abx').to_s)
+test((/x/).match('abx').to_s)
+test(/a/,/b/,/c/)
+test(/a/x,/b/x,/c/m)
+
+
+# multiline
+test( /
+pattern
+/x )
+
+
+# multiline
+test(
+/r
+eg
+e/x
+)
+
+# multiline
+test(
+/1/,/2/,/3/
+)
+
+# regexp after keyword
+res = case 'test';when /t..t/:1;else 0;end
+test(res)
\ No newline at end of file
diff --git a/bundles/ruby.tmbundle/Tests/modulo_ambiguity1.rb b/bundles/ruby.tmbundle/Tests/modulo_ambiguity1.rb
new file mode 100644
index 000000000..2b1b9f717
--- /dev/null
+++ b/bundles/ruby.tmbundle/Tests/modulo_ambiguity1.rb
@@ -0,0 +1,76 @@
+# purpose:
+# exercise constructs with modulo
+#
+# modulo in math data%2
+# literals %(a b), %W[1 2]
+#
+#
+#
+
+def test(v)
+ p v
+end
+
+x, y = 42, 33
+
+
+# -------------------------------------------
+#
+# Testarea for modulo
+#
+# -------------------------------------------
+
+# value % value
+test( 3%2 )
+test( 3 % 2 )
+test( 1234%(666) )
+test( (1234)%666 )
+
+# var % value
+test( x%2 )
+test( x%666 )
+test( x%(42) )
+test( x%-42-3 )
+test( x%+42+3 )
+
+# value % var
+test( 666%x )
+test( (42+4+2)%x )
+
+# var % var
+test( x % y )
+test( x%y )
+
+# -------------------------------------------
+#
+# Testarea for literals
+#
+# -------------------------------------------
+
+# literal with nothing
+test( %(a b c) )
+test( %(1 2 (3 4)) )
+test( %{TM rocks} )
+
+# literal with 'w'
+test( %W(1 2 3) )
+test( %W[1 2 3] )
+test( %W{1 2 3} )
+test( %W<1 2 3> )
+
+# literal with 'w' (multiline)
+test(%w(a
+b))
+
+# literal with 'q'
+test( %q(1 2 3) )
+test( %Q(1 2 3) )
+
+# literal with custom
+test( %q"1 2 3" )
+test( %q'1 2 3' )
+test( %q#1 2 3# )
+test( %?X.tainted? )
+test( %q/1 2 3/ )
+test( %q|1 2 3| )
+test( %q\1 2 3\ )
diff --git a/bundles/ruby.tmbundle/Tests/questionmark_ambiguity1.rb b/bundles/ruby.tmbundle/Tests/questionmark_ambiguity1.rb
new file mode 100644
index 000000000..d571673fa
--- /dev/null
+++ b/bundles/ruby.tmbundle/Tests/questionmark_ambiguity1.rb
@@ -0,0 +1,160 @@
+# purpose:
+# exercise constructs with questionmark
+#
+# numeric letters ?x
+# ternary operator condition ? case1 : case2
+#
+#
+#
+
+def test(v)
+ puts "#{v.inspect} => #{v.chr}"
+end
+def z(v)
+ v
+end
+
+
+
+# -------------------------------------------
+#
+# Testarea for numeric letters
+#
+# -------------------------------------------
+
+# begin of line
+test(
+?x)
+
+# normal letters
+test( ?a )
+test( ?A )
+test( ?0 )
+
+# misc symbols
+test( ?* )
+test( ?**2 )
+test( ?: )
+test( ?) )
+test( ?( )
+test( ?' ) # im a comment, not a string
+test( ?" ) # im a comment, not a string
+test( ?/ ) # im a comment, not a regexp
+
+# symbol '.'
+test( ?..succ )
+p ?...?..succ # im a .. range
+p ?....?..succ # im a ... range
+#p ?.....?..succ # invalid
+
+# symbol '#'
+test( ?# ); p 'im not a comment'
+
+# space ' '
+#test( ? ) # invalid
+
+# tab ' '
+#test( ? ) # invalid
+
+
+# symbol '?'
+test( ?? )
+test(??)
+
+# symbol '\\'
+test( ?\\ )
+
+# escaped as hex
+#test( ?\x ) # invalid
+test( ?\x1 )
+test( ?\x61 )
+#test( ?\x612 ) # invalid
+test( ?\X ) # valid.. but is not hex
+#test( ?\X11 ) # invalid
+
+# escaped as octal
+test( ?\0 )
+test( ?\07 )
+test( ?\017 )
+#test( ?\0173 ) # invalid
+#test( ?\08 ) # invalid
+#test( ?\09 ) # invalid
+#test( ?\0a ) # invalid
+test( ?\1 )
+test( ?\7 )
+test( ?\a )
+test( ?\f )
+
+# standard escapings
+test( ?\n ) # newline
+test( ?\b ) # backspace
+
+# escaped misc letters/symbols
+test( ?\8 )
+test( ?\9 )
+test( ?\_ )
+
+# ctrl/meta escaped
+test( ?\C-a )
+test( ?\C-g )
+test( ?\C-x )
+test( ?\C-A )
+test( ?\C-G )
+test( ?\c )
+test( ?\m )
+#test( ?\c-a ) # invalid
+#test( ?\C ) # invalid
+#test( ?\M ) # invalid
+test( ?\M-a )
+test( ?\M-\C-a )
+test( ?\C-\C-\M-a )
+test( ?\C-\M-a )
+test( ?\C-\M-\M-a )
+test( ?\C-\M-\C-\M-a )
+
+# misc tests
+p 'abc'.include?(?z)
+
+
+
+# -------------------------------------------
+#
+# Testarea for ternary operator
+#
+# -------------------------------------------
+a, b, val = 42, 24, true
+p(val ? 0 : 2)
+
+p [
+ val ? (a) : z(b) ,
+ val ? 'a' : 'b'
+]
+
+
+
+
+# -------------------------------------------
+#
+# Testarea for ternary operator and numeric letter
+#
+# -------------------------------------------
+p [
+
+# very ugly
+true ???:?? ,
+true ???:?: ,
+true ??::?: ,
+]
+
+
+
+# -------------------------------------------
+#
+# Testarea for neiter ternary operator nor numeric letter
+#
+# -------------------------------------------
+
+# not letters.. the questionmark is part of the methodname
+p(42.tainted?, 42.frozen?)
+
+
diff --git a/bundles/ruby.tmbundle/Tests/rubylexer/COPYING b/bundles/ruby.tmbundle/Tests/rubylexer/COPYING
new file mode 100644
index 000000000..b124cf581
--- /dev/null
+++ b/bundles/ruby.tmbundle/Tests/rubylexer/COPYING
@@ -0,0 +1,510 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard. To achieve this, non-free programs must
+be allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least
+ three years, to give the same user the materials specified in
+ Subsection 6a, above, for a charge no more than the cost of
+ performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+
+ Copyright (C)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James
+ Random Hacker.
+
+ , 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/bundles/ruby.tmbundle/Tests/rubylexer/g.rb b/bundles/ruby.tmbundle/Tests/rubylexer/g.rb
new file mode 100644
index 000000000..16df18d19
--- /dev/null
+++ b/bundles/ruby.tmbundle/Tests/rubylexer/g.rb
@@ -0,0 +1,14 @@
+j=9;def i(n) [n ?"d" : "e" , n] end
+
+p(i ?")
+p(j ?"d" : "e")
+
+def g(x=nil) x end
+def gg(x=nil) g x end
+p(gg :x)
+p(g :y)
+g=9
+p(gg :z)
+# g :w #error
+
+
diff --git a/bundles/ruby.tmbundle/Tests/rubylexer/newsyntax.rb b/bundles/ruby.tmbundle/Tests/rubylexer/newsyntax.rb
new file mode 100644
index 000000000..2d06fe082
--- /dev/null
+++ b/bundles/ruby.tmbundle/Tests/rubylexer/newsyntax.rb
@@ -0,0 +1,18 @@
+
+x, (*), z = [:x, :y, :z]
+p x
+p z
+
+x, (*y), z = [:x, :y, :z]
+p x
+p y
+p z
+
+p($/ = ' '; Array( "i'm in your house" ))
+
+class Foou
+ public
+ def [] x=-100,&y=nil; p x; 100 end
+end
+p Foou.new.[]?9 #value
+p Foou.new.[] ?9 #value
diff --git a/bundles/ruby.tmbundle/Tests/rubylexer/p.rb b/bundles/ruby.tmbundle/Tests/rubylexer/p.rb
new file mode 100644
index 000000000..90df69671
--- /dev/null
+++ b/bundles/ruby.tmbundle/Tests/rubylexer/p.rb
@@ -0,0 +1,1122 @@
+p(String *Class)
+class String
+class Class
+end
+end
+#def String(x) x.to_s end #it's already built-in. duh!
+def String.*(right) [self,right] end
+def String.<<(right) [self,:<<,right] end
+def String./(right) [self,:/,right] end
+def String.[](right) [self,:[],right] end
+p(String::Class)
+p(String:: Class)
+p(String ::Class)
+p(String :: Class)
+p(String< p
+end
+
+q=9
+Q=99
+
+p:p8
+false ? p: p8
+p :p8
+false ? p : p8
+
+false ? q:p8
+false ? q: p8
+false ? q :p8
+false ? q : p8
+
+#false ? Q:p8 #gives ruby indigestion
+false ? Q: p8
+#false ? Q :p8 #gives ruby indigestion
+false ? Q : p8
+
+p?:p8
+false ? p?: p8
+p? :p8
+false ? p? : p8
+
+P?:p8
+false ? P?: p8
+P? :p8
+false ? P? : p8
+
+self.[]:p8
+false ? self.[]: p8
+self.[] :p8
+false ? self.[] : p8
+
+self.<=>:p8
+false ? self.<=>: p8
+self.<=> :p8
+false ? self.<=> : p8
+
+self <=>:p8
+#false ? self <=>: p8 #gives ruby indigestion
+self <=> :p8
+#false ? self <=> : p8 #gives ruby indigestion
+end
+
+p <2)
+ p(p >2)
+ p(p> 2)
+ p(p > 2)
+
+end
+
+module M34
+ p(p~6)
+ p(p ~6)
+ p(p~ 6)
+ p(p ~ 6)
+ p(p*[1])
+ p(p *[1])
+ p(p* [1])
+ p(p * [1])
+ p(p&proc{})
+ p(p &proc{})
+ p(p& proc{})
+ p(p & proc{})
+ p(p !1)
+ p(p ?1)
+ p(p ! 1)
+ p(p ? 1 : 6)
+ p(p@a)
+ p(p @a)
+# p(p@ a) #wont
+# p(p @ a) #work
+
+ p(p#a
+)
+ p(p #a
+)
+ p(p# a
+)
+ p(p # a
+)
+ p(p$a)
+ p(p $a)
+# p(p$ a) #wont
+# p(p $ a) #work
+ p(p%Q{:foo})
+ p(p %Q{:foo})
+ p(p% Q{:foo})
+ p(p % Q{:foo})
+ p(p^6)
+ p(p ^6)
+ p(p^ 6)
+ p(p ^ 6)
+ p(p&7)
+ p(p &proc{7})
+ p(p& 7)
+ p(p & 7)
+ p(p(2))
+ p(p (2))
+ p(p( 2))
+ p(p ( 2))
+ p(p(p))
+ p(p())
+ p(p (p))
+ p(p ())
+ p(p ( p))
+ p(p ( ))
+ p(p( p))
+ p(p( ))
+ p(p)
+ p((p))
+ p(p )
+ p((p ))
+ p((p p))
+ p((p p,p))
+ p((p p))
+ p((p p,p))
+ p(p-0)
+ p(p -1)
+ p(p- 0)
+ p(p - 0)
+ p(p+9)
+ p(p +9)
+ p(p+ 9)
+ p(p + 9)
+ p(p[1])
+ p(p [1])
+ p(p[ 1])
+ p(p [ 1])
+ p(p{1})
+ p(p {1})
+ p(p{ 1})
+ p(p { 1})
+ p(p/1)
+ p(p /22/)
+ p(p/ 1)
+ p(p / 22)
+ p(p._)
+ p(p ._)
+ p(p. _)
+ p(p . _)
+ p(p:f)
+ p(p :f)
+ p(false ? p: f)
+ p(false ? p : f)
+ p((p;1))
+ p((p ;1))
+ p((p; 1))
+ p((p ; 1))
+ p(p<1)
+ p(p <1)
+ p(p< 1)
+ p(p < 1)
+ p(p<<1)
+ p(p <<1)
+foobar
+1
+ p(p<< 1)
+ p(p << 1)
+ p(p'j')
+ p(p 'j')
+ p(p' j')
+ p(p ' j')
+ p(p"k")
+ p(p "k")
+ p(p" k")
+ p(p " k")
+ p(p|4)
+ p(p |4)
+ p(p| 4)
+ p(p | 4)
+ p(p>2)
+ p(p >2)
+ p(p> 2)
+ p(p > 2)
+
+end
+
+
+def bob(x) x end
+def bill(x) x end
+p(bob %(22))
+for bob in [100] do p(bob %(22)) end
+p(bob %(22))
+def %(n) to_s+"%#{n}" end
+p(bill %(22))
+begin sdjkfsjkdfsd; rescue Object => bill; p(bill %(22)) end
+p(bill %(22))
+undef %
+
+class Object
+
+public :`
+def `(s)
+ print "bq: #{s}\n"
+end
+end
+
+69.`('what a world')
+
+79::`('what a word')
+
+p :`
+
+p{}
+p {}
+a=5
+p p +5
+p a +5
+
+def nil.+(x) ~x end
+def nil.[](*x) [x] end
+p( p + 5 )
+p( p +5 )
+p( p+5 )
+p( p[] )
+p( p [] )
+p( p [ ] )
+class NilClass; undef +,[] end
+
+class Foou
+ public
+ def [] x=-100,&y; p x; 100 end
+end
+a0=8
+p Foou.new.[]!false #value
+p Foou.new.[] !false #value
+p Foou.new.[]~9 #value
+p Foou.new.[] ~9 #value
+p Foou.new.[]-9 #op
+p Foou.new.[]+9 #op
+p Foou.new.[] -9 #value
+p Foou.new.[] +9 #value
+p Foou.new.[]<<9 #op
+p Foou.new.[] <<9 #value
+foobar
+9
+p Foou.new.[]%9 #op
+p Foou.new.[]/9 #op
+p Foou.new.[] %(9) #value
+p Foou.new.[] /9/ #value
+p Foou.new.[]$9 #value
+p Foou.new.[]a0 #value
+p Foou.new.[] $9 #value
+p Foou.new.[] a0 #value
+p Foou.new.[]{9} #lambda (op)
+p Foou.new.[] {9} #lambda (op)
+
+if p then p end
+
+p({:foo=>:bar}) #why does this work? i'd think that ':foo=' would be 1 token
+p EMPTY = 0
+p BLACK = 1
+p WHITE = - BLACK
+
+ a=b=c=0
+ a ? b:c
+ a ?b:c
+
+ p(a ? b:c)
+ p(a ?b:c)
+
+
+p~4
+p:f
+p(~4){}
+p(:f){}
+h={}
+h.default=:foo
+
+p def (h="foobar").default= v; p @v=v;v end
+p h
+
+p h.default=:b
+
+x, (*y) = [:x, :y, :z]
+p x
+p y
+
+x, *y = [:x, :y, :z]
+p x
+p y
+
+x, * = [:x, :y, :z]
+p x
+
+
+
+p Array("foo\nbar")
+
+
+
+p +(4)
+p -(4)
+
+p :'\\'
+
+class Foop
+ def Foop.bar a,b
+ p a,b
+ end
+end
+Foop.bar 1,2
+Foop::bar 3,4
+
+
+class Foop
+ def Foop::baz a,b
+ p :baz,a,b
+ end
+end
+Foop.baz 5,6
+Foop::baz 7,8
+
+
+
+without_creating=widgetname=nil
+ if without_creating && !widgetname #foo
+ fail ArgumentError,
+ "if set 'without_creating' to true, need to define 'widgetname'"
+ end
+
+
+
+=begin disable for now
+
+#class, module, and def should temporarily hide local variables
+def mopsdfjskdf arg; arg*2 end
+mopsdfjskdf=5
+ class C
+ p mopsdfjskdf %(3) #calls method
+ end
+
+module M
+ p mopsdfjskdf %(4) #calls method
+end
+
+ def d
+ p mopsdfjskdf %(5) #calls method
+ end
+p d
+p mopsdfjskdf %(6) #reads variable
+p proc{mopsdfjskdf %(7)}[] #reads variable
+
+#fancy symbols not supported yet
+p %s{symbol}
+=end
+
+#multiple assignment test
+proc {
+ a,b,c,d,e,f,g,h,i,j,k=1,2,3,4,5,6,7,8,9,10,11
+ p(b %(c))
+ p(a %(c))
+ p(k %(c))
+ p(p %(c))
+}.call
+
+
+=begin disable for now
+p "#{<~m)
+
+p <(foo=100)}
+ p( foo %(5))
+}.call
+
+
+p "#{<"PMK:njs;d|
+
+foobar0
+
+p "#{<"PMK:njs;d|
+
+foobar1
+}"
+
+def foo(a=<>|\|\||\&\&)=|\&\&|\|\|)/)
+p(:%)
+p( { :class => class_=0})
+p cls_name = {}[:class]
+
+
+p foo
+p "#{$!.class}"
+p :p
+p(:p)
+p(:"[]")
+p :"[]"
+p("\\")
+p(/\\/)
+p(/[\\]/)
+p 0x80
+p ?p
+p 0.1
+p 0.8
+p 0.9
+p(-1)
+p %/p/
+p %Q[]
+i=99
+p %Q[ #{i[0]+i[1]+(i[2])}\n]
+p(:side=>:top)
+p %w[a b c
+ d e f]
+p %w[a b c\n
+ d e f]
+p %w[\\]
+p %w[\]]
+p :+
+p 99 / 3
+
+a=99;b=3
+p 1+(a / b)
+p %Q[\"]
+p %Q[ some [nested] text]
+
+if false
+ formatter.format_element(element) do
+ amrita_expand_and_format1(element, context, formatter)
+ end
+end
+if false
+ ret = <<-END
+ @@parts_template = #{template.to_ruby}
+ def parts_template
+ @@parts_template
+ end
+
+ #{c.const_def_src.join("\n")}
+ def amrita_expand_and_format(element, context, formatter)
+ if element.tagname_symbol == :span and element.attrs.size == 0
+ amrita_expand_and_format1(element, context, formatter)
+ else
+ formatter.format_element(element) do
+ amrita_expand_and_format1(element, context, formatter)
+ end
+ end
+ end
+
+ def amrita_expand_and_format1(element, context, formatter)
+ #{method_src}
+ end
+ END
+ j=55
+end
+
+p '
+'
+p '\n'
+p "
+"
+p "\n"
+p %w/
+/
+p %w/\n/
+
+p %W/
+/
+p %W/\n/
+p(/
+/)
+p(/\n/)
+p proc {
+ p `
+ `
+ p `\n`
+}
+
+
+
+p(%r[foo]i)
+#breakpoint
+p <:b), {:a=>:b} #=> true
+ assert_ene Reg(:a=>:b), {:a=>:c} #=> false
+ assert_ene Reg(:a=>:b), {} #=> false
+ h={}
+ h.default=:b
+ assert_eee Reg(:a=>:b), h #=> true
+
+ assert_eee Reg(/^(a|b)$/=>33), {"a"=>33} #=> true
+ assert_eee Reg(/^(a|b)$/=>33), {"b"=>33} #=> true
+ assert_ene Reg(/^(a|b)$/=>33), {"a"=>133} #=> false
+ assert_ene Reg(/^(a|b)$/=>33), {"b"=>133} #=> false
+
+ assert_ene Reg(/^(a|b)$/=>33), {"c"=>33} #=> false
+
+ assert_eee Reg(/^(a|b)$/=>33), {"a"=>33,"b"=>33} #=> true
+ assert_ene Reg(/^(a|b)$/=>33), {"a"=>33,"b"=>133} #=> false
+ assert_ene Reg(/^(a|b)$/=>33), {"a"=>133,"b"=>33} #=> false
+ assert_ene Reg(/^(a|b)$/=>33), {"a"=>133,"b"=>133} #=> false
+
+
+ assert_eee Reg("a"=>33)|{"b"=>33}, {"a"=>33,"b"=>33} #=> true
+ assert_eee Reg("a"=>33)|{"b"=>33}, {"a"=>33,"b"=>133} #=> true
+ assert_ene Reg("a"=>33)|{"b"=>33}, {"a"=>133,"b"=>33} #=> false
+ assert_ene Reg("a"=>33)|{"b"=>33}, {"a"=>133,"b"=>133} #=> false
+
+ assert_eee Reg("a"=>33)|{"b"=>33}, {"b"=>33} #=> true
+
+ assert_eee Reg(:a.reg|:b => 44), {:a => 44} #=> true
+ assert_eee Reg(:a.reg|:b => 44), {:b => 44} #=> true
+ assert_ene Reg(:a.reg|:b => 44), {:a => 144} #=> false
+ assert_ene Reg(:a.reg|:b => 44), {:b => 144} #=> false
+
+ print "\n"
+ end
+
+ def assert_eee(left,right,message='assert_eee failed')
+ assert(
+ left===right,
+ message+" left=#{left.inspect} right=#{right.inspect}"
+ )
+ print ".";$stdout.flush
+ end
+
+ def assert_ene(left,right,message='assert_ene failed')
+ assert(
+ !(left===right),
+ message+" left=#{left.inspect} right=#{right.inspect}"
+ )
+ print ",";$stdout.flush
+ end
+end
+end
+ srand;seed=srand
+
+ opts=GetoptLong.new(["--seed", "-s", GetoptLong::REQUIRED_ARGUMENT])
+ opts.each{|opt,arg|
+ opt=='--seed' or raise :impossible
+ seed=arg
+ }
+
+ print "random seed is #{seed}\n"
+ srand seed
+
+
+TC_Reg.test_reg
diff --git a/bundles/ruby.tmbundle/Tests/rubylexer/w.rb b/bundles/ruby.tmbundle/Tests/rubylexer/w.rb
new file mode 100644
index 000000000..56de46332
--- /dev/null
+++ b/bundles/ruby.tmbundle/Tests/rubylexer/w.rb
@@ -0,0 +1,22 @@
+p %r{\/$}
+p %r~~m
+
+p [].push *[1,2,3]
+p /\n/
+
+$a=1
+@b=2
+@@c=3
+p(/\#$a \#@b \#@@c \#{$a+@b+@@c}/)
+
+
+class Foo
+attr :foo,true
+end
+f=Foo.new
+p f.foo
+p f.foo=9
+p f.foo =19
+p f.foo= 29
+p f.foo = 39
+p f.foo
diff --git a/bundles/ruby.tmbundle/Tests/test1.rb b/bundles/ruby.tmbundle/Tests/test1.rb
new file mode 100644
index 000000000..98a0965ba
--- /dev/null
+++ b/bundles/ruby.tmbundle/Tests/test1.rb
@@ -0,0 +1,302 @@
+# Ruby syntax test file for stuff we've gotten wrong in the past or are currently getting wrong
+
+#########
+#basics
+
+module samwi_78se
+
+ class mysuperclassofdoom < someotherclass
+
+ end
+end
+
+class gallo_way8 < kni9_ght
+
+ def sl_9ay(beast)
+
+ end
+
+ #These shouldn't capture the leading space before it
+ def my_method_of_doom(args)
+ 'yay'
+ rescue
+ 'whatever'
+ ensure
+ 'something else'
+ end
+
+ def my_method_of_doom(args);'yay';rescue;'whatever';ensure;'something else';end
+
+ #The indent here should not be broken
+
+end
+
+
+def hot?(cold)
+
+end
+
+def w00t!
+
+ unless l33t
+ sysbeep
+ end
+
+end
+
+###########
+# method names
+
+# method names can be keywords and should not be highlighted if they appear as explicit method invocations
+br = m.end(0) + b1
+x, y = b2vxay(m.begin(0) + b1)
+stream.next
+self.class
+
+
+# keyword.operator
+
+var1 == var2
+var1 === var2
+var1 =~ var2
+var1 = var2
+var1 * var2
+var1 - var2
+var1 + var2
+var1 % var2
+var1 ^ var2
+var1 & var2
+var1 * var2
+
+# Method
+u.whatever + 'something'
+u.whatever + ('something')
+u.whatever +( 'something')
+u.whatever+ 'something'
+u.whatever+ ('something')
+u.whatever+( 'something')
+
+u.whatever = 'something'
+u.whatever = ('something')
+u.whatever =( 'something')
+u.whatever= 'something'
+u.whatever= ('something')
+u.whatever=( 'something')
+
+u.whatever = 12345
+u.whatever = (12345)
+u.whatever =( 12345)
+u.whatever= 12345
+u.whatever= (12345)
+u.whatever=( 12345)
+u.whatever =12345
+u.whatever=12345
+
+u.whatever == 'something'
+u.whatever == ('something')
+u.whatever ==( 'something')
+u.whatever== 'something'
+u.whatever== ('something')
+u.whatever==( 'something')
+
+u.whatever === 'something'
+u.whatever === ('something')
+u.whatever ===( 'something')
+u.whatever=== 'something'
+u.whatever=== ('something')
+u.whatever===( 'something')
+
+u.password = 'something'
+u.password = ('something')
+u.password =( 'something')
+u.password= 'something'
+u.password= ('something')
+u.password=( 'something')
+
+u.abort_on_exception = 'something'
+u.abort_on_exception = ('something')
+u.abort_on_exception =( 'something')
+u.abort_on_exception= 'something'
+u.abort_on_exception= ('something')
+u.abort_on_exception=( 'something')
+
+u.success ? 'something' : 'something else'
+u.success ? ('something') : ('something else')
+u.success ?( 'something') :( 'something else') #?( shouldn't be scoped as constant.numeric
+u.success? 'something' : 'something else'
+u.success? ('something') : ('something else')
+u.success?( 'something') :( 'something else')
+
+# Function
+whatever = 'something'
+whatever = ('something')
+whatever =( 'something')
+whatever= 'something'
+whatever= ('something')
+whatever=( 'something')
+
+password = 'something'
+password = ('something')
+password =( 'something')
+password= 'something'
+password= ('something')
+password=( 'something')
+
+
+# this Totally kills Ruby Experimental ATM (Mon Jan 29 10:38:00 EST 2007)
+
+fred( )fred()
+fred( ) fred()
+fred( ).fred()
+fred() .fred()
+fred.fred()
+
+# /kills
+
+# method calls no dot or round brackets
+puts "shmoo"
+foo {}
+foo bar
+
+# Regular Variables
+foo
+bar
+foo = 1
+foo = bar
+
+
+############
+# numbers
+
+data += 0.chr
+99.downto(0)
+
+0.9 # number
+0.A # method invocation (0 -> A)
+0.A() # method invocation (0 -> A)
+0xCAFEBABE022409ad802046 # hex
+23402 # integer
+4.232 # decimal
+
+
+###########
+# strings
+
+'hello #{42} wor\'knjkld' # no interpolation or escapes except for slash-single-quote
+
+# double quoted string (allows for interpolation):
+"hello #{42} world" #-> "hello 42 world"
+"hello #@ivar world" #-> "hello 42 world"
+"hello #@@cvar world" #-> "hello 42 world"
+"hello #$gvar world" #-> "hello 42 world"
+
+'hello #@ivar world'
+'hello #@@cvar world'
+'hello #$gvar world'
+
+# escapes
+"hello #$gvar \"world" #-> "hello 42 \"world"
+
+# execute string (allows for interpolation):
+%x{ls #{dir}} #-> ".\n..\nREADME\nmain.rb"
+`ls #{dir}` #-> ".\n..\nREADME\nmain.rb"
+
+%Q{dude #{hey}}
+%Q!dude#{hey}!
+%W(dude#{hey})
+%q!dude#{hey}!
+%s{dude#{hey}}
+%w{dude#{hey}}
+%{woah#{hey}}
+% woah#{hey}
+
+# mod operator should not be interpreted as a string operator
+# (space as delimiter is legal Ruby: '% string ' => "string")
+if (data.size % 2) == 1
+line << ('%3s ' % str)
+
+
+###########
+# regexp
+
+/matchmecaseinsensitive/i
+/matchme/
+/ matchme /
+%r{matchme}
+
+32/23 #division, not regexp
+
+32 / 32 #division, not regexp
+
+gsub!(/ +/, '') #regexp, not division
+
+###########
+# symbols
+
+:BIG :aBC :AbC9 :symb :_asd :_9sd :__= :f00bar :abc!
+ :abc? :abc= :<< :< :>> :> :<=> :<= :>= :% :* :**
+ :+ :- :& :| :~ :=~ :== :=== :` :[]= :[] :/ :-@
+ :+@ :@aaa :@@bbb
+
+# else clause of ternary logic should not highlight as symbol
+val?(a):p(b)
+val?'a':'b'
+M[1]?(a+b):p(c+d)
+
+val ? (a) : p(b)
+val ? 'a' : 'b'
+M[1] ? (a+b) : p(c+d)
+
+# but we must also account for ? in method names
+thing.fred?(:someone)
+thing.fred? :someone
+thing.fred? thing2, :someone
+
+begin = {"(?=\\w)\\s*\\?:"}
+
+
+############
+#literal capable of interpolation:
+%W(a b#{42}c) #-> ["a", "b42c"]
+%W(ab c\nd \\\)ef)
+
+%(#{42}) #-> "42"
+
+
+############
+# multiline comments
+
+=begin
+stuff here
+... def must_not_highlight_keywords_in_comments end;
+stuff here too
+=end
+
+
+############
+#literal incapable of interpolation
+%w(a b#{42}c) #-> ["a", "b#{42}c"]############
+%w(ab c\nd \\\)ef) # heredoc tests
+
+append << not_heredoc
+
+heredoc = <
+
+
+
+ contactEmailRot13
+ wnzrf@tenlcebqhpgvbaf.arg
+ contactName
+ James Edward Gray II
+ deleted
+
+ 3988A501-119E-4C0E-A584-C5E75FC2D6C6
+ 8C102BE9-6E49-11D9-A933-000D93589AF6
+ EE5F1AE5-6C02-11D9-92BA-0011242E4184
+ 8394EDEF-87E8-11D9-A6A3-000D93589AF6
+ BE3B3E5E-733E-11D9-A833-000A95A89C98
+ 66708792-62C3-11D9-B8CF-000D93589AF6
+ 667089D2-62C3-11D9-B8CF-000D93589AF6
+ 667080D9-62C3-11D9-B8CF-000D93589AF6
+ 667081DE-62C3-11D9-B8CF-000D93589AF6
+ 66708259-62C3-11D9-B8CF-000D93589AF6
+ 66708052-62C3-11D9-B8CF-000D93589AF6
+ 6670881E-62C3-11D9-B8CF-000D93589AF6
+ 7990EE60-C850-4779-A8C0-7FD2C853B99B
+
+ description
+ Support for the <a href="http://www.ruby-lang.org/">Ruby</a> programming language.
+ mainMenu
+
+ excludedItems
+
+ E5158F94-CC52-4424-A495-14EF9272653F
+ EEE6D060-C5A0-400D-A2E0-0835013C5365
+ 76FCF165-54CB-4213-BC55-BD60B9C6A3EC
+ 6519CB08-8326-4B77-A251-54722FFBFC1F
+ 835FAAC6-5431-436C-998B-241F7226B99B
+ A83F68A9-F751-4BB4-AE16-56812878C16A
+ 47D203ED-EB9B-4653-A07B-A897800CEB76
+
+ items
+
+ 35222962-C50D-4D58-A6AE-71E7AD980BE4
+ 5289EE40-86B8-11D9-A8D4-000A95E13C98
+ ------------------------------------
+ 63F3B3B7-CBE2-426B-B551-657733F3868B
+ 6EA7AE06-3EA9-497D-A6DE-732DE43DA6E9
+ ------------------------------------
+ 8646378E-91F5-4771-AC7C-43FC49A93576
+ EE5F19BA-6C02-11D9-92BA-0011242E4184
+ ------------------------------------
+ EE5F1FB2-6C02-11D9-92BA-0011242E4184
+ FBFC214F-B019-4967-95D2-028F374A3221
+ 88BC3896-DC39-4307-A271-21D33340F15A
+ ------------------------------------
+ 9FB64639-F776-499B-BA6F-BB45F86F80FD
+ 7F79BC8D-8A4F-4570-973B-05DFEC25747F
+ B297E4B8-A8FF-49CE-B9C4-6D4911724D43
+ FDFABCB9-DF58-4469-AE11-5407A4FF4D70
+ ------------------------------------
+ A1433C73-A475-4B9F-8B46-E182C588ED7D
+ D52AE6E7-DB75-46C9-94B0-F90B186BE1B2
+ B32BD8CF-903E-42D9-B1D3-44F88F262134
+ F120CD22-35C0-4E41-8F12-E3C41E04DAB3
+ A2A5E4B3-D9C6-4C49-B4CB-8090D615485E
+ D94AD09E-ADF4-47C9-8236-C7B38B44804E
+ 803A6BDF-D74A-4B69-AFF0-98B824AB478D
+ 2765038A-1CFC-4BBD-B19C-6EB2B400D528
+ C03F02B1-8BE3-49F5-B983-48C1BDE2657C
+
+ submenus
+
+ 1BE427C6-0071-4BFF-8CDA-1DC13534E7D8
+
+ items
+
+ 931DD73E-615E-476E-9B0D-8341023AE730
+ DAA69A0C-FC1E-4509-9931-DFFB38B4D6AE
+ 2DDB6FE0-6111-4C40-A149-8E67E76F8272
+
+ name
+ Format
+
+ 2765038A-1CFC-4BBD-B19C-6EB2B400D528
+
+ items
+
+ 2DBEE50B-3097-4A57-AB48-3586CF392D8B
+ 0BA2B2F1-E767-4A03-9791-0AC0183251F1
+ B46D35B8-5DEB-4C10-A110-BA1965A2EB9C
+ 97054C4D-E4A3-45B1-9C00-B82DBCB30CAD
+
+ name
+ Idioms
+
+ 33312F8F-A75F-49E5-AC1B-B65944C1309C
+
+ items
+
+ 8021944C-CEA4-4983-8D1C-78D18D4004A1
+ 2514FC26-468C-4D08-A788-494A444C4286
+ ------------------------------------
+ 66802933-B49F-479B-9DF9-1D898FF1FA90
+
+ name
+ Strings
+
+ 42D15F0C-0A45-4580-944E-20229EB8C92E
+
+ items
+
+ 9E0B4D4B-2956-4B3A-800A-3D8CE54E66BF
+ BA9440C9-36C3-4031-BB61-67B581D5B179
+ ------------------------------------
+ B0CE57EC-FB2E-4482-8CCE-448DC2588715
+
+ name
+ Ordering
+
+ 607DFBB6-D4BD-46B1-A221-698CC657143B
+
+ items
+
+ DAE6A754-D906-4763-B816-CE67125CEF08
+ ------------------------------------
+ 263C94DC-63CF-4BA3-9692-C5582CA8F1AB
+ 6021BBDC-4AAD-447B-A0C2-A4BB31721558
+ 3DDB99C4-486D-4C11-A217-5680FDD8EC19
+ FD010022-E0E7-44DB-827F-33F7D9310DA2
+
+ name
+ Arrays
+
+ 6EA7AE06-3EA9-497D-A6DE-732DE43DA6E9
+
+ items
+
+ 1AD6A138-2E89-4D6A-AB3F-416BF9CE968D
+ ------------------------------------
+ 1BE427C6-0071-4BFF-8CDA-1DC13534E7D8
+ ------------------------------------
+ 05984208-D559-4C04-A69C-2019361A985A
+ BF4CA9F1-51CD-48D4-8357-852234F59046
+ ------------------------------------
+ ED6368FB-A11D-4622-9F42-7879481094F1
+
+ name
+ RDoc
+
+ 803A6BDF-D74A-4B69-AFF0-98B824AB478D
+
+ items
+
+ 0CB48BCA-3F6E-4AE0-85BC-08A1D2508216
+ 20AAD0BC-075D-4EC0-9057-E3E5E62C4125
+ ------------------------------------
+ 5AE7CFB4-418E-4E00-AD76-06DB755EE876
+ 5B46ECFD-23A4-4F0C-9951-F64C19C72C2B
+ 46BF99AD-E172-4D49-BCF7-072F4730E1D9
+ ------------------------------------
+ 9460392B-C036-4A76-A5AE-1191F10E4B1B
+ 3BA6762A-BB6B-489E-8006-F30F386AEF48
+ 2C07D4E7-D74F-4AE4-82BE-B0BA82247AFA
+ 8343ACF4-EEB7-44B5-B835-94826466D4D5
+ ------------------------------------
+ F6BF907E-FDF7-4D9B-9E57-BE159561349D
+ B904D4AA-D15D-48A4-8EB2-563BAF489332
+ CC300D44-6C3F-4F6C-A8AB-86F5A2DC57CF
+
+ name
+ Serialization
+
+ 8D131E43-1245-410B-A7D8-E00222CE5412
+
+ items
+
+ 07D1F987-7CDB-4EAD-B64A-27A93051700E
+ A3B9B76B-2BC5-425C-AB24-9FAAFC375798
+ 5DA9E1E8-2C54-420A-9B84-B040A1AF2B9E
+ 669A86AD-936F-4EDA-8E4E-6863804072DA
+ 6C6B9849-9631-49FF-A9F9-F0E94A1512C5
+ 1F72122A-35AD-4BA1-AA01-889A10319666
+ E23FE534-8061-4828-98A5-46270B6910B0
+ 197709C5-8382-4A59-B6D7-31A0CC0F23B7
+ 9D9E7BA3-8C5D-4532-83EA-326358C2F5BB
+ 98182B9E-7C61-4824-BE4C-9CD69C816037
+ CB03D11A-7204-48D0-92C1-E109034403E7
+ 52B8BF63-F09E-4789-8407-06168A8AE666
+ B79B9DAB-ABEF-44F6-BF7E-635E7BA11DFD
+ 4E409AA4-E7D4-46B7-A4E9-E32F992B33E9
+
+ name
+ Searching and Selection
+
+ 9E56B46B-80D0-4397-91B1-E5BEF5FF2811
+
+ items
+
+ ECBA4CA0-275F-460E-85BE-E82FEA2E2B26
+ 338EC03D-3FF4-4435-94E8-1CEF20CEC75D
+ 7E084412-80E6-4B70-8092-C03D1ECE4CD2
+ FDD73070-6D32-4301-A86A-C55B77C3D8ED
+ EC73D5CC-5F05-46B9-A6F4-82037E4A38C9
+ 3C04589C-5127-478E-97B3-CA7DD2EA7ECD
+ 689120C9-AB40-4081-8268-9362E00FA4A0
+ E54F7077-3C33-4B53-A4F7-21E16132D3AD
+ 02913388-EE8E-4C55-AC94-94F3D751F47E
+ 7A3CECED-452B-438E-A5C6-95B6BDC43243
+ 825B721D-4367-4DF7-98C0-F005695DF9E3
+ CD748479-D2A4-4AB5-95BD-4C89512BA210
+ 844DBD70-BC23-4FBF-9C18-F4A610239DF2
+ 1DD13CF5-39C0-4F10-B655-56DACEBC7F94
+ F3C5F719-EF03-4FF7-A777-4A8402FE3B6B
+ ------------------------------------
+ B563E0D7-513D-49B4-9733-1B04A6F25A74
+ ------------------------------------
+ 5A3754FC-43A3-462B-AB42-E3E951872E6F
+ BFB65D1C-62F1-485D-8A67-3E5A2E55107C
+ BD4CFD7B-1AC0-4569-9BDA-FD491F41F4E6
+
+ name
+ Each Element
+
+ A1433C73-A475-4B9F-8B46-E182C588ED7D
+
+ items
+
+ 0275EF39-9357-408F-AF20-79E415CA9504
+ ------------------------------------
+ 0F940CBC-2173-49FF-B6FD-98A62863F8F2
+ 667083EE-62C3-11D9-B8CF-000D93589AF6
+ 48D8E498-C9A5-4B1B-9A18-71A5860276FB
+ 4E9A7A73-875C-11D9-897C-000393CBCE2E
+ 6670835F-62C3-11D9-B8CF-000D93589AF6
+ 667082E6-62C3-11D9-B8CF-000D93589AF6
+ CD1609FA-47DA-4EE4-9C5B-5C56D953F5B1
+ F53E098D-D08E-4CE2-990A-B0BD70E60614
+ D121FC61-96A4-4B8F-8709-280EDA876FF3
+ 488B387C-50C0-4B2D-9260-5A7E7EAF9B42
+ ------------------------------------
+ E7A3BCF6-3594-453A-945D-4C5D81631CBF
+ B37B0E21-1B49-494A-BA56-367CF18DD0B2
+ 451A0596-1F72-4AFB-AF2F-45900FABB0F7
+ ------------------------------------
+ A05CBDD6-845D-45EB-94FB-F8787F5456BE
+ B2C3ADE8-E19E-4B87-9C6C-593D490114C7
+ 97DE939B-D243-4D5C-B953-1C9090912E7C
+ 33969819-62C5-4E03-B824-C2337205F364
+ 34FEBB9F-73CD-4DD4-A0A3-1CF2A5E3DE78
+ E16D24D2-CC7E-4786-BE0B-1725FC865D78
+ 21C0D711-F32A-4665-AA0D-B136F9DD3945
+ 49D69DEC-6991-49F4-8D9B-BA60BFDD3D17
+
+ name
+ Declarations
+
+ A2A5E4B3-D9C6-4C49-B4CB-8090D615485E
+
+ items
+
+ 418F1817-255F-430A-B09A-222964ED66A7
+ ------------------------------------
+ 8F594E5E-6F46-4E98-B5FB-1C8F3BA9828F
+ 50C56AC8-48F3-42A0-AF10-8164464AFAEF
+ 397FA09F-A30F-4EE4-920C-318D5004EE97
+ ------------------------------------
+ 332AA973-AA71-48CB-AEE9-1D71E11019AC
+ 8EBBB26F-980E-404E-8366-74E5772298F6
+ 678BDB83-FBBD-4E8E-BE0B-E1A98AECB247
+ A4E89D97-D5ED-48BB-B5FF-1BFB79211FCD
+ ------------------------------------
+ 8CEF9711-88D5-4202-AFB9-29EF4EFD25C1
+ C3C48948-4F49-484E-A8DE-DEB44723099E
+ 209D5D73-7A77-4931-A158-3FB6D5B48A88
+
+ name
+ Files
+
+ A2F24A2E-6791-4005-8E32-5D436AB075DB
+
+ items
+
+ 4991BB86-736E-4758-B9B2-E4FA90B9368F
+ 36853A11-0307-4AE7-B835-7CE6358717A5
+ 206D54AF-E67A-4DF0-B7F4-3D42FEB81685
+ 51954118-81D7-42B6-9A10-BE23D8B9FFE2
+ ------------------------------------
+ 567E3D18-BF2B-4379-8927-2777EC9F495E
+
+ name
+ Counting
+
+ B32BD8CF-903E-42D9-B1D3-44F88F262134
+
+ items
+
+ 59E811FF-E722-46BE-8938-04713612FABB
+ ------------------------------------
+ 855FC4EF-7B1E-48EE-AD4E-5ECB8ED79D1C
+ 4B72C5C3-6CA7-41AC-B2F9-51DEA25D469E
+ ------------------------------------
+ 21E75321-0CF7-45E8-A297-BCC7C0DDDD15
+
+ name
+ Blocks
+
+ B37B0E21-1B49-494A-BA56-367CF18DD0B2
+
+ items
+
+ A150C2D8-25B3-4339-BC92-8A0160A70486
+ 3D383096-A03F-4EF8-9060-3C727045AB34
+ D7A7D3C9-1714-4C50-8CC0-D83A03883E8F
+ ------------------------------------
+ AAD5D511-6BE7-41DA-8F2B-1593A48FBB08
+ 6C9D6B3D-D8E9-4606-9534-577C8D21FFF6
+ ------------------------------------
+ 58FDEA60-10AF-4C49-AA09-29B77030DB25
+ 7F46C90A-595B-4B83-A4F7-058F63CE4218
+ ------------------------------------
+ 7C6E88FA-CA0E-4110-8C75-A94E54286A75
+ 4E9D15B5-65D6-4A9A-9DEC-DE041D68C06F
+ 87D5F8AD-8DA6-4AED-A0D8-B51CAC980445
+ C44ED391-614F-4BA2-BB0F-87668EEA9954
+ 4A6EFD6B-88E2-4822-AD48-03460EDBC796
+ ------------------------------------
+ 988C8AEF-FC71-4455-9C4F-9338C05685A4
+ ------------------------------------
+ 7BC1E159-0C90-4B0D-8808-80165C11F59C
+
+ name
+ Methods
+
+ C03F02B1-8BE3-49F5-B983-48C1BDE2657C
+
+ items
+
+ 569C9822-8C41-4907-94C7-1A8A0031B66D
+ ------------------------------------
+ 05EE1046-5ED7-48F5-8693-1F066163B2F4
+ A7BF14E6-59B1-42E5-8755-8A72BF13685E
+
+ name
+ Rake
+
+ D52AE6E7-DB75-46C9-94B0-F90B186BE1B2
+
+ items
+
+ 607DFBB6-D4BD-46B1-A221-698CC657143B
+ A2F24A2E-6791-4005-8E32-5D436AB075DB
+ 9E56B46B-80D0-4397-91B1-E5BEF5FF2811
+ 42D15F0C-0A45-4580-944E-20229EB8C92E
+ 8D131E43-1245-410B-A7D8-E00222CE5412
+ 33312F8F-A75F-49E5-AC1B-B65944C1309C
+
+ name
+ Iterators
+
+ D94AD09E-ADF4-47C9-8236-C7B38B44804E
+
+ items
+
+ 31D1F145-33AB-4441-BA11-4D1C46928C4C
+ 00F66D41-25AF-4597-B67D-E540965A5222
+ 5297FD0C-98B1-4514-BBD1-1516810BECA6
+ ------------------------------------
+ B32C147D-44A6-478A-9D5D-189D7831E9A7
+ 43A61A22-6BEE-4997-961C-1CDE739C05FE
+ A243E96F-DC21-4AA0-B340-13A7674F6AFF
+ 429D0EF5-580D-4166-8F79-713DE96B77F1
+ 0E831E03-67E1-4357-8323-C60685C23C4F
+ 671F05E2-D9CC-485E-BB1B-B13EF20FAC65
+ 4C79256C-480A-459C-BDE8-BB0D972811DB
+ 79FEC3CC-2A40-4611-9A85-ECDB22FE0701
+ 711ED6C3-0F18-41FB-9A7D-3094BB319A85
+ A072BB1E-1DD1-45D3-9346-8CA3BA21B364
+ 1B925A4D-8EE4-442B-9254-293599F5717F
+ 68B21F6F-5D89-41FA-A19C-F29C2F912B4E
+ 82F8EEE0-2452-411E-8102-7BFDDBCA2E72
+ 09A11FDA-49FC-4466-8787-8D1D5D111A89
+ 29340695-E426-4F77-8CF7-C59360A549F4
+ F91C25EC-EC76-498B-BFB5-FDA8F57C5875
+ 7850AD5C-A90D-4E2C-A931-EADFF8D3D9A3
+ 05655BD8-23C6-445F-BFD1-420BF25C3030
+ 33639D7A-BD8C-4396-9C44-307B8AC87C9E
+ ------------------------------------
+ DB457094-1AC9-4856-AEFC-43A9576B6775
+ B186BAC0-D981-41AC-B8F4-34BAD2BC4EE6
+ F46A4687-E52D-40D2-9072-C215645EDBC6
+ ------------------------------------
+ C649F945-DAB8-4DA2-B73C-2EFF9D7D34F3
+ 942F20E2-C40A-44B8-A3F2-99AAC68CB534
+ 1C60D589-DD46-4109-90CA-6B34AEA2F298
+
+ name
+ Tests
+
+ E7A3BCF6-3594-453A-945D-4C5D81631CBF
+
+ items
+
+ BF487539-8085-4FF4-8601-1AD20FABAEDC
+ 83EED068-8C1C-4BAF-9893-902DC00616AB
+ 0CCBE04E-F4E2-4E55-9506-7DE67ACF8388
+ 05DFF82C-5A29-4EBD-93FE-C165FFFB5EA8
+ E98FB8F9-7302-431D-8BF2-275A68A6126C
+ 121B334B-2AA6-4E9A-A8B8-BF93B627982B
+ AFE1D078-EA16-45F5-AD8A-FAC1B523D861
+ C7AAAE45-487A-4B61-8962-D47675AAC05F
+ ------------------------------------
+ 2B73EC5F-06D2-460C-A14F-6FA05AFCF0CC
+ 0E85EC81-2FAB-4648-B590-119CC1BB6E41
+ A71A18CF-2D71-4BFF-AA0C-D9B8C59BC4EB
+
+ name
+ Classes and Modules
+
+ F120CD22-35C0-4E41-8F12-E3C41E04DAB3
+
+ items
+
+ E16EE658-1CA0-4950-954B-B962E50B754F
+ ------------------------------------
+ 840B9C4C-7037-4C3B-9028-EB9DC75EDB3E
+ B9E3A6DF-875D-11D9-897C-000393CBCE2E
+ ------------------------------------
+ F4EEB2B6-07D8-402F-8FC3-79B7308D2576
+
+ name
+ Hashes
+
+
+
+ name
+ Ruby
+ ordering
+
+ 35222962-C50D-4D58-A6AE-71E7AD980BE4
+ 5289EE40-86B8-11D9-A8D4-000A95E13C98
+ 63F3B3B7-CBE2-426B-B551-657733F3868B
+ 1AD6A138-2E89-4D6A-AB3F-416BF9CE968D
+ 931DD73E-615E-476E-9B0D-8341023AE730
+ DAA69A0C-FC1E-4509-9931-DFFB38B4D6AE
+ 2DDB6FE0-6111-4C40-A149-8E67E76F8272
+ BF4CA9F1-51CD-48D4-8357-852234F59046
+ 8646378E-91F5-4771-AC7C-43FC49A93576
+ EE5F19BA-6C02-11D9-92BA-0011242E4184
+ 76FCF165-54CB-4213-BC55-BD60B9C6A3EC
+ EE5F1FB2-6C02-11D9-92BA-0011242E4184
+ FBFC214F-B019-4967-95D2-028F374A3221
+ 9FB64639-F776-499B-BA6F-BB45F86F80FD
+ 7F79BC8D-8A4F-4570-973B-05DFEC25747F
+ B297E4B8-A8FF-49CE-B9C4-6D4911724D43
+ 835FAAC6-5431-436C-998B-241F7226B99B
+ 0275EF39-9357-408F-AF20-79E415CA9504
+ 59E811FF-E722-46BE-8938-04713612FABB
+ F4EEB2B6-07D8-402F-8FC3-79B7308D2576
+ 97054C4D-E4A3-45B1-9C00-B82DBCB30CAD
+ 569C9822-8C41-4907-94C7-1A8A0031B66D
+ 6519CB08-8326-4B77-A251-54722FFBFC1F
+ 47D203ED-EB9B-4653-A07B-A897800CEB76
+ C122CD92-DDBE-4869-9C7A-CC2B254C9411
+ 121B334B-2AA6-4E9A-A8B8-BF93B627982B
+ 58FDEA60-10AF-4C49-AA09-29B77030DB25
+ 33969819-62C5-4E03-B824-C2337205F364
+ 7E084412-80E6-4B70-8092-C03D1ECE4CD2
+ EC73D5CC-5F05-46B9-A6F4-82037E4A38C9
+ 825B721D-4367-4DF7-98C0-F005695DF9E3
+ BFB65D1C-62F1-485D-8A67-3E5A2E55107C
+ C649F945-DAB8-4DA2-B73C-2EFF9D7D34F3
+ 5AE7CFB4-418E-4E00-AD76-06DB755EE876
+ 9460392B-C036-4A76-A5AE-1191F10E4B1B
+ 2C07D4E7-D74F-4AE4-82BE-B0BA82247AFA
+ F6BF907E-FDF7-4D9B-9E57-BE159561349D
+ E5158F94-CC52-4424-A495-14EF9272653F
+ A83F68A9-F751-4BB4-AE16-56812878C16A
+ 05984208-D559-4C04-A69C-2019361A985A
+ ED6368FB-A11D-4622-9F42-7879481094F1
+ 88BC3896-DC39-4307-A271-21D33340F15A
+ FDFABCB9-DF58-4469-AE11-5407A4FF4D70
+ 0F940CBC-2173-49FF-B6FD-98A62863F8F2
+ 667083EE-62C3-11D9-B8CF-000D93589AF6
+ 48D8E498-C9A5-4B1B-9A18-71A5860276FB
+ 4E9A7A73-875C-11D9-897C-000393CBCE2E
+ 7BC1E159-0C90-4B0D-8808-80165C11F59C
+ 6670835F-62C3-11D9-B8CF-000D93589AF6
+ 667082E6-62C3-11D9-B8CF-000D93589AF6
+ CD1609FA-47DA-4EE4-9C5B-5C56D953F5B1
+ F53E098D-D08E-4CE2-990A-B0BD70E60614
+ D121FC61-96A4-4B8F-8709-280EDA876FF3
+ 488B387C-50C0-4B2D-9260-5A7E7EAF9B42
+ BF487539-8085-4FF4-8601-1AD20FABAEDC
+ 83EED068-8C1C-4BAF-9893-902DC00616AB
+ 0CCBE04E-F4E2-4E55-9506-7DE67ACF8388
+ 05DFF82C-5A29-4EBD-93FE-C165FFFB5EA8
+ E98FB8F9-7302-431D-8BF2-275A68A6126C
+ AFE1D078-EA16-45F5-AD8A-FAC1B523D861
+ C7AAAE45-487A-4B61-8962-D47675AAC05F
+ 2B73EC5F-06D2-460C-A14F-6FA05AFCF0CC
+ 0E85EC81-2FAB-4648-B590-119CC1BB6E41
+ A71A18CF-2D71-4BFF-AA0C-D9B8C59BC4EB
+ A150C2D8-25B3-4339-BC92-8A0160A70486
+ 3D383096-A03F-4EF8-9060-3C727045AB34
+ D7A7D3C9-1714-4C50-8CC0-D83A03883E8F
+ AAD5D511-6BE7-41DA-8F2B-1593A48FBB08
+ 6C9D6B3D-D8E9-4606-9534-577C8D21FFF6
+ 7F46C90A-595B-4B83-A4F7-058F63CE4218
+ 7C6E88FA-CA0E-4110-8C75-A94E54286A75
+ 87D5F8AD-8DA6-4AED-A0D8-B51CAC980445
+ 4E9D15B5-65D6-4A9A-9DEC-DE041D68C06F
+ C44ED391-614F-4BA2-BB0F-87668EEA9954
+ 4A6EFD6B-88E2-4822-AD48-03460EDBC796
+ 988C8AEF-FC71-4455-9C4F-9338C05685A4
+ 451A0596-1F72-4AFB-AF2F-45900FABB0F7
+ A05CBDD6-845D-45EB-94FB-F8787F5456BE
+ B2C3ADE8-E19E-4B87-9C6C-593D490114C7
+ 97DE939B-D243-4D5C-B953-1C9090912E7C
+ 34FEBB9F-73CD-4DD4-A0A3-1CF2A5E3DE78
+ E16D24D2-CC7E-4786-BE0B-1725FC865D78
+ 21C0D711-F32A-4665-AA0D-B136F9DD3945
+ 49D69DEC-6991-49F4-8D9B-BA60BFDD3D17
+ DAE6A754-D906-4763-B816-CE67125CEF08
+ 263C94DC-63CF-4BA3-9692-C5582CA8F1AB
+ 6021BBDC-4AAD-447B-A0C2-A4BB31721558
+ 3DDB99C4-486D-4C11-A217-5680FDD8EC19
+ FD010022-E0E7-44DB-827F-33F7D9310DA2
+ 4991BB86-736E-4758-B9B2-E4FA90B9368F
+ 36853A11-0307-4AE7-B835-7CE6358717A5
+ 206D54AF-E67A-4DF0-B7F4-3D42FEB81685
+ 51954118-81D7-42B6-9A10-BE23D8B9FFE2
+ 567E3D18-BF2B-4379-8927-2777EC9F495E
+ ECBA4CA0-275F-460E-85BE-E82FEA2E2B26
+ 338EC03D-3FF4-4435-94E8-1CEF20CEC75D
+ FDD73070-6D32-4301-A86A-C55B77C3D8ED
+ 3C04589C-5127-478E-97B3-CA7DD2EA7ECD
+ 689120C9-AB40-4081-8268-9362E00FA4A0
+ E54F7077-3C33-4B53-A4F7-21E16132D3AD
+ 02913388-EE8E-4C55-AC94-94F3D751F47E
+ 7A3CECED-452B-438E-A5C6-95B6BDC43243
+ CD748479-D2A4-4AB5-95BD-4C89512BA210
+ 844DBD70-BC23-4FBF-9C18-F4A610239DF2
+ 1DD13CF5-39C0-4F10-B655-56DACEBC7F94
+ F3C5F719-EF03-4FF7-A777-4A8402FE3B6B
+ B563E0D7-513D-49B4-9733-1B04A6F25A74
+ 5A3754FC-43A3-462B-AB42-E3E951872E6F
+ BD4CFD7B-1AC0-4569-9BDA-FD491F41F4E6
+ 9E0B4D4B-2956-4B3A-800A-3D8CE54E66BF
+ BA9440C9-36C3-4031-BB61-67B581D5B179
+ B0CE57EC-FB2E-4482-8CCE-448DC2588715
+ 07D1F987-7CDB-4EAD-B64A-27A93051700E
+ A3B9B76B-2BC5-425C-AB24-9FAAFC375798
+ 5DA9E1E8-2C54-420A-9B84-B040A1AF2B9E
+ 669A86AD-936F-4EDA-8E4E-6863804072DA
+ 6C6B9849-9631-49FF-A9F9-F0E94A1512C5
+ 1F72122A-35AD-4BA1-AA01-889A10319666
+ E23FE534-8061-4828-98A5-46270B6910B0
+ 197709C5-8382-4A59-B6D7-31A0CC0F23B7
+ 9D9E7BA3-8C5D-4532-83EA-326358C2F5BB
+ 98182B9E-7C61-4824-BE4C-9CD69C816037
+ CB03D11A-7204-48D0-92C1-E109034403E7
+ 52B8BF63-F09E-4789-8407-06168A8AE666
+ B79B9DAB-ABEF-44F6-BF7E-635E7BA11DFD
+ 4E409AA4-E7D4-46B7-A4E9-E32F992B33E9
+ 8021944C-CEA4-4983-8D1C-78D18D4004A1
+ 2514FC26-468C-4D08-A788-494A444C4286
+ 66802933-B49F-479B-9DF9-1D898FF1FA90
+ 855FC4EF-7B1E-48EE-AD4E-5ECB8ED79D1C
+ 4B72C5C3-6CA7-41AC-B2F9-51DEA25D469E
+ 21E75321-0CF7-45E8-A297-BCC7C0DDDD15
+ E16EE658-1CA0-4950-954B-B962E50B754F
+ 840B9C4C-7037-4C3B-9028-EB9DC75EDB3E
+ B9E3A6DF-875D-11D9-897C-000393CBCE2E
+ 418F1817-255F-430A-B09A-222964ED66A7
+ 8F594E5E-6F46-4E98-B5FB-1C8F3BA9828F
+ 50C56AC8-48F3-42A0-AF10-8164464AFAEF
+ 397FA09F-A30F-4EE4-920C-318D5004EE97
+ 332AA973-AA71-48CB-AEE9-1D71E11019AC
+ 8EBBB26F-980E-404E-8366-74E5772298F6
+ 678BDB83-FBBD-4E8E-BE0B-E1A98AECB247
+ A4E89D97-D5ED-48BB-B5FF-1BFB79211FCD
+ 8CEF9711-88D5-4202-AFB9-29EF4EFD25C1
+ C3C48948-4F49-484E-A8DE-DEB44723099E
+ 209D5D73-7A77-4931-A158-3FB6D5B48A88
+ 31D1F145-33AB-4441-BA11-4D1C46928C4C
+ 00F66D41-25AF-4597-B67D-E540965A5222
+ 5297FD0C-98B1-4514-BBD1-1516810BECA6
+ B32C147D-44A6-478A-9D5D-189D7831E9A7
+ 43A61A22-6BEE-4997-961C-1CDE739C05FE
+ A243E96F-DC21-4AA0-B340-13A7674F6AFF
+ 429D0EF5-580D-4166-8F79-713DE96B77F1
+ 0E831E03-67E1-4357-8323-C60685C23C4F
+ 671F05E2-D9CC-485E-BB1B-B13EF20FAC65
+ 4C79256C-480A-459C-BDE8-BB0D972811DB
+ 79FEC3CC-2A40-4611-9A85-ECDB22FE0701
+ 711ED6C3-0F18-41FB-9A7D-3094BB319A85
+ A072BB1E-1DD1-45D3-9346-8CA3BA21B364
+ 1B925A4D-8EE4-442B-9254-293599F5717F
+ 68B21F6F-5D89-41FA-A19C-F29C2F912B4E
+ 82F8EEE0-2452-411E-8102-7BFDDBCA2E72
+ 09A11FDA-49FC-4466-8787-8D1D5D111A89
+ 29340695-E426-4F77-8CF7-C59360A549F4
+ F91C25EC-EC76-498B-BFB5-FDA8F57C5875
+ 7850AD5C-A90D-4E2C-A931-EADFF8D3D9A3
+ 05655BD8-23C6-445F-BFD1-420BF25C3030
+ 33639D7A-BD8C-4396-9C44-307B8AC87C9E
+ DB457094-1AC9-4856-AEFC-43A9576B6775
+ B186BAC0-D981-41AC-B8F4-34BAD2BC4EE6
+ F46A4687-E52D-40D2-9072-C215645EDBC6
+ 942F20E2-C40A-44B8-A3F2-99AAC68CB534
+ 1C60D589-DD46-4109-90CA-6B34AEA2F298
+ 0CB48BCA-3F6E-4AE0-85BC-08A1D2508216
+ 20AAD0BC-075D-4EC0-9057-E3E5E62C4125
+ 5B46ECFD-23A4-4F0C-9951-F64C19C72C2B
+ 46BF99AD-E172-4D49-BCF7-072F4730E1D9
+ 3BA6762A-BB6B-489E-8006-F30F386AEF48
+ 8343ACF4-EEB7-44B5-B835-94826466D4D5
+ B904D4AA-D15D-48A4-8EB2-563BAF489332
+ CC300D44-6C3F-4F6C-A8AB-86F5A2DC57CF
+ 2DBEE50B-3097-4A57-AB48-3586CF392D8B
+ 0BA2B2F1-E767-4A03-9791-0AC0183251F1
+ B46D35B8-5DEB-4C10-A110-BA1965A2EB9C
+ 05EE1046-5ED7-48F5-8693-1F066163B2F4
+ A7BF14E6-59B1-42E5-8755-8A72BF13685E
+ EEE6D060-C5A0-400D-A2E0-0835013C5365
+ E00B62AC-6B1C-11D9-9B1F-000D93589AF6
+ 1D26F26C-C6F7-434F-84F8-FEE895372E8A
+ 6FEAF60F-F0F3-4618-9259-DE93285F50D1
+ 92E190C9-A861-4025-92D4-D6B5A24C22D4
+ A5D50494-EB97-48DE-A2BE-322DF52A7A7A
+ 6D75102B-6E51-4360-8F12-BE12327B6AE6
+ AEDD6A5F-417F-4177-8589-B07518ACA9DE
+ 1A7701FA-D866-498C-AD4C-7846538DB535
+
+ uuid
+ 467B298F-6227-11D9-BFB1-000D93589AF6
+
+