pry 0.6.8-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,616 @@
1
+ require "optparse"
2
+ require "method_source"
3
+ require "pry/command_base"
4
+ require "pry/pry_instance"
5
+
6
+ class Pry
7
+
8
+ # Default commands used by Pry.
9
+ class Commands < CommandBase
10
+
11
+ # We make this a lambda to avoid documenting it
12
+ meth_name_from_binding = lambda do |b|
13
+ meth_name = b.eval('__method__')
14
+ if [nil, :__binding__, :__binding_impl__].include?(meth_name)
15
+ nil
16
+ else
17
+ meth_name
18
+ end
19
+ end
20
+
21
+ check_for_dynamically_defined_method = lambda do |file|
22
+ if file =~ /(\(.*\))|<.*>/
23
+ raise "Cannot retrieve source for dynamically defined method."
24
+ end
25
+ end
26
+
27
+ remove_first_word = lambda do |text|
28
+ text.split.drop(1).join(' ')
29
+ end
30
+
31
+ command "whereami", "Show the code context for the session." do
32
+ file = target.eval('__FILE__')
33
+ line_num = target.eval('__LINE__')
34
+ klass = target.eval('self.class')
35
+
36
+ meth_name = meth_name_from_binding.call(target)
37
+ if !meth_name
38
+ output.puts "Cannot find containing method. Did you remember to use \`binding.pry\` ?"
39
+ next
40
+ end
41
+
42
+ check_for_dynamically_defined_method.call(file)
43
+
44
+ output.puts "--\nFrom #{file} @ line #{line_num} in #{klass}##{meth_name}:\n--"
45
+
46
+ # This method inspired by http://rubygems.org/gems/ir_b
47
+ File.open(file).each_with_index do |line, index|
48
+ line_n = index + 1
49
+ next unless line_n > (line_num - 6)
50
+ break if line_n > (line_num + 5)
51
+ if line_n == line_num
52
+ code =" =>#{line_n.to_s.rjust(3)}: #{line.chomp}"
53
+ if Pry.color
54
+ code = CodeRay.scan(code, :ruby).term
55
+ end
56
+ output.puts code
57
+ code
58
+ else
59
+ code = "#{line_n.to_s.rjust(6)}: #{line.chomp}"
60
+ if Pry.color
61
+ code = CodeRay.scan(code, :ruby).term
62
+ end
63
+ output.puts code
64
+ code
65
+ end
66
+ end
67
+ end
68
+
69
+ command "!", "Clear the input buffer. Useful if the parsing process goes wrong and you get stuck in the read loop." do
70
+ output.puts "Input buffer cleared!"
71
+ opts[:eval_string].clear
72
+ end
73
+
74
+ command "!pry", "Start a Pry session on current self; this even works mid-expression." do
75
+ Pry.start(target)
76
+ end
77
+
78
+ command "exit-program", "End the current program. Aliases: quit-program, !!!" do
79
+ exit
80
+ end
81
+
82
+ alias_command "quit-program", "exit-program", ""
83
+ alias_command "!!!", "exit-program", ""
84
+
85
+ command "toggle-color", "Toggle syntax highlighting." do
86
+ Pry.color = !Pry.color
87
+ output.puts "Syntax highlighting #{Pry.color ? "on" : "off"}"
88
+ end
89
+
90
+ command "simple-prompt", "Toggle the simple prompt." do
91
+ case Pry.active_instance.prompt
92
+ when Pry::SIMPLE_PROMPT
93
+ Pry.active_instance.prompt = Pry::DEFAULT_PROMPT
94
+ else
95
+ Pry.active_instance.prompt = Pry::SIMPLE_PROMPT
96
+ end
97
+ end
98
+
99
+ command "nesting", "Show nesting information." do
100
+ nesting = opts[:nesting]
101
+
102
+ output.puts "Nesting status:"
103
+ output.puts "--"
104
+ nesting.each do |level, obj|
105
+ if level == 0
106
+ output.puts "#{level}. #{Pry.view_clip(obj)} (Pry top level)"
107
+ else
108
+ output.puts "#{level}. #{Pry.view_clip(obj)}"
109
+ end
110
+ end
111
+ end
112
+
113
+ command "status", "Show status information." do
114
+ nesting = opts[:nesting]
115
+
116
+ output.puts "Status:"
117
+ output.puts "--"
118
+ output.puts "Receiver: #{Pry.view_clip(target.eval('self'))}"
119
+ output.puts "Nesting level: #{nesting.level}"
120
+ output.puts "Pry version: #{Pry::VERSION}"
121
+ output.puts "Ruby version: #{RUBY_VERSION}"
122
+
123
+ mn = meth_name_from_binding.call(target)
124
+ output.puts "Current method: #{mn ? mn : "N/A"}"
125
+ output.puts "Pry instance: #{Pry.active_instance}"
126
+ output.puts "Last result: #{Pry.view(Pry.last_result)}"
127
+ end
128
+
129
+ command "version", "Show Pry version." do
130
+ output.puts "Pry version: #{Pry::VERSION} on Ruby #{RUBY_VERSION}."
131
+ end
132
+
133
+ command "exit-all", "End all nested Pry sessions. Accepts optional return value. Aliases: !@" do
134
+ str = remove_first_word.call(opts[:val])
135
+ throw(:breakout, [0, target.eval(str)])
136
+ end
137
+
138
+ alias_command "!@", "exit-all", ""
139
+
140
+ command "ls", "Show the list of vars in the current scope. Type `ls --help` for more info." do |*args|
141
+ options = {}
142
+
143
+ # Set target local to the default -- note that we can set a different target for
144
+ # ls if we like: e.g ls my_var
145
+ target = target()
146
+
147
+ OptionParser.new do |opts|
148
+ opts.banner = %{Usage: ls [OPTIONS] [VAR]\n\
149
+ List information about VAR (the current context by default).
150
+ Shows local and instance variables by default.
151
+ --
152
+ }
153
+ opts.on("-g", "--globals", "Display global variables.") do
154
+ options[:g] = true
155
+ end
156
+
157
+ opts.on("-c", "--constants", "Display constants.") do
158
+ options[:c] = true
159
+ end
160
+
161
+ opts.on("-l", "--locals", "Display locals.") do
162
+ options[:l] = true
163
+ end
164
+
165
+ opts.on("-i", "--ivars", "Display instance variables.") do
166
+ options[:i] = true
167
+ end
168
+
169
+ opts.on("-k", "--class-vars", "Display class variables.") do
170
+ options[:k] = true
171
+ end
172
+
173
+ opts.on("-m", "--methods", "Display methods (public methods by default).") do
174
+ options[:m] = true
175
+ end
176
+
177
+ opts.on("-M", "--instance-methods", "Display instance methods (only relevant to classes and modules).") do
178
+ options[:M] = true
179
+ end
180
+
181
+ opts.on("-P", "--public", "Display public methods (with -m).") do
182
+ options[:P] = true
183
+ end
184
+
185
+ opts.on("-r", "--protected", "Display protected methods (with -m).") do
186
+ options[:r] = true
187
+ end
188
+
189
+ opts.on("-p", "--private", "Display private methods (with -m).") do
190
+ options[:p] = true
191
+ end
192
+
193
+ opts.on("-s", "--super", "Include superclass entries (relevant to constant and methods options).") do
194
+ options[:s] = true
195
+ end
196
+
197
+ opts.on("-a", "--all", "Display all types of entries.") do
198
+ options[:a] = true
199
+ end
200
+
201
+ opts.on("-v", "--verbose", "Verbose ouput.") do
202
+ options[:v] = true
203
+ end
204
+
205
+ opts.on_tail("-h", "--help", "Show this message.") do
206
+ output.puts opts
207
+ options[:h] = true
208
+ end
209
+ end.order(args) do |new_target|
210
+ target = Pry.binding_for(target.eval("#{new_target}")) if !options[:h]
211
+ end
212
+
213
+ # exit if we've displayed help
214
+ next if options[:h]
215
+
216
+ # default is locals/ivars/class vars.
217
+ # Only occurs when no options or when only option is verbose
218
+ options.merge!({
219
+ :l => true,
220
+ :i => true,
221
+ :k => true
222
+ }) if options.empty? || (options.size == 1 && options[:v])
223
+
224
+ # Display public methods by default if -m or -M switch is used.
225
+ options[:P] = true if (options[:m] || options[:M]) && !(options[:p] || options[:r])
226
+
227
+ info = {}
228
+ target_self = target.eval('self')
229
+
230
+ # ensure we have a real boolean and not a `nil` (important when
231
+ # interpolating in the string)
232
+ options[:s] = !!options[:s]
233
+
234
+ # Numbers (e.g 0, 1, 2) are for ordering the hash values in Ruby 1.8
235
+ i = -1
236
+
237
+ # Start collecting the entries selected by the user
238
+ info["local variables"] = [Array(target.eval("local_variables")).sort, i += 1] if options[:l] || options[:a]
239
+ info["instance variables"] = [Array(target.eval("instance_variables")).sort, i += 1] if options[:i] || options[:a]
240
+
241
+ info["class variables"] = [if target_self.is_a?(Module)
242
+ Array(target.eval("class_variables")).sort
243
+ else
244
+ Array(target.eval("self.class.class_variables")).sort
245
+ end, i += 1] if options[:k] || options[:a]
246
+
247
+ info["global variables"] = [Array(target.eval("global_variables")).sort, i += 1] if options[:g] || options[:a]
248
+
249
+ info["public methods"] = [Array(target.eval("public_methods(#{options[:s]})")).uniq.sort, i += 1] if (options[:m] && options[:P]) || options[:a]
250
+
251
+ info["protected methods"] = [Array(target.eval("protected_methods(#{options[:s]})")).sort, i += 1] if (options[:m] && options[:r]) || options[:a]
252
+
253
+ info["private methods"] = [Array(target.eval("private_methods(#{options[:s]})")).sort, i += 1] if (options[:m] && options[:p]) || options[:a]
254
+
255
+ info["public instance methods"] = [Array(target.eval("public_instance_methods(#{options[:s]})")).uniq.sort, i += 1] if target_self.is_a?(Module) && ((options[:M] && options[:P]) || options[:a])
256
+
257
+ info["protected instance methods"] = [Array(target.eval("protected_instance_methods(#{options[:s]})")).uniq.sort, i += 1] if target_self.is_a?(Module) && ((options[:M] && options[:r]) || options[:a])
258
+
259
+ info["private instance methods"] = [Array(target.eval("private_instance_methods(#{options[:s]})")).uniq.sort, i += 1] if target_self.is_a?(Module) && ((options[:M] && options[:p]) || options[:a])
260
+
261
+ # dealing with 1.8/1.9 compatibility issues :/
262
+ csuper = options[:s]
263
+ if Module.method(:constants).arity == 0
264
+ csuper = nil
265
+ end
266
+
267
+ info["constants"] = [Array(target_self.is_a?(Module) ? target.eval("constants(#{csuper})") :
268
+ target.eval("self.class.constants(#{csuper})")).uniq.sort, i += 1] if options[:c] || options[:a]
269
+
270
+ # verbose output?
271
+ if options[:v]
272
+
273
+ # verbose
274
+ info.sort_by { |k, v| v.last }.each do |k, v|
275
+ if !v.first.empty?
276
+ output.puts "#{k}:\n--"
277
+ if Pry.color
278
+ output.puts CodeRay.scan(Pry.view(v.first), :ruby).term
279
+ else
280
+ output.puts Pry.view(v.first)
281
+ end
282
+ output.puts
283
+ end
284
+ end
285
+
286
+ # plain
287
+ else
288
+ list = info.values.sort_by { |v| v.last }.map { |v| v.first }.inject(&:+)
289
+ if Pry.color
290
+ output.puts CodeRay.scan(Pry.view(list), :ruby).term
291
+ else
292
+ output.puts Pry.view(list)
293
+ end
294
+ list
295
+ end
296
+ end
297
+
298
+ command "cat-file", "Show output of file FILE" do |file_name|
299
+ if !file_name
300
+ output.puts "Must provide a file name."
301
+ next
302
+ end
303
+
304
+ contents = File.read(File.expand_path(file_name))
305
+ output.puts contents
306
+ contents
307
+ end
308
+
309
+ command "eval-file", "Eval a Ruby script. Type `eval-file --help` for more info." do |*args|
310
+ options = {}
311
+ target = target()
312
+ file_name = nil
313
+
314
+ OptionParser.new do |opts|
315
+ opts.banner = %{Usage: eval-file [OPTIONS] FILE
316
+ Eval a Ruby script at top-level or in the specified context. Defaults to top-level.
317
+ e.g: eval-file -c self "hello.rb"
318
+ --
319
+ }
320
+ opts.on("-c", "--context CONTEXT", "Eval the script in the specified context.") do |context|
321
+ options[:c] = true
322
+ target = Pry.binding_for(target.eval(context))
323
+ end
324
+
325
+ opts.on_tail("-h", "--help", "This message.") do
326
+ output.puts opts
327
+ options[:h] = true
328
+ end
329
+ end.order(args) do |v|
330
+ file_name = v
331
+ end
332
+
333
+ next if options[:h]
334
+
335
+ if !file_name
336
+ output.puts "You need to specify a file name. Type `eval-file --help` for help"
337
+ next
338
+ end
339
+
340
+ old_constants = Object.constants
341
+ if options[:c]
342
+ target_self = target.eval('self')
343
+ target.eval(File.read(File.expand_path(file_name)))
344
+ output.puts "--\nEval'd '#{file_name}' in the `#{target_self}` context."
345
+ else
346
+ TOPLEVEL_BINDING.eval(File.read(File.expand_path(file_name)))
347
+ output.puts "--\nEval'd '#{file_name}' at top-level."
348
+ end
349
+ new_constants = Object.constants - old_constants
350
+ output.puts "Brought in the following top-level constants: #{new_constants.inspect}" if !new_constants.empty?
351
+ end
352
+
353
+ command "cat", "Show output of VAR.inspect. Aliases: inspect" do |obj|
354
+ if !obj
355
+ output.puts "Must provide an object to inspect."
356
+ next
357
+ end
358
+
359
+ output.puts Pry.view(target.eval("#{obj}"))
360
+ end
361
+
362
+ alias_command "inspect", "cat", ""
363
+
364
+ command "cd", "Start a Pry session on VAR (use `cd ..` to go back and `cd /` to return to Pry top-level)", :keep_retval => true do |obj|
365
+ if !obj
366
+ output.puts "Must provide an object."
367
+ next
368
+ end
369
+
370
+ throw(:breakout, opts[:nesting].level) if obj == ".."
371
+
372
+ if obj == "/"
373
+ throw(:breakout, 1) if opts[:nesting].level > 0
374
+ next
375
+ end
376
+
377
+ target.eval("#{obj}.pry")
378
+ end
379
+
380
+ command "show-doc", "Show the comments above METH. Type `show-doc --help` for more info." do |*args|
381
+ options = {}
382
+ target = target()
383
+ meth_name = nil
384
+
385
+ OptionParser.new do |opts|
386
+ opts.banner = %{Usage: show-doc [OPTIONS] [METH]
387
+ Show the comments above method METH. Shows _method_ comments (rather than instance methods) by default.
388
+ e.g show-doc hello_method
389
+ --
390
+ }
391
+ opts.on("-M", "--instance-methods", "Operate on instance methods instead.") do
392
+ options[:M] = true
393
+ end
394
+
395
+ opts.on("-c", "--context CONTEXT", "Select object context to run under.") do |context|
396
+ target = Pry.binding_for(target.eval(context))
397
+ end
398
+
399
+ opts.on_tail("-h", "--help", "This message.") do
400
+ output.puts opts
401
+ options[:h] = true
402
+ end
403
+ end.order(args) do |v|
404
+ meth_name = v
405
+ end
406
+
407
+ next if options[:h]
408
+
409
+ if !meth_name
410
+ output.puts "You need to specify a method. Type `show-doc --help` for help"
411
+ next
412
+ end
413
+
414
+ begin
415
+ if options[:M]
416
+ meth = target.eval("instance_method(:#{meth_name})")
417
+ else
418
+ meth = target.eval("method(:#{meth_name})")
419
+ end
420
+ rescue
421
+ output.puts "Invalid method name: #{meth_name}. Type `show-doc --help` for help"
422
+ next
423
+ end
424
+
425
+ doc = meth.comment
426
+ file, line = meth.source_location
427
+ check_for_dynamically_defined_method.call(file)
428
+
429
+ output.puts "--\nFrom #{file} @ line ~#{line}:\n--"
430
+
431
+ if Pry.color
432
+ doc = CodeRay.scan(doc, :ruby).term
433
+ end
434
+
435
+ output.puts doc
436
+ doc
437
+ end
438
+
439
+ command "show-method", "Show the source for METH. Type `show-method --help` for more info." do |*args|
440
+ options = {}
441
+ target = target()
442
+ meth_name = nil
443
+
444
+ OptionParser.new do |opts|
445
+ opts.banner = %{Usage: show-method [OPTIONS] [METH]
446
+ Show the source for method METH. Shows _method_ source (rather than instance methods) by default.
447
+ e.g: show-method hello_method
448
+ --
449
+ }
450
+ opts.on("-M", "--instance-methods", "Operate on instance methods instead.") do
451
+ options[:M] = true
452
+ end
453
+
454
+ opts.on("-c", "--context CONTEXT", "Select object context to run under.") do |context|
455
+ target = Pry.binding_for(target.eval(context))
456
+ end
457
+
458
+ opts.on_tail("-h", "--help", "This message.") do
459
+ output.puts opts
460
+ options[:h] = true
461
+ end
462
+ end.order(args) do |v|
463
+ meth_name = v
464
+ end
465
+
466
+ next if options[:h]
467
+
468
+ # If no method name is given then use current method, if it exists
469
+ meth_name = meth_name_from_binding.call(target) if !meth_name
470
+
471
+ if !meth_name
472
+ output.puts "You need to specify a method. Type `show-method --help` for help"
473
+ next
474
+ end
475
+
476
+ begin
477
+ if options[:M]
478
+ meth = target.eval("instance_method(:#{meth_name})")
479
+ else
480
+ meth = target.eval("method(:#{meth_name})")
481
+ end
482
+ rescue
483
+ target_self = target.eval('self')
484
+ if !options[:M]&& target_self.is_a?(Module) &&
485
+ target_self.method_defined?(meth_name)
486
+ output.puts "Did you mean: show-method -M #{meth_name} ?"
487
+ end
488
+ output.puts "Invalid method name: #{meth_name}. Type `show-method --help` for help"
489
+ next
490
+ end
491
+
492
+ code = meth.source
493
+ file, line = meth.source_location
494
+ check_for_dynamically_defined_method.call(file)
495
+
496
+ output.puts "--\nFrom #{file} @ line #{line}:\n--"
497
+
498
+ if Pry.color
499
+ code = CodeRay.scan(code, :ruby).term
500
+ end
501
+
502
+ output.puts code
503
+ code
504
+ end
505
+
506
+ command "show-command", "Show sourcecode for a Pry command, e.g: show-command cd" do |command_name|
507
+ if !command_name
508
+ output.puts "You must provide a command name."
509
+ next
510
+ end
511
+
512
+ if commands[command_name]
513
+ meth = commands[command_name][:action]
514
+
515
+ code = meth.source
516
+ file, line = meth.source_location
517
+ check_for_dynamically_defined_method.call(file)
518
+
519
+ output.puts "--\nFrom #{file} @ line #{line}:\n--"
520
+
521
+ if Pry.color
522
+ code = CodeRay.scan(code, :ruby).term
523
+ end
524
+
525
+ output.puts code
526
+ code
527
+ else
528
+ output.puts "No such command: #{command_name}."
529
+ end
530
+ end
531
+
532
+ command "jump-to", "Jump to a Pry session further up the stack, exiting all sessions below." do |break_level|
533
+ break_level = break_level.to_i
534
+ nesting = opts[:nesting]
535
+
536
+ case break_level
537
+ when nesting.level
538
+ output.puts "Already at nesting level #{nesting.level}"
539
+ when (0...nesting.level)
540
+ throw(:breakout, break_level + 1)
541
+ else
542
+ max_nest_level = nesting.level - 1
543
+ output.puts "Invalid nest level. Must be between 0 and #{max_nest_level}. Got #{break_level}."
544
+ end
545
+ end
546
+
547
+ command "exit", "End the current Pry session. Accepts optional return value. Aliases: quit, back" do
548
+ str = remove_first_word.call(opts[:val])
549
+ throw(:breakout, [opts[:nesting].level, target.eval(str)])
550
+ end
551
+
552
+ alias_command "quit", "exit", ""
553
+ alias_command "back", "exit", ""
554
+
555
+ command "game", "" do |highest|
556
+ highest = highest ? highest.to_i : 100
557
+ num = rand(highest)
558
+ output.puts "Guess the number between 0-#{highest}: ('.' to quit)"
559
+ count = 0
560
+ while(true)
561
+ count += 1
562
+ str = Readline.readline("game > ", true)
563
+ break if str == "." || !str
564
+ val = str.to_i
565
+ output.puts "Too large!" if val > num
566
+ output.puts "Too small!" if val < num
567
+ if val == num
568
+ output.puts "Well done! You guessed right! It took you #{count} guesses."
569
+ break
570
+ end
571
+ end
572
+ end
573
+
574
+ command "east-coker", "" do
575
+ text = %{
576
+ --
577
+ Now the light falls
578
+ Across the open field, leaving the deep lane
579
+ Shuttered with branches, dark in the afternoon,
580
+ Where you lean against a bank while a van passes,
581
+ And the deep lane insists on the direction
582
+ Into the village, in the electric heat
583
+ Hypnotised. In a warm haze the sultry light
584
+ Is absorbed, not refracted, by grey stone.
585
+ The dahlias sleep in the empty silence.
586
+ Wait for the early owl.
587
+ -- T.S Eliot
588
+ }
589
+ output.puts text
590
+ text
591
+ end
592
+
593
+ command "cohen-poem", "" do
594
+ text = %{
595
+ --
596
+ When this American woman,
597
+ whose thighs are bound in casual red cloth,
598
+ comes thundering past my sitting place
599
+ like a forest-burning Mongol tribe,
600
+ the city is ravished
601
+ and brittle buildings of a hundred years
602
+ splash into the street;
603
+ and my eyes are burnt
604
+ for the embroidered Chinese girls,
605
+ already old,
606
+ and so small between the thin pines
607
+ on these enormous landscapes,
608
+ that if you turn your head
609
+ they are lost for hours.
610
+ -- Leonard Cohen
611
+ }
612
+ output.puts text
613
+ text
614
+ end
615
+ end
616
+ end