rcodetools 0.5.0.0 → 0.7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/CHANGES +14 -0
  2. data/README +63 -0
  3. data/README.TDC +158 -0
  4. data/README.ja +84 -0
  5. data/README.vim +11 -0
  6. data/Rakefile +15 -2
  7. data/THANKS +5 -0
  8. data/bin/rct-complete +4 -2
  9. data/bin/rct-doc +4 -2
  10. data/bin/rct-meth-args +1 -1
  11. data/bin/xmpfilter +7 -1
  12. data/icicles-rcodetools.el +2 -1
  13. data/lib/rcodetools/completion.rb +36 -18
  14. data/lib/rcodetools/doc.rb +3 -0
  15. data/lib/rcodetools/fork.rb +222 -0
  16. data/lib/rcodetools/fork_config.rb +26 -0
  17. data/lib/rcodetools/options.rb +34 -1
  18. data/lib/rcodetools/xmpfilter.rb +106 -18
  19. data/lib/rcodetools/xmptestunitfilter.rb +116 -55
  20. data/lib/ruby_toggle_file.rb +99 -0
  21. data/rcodetools.el +64 -9
  22. data/rcodetools.vim +41 -6
  23. data/test/data/completion_class_info-input.rb +1 -0
  24. data/test/data/completion_class_info-output.rb +10 -0
  25. data/test/data/completion_class_info_no_candidates-input.rb +1 -0
  26. data/test/data/completion_class_info_no_candidates-output.rb +1 -0
  27. data/test/data/completion_detect_rbtest-input.rb +7 -0
  28. data/test/data/completion_detect_rbtest-output.rb +2 -0
  29. data/test/data/completion_detect_rbtest2-input.rb +1 -0
  30. data/test/data/completion_detect_rbtest2-output.rb +2 -0
  31. data/test/data/completion_in_method-input.rb +3 -0
  32. data/test/data/completion_in_method-output.rb +1 -0
  33. data/test/data/completion_in_method-test.rb +6 -0
  34. data/test/data/completion_rbtest-input.rb +7 -0
  35. data/test/data/completion_rbtest-output.rb +2 -0
  36. data/test/data/doc_detect_rbtest-input.rb +1 -0
  37. data/test/data/doc_detect_rbtest-output.rb +1 -0
  38. data/test/data/doc_detect_rbtest2-input.rb +7 -0
  39. data/test/data/doc_detect_rbtest2-output.rb +1 -0
  40. data/test/data/doc_rbtest-input.rb +7 -0
  41. data/test/data/doc_rbtest-output.rb +1 -0
  42. data/test/data/rspec-input.rb +9 -9
  43. data/test/data/rspec-output.rb +21 -21
  44. data/test/data/rspec_poetry-input.rb +9 -9
  45. data/test/data/rspec_poetry-output.rb +21 -21
  46. data/test/data/sample_test_script.rb +9 -0
  47. data/test/data/unit_test_detect_rbtest-input.rb +50 -0
  48. data/test/data/unit_test_detect_rbtest-output.rb +52 -0
  49. data/test/data/unit_test_detect_rbtest2-input.rb +6 -0
  50. data/test/data/unit_test_detect_rbtest2-output.rb +6 -0
  51. data/test/data/unit_test_rbtest-input.rb +6 -0
  52. data/test/data/unit_test_rbtest-output.rb +6 -0
  53. data/test/test_completion.rb +37 -3
  54. data/test/test_doc.rb +2 -0
  55. data/test/test_functional.rb +75 -14
  56. data/test/test_options.rb +1 -0
  57. data/test/test_ruby_toggle_file.rb +125 -0
  58. data/test/test_run.rb +7 -3
  59. data/test/test_xmpfilter.rb +132 -5
  60. data/test/test_xmptestunitfilter.rb +1 -0
  61. metadata +76 -43
@@ -1,7 +1,8 @@
1
- #! /home/batsman/usr//bin/ruby
1
+ #! /home/batsman/usr/bin/ruby
2
2
  require 'rcodetools/xmpfilter'
3
3
  require 'rcodetools/options'
4
4
 
5
+ include Rcodetools
5
6
  options = DEFAULT_OPTIONS
6
7
  rails_settings = false
7
8
  klass = XMPFilter
@@ -71,5 +72,10 @@ end
71
72
  targetcode = ARGF.read
72
73
  Dir.chdir options[:wd] if options[:wd]
73
74
 
75
+ if XMPFilter.detect_rbtest(targetcode, options)
76
+ require 'rcodetools/xmptestunitfilter'
77
+ klass = XMPTestUnitFilter
78
+ end
79
+
74
80
  # Do the job. dispatched by klass.
