rcodetools 0.5.0.0 → 0.7.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 (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