rcodetools 0.7.0.0 → 0.8.0.0

Sign up to get free protection for your applications and to get access to all the features.
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)