rcodetools 0.7.0.0 → 0.8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. data/CHANGES +12 -0
  2. data/README +1 -1
  3. data/README.emacs +21 -4
  4. data/README.ja +1 -1
  5. data/README.xmpfilter +159 -74
  6. data/Rakefile +3 -37
  7. data/anything-rcodetools.el +142 -0
  8. data/bin/rct-complete +1 -1
  9. data/bin/rct-doc +1 -1
  10. data/bin/rct-meth-args +33 -2
  11. data/bin/xmpfilter +5 -1
  12. data/lib/rcodetools/compat.rb +14 -0
  13. data/lib/rcodetools/completion.rb +8 -6
  14. data/lib/rcodetools/fork.rb +15 -8
  15. data/lib/rcodetools/options.rb +8 -0
  16. data/lib/rcodetools/xmpfilter.rb +80 -33
  17. data/lib/rcodetools/xmptestunitfilter.rb +76 -21
  18. data/lib/ruby_toggle_file.rb +1 -1
  19. data/rcodetools.el +213 -20
  20. data/test/test_functional.rb +36 -68
  21. data/test/test_method_analyzer.rb +28 -20
  22. data/test/test_ruby_toggle_file.rb +118 -69
  23. data/test/test_xmpfilter.rb +75 -47
  24. data/test/test_xmptestunitfilter.rb +12 -11
  25. metadata +83 -133
  26. data/test/data/add_markers-input.rb +0 -2
  27. data/test/data/add_markers-output.rb +0 -2
  28. data/test/data/bindings-input.rb +0 -26
  29. data/test/data/bindings-output.rb +0 -31
  30. data/test/data/completion-input.rb +0 -1
  31. data/test/data/completion-output.rb +0 -2
  32. data/test/data/completion_class_info-input.rb +0 -1
  33. data/test/data/completion_class_info-output.rb +0 -10
  34. data/test/data/completion_class_info_no_candidates-input.rb +0 -1
  35. data/test/data/completion_class_info_no_candidates-output.rb +0 -1
  36. data/test/data/completion_detect_rbtest-input.rb +0 -7
  37. data/test/data/completion_detect_rbtest-output.rb +0 -2
  38. data/test/data/completion_detect_rbtest2-input.rb +0 -1
  39. data/test/data/completion_detect_rbtest2-output.rb +0 -2
  40. data/test/data/completion_emacs-input.rb +0 -1
  41. data/test/data/completion_emacs-output.rb +0 -6
  42. data/test/data/completion_emacs_icicles-input.rb +0 -1
  43. data/test/data/completion_emacs_icicles-output.rb +0 -6
  44. data/test/data/completion_in_method-input.rb +0 -3
  45. data/test/data/completion_in_method-output.rb +0 -1
  46. data/test/data/completion_in_method-test.rb +0 -6
  47. data/test/data/completion_rbtest-input.rb +0 -7
  48. data/test/data/completion_rbtest-output.rb +0 -2
  49. data/test/data/doc-input.rb +0 -1
  50. data/test/data/doc-output.rb +0 -1
  51. data/test/data/doc_detect_rbtest-input.rb +0 -1
  52. data/test/data/doc_detect_rbtest-output.rb +0 -1
  53. data/test/data/doc_detect_rbtest2-input.rb +0 -7
  54. data/test/data/doc_detect_rbtest2-output.rb +0 -1
  55. data/test/data/doc_rbtest-input.rb +0 -7
  56. data/test/data/doc_rbtest-output.rb +0 -1
  57. data/test/data/no_warnings-input.rb +0 -3
  58. data/test/data/no_warnings-output.rb +0 -4
  59. data/test/data/refe-input.rb +0 -1
  60. data/test/data/refe-output.rb +0 -1
  61. data/test/data/ri-input.rb +0 -1
  62. data/test/data/ri-output.rb +0 -1
  63. data/test/data/ri_emacs-input.rb +0 -1
  64. data/test/data/ri_emacs-output.rb +0 -1
  65. data/test/data/ri_vim-input.rb +0 -1
  66. data/test/data/ri_vim-output.rb +0 -1
  67. data/test/data/rspec-input.rb +0 -48
  68. data/test/data/rspec-output.rb +0 -52
  69. data/test/data/rspec_poetry-input.rb +0 -48
  70. data/test/data/rspec_poetry-output.rb +0 -52
  71. data/test/data/simple_annotation-input.rb +0 -8
  72. data/test/data/simple_annotation-output.rb +0 -8
  73. data/test/data/unit_test-input.rb +0 -50
  74. data/test/data/unit_test-output.rb +0 -52
  75. data/test/data/unit_test_detect_rbtest-input.rb +0 -50
  76. data/test/data/unit_test_detect_rbtest-output.rb +0 -52
  77. data/test/data/unit_test_detect_rbtest2-input.rb +0 -6
  78. data/test/data/unit_test_detect_rbtest2-output.rb +0 -6
  79. data/test/data/unit_test_poetry-input.rb +0 -50
  80. data/test/data/unit_test_poetry-output.rb +0 -52
  81. data/test/data/unit_test_rbtest-input.rb +0 -6
  82. data/test/data/unit_test_rbtest-output.rb +0 -6
  83. data/test/test_run.rb +0 -45
