pry 0.6.7-i386-mswin32

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