virb 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ pkg/
2
+ .virb
data/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # Virb
2
+
3
+ Virb is an interactive Vim mode for IRB, Rails console, and Pry.
4
+
5
+ ## Motivation
6
+
7
+ The IRB is Ruby's interactive REPL. IRB is a very handy tool, but its
8
+ text-editing capabilities are limited. Virb wraps an IRB session in a Vim
9
+ session and gives you convenient ways to evaluate Ruby code from Vim.
10
+
11
+ Virb inverts the approach taken by
12
+ the [interactive_editor](https://github.com/jberkel/interactive_editor) gem and
13
+ similar solutions which let you pop out into Vim from IRB and come back to IRB
14
+ to see the results. Virb keeps you in Vim at all times, calling IRB behind the
15
+ scenes and fetching IBR's output to display inside Vim.
16
+
17
+ ## Install
18
+
19
+ gem install virb
20
+
21
+ Virb requires Ruby 1.9 and Vim 7.2 or above. Virb has been tested only on OS X
22
+ 10.8 and Ubuntu Linux.
23
+
24
+
25
+ ## Using Virb
26
+
27
+ Start up Virb with the command
28
+
29
+ virb [file]
30
+
31
+ The optional `file` is a text file that contains Ruby code that you
32
+ would like to run interactively.
33
+
34
+ Virb opens 2 Vim buffers. The bottom buffer is the interactive buffer,
35
+ where you can edit Ruby code and then send it to the underlying interactive
36
+ Ruby session for evaluation. The top buffer is the output buffer, where you
37
+ can see the IRB session you are controlling from the interactive buffer.
38
+
39
+ To evaluate code in the interactive buffer:
40
+
41
+ To evaluate a line of code, put the cursor on it, and press ENTER in normal mode.
42
+
43
+ To evaluate several lines of code, you can either
44
+
45
+ 1. select the lines in Vim's visual mode, and press ENTER to evaluate them;
46
+ 2. use an ed-style range command: `:[range]Virb`
47
+
48
+ If IRB takes too long (more than about half a second) to evaluate your code,
49
+ you may need to manually force the session buffer to update itself. You can
50
+ force an update by pressing SPACE in normal mode.
51
+
52
+
53
+ ## Using Virb with Pry
54
+
55
+ Make sure you have the `pry` gem installed. Then you can run this:
56
+
57
+ virb-pry [file]
58
+
59
+ When virb opens, you should be able to send your code for evaluation to Pry and
60
+ get Pry output in the virb session buffer.
61
+
62
+ ## How to wrap Rails console with Virb
63
+
64
+ If you want to use Virb with the standard Rails console:
65
+
66
+ Put this in your Gemfile:
67
+
68
+ group :development do
69
+ gem 'virb'
70
+ end
71
+
72
+ and start Rails console as you do normally. You should see the Virb interface
73
+ open, where you can interact with the Ralis console through a Vim buffer and
74
+ see its output in the other Vim buffer.
75
+
76
+ If you want to use Virb with Pry and Rails console:
77
+
78
+ Put this in your Gemfile:
79
+
80
+ group :development do
81
+ gem 'pry'
82
+ gem 'virb'
83
+ end
84
+
85
+ and start Rails console like this:
86
+
87
+ VIRB=pry rails c
88
+
89
+
90
+ ## Caveats
91
+
92
+ The normal command line options for `irb` and `pry` do not work with `virb`.
93
+
94
+
95
+ ## Author
96
+
97
+ Virb was written by [Daniel Choi](http://danielchoi.com/software), an independent software developer based in Cambridge, Massachusetts.
98
+
99
+ * [GitHub](http://github.com/danchoi)
100
+ * [Twitter](http://twitter.com/danchoi)
101
+ * I am available for short to medium-term consulting projects: [Email](mailto:dhchoi@gmail.com)
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ desc "release and build and push new website"
7
+ task :push => [:release, :web]
8
+
9
+ desc "build and push website"
10
+ task :web => :build_webpage do
11
+ puts "Building and pushing website"
12
+ Dir.chdir "../project-webpages" do
13
+ `scp out/virb.html zoe2@instantwatcher.com:~/danielchoi.com/public/software/`
14
+ `rsync -avz out/images-virb zoe2@instantwatcher.com:~/danielchoi.com/public/software/`
15
+ `rsync -avz out/stylesheets zoe2@instantwatcher.com:~/danielchoi.com/public/software/`
16
+ `rsync -avz out/lightbox2 zoe2@instantwatcher.com:~/danielchoi.com/public/software/`
17
+ end
18
+ `open http://danielchoi.com/software/virb.html`
19
+ end
20
+
21
+ desc "build webpage"
22
+ task :build_webpage do
23
+ `cp README.md ../project-webpages/src/virb.README.markdown`
24
+ require "./lib/virb/version"
25
+ version = Virb::VERSION
26
+ puts "Version detected: #{version}"
27
+ Dir.chdir "../project-webpages" do
28
+ puts `ruby gen.rb virb #{version}`
29
+ `open out/virb.html`
30
+ end
31
+ end
32
+
33
+ task :default => :test
34
+
data/bin/virb ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if %w{ -h --help --version -v }.include?(ARGV[0])
4
+ require 'virb/version'
5
+ puts <<END
6
+ virb #{Virb::VERSION}
7
+
8
+ For instructions, please visit http://github.com/danchoi/virb
9
+ Author: Daniel Choi
10
+ License: MIT
11
+ END
12
+ exit
13
+ end
14
+ require 'virb/default'
15
+ IRB.start
data/bin/virb-pry ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if %w{ -h --help --version -v }.include?(ARGV[0])
4
+ require 'virb/version'
5
+ puts <<END
6
+ virb #{Virb::VERSION}
7
+
8
+ For instructions, please visit http://github.com/danchoi/virb
9
+ Author: Daniel Choi
10
+ License: MIT
11
+ END
12
+ exit
13
+ end
14
+ require 'virb/pry'
15
+ Virb::Pry.start
data/images/virb1.png ADDED
Binary file
data/images/virb2.png ADDED
Binary file
data/images/virb3.png ADDED
Binary file
@@ -0,0 +1,459 @@
1
+ #
2
+ # irb.rb - irb main module
3
+ # $Release Version: 0.9.6 $
4
+ # $Revision: 31641 $
5
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
6
+ #
7
+ # Modified for virb by Daniel Choi dhchoi@gmail.com
8
+ # --
9
+ #
10
+ #
11
+ #
12
+ require "e2mmap"
13
+
14
+ require 'stringio'
15
+
16
+ require "irb/init"
17
+ require "irb/context"
18
+ require "irb/extend-command"
19
+ #require "irb/workspace"
20
+
21
+ require "irb/ruby-lex"
22
+ require "irb/input-method"
23
+ require "irb/locale"
24
+
25
+ `rm -rf .virb`
26
+ `mkdir -p .virb`
27
+ unless File.exist?('.virb/fifo')
28
+ `mkfifo .virb/fifo`
29
+ end
30
+ `touch .virb/session`
31
+
32
+ STDOUT.sync = true
33
+
34
+ $outfile = '.virb/session'
35
+ STDERR.reopen "/dev/null" # this prevent logging to cursor location in rails c
36
+ $infifo = '.virb/fifo'
37
+
38
+ module IRB
39
+ class StdioInputMethod < InputMethod
40
+ def initialize
41
+ super
42
+ @line_no = 0
43
+ @line = []
44
+ @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
45
+ @stdout = IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
46
+ end
47
+
48
+ def gets
49
+ print @prompt
50
+ line = @stdin.gets
51
+ print line # this is added by dan choi to ensure echoing of executed code in session window
52
+ @line[@line_no += 1] = line
53
+ end
54
+
55
+ def eof?
56
+ @stdin.eof?
57
+ end
58
+
59
+ def readable_atfer_eof?
60
+ true
61
+ end
62
+
63
+ def line(line_no)
64
+ @line[line_no]
65
+ end
66
+
67
+ def encoding
68
+ @stdin.external_encoding
69
+ end
70
+ end
71
+ end
72
+
73
+ module IRB
74
+
75
+ class Abort < Exception;end
76
+
77
+ #
78
+ @CONF = {}
79
+
80
+ def IRB.conf
81
+ @CONF
82
+ end
83
+
84
+ # IRB version method
85
+ def IRB.version
86
+ if v = @CONF[:VERSION] then return v end
87
+
88
+ require "irb/version"
89
+ rv = @RELEASE_VERSION.sub(/\.0/, "")
90
+ @CONF[:VERSION] = format("irb %s(%s)", rv, @LAST_UPDATE_DATE)
91
+ end
92
+
93
+ def IRB.CurrentContext
94
+ IRB.conf[:MAIN_CONTEXT]
95
+ end
96
+
97
+ # initialize IRB and start TOP_LEVEL irb
98
+ def IRB.start(ap_path = nil)
99
+
100
+ vimscript = File.join(File.dirname(__FILE__), '..', 'virb.vim')
101
+
102
+ # strip args so IRB doesn't think it's loading a file
103
+ args = ARGV.dup
104
+ while ARGV.shift
105
+ # pass
106
+ end
107
+
108
+
109
+ fork do
110
+ original_start ap_path
111
+ end
112
+
113
+ exec("vim -S #{vimscript} #{args.join(' ')} && rm -rf .virb && kill 0")
114
+ end
115
+
116
+ def IRB.original_start(ap_path = nil)
117
+ $0 = File::basename(ap_path, ".rb") if ap_path
118
+
119
+ IRB.setup(ap_path)
120
+
121
+ if @CONF[:SCRIPT]
122
+ irb = Irb.new(nil, @CONF[:SCRIPT])
123
+ else
124
+ irb = Irb.new
125
+ end
126
+
127
+ @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
128
+ @CONF[:MAIN_CONTEXT] = irb.context
129
+
130
+ trap("SIGINT") do
131
+ irb.signal_handle
132
+ end
133
+
134
+ begin
135
+ catch(:IRB_EXIT) do
136
+ irb.eval_input
137
+ end
138
+ ensure
139
+ irb_at_exit
140
+ end
141
+ # print "\n"
142
+
143
+
144
+ end
145
+
146
+ def IRB.irb_at_exit
147
+ @CONF[:AT_EXIT].each{|hook| hook.call}
148
+ end
149
+
150
+ def IRB.irb_exit(irb, ret)
151
+ throw :IRB_EXIT, ret
152
+ end
153
+
154
+ def IRB.irb_abort(irb, exception = Abort)
155
+ if defined? Thread
156
+ irb.context.thread.raise exception, "abort then interrupt!"
157
+ else
158
+ raise exception, "abort then interrupt!"
159
+ end
160
+ end
161
+
162
+ #
163
+ # irb interpreter main routine
164
+ #
165
+ class Irb
166
+ def initialize(workspace = nil, input_method = StdioInputMethod.new , output_method = nil)
167
+
168
+ # input_method is hard to override
169
+
170
+ @context = Context.new(self, workspace, input_method, output_method)
171
+ @context.main.extend ExtendCommandBundle
172
+ @signal_status = :IN_IRB
173
+
174
+ @scanner = RubyLex.new
175
+ @scanner.exception_on_syntax_error = false
176
+
177
+ @outfile = File.open($outfile, 'w')
178
+ $stderr = @outfile
179
+ $stdout = @outfile
180
+ end
181
+ attr_reader :context
182
+ attr_accessor :scanner
183
+
184
+ def eval_input
185
+ @scanner.set_prompt do
186
+ |ltype, indent, continue, line_no|
187
+ if ltype
188
+ f = @context.prompt_s
189
+ elsif continue
190
+ f = @context.prompt_c
191
+ elsif indent > 0
192
+ f = @context.prompt_n
193
+ else
194
+ f = @context.prompt_i
195
+ end
196
+ f = "" unless f
197
+ if @context.prompting?
198
+ @context.io.prompt = p = prompt(f, ltype, indent, line_no)
199
+ else
200
+ @context.io.prompt = p = ""
201
+ end
202
+ if @context.auto_indent_mode
203
+ unless ltype
204
+ ind = prompt(@context.prompt_i, ltype, indent, line_no)[/.*\z/].size +
205
+ indent * 2 - p.size
206
+ ind += 2 if continue
207
+ @context.io.prompt = p + " " * ind if ind > 0
208
+ end
209
+ end
210
+ end
211
+
212
+ # puts @context.io.inspect
213
+ fd = IO.sysopen($infifo)
214
+ @newio = IO.new(fd)
215
+ @context.io.instance_variable_set(:@stdin, @newio)
216
+ #@context.io.instance_variable_set(:@stdout, @outfile)
217
+
218
+ @scanner.set_input(@context.io) do
219
+ signal_status(:IN_INPUT) do
220
+
221
+ if @newio.nil? || @newio.eof?
222
+ fd = IO.sysopen($infifo)
223
+ @newio = IO.new(fd)
224
+ @context.io.instance_variable_set(:@stdin, @newio)
225
+ end
226
+
227
+ if l = @context.io.gets
228
+ print l if @context.verbose?
229
+ else
230
+ if @context.ignore_eof? and @context.io.readable_after_eof?
231
+ l = "\n"
232
+ if @context.verbose?
233
+ printf "Use \"exit\" to leave %s\n", @context.ap_name
234
+ end
235
+ else
236
+ print "\n"
237
+ end
238
+ end
239
+ l
240
+ end
241
+ end
242
+
243
+ @scanner.each_top_level_statement do |line, line_no|
244
+ signal_status(:IN_EVAL) do
245
+ begin
246
+ line.untaint
247
+
248
+ # This is to handle puts etc which print to stdout instead
249
+ # of returning a value
250
+ stringio = StringIO.new
251
+ $stdout = stringio
252
+ @context.evaluate(line, line_no)
253
+ $stdout = @outfile
254
+
255
+ stringio.rewind
256
+ print stringio.read
257
+ output_value if @context.echo?
258
+
259
+ exc = nil
260
+ rescue Interrupt => exc
261
+ rescue SystemExit, SignalException
262
+ raise
263
+ rescue Exception => exc
264
+ end
265
+ if exc
266
+ print exc.class, ": ", exc, "\n"
267
+ if exc.backtrace[0] =~ /irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ &&
268
+ !(SyntaxError === exc)
269
+ irb_bug = true
270
+ else
271
+ irb_bug = false
272
+ end
273
+
274
+ messages = []
275
+ lasts = []
276
+ levels = 0
277
+ for m in exc.backtrace
278
+ m = @context.workspace.filter_backtrace(m) unless irb_bug
279
+ if m
280
+ if messages.size < @context.back_trace_limit
281
+ messages.push "\tfrom "+m
282
+ else
283
+ lasts.push "\tfrom "+m
284
+ if lasts.size > @context.back_trace_limit
285
+ lasts.shift
286
+ levels += 1
287
+ end
288
+ end
289
+ end
290
+ end
291
+ print messages.join("\n"), "\n"
292
+ unless lasts.empty?
293
+ printf "... %d levels...\n", levels if levels > 0
294
+ print lasts.join("\n")
295
+ end
296
+ print "Maybe IRB bug!\n" if irb_bug
297
+ end
298
+ if $SAFE > 2
299
+ abort "Error: irb does not work for $SAFE level higher than 2"
300
+ end
301
+ end
302
+ end
303
+ end
304
+
305
+ # DANCHOI
306
+ def print *s
307
+ @outfile.print *s
308
+ @outfile.flush
309
+ end
310
+
311
+ def suspend_name(path = nil, name = nil)
312
+ @context.irb_path, back_path = path, @context.irb_path if path
313
+ @context.irb_name, back_name = name, @context.irb_name if name
314
+ begin
315
+ yield back_path, back_name
316
+ ensure
317
+ @context.irb_path = back_path if path
318
+ @context.irb_name = back_name if name
319
+ end
320
+ end
321
+
322
+ def suspend_workspace(workspace)
323
+ @context.workspace, back_workspace = workspace, @context.workspace
324
+ begin
325
+ yield back_workspace
326
+ ensure
327
+ @context.workspace = back_workspace
328
+ end
329
+ end
330
+
331
+ def suspend_input_method(input_method)
332
+ back_io = @context.io
333
+ @context.instance_eval{@io = input_method}
334
+ begin
335
+ yield back_io
336
+ ensure
337
+ @context.instance_eval{@io = back_io}
338
+ end
339
+ end
340
+
341
+ def suspend_context(context)
342
+ @context, back_context = context, @context
343
+ begin
344
+ yield back_context
345
+ ensure
346
+ @context = back_context
347
+ end
348
+ end
349
+
350
+ def signal_handle
351
+ unless @context.ignore_sigint?
352
+ print "\nabort!\n" if @context.verbose?
353
+ exit
354
+ end
355
+
356
+ case @signal_status
357
+ when :IN_INPUT
358
+ print "^C\n"
359
+ raise RubyLex::TerminateLineInput
360
+ when :IN_EVAL
361
+ IRB.irb_abort(self)
362
+ when :IN_LOAD
363
+ IRB.irb_abort(self, LoadAbort)
364
+ when :IN_IRB
365
+ # ignore
366
+ else
367
+ # ignore other cases as well
368
+ end
369
+ end
370
+
371
+ def signal_status(status)
372
+ return yield if @signal_status == :IN_LOAD
373
+
374
+ signal_status_back = @signal_status
375
+ @signal_status = status
376
+ begin
377
+ yield
378
+ ensure
379
+ @signal_status = signal_status_back
380
+ end
381
+ end
382
+
383
+ def prompt(prompt, ltype, indent, line_no)
384
+ p = prompt.dup
385
+ p.gsub!(/%([0-9]+)?([a-zA-Z])/) do
386
+ case $2
387
+ when "N"
388
+ @context.irb_name
389
+ when "m"
390
+ @context.main.to_s
391
+ when "M"
392
+ @context.main.inspect
393
+ when "l"
394
+ ltype
395
+ when "i"
396
+ if $1
397
+ format("%" + $1 + "d", indent)
398
+ else
399
+ indent.to_s
400
+ end
401
+ when "n"
402
+ if $1
403
+ format("%" + $1 + "d", line_no)
404
+ else
405
+ line_no.to_s
406
+ end
407
+ when "%"
408
+ "%"
409
+ end
410
+ end
411
+ p
412
+ end
413
+
414
+ def output_value
415
+ # printf @context.return_format, @context.inspect_last_value
416
+ r = sprintf @context.return_format, @context.inspect_last_value
417
+ print r
418
+ end
419
+
420
+ def inspect
421
+ ary = []
422
+ for iv in instance_variables
423
+ case (iv = iv.to_s)
424
+ when "@signal_status"
425
+ ary.push format("%s=:%s", iv, @signal_status.id2name)
426
+ when "@context"
427
+ ary.push format("%s=%s", iv, eval(iv).__to_s__)
428
+ else
429
+ ary.push format("%s=%s", iv, eval(iv))
430
+ end
431
+ end
432
+ format("#<%s: %s>", self.class, ary.join(", "))
433
+ end
434
+ end
435
+
436
+ # Singleton method
437
+ def @CONF.inspect
438
+ IRB.version unless self[:VERSION]
439
+
440
+ array = []
441
+ for k, v in sort{|a1, a2| a1[0].id2name <=> a2[0].id2name}
442
+ case k
443
+ when :MAIN_CONTEXT, :__TMP__EHV__
444
+ array.push format("CONF[:%s]=...myself...", k.id2name)
445
+ when :PROMPT
446
+ s = v.collect{
447
+ |kk, vv|
448
+ ss = vv.collect{|kkk, vvv| ":#{kkk.id2name}=>#{vvv.inspect}"}
449
+ format(":%s=>{%s}", kk.id2name, ss.join(", "))
450
+ }
451
+ array.push format("CONF[:%s]={%s}", k.id2name, s.join(", "))
452
+ else
453
+ array.push format("CONF[:%s]=%s", k.id2name, v.inspect)
454
+ end
455
+ end
456
+ array.join("\n")
457
+ end
458
+ end
459
+
data/lib/virb/pry.rb ADDED
@@ -0,0 +1,81 @@
1
+ `rm -rf .virb`
2
+ `mkdir -p .virb`
3
+ unless File.exist?('.virb/fifo')
4
+ `mkfifo .virb/fifo`
5
+ end
6
+ `touch .virb/session`
7
+
8
+ module Virb
9
+ class Pry
10
+ class Fifo
11
+ def initialize
12
+ reinit_fifo
13
+ end
14
+ def reinit_fifo
15
+ fd = IO.sysopen(".virb/fifo")
16
+ @io = IO.new(fd, 'r')
17
+ end
18
+ def readline(current_prompt)
19
+ $stdout.print current_prompt
20
+ if @io.eof?
21
+ reinit_fifo
22
+ end
23
+ x = @io.gets
24
+ $stdout.print x
25
+ x
26
+ end
27
+ def rewind
28
+ end
29
+ end
30
+
31
+ # fakes a tty stdout
32
+ class Output
33
+ def initialize
34
+ @out = File.open(".virb/session", "w")
35
+ @out.sync = true
36
+ end
37
+ def print s
38
+ @out.print s
39
+ end
40
+ def puts s
41
+ @out.puts s
42
+ end
43
+ def write s
44
+ @out.write s
45
+ end
46
+ def flush
47
+ @out.flush
48
+ end
49
+ def tty?
50
+ true
51
+ end
52
+ end
53
+
54
+ def self.start
55
+ pgid = Process.getpgid(Process.pid())
56
+
57
+ pid = fork do
58
+ ENV['TERM'] = 'dumb'
59
+ require 'pry'
60
+
61
+ out = Virb::Pry::Output.new
62
+ $stdout = out
63
+ $stderr = out
64
+
65
+ ::Pry.cli = true
66
+ ::Pry.color = false
67
+ ::Pry.config.pager = false
68
+ ::Pry.config.print = ::Pry::SIMPLE_PRINT
69
+ ::Pry.config.auto_indent = false # turns off ansi control escape sequences
70
+ input = Fifo.new
71
+ ::Pry.input = input
72
+ ::Pry.config.output = out
73
+ ::Pry.start(TOPLEVEL_BINDING.eval('self'))
74
+ end
75
+
76
+ args = ARGV.dup
77
+ vimscript = File.join(File.dirname(__FILE__), '..', 'virb.vim')
78
+ exec("vim -S #{vimscript} #{args.join(' ')} && rm -rf .virb && kill 0")
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,205 @@
1
+ module PryRails
2
+ Commands = Pry::CommandSet.new do
3
+ create_command "show-routes", "Print out all defined routes in match order, with names." do
4
+ group "Rails"
5
+
6
+ def options(opt)
7
+ opt.banner unindent <<-USAGE
8
+ Usage: show-routes [-G]
9
+
10
+ show-routes displays the current Rails app's routes.
11
+ USAGE
12
+
13
+ opt.on :G, "grep", "Filter output by regular expression", :argument => true
14
+ end
15
+
16
+ def process
17
+ Rails.application.reload_routes!
18
+ all_routes = Rails.application.routes.routes
19
+
20
+ all_routes = begin
21
+ begin
22
+ # rails 4
23
+ require 'action_dispatch/routing/inspector'
24
+ inspector = ActionDispatch::Routing::RoutesInspector.new
25
+ rescue LoadError => e
26
+ # rails 3.2
27
+ require 'rails/application/route_inspector'
28
+ inspector = Rails::Application::RouteInspector.new
29
+ end
30
+ inspector.format(all_routes)
31
+ rescue LoadError => e
32
+ # rails 3.0 and 3.1. cribbed from
33
+ # https://github.com/rails/rails/blob/3-1-stable/railties/lib/rails/tasks/routes.rake
34
+ routes = all_routes.collect do |route|
35
+
36
+ reqs = route.requirements.dup
37
+ reqs[:to] = route.app unless route.app.class.name.to_s =~ /^ActionDispatch::Routing/
38
+ reqs = reqs.empty? ? "" : reqs.inspect
39
+
40
+ {:name => route.name.to_s, :verb => route.verb.to_s, :path => route.path, :reqs => reqs}
41
+ end
42
+
43
+ # Skip the route if it's internal info route
44
+ routes.reject! { |r| r[:path] =~ %r{/rails/info/properties|^/assets} }
45
+
46
+ name_width = routes.map{ |r| r[:name].length }.max
47
+ verb_width = routes.map{ |r| r[:verb].length }.max
48
+ path_width = routes.map{ |r| r[:path].length }.max
49
+
50
+ routes.map do |r|
51
+ "#{r[:name].rjust(name_width)} #{r[:verb].ljust(verb_width)} #{r[:path].ljust(path_width)} #{r[:reqs]}"
52
+ end
53
+ end
54
+
55
+ output.puts all_routes.grep(Regexp.new(opts[:G] || ".")).join "\n"
56
+ end
57
+ end
58
+
59
+ create_command "show-models", "Print out all defined models, with attribrutes." do
60
+ group "Rails"
61
+
62
+ def options(opt)
63
+ opt.banner unindent <<-USAGE
64
+ Usage: show-models
65
+
66
+ show-models displays the current Rails app's models.
67
+ USAGE
68
+
69
+ opt.on :G, "grep", "Color output red by regular expression", :argument => true
70
+ end
71
+
72
+ def process
73
+ Rails.application.eager_load!
74
+
75
+ if defined?(ActiveRecord::Base)
76
+ models = ActiveRecord::Base.descendants.map do |mod|
77
+ model_string = mod.to_s + "\n"
78
+ if mod.table_exists?
79
+ model_string << mod.columns.map { |col| " #{col.name}: #{col.type.to_s}" }.join("\n")
80
+ else
81
+ model_string << " Table doesn't exist"
82
+ end
83
+ mod.reflections.each do |model,ref|
84
+ model_string << "\n #{ref.macro.to_s} #{model}"
85
+ model_string << " through #{ref.options[:through]}" unless ref.options[:through].nil?
86
+ end
87
+ model_string
88
+ end.join("\n")
89
+ elsif defined?(Mongoid::Document)
90
+ models = get_files.map do |path|
91
+ mod = extract_class_name(path)
92
+ model_string = "\033[1;34m#{mod.to_s}\033[0m\n"
93
+ begin
94
+ if mod.constantize.included_modules.include?(Mongoid::Document)
95
+ model_string << mod.constantize.fields.values.sort_by(&:name).map { |col|
96
+ " #{col.name}: \033[1;33m#{col.options[:type].to_s.downcase}\033[0m"
97
+ }.join("\n")
98
+ mod.constantize.relations.each do |model,ref|
99
+ model_string << "\n #{kind_of_relation(ref.relation.to_s)} \033[1;34m#{model}\033[0m"
100
+ model_string << ", autosave" if ref.options[:autosave]
101
+ model_string << ", autobuild" if ref.options[:autobuild]
102
+ model_string << ", validate" if ref.options[:validate]
103
+ model_string << ", dependent-#{ref.options[:dependent]}" if ref.options[:dependent]
104
+ end
105
+ else
106
+ model_string << " Collection doesn't exist"
107
+ end
108
+ model_string
109
+
110
+ rescue Exception
111
+ STDERR.puts "Warning: exception #{$!} raised while trying to load model class #{path}"
112
+ end
113
+ end.join("\n")
114
+ end
115
+
116
+ models.gsub!(Regexp.new(opts[:G] || ".", Regexp::IGNORECASE)) { |s| text.red(s) } unless opts[:G].nil?
117
+ output.puts models
118
+ end
119
+
120
+ def get_files(prefix ='')
121
+ Dir.glob(prefix << "app/models/**/*.rb")
122
+ end
123
+
124
+ def extract_class_name(filename)
125
+ filename.split('/')[2..-1].collect { |i| i.camelize }.join('::').chomp(".rb")
126
+ end
127
+
128
+ def kind_of_relation(string)
129
+ case string.gsub('Mongoid::Relations::', '')
130
+ when 'Referenced::Many' then 'has_many'
131
+ when 'Referenced::One' then 'has_one'
132
+ when 'Referenced::In' then 'belongs_to'
133
+ when 'Embedded::Many' then 'embeds_many'
134
+ when 'Embedded::One' then 'embeds_one'
135
+ when 'Embedded::In' then 'embedded_in'
136
+ end
137
+ end
138
+ end
139
+
140
+ create_command "show-middleware" do
141
+ group "Rails"
142
+
143
+ def options(opt)
144
+ opt.banner unindent <<-USAGE
145
+ Usage: show-middleware [-G]
146
+
147
+ show-middleware shows the Rails app's middleware.
148
+
149
+ If this pry REPL is attached to a Rails server, the entire middleware
150
+ stack is displayed. Otherwise, only the middleware Rails knows about is
151
+ printed.
152
+ USAGE
153
+
154
+ opt.on :G, "grep", "Filter output by regular expression", :argument => true
155
+ end
156
+
157
+ def process
158
+ # assumes there is only one Rack::Server instance
159
+ server = nil
160
+ ObjectSpace.each_object(Rack::Server) do |object|
161
+ server = object
162
+ end
163
+
164
+ middlewares = []
165
+
166
+ if server
167
+ stack = server.instance_variable_get("@wrapped_app")
168
+ middlewares << stack.class.to_s
169
+
170
+ while stack.instance_variable_defined?("@app") do
171
+ stack = stack.instance_variable_get("@app")
172
+ # Rails 3.0 uses the Application class rather than the application
173
+ # instance itself, so we grab the instance.
174
+ stack = Rails.application if stack == Rails.application.class
175
+ middlewares << stack.class.to_s if stack != Rails.application
176
+ end
177
+ else
178
+ middleware_names = Rails.application.middleware.map do |middleware|
179
+ # After Rails 3.0, the middleware are wrapped in a special class
180
+ # that responds to #name.
181
+ if middleware.respond_to?(:name)
182
+ middleware.name
183
+ else
184
+ middleware.inspect
185
+ end
186
+ end
187
+ middlewares.concat middleware_names
188
+ end
189
+ middlewares << Rails.application.class.to_s
190
+ print_middleware middlewares.grep(Regexp.new(opts[:G] || "."))
191
+ end
192
+
193
+ def print_middleware(middlewares)
194
+ middlewares.each do |middleware|
195
+ string = if middleware == Rails.application.class.to_s
196
+ "run #{middleware}.routes"
197
+ else
198
+ "use #{middleware}"
199
+ end
200
+ output.puts string
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ module Virb
4
+ class Railtie < Rails::Railtie
5
+ if ENV['VIRB'] == 'pry'
6
+ require 'pry'
7
+ require 'virb/pry'
8
+ console do
9
+ if Rails::VERSION::MAJOR == 3
10
+ Rails::Console::IRB = Virb::Pry
11
+ unless defined? Virb::Pry::ExtendCommandBundle
12
+ Virb::Pry::ExtendCommandBundle = Module.new
13
+ end
14
+ end
15
+ if Rails::VERSION::MAJOR == 4
16
+ Rails.application.config.console = Virb::Pry
17
+ end
18
+
19
+ if (Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR >= 2) || Rails::VERSION::MAJOR == 4
20
+ require 'rails/console/app'
21
+ require 'rails/console/helpers'
22
+ TOPLEVEL_BINDING.eval('self').extend ::Rails::ConsoleMethods
23
+ end
24
+ end
25
+ require "virb/pry_commands"
26
+ ::Pry.commands.import PryRails::Commands
27
+
28
+ # do this to prevent the sql output from going to vim interactive buffer
29
+ STDERR.reopen("/dev/null")
30
+
31
+ else
32
+ require 'virb/default'
33
+ console do
34
+ if Rails::VERSION::MAJOR == 3
35
+ Rails::Console::IRB = IRB
36
+ end
37
+ if Rails::VERSION::MAJOR == 4
38
+ Rails.application.config.console = IRB
39
+ end
40
+
41
+ if (Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR >= 2) || Rails::VERSION::MAJOR == 4
42
+ require 'rails/console/app'
43
+ require 'rails/console/helpers'
44
+ TOPLEVEL_BINDING.eval('self').extend ::Rails::ConsoleMethods
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module Virb
2
+ VERSION = '0.0.2'
3
+ end
data/lib/virb.rb ADDED
@@ -0,0 +1,6 @@
1
+
2
+
3
+ if defined?(Rails)
4
+ require 'virb/railtie'
5
+ end
6
+
data/lib/virb.vim ADDED
@@ -0,0 +1,84 @@
1
+ "=================================================
2
+ " File: virb.vim
3
+ " Description: A Vim shell for irb and rails console
4
+ " Author: Daniel Choi <dhchoi@gmail.com>
5
+ " ================================================
6
+
7
+ if exists("g:loaded_virb") || &cp
8
+ finish
9
+ endif
10
+ let g:loaded_virb = 1
11
+
12
+ let s:fifo = ".virb/fifo"
13
+
14
+ " split into two windows: a session buffer and a interactive buffer
15
+
16
+ function! s:focus_virb_output_window()
17
+ if bufwinnr(s:virb_output_bufnr) == winnr()
18
+ return
19
+ end
20
+ let winnr = bufwinnr(s:virb_output_bufnr)
21
+ if winnr == -1
22
+ " create window
23
+ split! .virb/session
24
+ exec "buffer" . s:virb_output_bufnr
25
+ else
26
+ exec winnr . "wincmd w"
27
+ endif
28
+ endfunc
29
+
30
+ function! VirbStatusLine()
31
+ let line = "%<*virb interactive buffer* %r%=%-14.(%l,%c%V%)\ %P"
32
+ return line
33
+ endfunc
34
+
35
+ split! .virb/session
36
+ setlocal autoread
37
+ let s:virb_output_bufnr = bufnr('%')
38
+ setlocal nomodifiable
39
+ setlocal nu
40
+
41
+ " in interactive buffer
42
+ wincmd p
43
+ setlocal nu
44
+ setlocal statusline=%!VirbStatusLine()
45
+ command! -bar -range Virb :<line1>,<line2>call Virb()
46
+
47
+ " main execution function
48
+ func! Virb() range
49
+ let s:mtime = getftime(".virb/session")
50
+ let cmd = ":".a:firstline.",".a:lastline."w >> .virb/fifo"
51
+ exec cmd
52
+ if $VIRB == 'pry'
53
+ " a little slower
54
+ :sleep 600m
55
+ else
56
+ :sleep 400m
57
+ endif
58
+ :call VirbRefresh()
59
+ endfunc
60
+
61
+ func! VirbRefresh()
62
+ :call s:focus_virb_output_window()
63
+ ":exec ":checktime ".s:virb_output_bufnr
64
+ :e!
65
+ :normal G
66
+ syn match irbprompt /^irb\S\+\(>\|\*\).*$/
67
+ " [2] pry(main)>
68
+ syn match irbprompt /^\[\d\+\] pry.*$/
69
+ hi def link irbprompt Comment
70
+ :wincmd p
71
+ endfunc
72
+
73
+ if !hasmapto('<Plug>VirbRun')
74
+ " this is global
75
+ nnoremap <cr> :call Virb()<cr>
76
+ vnoremap <cr> :call Virb()<cr>
77
+ endif
78
+
79
+ if !hasmapto('<Plug>VirbRefresh')
80
+ " this is global
81
+ nnoremap <space> :checkt<CR>
82
+ endif
83
+
84
+
data/notes ADDED
@@ -0,0 +1,42 @@
1
+ todo
2
+ - Virb command
3
+
4
+
5
+ Pry
6
+
7
+
8
+ See pry.rb for start of Pry integration
9
+
10
+
11
+ def redirect_pry_io(new_in, new_out = StringIO.new)
12
+ old_in = Pry.input
13
+ old_out = Pry.output
14
+
15
+ Pry.input = new_in
16
+ Pry.output = new_out
17
+ begin
18
+ yield
19
+ ensure
20
+ Pry.input = old_in
21
+ Pry.output = old_out
22
+ end
23
+ end
24
+
25
+ InputTester.new("exit-all")
26
+
27
+
28
+
29
+ class InputTester
30
+ def initialize(*actions)
31
+ @orig_actions = actions.dup
32
+ @actions = actions
33
+ end
34
+
35
+ def readline(*)
36
+ @actions.shift
37
+ end
38
+
39
+ def rewind
40
+ @actions = @orig_actions.dup
41
+ end
42
+ end
data/virb.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ $:.push File.expand_path("../lib", __FILE__)
4
+ require 'virb/version'
5
+ Gem::Specification.new do |s|
6
+ s.name = "virb"
7
+ s.version = Virb::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.required_ruby_version = '>= 1.9.0'
10
+
11
+ s.authors = ["Daniel Choi"]
12
+ s.email = ["dhchoi@gmail.com"]
13
+ s.homepage = "http://danielchoi.com/software/virb.html"
14
+ s.summary = %q{A Vim shell for irb and rails console}
15
+ s.description = %q{A Vim shell for irb and rails console}
16
+
17
+ s.rubyforge_project = "virb"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.executables = ['virb', 'virb-pry']
21
+ # s.require_paths = ["lib"]
22
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: virb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Daniel Choi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-24 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A Vim shell for irb and rails console
15
+ email:
16
+ - dhchoi@gmail.com
17
+ executables:
18
+ - virb
19
+ - virb-pry
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - .gitignore
24
+ - README.md
25
+ - Rakefile
26
+ - bin/virb
27
+ - bin/virb-pry
28
+ - images/virb1.png
29
+ - images/virb2.png
30
+ - images/virb3.png
31
+ - lib/virb.rb
32
+ - lib/virb.vim
33
+ - lib/virb/default.rb
34
+ - lib/virb/pry.rb
35
+ - lib/virb/pry_commands.rb
36
+ - lib/virb/railtie.rb
37
+ - lib/virb/version.rb
38
+ - notes
39
+ - virb.gemspec
40
+ homepage: http://danielchoi.com/software/virb.html
41
+ licenses: []
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: 1.9.0
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project: virb
60
+ rubygems_version: 1.8.23
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: A Vim shell for irb and rails console
64
+ test_files: []