data/bin/rct-complete CHANGED
@@ -1,4 +1,4 @@
1
- #! /home/batsman/usr/bin/ruby
1
+ #! /home/mfp/ruby1.8/bin/ruby
2
2
  require 'rcodetools/xmpfilter'
3
3
  require 'rcodetools/completion'
4
4
  require 'rcodetools/options'
data/bin/rct-doc CHANGED
@@ -1,4 +1,4 @@
1
- #! /home/batsman/usr/bin/ruby
1
+ #! /home/mfp/ruby1.8/bin/ruby
2
2
  require 'rcodetools/xmpfilter'
3
3
  require 'rcodetools/doc'
4
4
  require 'rcodetools/options'
data/bin/rct-meth-args CHANGED
@@ -1,4 +1,4 @@
1
- #! /home/batsman/usr/bin/ruby
1
+ #! /home/mfp/ruby1.8/bin/ruby
2
2
  # Copyright (c)
3
3
  # 2006-2007 Mauricio Fernandez <mfp@acm.org> http://eigenclass.org
4
4
  # 2006-2007 rubikitch <rubikitch@ruby-lang.org> http://www.rubyist.net/~rubikitch/
@@ -6,6 +6,7 @@
6
6
  # Use and distribution subject to the same conditions as Ruby.
7
7
 
8
8
  require 'rcodetools/options'
9
+ include Rcodetools
9
10
  $VERBOSE = nil
10
11
  $__method_args_off = true
11
12
 
@@ -22,6 +23,7 @@ rct-meth-args [-Idirectory] [-i] [-m] [-c] [-n] <file> [<file> ...]
22
23
 
23
24
  -n print the filename and line number with output lines
24
25
  -t generate TAGS output
26
+ --summarize summary output sorted by method name
25
27
 
26
28
  The given files will be #require()d in order.
27
29
  Examples:
@@ -29,7 +31,7 @@ Examples:
29
31
  rct-meth-args thread
30
32
  rct-meth-args -c rubygems
31
33
  EOF
32
- exit
34
+ exit # '
33
35
  end
34
36
 
35
37
  def debugprint(*args)
@@ -98,6 +100,33 @@ module MethodArgs
98
100
  end
99
101
  end
100
102
 
103
+ class SummarizePrinter
104
+ def initialize
105
+ @hash = Hash.new
106
+ at_exit { print_result }
107
+ end
108
+
109
+ def method_info(io, x)
110
+ @io = io
111
+ prefix = x[:location] ? "#{x[:location].filename}:#{x[:location].lineno}:" : ""
112
+ (@hash[x[:meth]]||=[]) << "#{prefix}#{x[:fullname]}#{x[:arg_desc]}" unless x[:klass].to_s == "<Struct>"
113
+ end
114
+
115
+ def included_location(io, x)
116
+ # not implemented
117
+ end
118
+
119
+ def print_result
120
+ @hash.keys.sort.each do |meth|
121
+ @io.puts meth
122
+ @hash[meth].each do |line|
123
+ @io.puts line
124
+ end
125
+ @io.puts
126
+ end
127
+ end
128
+ end
129
+
101
130
  class TagsPrinter
102
131
  def initialize
103
132
  @previous_filename = ""
@@ -129,6 +158,7 @@ module MethodArgs
129
158
  arg_desc = " " + arg_desc unless arg_desc.empty?
130
159
  flag = is_singleton ? "." : "#"