75
81
  puts klass.run(targetcode, options)
@@ -28,7 +28,8 @@ See also `rct-interactive'."
28
28
  (icicle-point-position-in-candidate 'input-end)
29
29
  pattern klass alist
30
30
  (icicle-candidate-help-fn
31
- (lambda (result) (ri (cdr (assoc result alist)))))) ;bindings
31
+ (lambda (result)
32
+ (ri (cdr (assoc result alist)))))) ;bindings
32
33
  (rct-exec-and-eval rct-complete-command-name "--completion-emacs-icicles"))
33
34
 
34
35
  (provide 'icicles-rcodetools)
@@ -3,6 +3,9 @@
3
3
 
4
4
  require 'rcodetools/xmpfilter'
5
5
  require 'enumerator'
6
+
7
+ module Rcodetools
8
+
6
9
  # Common routines for XMPCompletionFilter/XMPDocFilter
7
10
  module ProcessParticularLine
8
11
  def fill_literal!(expr)
@@ -156,7 +159,7 @@ XXX
156
159
  debugprint "newcode", newcode.gsub(/;/, "\n"), "-"*80
157
160
  stdout, stderr = execute(newcode)
158
161
  output = stderr.readlines
159
- debugprint "stdout", output, "-"*80
162
+ debugprint "stderr", output, "-"*80
160
163
  output = output.reject{|x| /^-:[0-9]+: warning/.match(x)}
161
164
  runtime_data = extract_data(output)
162
165
  if exception = /^-:[0-9]+:.*/m.match(output.join)
@@ -164,6 +167,7 @@ XXX
164
167
  end
165
168
  begin
166
169
  dat = runtime_data.results[1][0]
170
+ debugprint "dat = #{dat.inspect}"
167
171
  [dat[0], dat[1..-1].to_s]
168
172
  rescue
169
173
  raise RuntimeDataError, runtime_data.inspect
@@ -219,11 +223,11 @@ class XMPCompletionFilter < XMPFilter
219
223
  set_expr_and_postfix!(expr, column){|c| /^.{#{c}}/ }
220
224
  @prefix = expr
221
225
  case expr
222
- when /^\$\w+$/ # global variable
226
+ when /^\$\w*$/ # global variable
223
227
  __prepare_line 'nil', 'global_variables', '%n'
224
- when /^@@\w+$/ # class variable
228
+ when /^@@\w*$/ # class variable
225
229
  __prepare_line 'nil', 'Module === self ? class_variables : self.class.class_variables', '%n'
226
- when /^@\w+$/ # instance variable
230
+ when /^@\w*$/ # instance variable
227
231
  __prepare_line 'nil', 'instance_variables', '%n'
228
232
  when /^([A-Z].*)::([^.]*)$/ # nested constants / class methods
229
233
  @prefix = $2
@@ -277,15 +281,21 @@ exit
277
281
  EOC
278
282
  end
279
283
 
284
+ def candidates_with_class(code, lineno, column=nil)
285
+ klass, methods = runtime_data_with_class(code, lineno, column) rescue ["", ""]
286
+ raise NoCandidates, "No candidates." if methods.nil? or methods.empty?
287
+ [klass, methods.split(/ /).sort]
288
+ end
289
+
280
290
  # Array of completion candidates.
291
+ class NoCandidates < RuntimeError; end
281
292
  def candidates(code, lineno, column=nil)
282
- methods = runtime_data(code, lineno, column) rescue ""
283
- methods.split(/ /).sort
293
+ candidates_with_class(code, lineno, column)[1]
284
294
  end
285
295
 
286
296
  # Completion code for editors.
287
297
  def completion_code(code, lineno, column=nil)
288
- candidates(code, lineno, column).join("\n")
298
+ candidates(code, lineno, column).join("\n") rescue "\n"
289
299
  end
290
300
  end
291
301
 
@@ -299,6 +309,8 @@ class XMPCompletionClassInfoFilter < XMPCompletionFilter
299
309
 
300
310
  def completion_code(code, lineno, column=nil)
301
311
  candidates(code, lineno, column).join("\n").tr("\0", "\t")
312
+ rescue NoCandidates
313
+ ""
302
314
  end
303
315
  end
304
316
 
@@ -318,23 +330,27 @@ class XMPCompletionEmacsFilter < XMPCompletionFilter
318
330
  table << "))\n"
319
331
  alist << "))\n"
320
332
  rescue Exception => err
321
- return %Q[(error "#{err.message}")]
333
+ return error_code(err)
322
334
  end
323
335
  elisp << table << alist
324
336
  elisp << %Q[(setq pattern "#{prefix}")\n]
325
337
  elisp << %Q[(try-completion pattern rct-method-completion-table nil)\n]
326
338
  elisp << ")" # /progn
327
339
  end
328
- end
329
340
 
330
- class XMPCompletionEmacsIciclesFilter < XMPCompletionFilter
331
- @candidates_with_description_flag = true
341
+ def error_code(err)
342
+ case err
343
+ when NoCandidates
344
+ %Q[(error "#{err.message}")]
345
+ else
346
+ %Q[(error "#{err.message}\n#{err.backtrace.join("\n")}")]
347
+ end
332
348
 
333
- def candidates(code, lineno, column=nil)
334
- klass, methods = runtime_data_with_class(code, lineno, column) rescue ["", ""]
335
- @klass = klass
336
- methods.split(/ /).sort
337
349
  end
350
+ end
351
+
352
+ class XMPCompletionEmacsIciclesFilter < XMPCompletionEmacsFilter
353
+ @candidates_with_description_flag = true
338
354
 
339
355
  def completion_code(code, lineno, column=nil)
340
356
  elisp = "(progn\n"
@@ -342,7 +358,8 @@ class XMPCompletionEmacsIciclesFilter < XMPCompletionFilter
342
358
  help_alist = "(setq alist '("
343
359
 
344
360
  begin
345
- candidates(code, lineno, column).sort.each do |minfo|
361
+ klass, cands = candidates_with_class(code, lineno, column)
362
+ cands.sort.each do |minfo|
346
363
  meth, description = split_method_info(minfo)
347
364
  table << format('("%s\\t[%s]") ', meth, description)
348
365
  help_alist << format('("%s" . "%s")', meth, description)
@@ -350,12 +367,13 @@ class XMPCompletionEmacsIciclesFilter < XMPCompletionFilter
350
367
  table << "))\n"
351
368
  help_alist << "))\n"
352
369
  rescue Exception => err
353
- return %Q[(error "#{err.message}")]
370
+ return error_code(err)
354
371
  end
355
372
  elisp << table << help_alist
356
373
  elisp << %Q[(setq pattern "#{prefix}")\n]
357
- elisp << %Q[(setq klass "#{@klass}")\n]
374
+ elisp << %Q[(setq klass "#{klass}")\n]
358
375
  elisp << ")" # /progn
359
376
  end
360
377
  end
361
378
 
379
+ end
@@ -1,6 +1,8 @@
1
1
  require 'rcodetools/completion'
2
2
  # Call Ri for any editors!!
3
3
  # by rubikitch <rubikitch@ruby-lang.org>
4
+ module Rcodetools
5
+
4
6
  class XMPDocFilter < XMPFilter
5
7
  include ProcessParticularLine
6
8
 
@@ -163,3 +165,4 @@ class XMPRiVimFilter < XMPDocFilter
163
165
  end
164
166
  end
165
167
 
168
+ end
@@ -0,0 +1,222 @@
1
+ ## Rcodetools version of ruby_fork
2
+ #
3
+ # Based on ruby_fork.rb by Ryan Davis, Eric Hodel, Zen Spider Software
4
+ #
5
+ # (The MIT License)
6
+ #
7
+ # Copyright (c) 2006 Ryan Davis, Eric Hodel, Zen Spider Software <support@zenspider.com>
8
+ # 2007 rubikitch <rubikitch@ruby-lang.org>
9
+ #
10
+ # Permission is hereby granted, free of charge, to any person obtaining
11
+ # a copy of this software and associated documentation files (the
12
+ # "Software"), to deal in the Software without restriction, including
13
+ # without limitation the rights to use, copy, modify, merge, publish,
14
+ # distribute, sublicense, and/or sell copies of the Software, and to
15
+ # permit persons to whom the Software is furnished to do so, subject to
16
+ # the following conditions:
17
+ #
18
+ # The above copyright notice and this permission notice shall be
19
+ # included in all copies or substantial portions of the Software.
20
+ #
21
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
+
29
+ require 'optparse'
30
+ require 'socket'
31
+ require 'rcodetools/fork_config'
32
+
33
+ module Rcodetools
34
+ module Fork
35
+
36
+ USAGE_HELP = <<XXX
37
+
38
+ rct-fork and rct-fork-client (we) are originally ruby_fork/ruby_fork_client in ZenTest by Zen Spider Software and are slightly modified for rcodetools.
39
+ Completion or document browsing in a script with heavy libraries such as Rails takes a significant latency.
40
+ We eliminate constant overhead of loading heavy libraries.
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.
43
+
44
+ rct-fork-client connects to the rct-fork server and runs script in server's environment.
45
+
46
+ xmpfilter/rct-complete/rct-doc can auto-detect rct-fork process with --fork option.
47
+ This means that once you start up rct-fork, you do not have to start up rct-fork-client manually.
48
+
49
+ demo/fork-demo.sh shows rct-fork example.
50
+
51
+ !!WARNING!!
52
+ We are only meant to run xmpfilter/rct-complete/rct-doc!
53
+ If you want to run other programs, use original ruby_fork/ruby_fork_client.
54
+ XXX
55
+ # '
56
+
57
+ DEFAULT_SETTINGS = {
58
+ :requires => [],
59
+ :code => [],
60
+ :extra_paths => [],
61
+ :port => PORT,
62
+ }
63
+
64
+ def self.add_env_args(opts, settings)
65
+ opts.separator ''
66
+ opts.separator 'Process environment options:'
67
+
68
+ opts.separator ''
69
+ opts.on('-e CODE', 'Execute CODE in parent process.',
70
+ 'May be specified multiple times.') do |code|
71
+ settings[:code] << code
72
+ end
73
+
74
+ opts.separator ''
75
+ opts.on('-I DIRECTORY', 'Adds DIRECTORY to $LOAD_PATH.',
76
+ 'May be specified multiple times.') do |dir|
77
+ settings[:extra_paths] << dir
78
+ end
79
+
80
+ opts.separator ''
81
+ opts.on('-r LIBRARY', 'Require LIBRARY in the parent process.',
82
+ 'May be specified multiple times.') do |lib|
83
+ settings[:requires] << lib
84
+ end
85
+ end
86
+
87
+ def self.daemonize(io = File.open('/dev/null', 'r+'))
88
+ fork and exit!
89
+ Process.setsid
90
+ fork and exit!
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
96
+
97
+ yield if block_given?
98
+ end
99
+
100
+ def self.parse_client_args(args)
101
+ settings = Marshal.load Marshal.dump(DEFAULT_SETTINGS)
102
+
103
+ opts = OptionParser.new do |opts|
104
+ opts.banner = "Usage: #{$0} [options]\n#{USAGE_HELP}"
105
+
106
+ opts.separator ''
107
+ opts.on('-p', '--port PORT',
108
+ 'Listen for connections on PORT.',
109
+ "Default: #{settings[:port]}") do |port|
110
+ settings[:port] = port.to_i
111
+ end
112
+
113
+ opts.separator ''
114
+ opts.on('-h', '--help', 'You\'re looking at it.') do
115
+ $stderr.puts opts
116
+ exit 1
117
+ end
118
+
119
+ add_env_args opts, settings
120
+ end
121
+
122
+ opts.parse! args
123
+
124
+ return settings
125
+ end
126
+
127
+ def self.parse_server_args(args)
128
+ settings = Marshal.load Marshal.dump(DEFAULT_SETTINGS)
129
+
130
+ opts = OptionParser.new do |opts|
131
+ opts.banner = "Usage: #{$0} [options]\n#{USAGE_HELP}"
132
+
133
+ opts.separator ''
134
+ opts.on('-p', '--port PORT',
135
+ 'Listen for connections on PORT.',
136
+ "Default: #{settings[:port]}") do |port|
137
+ settings[:port] = port.to_i
138
+ end
139
+
140
+ opts.separator ''
141
+ opts.on('-h', '--help', 'You\'re looking at it.') do
142
+ $stderr.puts opts
143
+ exit 1
144
+ end
145
+
146
+ add_env_args opts, settings
147
+ end
148
+
149
+ opts.parse! args
150
+
151
+ return settings
152
+ end
153
+
154
+ def self.start_client(args = ARGV)
155
+ trap 'INT' do exit 1 end # Exit gracefully
156
+
157
+ settings = parse_client_args args
158
+
159
+ args = Marshal.dump [settings, ARGV]
160
+
161
+ socket = TCPSocket.new 'localhost', settings[:port]
162
+
163
+ socket.puts args.length
164
+ socket.write args
165
+ socket.close_write
166
+
167
+ until socket.eof?
168
+ $stdout.puts socket.gets
169
+ end
170
+ end
171
+
172
+ def self.start_server(args = ARGV)
173
+ write_pwd
174
+ settings = parse_server_args args
175
+ setup_environment settings
176
+
177
+ server = TCPServer.new 'localhost', settings[:port]
178
+
179
+ $stderr.puts "#{$0} Running as PID #{$$} on #{settings[:port]}"
180
+
181
+ loop do
182
+ Thread.new server.accept do |socket|
183
+ begin
184
+ args_length = socket.gets.to_i
185
+ args = socket.read args_length
186
+ settings, argv = Marshal.load args
187
+
188
+ fork do
189
+ daemonize socket do
190
+ ARGV.replace argv
191
+ setup_environment settings
192
+ socket.close
193
+ end
194
+ end
195
+
196
+ socket.close # close my copy.
197
+ rescue => e
198
+ socket.close if socket
199
+ end
200
+ end
201
+ end
202
+ rescue Interrupt, SystemExit
203
+ File.unlink PWD_FILE
204
+ rescue Exception => e
205
+ File.unlink PWD_FILE
206
+ puts "Failed to catch #{e.class}:#{e.message}"
207
+ puts "\t#{e.backtrace.join "\n\t"}"
208
+ end
209
+
210
+ def self.setup_environment(settings)
211
+ settings[:extra_paths].map! { |dir| dir.split ':' }
212
+ settings[:extra_paths].flatten!
213
+ settings[:extra_paths].each { |dir| $:.unshift dir }
214
+
215
+ settings[:requires].each { |file| require file }
216
+
217
+ settings[:code].each { |code| eval code }
218
+ end
219
+
220
+ end
221
+
222
+ end
@@ -0,0 +1,26 @@
1
+
2
+ module Rcodetools
3
+
4
+ module Fork
5
+ PORT = 9085
6
+ # Contains $PWD of rct-fork server. Exists only while running.
7
+ PWD_FILE = File.expand_path "~/.rct-fork.pwd"
8
+
9
+ def self.chdir_fork_directory
10
+ if run?
11
+ Dir.chdir File.read(PWD_FILE)
12
+ else
13
+ raise "rct-fork is not running."
14
+ end
15
+ end
16
+
17
+ def self.write_pwd
18
+ open(PWD_FILE, "w"){|f| f.print Dir.pwd }
19
+ end
20
+
21
+ def self.run?
22
+ File.file? PWD_FILE
23
+ end
24
+ end
25
+
26
+ end
@@ -1,5 +1,6 @@
1
1
  require 'optparse'
2
2
 
3
+ module Rcodetools
3
4
  # Domain specific OptionParser extensions
4
5
  module OptionHandler
5
6
  def set_banner
@@ -15,6 +16,15 @@ module OptionHandler
15
16
  on("--column=COLUMN", "Current column number.") do |n|
16
17
  options[:column] = n.to_i
17
18
  end
19
+ on("-t TEST", "--test=TEST",
20
+ "Execute test script. ",
21
+ "TEST is TESTSCRIPT, TESTSCRIPT@TESTMETHOD, or TESTSCRIPT@LINENO.",
22
+ "You must specify --filename option.") do |t|
23
+ options[:test_script], options[:test_method] = t.split(/@/)
24
+ end
25
+ on("--filename=FILENAME", "Filename of standard input.") do |f|
26
+ options[:filename] = f
27
+ end
18
28
  end
19
29
 
20
30
  def handle_interpreter(options)
@@ -36,7 +46,15 @@ module OptionHandler
36
46
  on("-e EXPR", "--eval=EXPR", "--stub=EXPR", "Evaluate EXPR after execution.") do |expr|
37
47
  options[:evals] << expr
38
48
  end
39
-
49
+ on("--fork", "Use rct-fork-client if rct-fork is running.") do
50
+ options[:detect_rct_fork] = true
51
+ end
52
+ on("--rbtest", "Use rbtest.") do
53
+ options[:use_rbtest] = true
54
+ end
55
+ on("--detect-rbtest", "Use rbtest if '=begin test_*' blocks exist.") do
56
+ options[:detect_rbtest] = true
57
+ end
40
58
  end
41
59
 
42
60
  def handle_misc(options)
@@ -79,6 +97,15 @@ def set_extra_opts(options)
79
97
  end
80
98
  end
81
99
 
100
+ def check_opts(options)
101
+ if options[:test_script]
102
+ unless options[:filename]
103
+ $stderr.puts "You must specify --filename as well as -t(--test)."
104
+ exit 1
105
+ end
106
+ end
107
+ end
108
+
82
109
  DEFAULT_OPTIONS = {
83
110
  :interpreter => "ruby",
84
111
  :options => ["hoge"],
@@ -92,4 +119,10 @@ DEFAULT_OPTIONS = {
92
119
  :use_parentheses => true,
93
120
  :column => nil,
94
121
  :output_stdout => true,
122
+ :test_script => nil,
123
+ :test_method => nil,
124
+ :detect_rct_fork => false,
125
+ :use_rbtest => false,
126
+ :detect_rbtest => false,
95
127
  }
128
+ end # /Rcodetools