pry 0.6.7pre4-i386-mswin32 → 0.6.8-i386-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,150 +1,150 @@
1
- class Pry
2
-
3
- # Basic command functionality. All user-defined commands must
4
- # inherit from this class. It provides the `command` method.
5
- class CommandBase
6
- class << self
7
- attr_accessor :commands
8
- attr_accessor :opts, :output, :target
9
-
10
- # private because we want to force function style invocation. We require
11
- # that the location where the block is defined has the `opts`
12
- # method in scope.
13
- private
14
-
15
- # Defines a new Pry command.
16
- # @param [String, Array] names The name of the command (or array of
17
- # command name aliases).
18
- # @param [String] description A description of the command.
19
- # @param [Hash] options The optional configuration parameters.
20
- # @option options [Boolean] :keep_retval Whether or not to use return value
21
- # of the block for return of `command` or just to return `nil`
22
- # (the default).
23
- # @yield The action to perform. The parameters in the block
24
- # determines the parameters the command will receive. All
25
- # parameters passed into the block will be strings. Successive
26
- # command parameters are separated by whitespace at the Pry prompt.
27
- # @example
28
- # class MyCommands < Pry::CommandBase
29
- # command "greet", "Greet somebody" do |name|
30
- # puts "Good afternoon #{name.capitalize}!"
31
- # end
32
- # end
33
- #
34
- # # From pry:
35
- # # pry(main)> _pry_.commands = MyCommands
36
- # # pry(main)> greet john
37
- # # Good afternoon John!
38
- # # pry(main)> help greet
39
- # # Greet somebody
40
- def command(names, description="No description.", options={}, &block)
41
- options = {
42
- :keep_retval => false
43
- }.merge!(options)
44
-
45
- @commands ||= {}
46
-
47
- Array(names).each do |name|
48
- commands[name] = {
49
- :description => description,
50
- :action => block,
51
- :keep_retval => options[:keep_retval]
52
- }
53
- end
54
- end
55
-
56
- # Delete a command or an array of commands.
57
- # Useful when inheriting from another command set and pruning
58
- # those commands down to the ones you want.
59
- # @param [Array<String>] names The command name or array
60
- # of command names you want to delete
61
- # @example Deleteing inherited commands
62
- # class MyCommands < Pry::Commands
63
- # delete "show_method", "show_imethod", "show_doc", "show_idoc"
64
- # end
65
- # Pry.commands = MyCommands
66
- def delete(*names)
67
- names.each { |name| commands.delete(name) }
68
- end
69
-
70
- # Execute a command (this enables commands to call other commands).
71
- # @param [String] name The command to execute
72
- # @param [Array] args The parameters to pass to the command.
73
- # @example Wrap one command with another
74
- # class MyCommands < Pry::Commands
75
- # command "ls2" do
76
- # output.puts "before ls"
77
- # run "ls"
78
- # output.puts "after ls"
79
- # end
80
- # end
81
- def run(name, *args)
82
- action = opts[:commands][name][:action]
83
- instance_exec(*args, &action)
84
- end
85
-
86
- # Import commands from another command object.
87
- # @param [Pry::CommandBase] klass The class to import from (must
88
- # be a subclass of `Pry::CommandBase`)
89
- # @param [Array<String>] names The commands to import.
90
- # @example
91
- # class MyCommands < Pry::CommandBase
92
- # import_from Pry::Commands, "ls", "show_method", "cd"
93
- # end
94
- def import_from(klass, *names)
95
- imported_hash = Hash[klass.commands.select { |k, v| names.include?(k) }]
96
- commands.merge!(imported_hash)
97
- end
98
-
99
- # Create an alias for a command.
100
- # @param [String] new_command The alias name.
101
- # @param [String] orig_command The original command name.
102
- # @param [String] desc The optional description.
103
- # @example
104
- # class MyCommands < Pry::CommandBase
105
- # alias_command "help_alias", "help"
106
- # end
107
- def alias_command(new_command_name, orig_command_name, desc=nil)
108
- commands[new_command_name] = commands[orig_command_name].dup
109
- commands[new_command_name][:description] = desc if desc
110
- end
111
-
112
- # Set the description for a command (replacing the old
113
- # description.)
114
- # @param [String] name The command name.
115
- # @param [String] description The command description.
116
- # @example
117
- # class MyCommands < Pry::CommandBase
118
- # desc "help", "help description"
119
- # end
120
- def desc(name, description)
121
- commands[name][:description] = description
122
- end
123
- end
124
-
125
- command "help", "This menu." do |cmd|
126
- command_info = opts[:commands]
127
- param = cmd
128
-
129
- if !param
130
- output.puts "Command list:"
131
- output.puts "--"
132
- command_info.each do |k, data|
133
- output.puts "#{k}".ljust(18) + data[:description] if !data[:description].empty?
134
- end
135
- else
136
- if command_info[param]
137
- output.puts command_info[param][:description]
138
- else
139
- output.puts "No info for command: #{param}"
140
- end
141
- end
142
- end
143
-
144
- # Ensures that commands can be inherited
145
- def self.inherited(klass)
146
- klass.commands = commands.dup
147
- end
148
-
149
- end
150
- end
1
+ class Pry
2
+
3
+ # Basic command functionality. All user-defined commands must
4
+ # inherit from this class. It provides the `command` method.
5
+ class CommandBase
6
+ class << self
7
+ attr_accessor :commands
8
+ attr_accessor :opts, :output, :target
9
+
10
+ # private because we want to force function style invocation. We require
11
+ # that the location where the block is defined has the `opts`
12
+ # method in scope.
13
+ private
14
+
15
+ # Defines a new Pry command.
16
+ # @param [String, Array] names The name of the command (or array of
17
+ # command name aliases).
18
+ # @param [String] description A description of the command.
19
+ # @param [Hash] options The optional configuration parameters.
20
+ # @option options [Boolean] :keep_retval Whether or not to use return value
21
+ # of the block for return of `command` or just to return `nil`
22
+ # (the default).
23
+ # @yield The action to perform. The parameters in the block
24
+ # determines the parameters the command will receive. All
25
+ # parameters passed into the block will be strings. Successive
26
+ # command parameters are separated by whitespace at the Pry prompt.
27
+ # @example
28
+ # class MyCommands < Pry::CommandBase
29
+ # command "greet", "Greet somebody" do |name|
30
+ # puts "Good afternoon #{name.capitalize}!"
31
+ # end
32
+ # end
33
+ #
34
+ # # From pry:
35
+ # # pry(main)> _pry_.commands = MyCommands
36
+ # # pry(main)> greet john
37
+ # # Good afternoon John!
38
+ # # pry(main)> help greet
39
+ # # Greet somebody
40
+ def command(names, description="No description.", options={}, &block)
41
+ options = {
42
+ :keep_retval => false
43
+ }.merge!(options)
44
+
45
+ @commands ||= {}
46
+
47
+ Array(names).each do |name|
48
+ commands[name] = {
49
+ :description => description,
50
+ :action => block,
51
+ :keep_retval => options[:keep_retval]
52
+ }
53
+ end
54
+ end
55
+
56
+ # Delete a command or an array of commands.
57
+ # Useful when inheriting from another command set and pruning
58
+ # those commands down to the ones you want.
59
+ # @param [Array<String>] names The command name or array
60
+ # of command names you want to delete
61
+ # @example Deleteing inherited commands
62
+ # class MyCommands < Pry::Commands
63
+ # delete "show_method", "show_imethod", "show_doc", "show_idoc"
64
+ # end
65
+ # Pry.commands = MyCommands
66
+ def delete(*names)
67
+ names.each { |name| commands.delete(name) }
68
+ end
69
+
70
+ # Execute a command (this enables commands to call other commands).
71
+ # @param [String] name The command to execute
72
+ # @param [Array] args The parameters to pass to the command.
73
+ # @example Wrap one command with another
74
+ # class MyCommands < Pry::Commands
75
+ # command "ls2" do
76
+ # output.puts "before ls"
77
+ # run "ls"
78
+ # output.puts "after ls"
79
+ # end
80
+ # end
81
+ def run(name, *args)
82
+ action = opts[:commands][name][:action]
83
+ instance_exec(*args, &action)
84
+ end
85
+
86
+ # Import commands from another command object.
87
+ # @param [Pry::CommandBase] klass The class to import from (must
88
+ # be a subclass of `Pry::CommandBase`)
89
+ # @param [Array<String>] names The commands to import.
90
+ # @example
91
+ # class MyCommands < Pry::CommandBase
92
+ # import_from Pry::Commands, "ls", "show_method", "cd"
93
+ # end
94
+ def import_from(klass, *names)
95
+ imported_hash = Hash[klass.commands.select { |k, v| names.include?(k) }]
96
+ commands.merge!(imported_hash)
97
+ end
98
+
99
+ # Create an alias for a command.
100
+ # @param [String] new_command The alias name.
101
+ # @param [String] orig_command The original command name.
102
+ # @param [String] desc The optional description.
103
+ # @example
104
+ # class MyCommands < Pry::CommandBase
105
+ # alias_command "help_alias", "help"
106
+ # end
107
+ def alias_command(new_command_name, orig_command_name, desc=nil)
108
+ commands[new_command_name] = commands[orig_command_name].dup
109
+ commands[new_command_name][:description] = desc if desc
110
+ end
111
+
112
+ # Set the description for a command (replacing the old
113
+ # description.)
114
+ # @param [String] name The command name.
115
+ # @param [String] description The command description.
116
+ # @example
117
+ # class MyCommands < Pry::CommandBase
118
+ # desc "help", "help description"
119
+ # end
120
+ def desc(name, description)
121
+ commands[name][:description] = description
122
+ end
123
+ end
124
+
125
+ command "help", "This menu." do |cmd|
126
+ command_info = opts[:commands]
127
+ param = cmd
128
+
129
+ if !param
130
+ output.puts "Command list:"
131
+ output.puts "--"
132
+ command_info.each do |k, data|
133
+ output.puts "#{k}".ljust(18) + data[:description] if !data[:description].empty?
134
+ end
135
+ else
136
+ if command_info[param]
137
+ output.puts command_info[param][:description]
138
+ else
139
+ output.puts "No info for command: #{param}"
140
+ end
141
+ end
142
+ end
143
+
144
+ # Ensures that commands can be inherited
145
+ def self.inherited(klass)
146
+ klass.commands = commands.dup
147
+ end
148
+
149
+ end
150
+ end
@@ -1,577 +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 "!", "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
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