131
160
  x = { :arg_desc => arg_desc, :klass => klass,
161
+ :meth => meth.to_s,
132
162
  :fullname => [klass, flag, meth].join,
133
163
  :location => with_location && location,
134
164
  }
@@ -255,6 +285,7 @@ ARGV.each do |arg|
255
285
  case arg
256
286
  when "-n"; $__with_location = true
257
287
  when "-t"; $__printer = TagsPrinter.new; $__with_location = true
288
+ when "--summarize"; $__printer = SummarizePrinter.new
258
289
  when /-I(.+)$/; $:.unshift $1
259
290
  when "-I"; i_opt_p = true
260
291
  when "--dev"; OptionHandler.auto_include_paths($:, Dir.pwd)
data/bin/xmpfilter CHANGED
@@ -1,4 +1,4 @@
1
- #! /home/batsman/usr/bin/ruby
1
+ #! /home/mfp/ruby1.8/bin/ruby
2
2
  require 'rcodetools/xmpfilter'
3
3
  require 'rcodetools/options'
4
4
 
@@ -25,6 +25,10 @@ opts = OptionParser.new do |opts|
25
25
  klass = XMPRSpecFilter
26
26
  options[:interpreter] = "spec"
27
27
  end
28
+ opts.on("--expectations", "Complete expectations expectations.") do
29
+ require 'rcodetools/xmptestunitfilter'
30
+ klass = XMPExpectationsFilter
31
+ end
28
32
  opts.on("-m", "--markers", "Add # => markers.") do
29
33
  klass = XMPAddMarkers
30
34
  end
@@ -0,0 +1,14 @@
1
+ if RUBY_VERSION >= "1.9"
2
+ class String
3
+ alias :each :each_line
4
+ include Enumerable
5
+ end
6
+
7
+ module Enumerable
8
+ alias :enum_with_index :each_with_index
9
+ end
10
+
11
+ class Array
12
+ alias :to_s :join
13
+ end
14
+ end
@@ -81,8 +81,8 @@ module ProcessParticularLine
81
81
  def aref_or_aset?(right_stripped, last_char)
82
82
  if last_char == ?[
83
83
  case right_stripped
84
- when /\]\s*=/: "[]="
85
- when /\]/: "[]"
84
+ when /\]\s*=/ then "[]="
85
+ when /\]/ then "[]"
86
86
  end
87
87
  end
88
88
  end
@@ -182,7 +182,7 @@ XXX
182
182
  code = <<-EOC
183
183
  #{result} = #{v}.method(#{meth}).inspect.match( %r[\\A#<(?:Unbound)?Method: (.*?)>\\Z] )[1].sub(/\\A.*?\\((.*?)\\)(.*)\\Z/){ "\#{$1}\#{$2}" }.sub(/#<Class:(.*?)>#/) { "\#{$1}." }
184
184
  #{result} = #{v}.to_s + ".new" if #{result} == 'Class#new' and #{v}.private_method_defined?(:initialize)
185
- #{result} = "Object#" + #{meth} if #{result} =~ /^Kernel#/ and Kernel.instance_methods(false).include? #{meth}
185
+ #{result} = "Object#" + #{meth} if #{result} =~ /^Kernel#/ and Kernel.instance_methods(false).map{|x| x.to_s}.include? #{meth}
186
186
  #{result}
187
187
  EOC
188
188
  end
@@ -212,7 +212,9 @@ class XMPCompletionFilter < XMPFilter
212
212
 
213
213
  def methods_map_code(recv)
214
214
  # delimiter is \0
215
- %Q[map{|m| "\#{m}\\0" + #{magic_help_code((recv), 'm')}}]
215
+ m = "#{VAR}_m"
216
+ mhc = magic_help_code((recv), m)
217
+ %Q[map{|%s| "\#{%s}\\0" + %s}] % [m, m, mhc]
216
218
  end
217
219
 
218
220
  def split_method_info(minfo)
@@ -235,7 +237,7 @@ class XMPCompletionFilter < XMPFilter
235
237
  %Q[#$1.constants + #$1.methods(true).#{methods_map_code($1)}]
236
238
  when /^[A-Z]\w*$/ # normal constants
237
239
  __prepare_line 'nil', 'Module.constants', '%n'
238
- when /^(.*::.+)\.(.+)$/ # toplevel class methods
240
+ when /^(.*::.+)\.(.*)$/ # toplevel class methods
239
241
  @prefix = $2
240
242
  __prepare_line $1, "#$1.methods",
241
243
  %Q[%n.#{methods_map_code($1)}]
@@ -274,7 +276,7 @@ class XMPCompletionFilter < XMPFilter
274
276
  idx = 1
275
277
  oneline_ize(<<EOC)
276
278
  #{rcv} = (#{recv})
277
- #{v} = (#{all_completion_expr}).grep(/^#{Regexp.quote(@prefix)}/)
279
+ #{v} = (#{all_completion_expr}).map{|x| x.to_s}.grep(/^#{Regexp.quote(@prefix)}/)
278
280
  #{rcv} = Module === #{rcv} ? #{rcv} : #{rcv}.class
279
281
  $stderr.puts("#{MARKER}[#{idx}] => " + #{rcv}.to_s + " " + #{v}.join(" ")) || #{v}
280
282
  exit
@@ -39,7 +39,7 @@ rct-fork and rct-fork-client (we) are originally ruby_fork/ruby_fork_client in Z
39
39
  Completion or document browsing in a script with heavy libraries such as Rails takes a significant latency.
40
40
  We eliminate constant overhead of loading heavy libraries.
41
41
 
42
- rct-fork loads libraries you want to pre-load and opens up a server socket and waits for connection. When a connection comes in rct-fork forks to make a copy of the environment.
42
+ rct-fork loads libraries you want to pre-load and opens up a server socket and waits for connection. When a connection comes in rct-fork forks to make a copy of the environment. rct-fork loads rubygems at startup.
43
43
 
44
44
  rct-fork-client connects to the rct-fork server and runs script in server's environment.
45
45
 
@@ -89,10 +89,9 @@ XXX
89
89
  Process.setsid
90
90
  fork and exit!
91
91
 
92
- # Rcodetools version does not have to reopen IOs because they are already reopened.
93
- # STDIN.reopen io
94
- # STDOUT.reopen io
95
- # STDERR.reopen io
92
+ STDIN.reopen io
93
+ STDOUT.reopen io
94
+ STDERR.reopen io
96
95
 
97
96
  yield if block_given?
98
97
  end
@@ -170,6 +169,10 @@ XXX
170
169
  end
171
170
 
172
171
  def self.start_server(args = ARGV)
172
+ begin
173
+ require 'rubygems'
174
+ rescue LoadError
175
+ end
173
176
  write_pwd
174
177
  settings = parse_server_args args
175
178
  setup_environment settings
@@ -212,9 +215,13 @@ XXX
212
215
  settings[:extra_paths].flatten!
213
216
  settings[:extra_paths].each { |dir| $:.unshift dir }
214
217
 
215
- settings[:requires].each { |file| require file }
216
-
217
- settings[:code].each { |code| eval code }
218
+ begin
219
+ settings[:requires].each { |file| require file }
220
+ settings[:code].each { |code| eval code, TOPLEVEL_BINDING }
221
+ rescue Exception
222
+ $@.reject! {|s| s =~ %r!rcodetools/fork\.rb!}
223
+ raise
224
+ end
218
225
  end
219
226
 
220
227
  end
@@ -66,6 +66,12 @@ module OptionHandler
66
66
  on("--debug", "Write transformed source code to xmp-tmp.PID.rb.") do
67
67
  options[:dump] = "xmp-tmp.#{Process.pid}.rb"
68
68
  end
69
+ on("--tmpfile", "--tempfile", "Use tmpfile instead of open3. (non-windows)") do
70
+ options[:execute_ruby_tmpfile] = true
71
+ end
72
+ on("-w N", "--width N", Integer, "Set width of multi-line annotation. (xmpfilter only)") do |width|
73
+ options[:width] = width
74
+ end
69
75
  separator ""
70
76
  on("-h", "--help", "Show this message") do
71
77
  puts self
@@ -110,6 +116,7 @@ DEFAULT_OPTIONS = {
110
116
  :interpreter => "ruby",
111
117
  :options => ["hoge"],
112
118
  :min_codeline_size => 50,
119
+ :width => 79,
113
120
  :libs => [],
114
121
  :evals => [],
115
122
  :include_paths => [],
@@ -124,5 +131,6 @@ DEFAULT_OPTIONS = {
124
131
  :detect_rct_fork => false,
125
132
  :use_rbtest => false,
126
133
  :detect_rbtest => false,
134
+ :execute_ruby_tmpfile => false,
127
135
  }
128
136
  end # /Rcodetools
@@ -1,14 +1,17 @@
1
1
  #!/usr/bin/env ruby
2
- # Copyright (c) 2005-2007 Mauricio Fernandez <mfp@acm.org> http://eigenclass.org
2
+ # Copyright (c) 2005-2008 Mauricio Fernandez <mfp@acm.org> http://eigenclass.org
3
3
  # rubikitch <rubikitch@ruby-lang.org>
4
4
  # Use and distribution subject to the terms of the Ruby license.
5
5
 
6
+ ENV['HOME'] ||= "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}"
6
7
  require 'rcodetools/fork_config'
8
+ require 'rcodetools/compat'
9
+ require 'tmpdir'
7
10
 
8
11
  module Rcodetools
9
12
 
10
13
  class XMPFilter
11
- VERSION = "0.7.0"
14
+ VERSION = "0.8.0"
12
15
 
13
16
  MARKER = "!XMP#{Time.new.to_i}_#{Process.pid}_#{rand(1000000)}!"
14
17
  XMP_RE = Regexp.new("^" + Regexp.escape(MARKER) + '\[([0-9]+)\] (=>|~>|==>) (.*)')
@@ -21,17 +24,18 @@ class XMPFilter
21
24
  :include_paths => [], :warnings => true,
22
25
  :use_parentheses => true}
23
26
 
24
- def self.windows?
27
+ def windows?
25
28
  /win|mingw/ =~ RUBY_PLATFORM && /darwin/ !~ RUBY_PLATFORM
26
29
  end
27
30
 
28
- Interpreter = Struct.new(:options, :execute_method, :accept_debug, :chdir_proc)
31
+ Interpreter = Struct.new(:options, :execute_method, :accept_debug, :accept_include_paths, :chdir_proc)
29
32
  INTERPRETER_RUBY = Interpreter.new(["-w"],
30
- windows? ? :execute_tmpfile : :execute_popen,
31
- true, nil)
32
- INTERPRETER_RBTEST = Interpreter.new(["-S", "rbtest"], :execute_script, false, nil)
33
- INTERPRETER_FORK = Interpreter.new(["-S", "rct-fork-client"], :execute_tmpfile, false,
34
- lambda { Fork::chdir_fork_directory })
33
+ :execute_ruby, true, true, nil)
34
+ INTERPRETER_RBTEST = Interpreter.new(["-S", "rbtest"],
35
+ :execute_script, false, false, nil)
36
+ INTERPRETER_FORK = Interpreter.new(["-S", "rct-fork-client"],
37
+ :execute_tmpfile, false, true,
38
+ lambda { Fork::chdir_fork_directory })
35
39
 
36
40
  def self.detect_rbtest(code, opts)
37
41
  opts[:use_rbtest] ||= (opts[:detect_rbtest] and code =~ /^=begin test./) ? true : false
@@ -58,7 +62,10 @@ class XMPFilter
58
62
  test_script = options[:test_script]
59
63
  test_method = options[:test_method]
60
64
  filename = options[:filename]
65
+ @execute_ruby_tmpfile = options[:execute_ruby_tmpfile]
61
66
  @postfix = ""
67
+ @stdin_path = nil
68
+ @width = options[:width]
62
69
 
63
70
  initialize_rct_fork if options[:detect_rct_fork]
64
71
  initialize_rbtest if options[:use_rbtest]
@@ -82,7 +89,7 @@ class XMPFilter
82
89
  basedir = common_path(test_script, filename)
83
90
  relative_filename = filename[basedir.length+1 .. -1].sub(%r!^lib/!, '')
84
91
  @evals << %Q!$LOADED_FEATURES << #{relative_filename.dump}!
85
- @evals << %Q!require 'test/unit'!
92
+ @evals << safe_require_code('test/unit')
86
93
  @evals << %Q!load #{test_script.dump}!
87
94
  end
88
95
  test_method = get_test_method_from_lineno(test_script, test_method.to_i) if test_method =~ /^\d/
@@ -114,24 +121,30 @@ class XMPFilter
114
121
  ret
115
122
  end
116
123
 
124
+ SINGLE_LINE_RE = /^(?!(?:\s+|(?:\s*#.+)?)# ?=>)(.*) # ?=>.*/
125
+ MULTI_LINE_RE = /^(.*)\n(( *)# ?=>.*(?:\n|\z))(?: *# .*\n)*/
117
126
  def annotate(code)
118
127
  idx = 0
119
- newcode = code.gsub(/^(.*) # =>.*/){|l| prepare_line($1, idx += 1) }
120
- if @dump
121
- File.open(@dump, "w"){|f| f.puts newcode}
122
- end
128
+ newcode = code.gsub(SINGLE_LINE_RE){ prepare_line($1, idx += 1) }
129
+ newcode.gsub!(MULTI_LINE_RE){ prepare_line($1, idx += 1, true)}
130
+ File.open(@dump, "w"){|f| f.puts newcode} if @dump
123
131
  stdout, stderr = execute(newcode)
124
132
  output = stderr.readlines
125
133
  runtime_data = extract_data(output)
126
134
  idx = 0
127
- annotated = code.gsub(/^(.*) # =>.*/) do |l|
135
+ annotated = code.gsub(SINGLE_LINE_RE) { |l|
128
136
  expr = $1
129
137
  if /^\s*#/ =~ l
130
138
  l
131
139
  else
132
140
  annotated_line(l, expr, runtime_data, idx += 1)
133
141
  end
134
- end.gsub(/ # !>.*/, '').gsub(/# (>>|~>)[^\n]*\n/m, "");
142
+ }
143
+ annotated.gsub!(/ # !>.*/, '')
144
+ annotated.gsub!(/# (>>|~>)[^\n]*\n/m, "");
145
+ annotated.gsub!(MULTI_LINE_RE) { |l|
146
+ annotated_multi_line(l, $1, $3, runtime_data, idx += 1)
147
+ }
135
148
  ret = final_decoration(annotated, output)
136
149
  if @output_stdout and (s = stdout.read) != ""
137
150
  ret << s.inject(""){|s,line| s + "# >> #{line}".chomp + "\n" }
@@ -143,13 +156,28 @@ class XMPFilter
143
156
  "#{expression} # => " + (runtime_data.results[idx].map{|x| x[1]} || []).join(", ")
144
157
  end
145
158
 
146
- def prepare_line_annotation(expr, idx)
159
+ def annotated_multi_line(line, expression, indent, runtime_data, idx)
160
+ pretty = (runtime_data.results[idx].map{|x| x[1]} || []).join(", ")
161
+ first, *rest = pretty.to_a
162
+ rest.inject("#{expression}\n#{indent}# => #{first}") {|s, l| s << "#{indent}# " << l }
163
+ end
164
+
165
+ def prepare_line_annotation(expr, idx, multi_line=false)
147
166
  v = "#{VAR}"
148
167
  blocal = "__#{VAR}"
149
168
  blocal2 = "___#{VAR}"
169
+ lastmatch = "____#{VAR}"
170
+ if multi_line
171
+ pp = safe_require_code "pp"
172
+ result = "((begin; #{lastmatch} = $~; PP.pp(#{v}, '', #{@width-5}).gsub(/\\r?\\n/, 'PPPROTECT'); ensure; $~ = #{lastmatch} end))"
173
+ else
174
+ pp = ''
175
+ result = "#{v}.inspect"
176
+ end
150
177
  oneline_ize(<<-EOF).chomp
178
+ #{pp}
151
179
  #{v} = (#{expr})
152
- $stderr.puts("#{MARKER}[#{idx}] => " + #{v}.class.to_s + " " + #{v}.inspect) || begin
180
+ $stderr.puts("#{MARKER}[#{idx}] => " + #{v}.class.to_s + " " + #{result}) || begin
153
181
  $stderr.puts local_variables
154
182
  local_variables.each{|#{blocal}|
155
183
  #{blocal2} = eval(#{blocal})
@@ -168,6 +196,17 @@ end || #{v}
168
196
  end
169
197
  alias_method :prepare_line, :prepare_line_annotation
170
198
 
199
+ def safe_require_code(lib)
200
+ oldverbose = "$#{VAR}_old_verbose"
201
+ "#{oldverbose} = $VERBOSE; $VERBOSE = false; require '#{lib}'; $VERBOSE = #{oldverbose}"
202
+ end
203
+ private :safe_require_code
204
+
205
+ def execute_ruby(code)
206
+ meth = (windows? or @execute_ruby_tmpfile) ? :execute_tmpfile : :execute_popen
207
+ __send__ meth, code
208
+ end
209
+
171
210
  def execute_tmpfile(code)
172
211
  ios = %w[_ stdin stdout stderr]
173
212
  stdin, stdout, stderr = (1..3).map do |i|
@@ -182,6 +221,7 @@ end || #{v}
182
221
  end
183
222
  stdin.puts code
184
223
  stdin.close
224
+ @stdin_path = File.expand_path stdin.path
185
225
  exe_line = <<-EOF.map{|l| l.strip}.join(";")
186
226
  $stdout.reopen('#{File.expand_path(stdout.path)}', 'w')
187
227
  $stderr.reopen('#{File.expand_path(stderr.path)}', 'w')
@@ -209,20 +249,25 @@ end || #{v}
209
249
  end
210
250
 
211
251
  def execute_script(code)
212
- codefile = "xmpfilter.tmpfile_#{Process.pid}.rb"
213
- File.open(codefile, "w"){|f| f.puts code}
214
- path = File.expand_path(codefile)
252
+ path = File.expand_path("xmpfilter.tmpfile_#{Process.pid}.rb", Dir.tmpdir)
253
+ File.open(path, "w"){|f| f.puts code}
215
254
  at_exit { File.unlink path if File.exist? path}
216
- stdout, stderr = (1..2).map do |i|
255
+ stdout_path, stderr_path = (1..2).map do |i|
217
256
  fname = "xmpfilter.tmpfile_#{Process.pid}-#{i}.rb"
218
- fullname = File.expand_path(fname)
219
- at_exit { File.unlink fullname if File.exist? fullname}
220
- File.open(fname, "w+")
257
+ File.expand_path(fname, Dir.tmpdir)
221
258
  end
222
- args = *(interpreter_command << %["#{codefile}"] << "2>" <<
223
- %["#{stderr.path}"] << ">" << %["#{stdout.path}"])
259
+ args = *(interpreter_command << %["#{path}"] << "2>" <<
260
+ %["#{stderr_path}"] << ">" << %["#{stdout_path}"])
224
261
  system(args.join(" "))
225
- [stdout, stderr]
262
+
263
+ [stdout_path, stderr_path].map do |fullname|
264
+ f = File.open(fullname, "r")
265
+ at_exit {
266
+ f.close unless f.closed?
267
+ File.unlink fullname if File.exist? fullname
268
+ }
269
+ f
270
+ end
226
271
  end
227
272
 
228
273
  def execute(code)
@@ -232,7 +277,7 @@ end || #{v}
232
277
  def interpreter_command
233
278
  r = [ @interpreter ] + @interpreter_info.options
234
279
  r << "-d" if $DEBUG and @interpreter_info.accept_debug
235
- r << "-I#{@include_paths.join(":")}" unless @include_paths.empty?
280
+ r << "-I#{@include_paths.join(":")}" if @interpreter_info.accept_include_paths and !@include_paths.empty?
236
281
  @libs.each{|x| r << "-r#{x}" } unless @libs.empty?
237
282
  (r << "-").concat @options unless @options.empty?
238
283
  r
@@ -247,7 +292,7 @@ end || #{v}
247
292
  case op
248
293
  when "=>"
249
294
  klass, value = /(\S+)\s+(.*)/.match(result).captures
250
- results[result_id.to_i] << [klass, value]
295
+ results[result_id.to_i] << [klass, value.gsub(/PPPROTECT/, "\n")]
251
296
  when "~>"
252
297
  exceptions[result_id.to_i] << result
253
298
  when "==>"
@@ -273,14 +318,16 @@ end || #{v}
273
318
  end
274
319
  end
275
320
  output = output.reject{|x| /^-:[0-9]+: warning/.match(x)}
276
- if exception = /^-:[0-9]+:.*/m.match(output.join)
277
- ret << exception[0].map{|line| "# ~> " + line }
321
+ if exception = /^-e?:[0-9]+:.*|^(?!!XMP)[^\n]+:[0-9]+:in .*/m.match(output.join)
322
+ err = exception[0]
323
+ err.gsub!(Regexp.union(@stdin_path), '-') if @stdin_path
324
+ ret << err.map{|line| "# ~> " + line }
278
325
  end
279
326
  ret
280
327
  end
281
328
 
282
329
  def oneline_ize(code)
283
- "((" + code.gsub(/\r?\n|\r/, ';') + "))#{@postfix}\n"
330
+ "((" + code.gsub(/\r?\n|\r/, ';') + "));#{@postfix}\n"
284
331
  end
285
332
 
286
333
  def debugprint(*args)