pry 0.6.7-i386-mswin32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gemtest +0 -0
- data/CHANGELOG +83 -0
- data/LICENSE +25 -0
- data/README.markdown +312 -0
- data/Rakefile +103 -0
- data/bin/pry +82 -0
- data/examples/example_basic.rb +17 -0
- data/examples/example_command_override.rb +35 -0
- data/examples/example_commands.rb +39 -0
- data/examples/example_hooks.rb +12 -0
- data/examples/example_image_edit.rb +71 -0
- data/examples/example_input.rb +10 -0
- data/examples/example_input2.rb +32 -0
- data/examples/example_output.rb +14 -0
- data/examples/example_print.rb +9 -0
- data/examples/example_prompt.rb +12 -0
- data/lib/pry.rb +32 -0
- data/lib/pry/command_base.rb +150 -0
- data/lib/pry/commands.rb +577 -0
- data/lib/pry/completion.rb +202 -0
- data/lib/pry/core_extensions.rb +55 -0
- data/lib/pry/hooks.rb +8 -0
- data/lib/pry/print.rb +19 -0
- data/lib/pry/prompts.rb +26 -0
- data/lib/pry/pry_class.rb +186 -0
- data/lib/pry/pry_instance.rb +316 -0
- data/lib/pry/version.rb +3 -0
- data/test/test.rb +681 -0
- data/test/test_helper.rb +38 -0
- metadata +131 -0
@@ -0,0 +1,316 @@
|
|
1
|
+
class Pry
|
2
|
+
|
3
|
+
# The list of configuration options.
|
4
|
+
CONFIG_OPTIONS = [:input, :output, :commands, :print,
|
5
|
+
:prompt, :hooks]
|
6
|
+
|
7
|
+
attr_accessor *CONFIG_OPTIONS
|
8
|
+
|
9
|
+
# Create a new `Pry` object.
|
10
|
+
# @param [Hash] options The optional configuration parameters.
|
11
|
+
# @option options [#readline] :input The object to use for input.
|
12
|
+
# @option options [#puts] :output The object to use for output.
|
13
|
+
# @option options [Pry::CommandBase] :commands The object to use for
|
14
|
+
# commands. (see commands.rb)
|
15
|
+
# @option options [Hash] :hooks The defined hook Procs (see hooks.rb)
|
16
|
+
# @option options [Array<Proc>] :default_prompt The array of Procs
|
17
|
+
# to use for the prompts. (see prompts.rb)
|
18
|
+
# @option options [Proc] :print The Proc to use for the 'print'
|
19
|
+
# component of the REPL. (see print.rb)
|
20
|
+
def initialize(options={})
|
21
|
+
|
22
|
+
default_options = {}
|
23
|
+
CONFIG_OPTIONS.each { |v| default_options[v] = Pry.send(v) }
|
24
|
+
default_options.merge!(options)
|
25
|
+
|
26
|
+
CONFIG_OPTIONS.each do |key|
|
27
|
+
instance_variable_set("@#{key}", default_options[key])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Get nesting data.
|
32
|
+
# This method should not need to be accessed directly.
|
33
|
+
# @return [Array] The unparsed nesting information.
|
34
|
+
def nesting
|
35
|
+
self.class.nesting
|
36
|
+
end
|
37
|
+
|
38
|
+
# Set nesting data.
|
39
|
+
# This method should not need to be accessed directly.
|
40
|
+
# @param v nesting data.
|
41
|
+
def nesting=(v)
|
42
|
+
self.class.nesting = v
|
43
|
+
end
|
44
|
+
|
45
|
+
# Return parent of current Pry session.
|
46
|
+
# @return [Pry] The parent of the current Pry session.
|
47
|
+
def parent
|
48
|
+
idx = Pry.sessions.index(self)
|
49
|
+
|
50
|
+
if idx > 0
|
51
|
+
Pry.sessions[idx - 1]
|
52
|
+
else
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Execute the hook `hook_name`, if it is defined.
|
58
|
+
# @param [Symbol] hook_name The hook to execute
|
59
|
+
# @param [Array] args The arguments to pass to the hook.
|
60
|
+
def exec_hook(hook_name, *args, &block)
|
61
|
+
hooks[hook_name].call(*args, &block) if hooks[hook_name]
|
62
|
+
end
|
63
|
+
|
64
|
+
# Start a read-eval-print-loop.
|
65
|
+
# If no parameter is given, default to top-level (main).
|
66
|
+
# @param [Object, Binding] target The receiver of the Pry session
|
67
|
+
# @return [Object] The target of the Pry session or an explictly given
|
68
|
+
# return value. If given return value is `nil` or no return value
|
69
|
+
# is specified then `target` will be returned.
|
70
|
+
# @example
|
71
|
+
# Pry.new.repl(Object.new)
|
72
|
+
def repl(target=TOPLEVEL_BINDING)
|
73
|
+
target = Pry.binding_for(target)
|
74
|
+
target_self = target.eval('self')
|
75
|
+
|
76
|
+
exec_hook :before_session, output, target_self
|
77
|
+
|
78
|
+
# cannot rely on nesting.level as
|
79
|
+
# nesting.level changes with new sessions
|
80
|
+
nesting_level = nesting.size
|
81
|
+
|
82
|
+
Pry.active_instance = self
|
83
|
+
|
84
|
+
# Make sure special locals exist
|
85
|
+
target.eval("_pry_ = Pry.active_instance")
|
86
|
+
target.eval("_ = Pry.last_result")
|
87
|
+
|
88
|
+
break_data = catch(:breakout) do
|
89
|
+
nesting.push [nesting.size, target_self, self]
|
90
|
+
loop do
|
91
|
+
rep(target)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
nesting.pop
|
96
|
+
|
97
|
+
exec_hook :after_session, output, target_self
|
98
|
+
|
99
|
+
# If break_data is an array, then the last element is the return value
|
100
|
+
break_level, return_value = Array(break_data)
|
101
|
+
|
102
|
+
# keep throwing until we reach the desired nesting level
|
103
|
+
if nesting_level != break_level
|
104
|
+
throw :breakout, break_data
|
105
|
+
end
|
106
|
+
|
107
|
+
# if one was provided, return the return value
|
108
|
+
return return_value if return_value
|
109
|
+
|
110
|
+
# otherwise return the target_self
|
111
|
+
target_self
|
112
|
+
end
|
113
|
+
|
114
|
+
# Perform a read-eval-print.
|
115
|
+
# If no parameter is given, default to top-level (main).
|
116
|
+
# @param [Object, Binding] target The receiver of the read-eval-print
|
117
|
+
# @example
|
118
|
+
# Pry.new.rep(Object.new)
|
119
|
+
def rep(target=TOPLEVEL_BINDING)
|
120
|
+
target = Pry.binding_for(target)
|
121
|
+
print.call output, re(target)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Perform a read-eval
|
125
|
+
# If no parameter is given, default to top-level (main).
|
126
|
+
# @param [Object, Binding] target The receiver of the read-eval-print
|
127
|
+
# @return [Object] The result of the eval or an `Exception` object in case of error.
|
128
|
+
# @example
|
129
|
+
# Pry.new.re(Object.new)
|
130
|
+
def re(target=TOPLEVEL_BINDING)
|
131
|
+
target = Pry.binding_for(target)
|
132
|
+
|
133
|
+
if input == Readline
|
134
|
+
# Readline tab completion
|
135
|
+
Readline.completion_proc = Pry::InputCompleter.build_completion_proc(target, commands.commands.keys)
|
136
|
+
end
|
137
|
+
|
138
|
+
# eval the expression and save to last_result
|
139
|
+
Pry.last_result = target.eval r(target)
|
140
|
+
|
141
|
+
# save the pry instance to active_instance
|
142
|
+
Pry.active_instance = self
|
143
|
+
|
144
|
+
# define locals _pry_ and _ (active instance and last expression)
|
145
|
+
target.eval("_pry_ = Pry.active_instance")
|
146
|
+
target.eval("_ = Pry.last_result")
|
147
|
+
rescue SystemExit => e
|
148
|
+
exit
|
149
|
+
rescue Exception => e
|
150
|
+
e
|
151
|
+
end
|
152
|
+
|
153
|
+
# Perform a read.
|
154
|
+
# If no parameter is given, default to top-level (main).
|
155
|
+
# This is a multi-line read; so the read continues until a valid
|
156
|
+
# Ruby expression is received.
|
157
|
+
# Pry commands are also accepted here and operate on the target.
|
158
|
+
# @param [Object, Binding] target The receiver of the read.
|
159
|
+
# @return [String] The Ruby expression.
|
160
|
+
# @example
|
161
|
+
# Pry.new.r(Object.new)
|
162
|
+
def r(target=TOPLEVEL_BINDING)
|
163
|
+
target = Pry.binding_for(target)
|
164
|
+
eval_string = ""
|
165
|
+
|
166
|
+
loop do
|
167
|
+
current_prompt = select_prompt(eval_string.empty?, target.eval('self'))
|
168
|
+
|
169
|
+
val = readline(current_prompt)
|
170
|
+
|
171
|
+
# exit pry if we receive EOF character
|
172
|
+
if !val
|
173
|
+
output.puts
|
174
|
+
throw(:breakout, nesting.level)
|
175
|
+
end
|
176
|
+
|
177
|
+
val.chomp!
|
178
|
+
|
179
|
+
Pry.cmd_ret_value = process_commands(val, eval_string, target)
|
180
|
+
|
181
|
+
if Pry.cmd_ret_value
|
182
|
+
eval_string << "Pry.cmd_ret_value\n"
|
183
|
+
else
|
184
|
+
eval_string << "#{val}\n"
|
185
|
+
end
|
186
|
+
|
187
|
+
break eval_string if valid_expression?(eval_string)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Process Pry commands. Pry commands are not Ruby methods and are evaluated
|
192
|
+
# prior to Ruby expressions.
|
193
|
+
# Commands can be modified/configured by the user: see `Pry::Commands`
|
194
|
+
# This method should not need to be invoked directly - it is called
|
195
|
+
# by `Pry#r`.
|
196
|
+
# @param [String] val The current line of input.
|
197
|
+
# @param [String] eval_string The cumulative lines of input for
|
198
|
+
# multi-line input.
|
199
|
+
# @param [Binding] target The receiver of the commands.
|
200
|
+
def process_commands(val, eval_string, target)
|
201
|
+
def val.clear() replace("") end
|
202
|
+
def eval_string.clear() replace("") end
|
203
|
+
|
204
|
+
pattern, cmd_data = commands.commands.find do |name, cmd_data|
|
205
|
+
/^#{name}(?!\S)(?:\s+(.+))?/ =~ val
|
206
|
+
end
|
207
|
+
|
208
|
+
# no command was matched, so return to caller
|
209
|
+
return if !pattern
|
210
|
+
|
211
|
+
args_string = $1
|
212
|
+
args = args_string ? Shellwords.shellwords(args_string) : []
|
213
|
+
action = cmd_data[:action]
|
214
|
+
keep_retval = cmd_data[:keep_retval]
|
215
|
+
|
216
|
+
options = {
|
217
|
+
:val => val,
|
218
|
+
:eval_string => eval_string,
|
219
|
+
:nesting => nesting,
|
220
|
+
:commands => commands.commands
|
221
|
+
}
|
222
|
+
|
223
|
+
# set some useful methods to be used by the action blocks
|
224
|
+
commands.opts = options
|
225
|
+
commands.target = target
|
226
|
+
commands.output = output
|
227
|
+
|
228
|
+
case action.arity <=> 0
|
229
|
+
when -1
|
230
|
+
|
231
|
+
# Use instance_exec() to make the `opts` method, etc available
|
232
|
+
ret_value = commands.instance_exec(*args, &action)
|
233
|
+
when 1, 0
|
234
|
+
|
235
|
+
# ensure that we get the right number of parameters
|
236
|
+
# since 1.8.7 complains about incorrect arity (1.9.2
|
237
|
+
# doesn't care)
|
238
|
+
args_with_corrected_arity = args.values_at *0..(action.arity - 1)
|
239
|
+
ret_value = commands.instance_exec(*args_with_corrected_arity, &action)
|
240
|
+
end
|
241
|
+
|
242
|
+
# a command was processed so we can now clear the input string
|
243
|
+
val.clear
|
244
|
+
|
245
|
+
# return value of block only if :keep_retval is true
|
246
|
+
ret_value if keep_retval
|
247
|
+
end
|
248
|
+
|
249
|
+
# Returns the next line of input to be used by the pry instance.
|
250
|
+
# This method should not need to be invoked directly.
|
251
|
+
# @param [String] current_prompt The prompt to use for input.
|
252
|
+
# @return [String] The next line of input.
|
253
|
+
def readline(current_prompt="> ")
|
254
|
+
|
255
|
+
if input == Readline
|
256
|
+
|
257
|
+
# Readline must be treated differently
|
258
|
+
# as it has a second parameter.
|
259
|
+
input.readline(current_prompt, true)
|
260
|
+
else
|
261
|
+
if input.method(:readline).arity == 1
|
262
|
+
input.readline(current_prompt)
|
263
|
+
else
|
264
|
+
input.readline
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
# Returns the appropriate prompt to use.
|
270
|
+
# This method should not need to be invoked directly.
|
271
|
+
# @param [Boolean] first_line Whether this is the first line of input
|
272
|
+
# (and not multi-line input).
|
273
|
+
# @param [Object] target_self The receiver of the Pry session.
|
274
|
+
# @return [String] The prompt.
|
275
|
+
def select_prompt(first_line, target_self)
|
276
|
+
|
277
|
+
if first_line
|
278
|
+
Array(prompt).first.call(target_self, nesting.level)
|
279
|
+
else
|
280
|
+
Array(prompt).last.call(target_self, nesting.level)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
if RUBY_VERSION =~ /1.9/
|
285
|
+
require 'ripper'
|
286
|
+
|
287
|
+
# Determine if a string of code is a valid Ruby expression.
|
288
|
+
# Ruby 1.9 uses Ripper, Ruby 1.8 uses RubyParser.
|
289
|
+
# @param [String] code The code to validate.
|
290
|
+
# @return [Boolean] Whether or not the code is a valid Ruby expression.
|
291
|
+
# @example
|
292
|
+
# valid_expression?("class Hello") #=> false
|
293
|
+
# valid_expression?("class Hello; end") #=> true
|
294
|
+
def valid_expression?(code)
|
295
|
+
!!Ripper::SexpBuilder.new(code).parse
|
296
|
+
end
|
297
|
+
|
298
|
+
else
|
299
|
+
require 'ruby_parser'
|
300
|
+
|
301
|
+
# Determine if a string of code is a valid Ruby expression.
|
302
|
+
# Ruby 1.9 uses Ripper, Ruby 1.8 uses RubyParser.
|
303
|
+
# @param [String] code The code to validate.
|
304
|
+
# @return [Boolean] Whether or not the code is a valid Ruby expression.
|
305
|
+
# @example
|
306
|
+
# valid_expression?("class Hello") #=> false
|
307
|
+
# valid_expression?("class Hello; end") #=> true
|
308
|
+
def valid_expression?(code)
|
309
|
+
RubyParser.new.parse(code)
|
310
|
+
rescue Racc::ParseError, SyntaxError
|
311
|
+
false
|
312
|
+
else
|
313
|
+
true
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
data/lib/pry/version.rb
ADDED
data/test/test.rb
ADDED
@@ -0,0 +1,681 @@
|
|
1
|
+
direc = File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bacon'
|
5
|
+
require "#{direc}/../lib/pry"
|
6
|
+
require "#{direc}/test_helper"
|
7
|
+
|
8
|
+
puts "Ruby Version #{RUBY_VERSION}"
|
9
|
+
puts "Testing Pry #{Pry::VERSION}"
|
10
|
+
puts "With method_source version #{MethodSource::VERSION}"
|
11
|
+
puts "--"
|
12
|
+
|
13
|
+
describe Pry do
|
14
|
+
describe "open a Pry session on an object" do
|
15
|
+
describe "rep" do
|
16
|
+
|
17
|
+
before do
|
18
|
+
class Hello
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
after do
|
23
|
+
Object.send(:remove_const, :Hello)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should set an ivar on an object' do
|
27
|
+
input_string = "@x = 10"
|
28
|
+
input = InputTester.new(input_string)
|
29
|
+
o = Object.new
|
30
|
+
|
31
|
+
pry_tester = Pry.new(:input => input, :output => Pry::NullOutput)
|
32
|
+
pry_tester.rep(o)
|
33
|
+
o.instance_variable_get(:@x).should == 10
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should make self evaluate to the receiver of the rep session' do
|
37
|
+
o = Object.new
|
38
|
+
str_output = StringIO.new
|
39
|
+
|
40
|
+
pry_tester = Pry.new(:input => InputTester.new("self"), :output => str_output)
|
41
|
+
pry_tester.rep(o)
|
42
|
+
str_output.string.should =~ /#{o.to_s}/
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should work with multi-line input' do
|
46
|
+
o = Object.new
|
47
|
+
str_output = StringIO.new
|
48
|
+
|
49
|
+
pry_tester = Pry.new(:input => InputTester.new("x = ", "1 + 4"), :output => str_output)
|
50
|
+
pry_tester.rep(o)
|
51
|
+
str_output.string.should =~ /5/
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should define a nested class under Hello and not on top-level or Pry' do
|
55
|
+
pry_tester = Pry.new(:input => InputTester.new("class Nested", "end"), :output => Pry::NullOutput)
|
56
|
+
pry_tester.rep(Hello)
|
57
|
+
Hello.const_defined?(:Nested).should == true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "repl" do
|
62
|
+
describe "basic functionality" do
|
63
|
+
it 'should set an ivar on an object and exit the repl' do
|
64
|
+
input_strings = ["@x = 10", "exit"]
|
65
|
+
input = InputTester.new(*input_strings)
|
66
|
+
|
67
|
+
o = Object.new
|
68
|
+
|
69
|
+
pry_tester = Pry.start(o, :input => input, :output => Pry::NullOutput)
|
70
|
+
|
71
|
+
o.instance_variable_get(:@x).should == 10
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should execute start session and end session hooks' do
|
75
|
+
input = InputTester.new("exit")
|
76
|
+
str_output = StringIO.new
|
77
|
+
o = Object.new
|
78
|
+
|
79
|
+
pry_tester = Pry.start(o, :input => input, :output => str_output)
|
80
|
+
str_output.string.should =~ /Beginning.*#{o}/
|
81
|
+
str_output.string.should =~ /Ending.*#{o}/
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "nesting" do
|
86
|
+
after do
|
87
|
+
Pry.reset_defaults
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should nest properly' do
|
91
|
+
Pry.input = InputTester.new("pry", "pry", "pry", "\"nest:\#\{Pry.nesting.level\}\"", "exit_all")
|
92
|
+
|
93
|
+
str_output = StringIO.new
|
94
|
+
Pry.output = str_output
|
95
|
+
|
96
|
+
o = Object.new
|
97
|
+
|
98
|
+
pry_tester = o.pry
|
99
|
+
str_output.string.should =~ /nest:3/
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "defining methods" do
|
104
|
+
it 'should define a method on the singleton class of an object when performing "def meth;end" inside the object' do
|
105
|
+
[Object.new, {}, []].each do |val|
|
106
|
+
str_input = StringIO.new("def hello;end")
|
107
|
+
Pry.new(:input => str_input, :output => StringIO.new).rep(val)
|
108
|
+
|
109
|
+
val.methods(false).map(&:to_sym).include?(:hello).should == true
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should define an instance method on the module when performing "def meth;end" inside the module' do
|
114
|
+
str_input = StringIO.new("def hello;end")
|
115
|
+
hello = Module.new
|
116
|
+
Pry.new(:input => str_input, :output => StringIO.new).rep(hello)
|
117
|
+
hello.instance_methods(false).map(&:to_sym).include?(:hello).should == true
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should define an instance method on the class when performing "def meth;end" inside the class' do
|
121
|
+
str_input = StringIO.new("def hello;end")
|
122
|
+
hello = Class.new
|
123
|
+
Pry.new(:input => str_input, :output => StringIO.new).rep(hello)
|
124
|
+
hello.instance_methods(false).map(&:to_sym).include?(:hello).should == true
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should define a method on the class of an object when performing "def meth;end" inside an immediate value or Numeric' do
|
128
|
+
# should include float in here, but test fails for some reason
|
129
|
+
# on 1.8.7, no idea why!
|
130
|
+
[:test, 0, true, false, nil].each do |val|
|
131
|
+
str_input = StringIO.new("def hello;end")
|
132
|
+
Pry.new(:input => str_input, :output => StringIO.new).rep(val)
|
133
|
+
val.class.instance_methods(false).map(&:to_sym).include?(:hello).should == true
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
describe "commands" do
|
141
|
+
it 'should run a command with no parameter' do
|
142
|
+
pry_tester = Pry.new
|
143
|
+
pry_tester.commands = CommandTester
|
144
|
+
pry_tester.input = InputTester.new("command1", "exit_all")
|
145
|
+
pry_tester.commands = CommandTester
|
146
|
+
|
147
|
+
str_output = StringIO.new
|
148
|
+
pry_tester.output = str_output
|
149
|
+
|
150
|
+
pry_tester.rep
|
151
|
+
|
152
|
+
str_output.string.should =~ /command1/
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should run a command with one parameter' do
|
156
|
+
pry_tester = Pry.new
|
157
|
+
pry_tester.commands = CommandTester
|
158
|
+
pry_tester.input = InputTester.new("command2 horsey", "exit_all")
|
159
|
+
pry_tester.commands = CommandTester
|
160
|
+
|
161
|
+
str_output = StringIO.new
|
162
|
+
pry_tester.output = str_output
|
163
|
+
|
164
|
+
pry_tester.rep
|
165
|
+
|
166
|
+
str_output.string.should =~ /horsey/
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe "Object#pry" do
|
171
|
+
|
172
|
+
after do
|
173
|
+
Pry.reset_defaults
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should start a pry session on the receiver (first form)" do
|
177
|
+
Pry.input = InputTester.new("self", "exit")
|
178
|
+
|
179
|
+
str_output = StringIO.new
|
180
|
+
Pry.output = str_output
|
181
|
+
|
182
|
+
20.pry
|
183
|
+
|
184
|
+
str_output.string.should =~ /20/
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should start a pry session on the receiver (second form)" do
|
188
|
+
Pry.input = InputTester.new("self", "exit")
|
189
|
+
|
190
|
+
str_output = StringIO.new
|
191
|
+
Pry.output = str_output
|
192
|
+
|
193
|
+
pry 20
|
194
|
+
|
195
|
+
str_output.string.should =~ /20/
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should error if more than one argument is passed to Object#pry" do
|
199
|
+
lambda { pry(20, :input => Readline) }.should.raise ArgumentError
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "Pry.binding_for" do
|
204
|
+
it 'should return TOPLEVEL_BINDING if parameter self is main' do
|
205
|
+
_main_ = lambda { TOPLEVEL_BINDING.eval('self') }
|
206
|
+
Pry.binding_for(_main_.call).is_a?(Binding).should == true
|
207
|
+
Pry.binding_for(_main_.call).should == TOPLEVEL_BINDING
|
208
|
+
Pry.binding_for(_main_.call).should == Pry.binding_for(_main_.call)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
|
213
|
+
describe "test Pry defaults" do
|
214
|
+
|
215
|
+
after do
|
216
|
+
Pry.reset_defaults
|
217
|
+
end
|
218
|
+
|
219
|
+
describe "input" do
|
220
|
+
|
221
|
+
after do
|
222
|
+
Pry.reset_defaults
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'should set the input default, and the default should be overridable' do
|
226
|
+
Pry.input = InputTester.new("5")
|
227
|
+
|
228
|
+
str_output = StringIO.new
|
229
|
+
Pry.output = str_output
|
230
|
+
Pry.new.rep
|
231
|
+
str_output.string.should =~ /5/
|
232
|
+
|
233
|
+
Pry.new(:input => InputTester.new("6")).rep
|
234
|
+
str_output.string.should =~ /6/
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'should pass in the prompt if readline arity is 1' do
|
238
|
+
Pry.prompt = proc { "A" }
|
239
|
+
|
240
|
+
arity_one_input = Class.new do
|
241
|
+
attr_accessor :prompt
|
242
|
+
def readline(prompt)
|
243
|
+
@prompt = prompt
|
244
|
+
"exit"
|
245
|
+
end
|
246
|
+
end.new
|
247
|
+
|
248
|
+
Pry.start(self, :input => arity_one_input, :output => Pry::NullOutput)
|
249
|
+
arity_one_input.prompt.should == Pry.prompt.call
|
250
|
+
end
|
251
|
+
|
252
|
+
it 'should not pass in the prompt if the arity is 0' do
|
253
|
+
Pry.prompt = proc { "A" }
|
254
|
+
|
255
|
+
arity_zero_input = Class.new do
|
256
|
+
def readline
|
257
|
+
"exit"
|
258
|
+
end
|
259
|
+
end.new
|
260
|
+
|
261
|
+
lambda { Pry.start(self, :input => arity_zero_input, :output => Pry::NullOutput) }.should.not.raise Exception
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'should not pass in the prompt if the arity is -1' do
|
265
|
+
Pry.prompt = proc { "A" }
|
266
|
+
|
267
|
+
arity_multi_input = Class.new do
|
268
|
+
attr_accessor :prompt
|
269
|
+
|
270
|
+
def readline(*args)
|
271
|
+
@prompt = args.first
|
272
|
+
"exit"
|
273
|
+
end
|
274
|
+
end.new
|
275
|
+
|
276
|
+
Pry.start(self, :input => arity_multi_input, :output => Pry::NullOutput)
|
277
|
+
arity_multi_input.prompt.should == nil
|
278
|
+
end
|
279
|
+
|
280
|
+
end
|
281
|
+
|
282
|
+
it 'should set the output default, and the default should be overridable' do
|
283
|
+
Pry.input = InputTester.new("5", "6", "7")
|
284
|
+
|
285
|
+
str_output = StringIO.new
|
286
|
+
Pry.output = str_output
|
287
|
+
|
288
|
+
Pry.new.rep
|
289
|
+
str_output.string.should =~ /5/
|
290
|
+
|
291
|
+
Pry.new.rep
|
292
|
+
str_output.string.should =~ /5\n.*6/
|
293
|
+
|
294
|
+
str_output2 = StringIO.new
|
295
|
+
Pry.new(:output => str_output2).rep
|
296
|
+
str_output2.string.should.not =~ /5\n.*6/
|
297
|
+
str_output2.string.should =~ /7/
|
298
|
+
end
|
299
|
+
|
300
|
+
describe "Pry.run_command" do
|
301
|
+
before do
|
302
|
+
class RCTest
|
303
|
+
def a() end
|
304
|
+
B = 20
|
305
|
+
@x = 10
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
after do
|
310
|
+
Object.remove_const(:RCTest)
|
311
|
+
end
|
312
|
+
|
313
|
+
it "should execute command in the appropriate object context" do
|
314
|
+
result = Pry.run_command "ls", :context => RCTest
|
315
|
+
result.map(&:to_sym).should == [:@x]
|
316
|
+
end
|
317
|
+
|
318
|
+
it "should execute command with parameters in the appropriate object context" do
|
319
|
+
result = Pry.run_command "ls -M", :context => RCTest
|
320
|
+
result.map(&:to_sym).should == [:a]
|
321
|
+
end
|
322
|
+
|
323
|
+
it "should execute command and show output with :show_output => true flag" do
|
324
|
+
str = StringIO.new
|
325
|
+
Pry.output = str
|
326
|
+
result = Pry.run_command "ls -av", :context => RCTest, :show_output => true
|
327
|
+
str.string.should =~ /global variables/
|
328
|
+
Pry.output = $stdout
|
329
|
+
end
|
330
|
+
|
331
|
+
it "should execute command with multiple parameters" do
|
332
|
+
result = Pry.run_command "ls -c -M RCTest"
|
333
|
+
result.map(&:to_sym).should == [:a, :B]
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
describe "commands" do
|
338
|
+
it 'should define a command that keeps its return value' do
|
339
|
+
class Command68 < Pry::CommandBase
|
340
|
+
command "hello", "", :keep_retval => true do
|
341
|
+
:kept_hello
|
342
|
+
end
|
343
|
+
end
|
344
|
+
str_output = StringIO.new
|
345
|
+
Pry.new(:input => StringIO.new("hello"), :output => str_output, :commands => Command68).rep
|
346
|
+
str_output.string.should =~ /:kept_hello/
|
347
|
+
|
348
|
+
Object.remove_const(:Command68)
|
349
|
+
end
|
350
|
+
|
351
|
+
it 'should define a command that does NOT keep its return value' do
|
352
|
+
class Command68 < Pry::CommandBase
|
353
|
+
command "hello", "", :keep_retval => false do
|
354
|
+
:kept_hello
|
355
|
+
end
|
356
|
+
end
|
357
|
+
str_output = StringIO.new
|
358
|
+
Pry.new(:input => StringIO.new("hello"), :output => str_output, :commands => Command68).rep
|
359
|
+
(str_output.string =~ /:kept_hello/).should == nil
|
360
|
+
|
361
|
+
Object.remove_const(:Command68)
|
362
|
+
end
|
363
|
+
|
364
|
+
|
365
|
+
it 'should set the commands default, and the default should be overridable' do
|
366
|
+
class Command0 < Pry::CommandBase
|
367
|
+
command "hello" do
|
368
|
+
output.puts "hello world"
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
Pry.commands = Command0
|
373
|
+
|
374
|
+
str_output = StringIO.new
|
375
|
+
Pry.new(:input => InputTester.new("hello"), :output => str_output).rep
|
376
|
+
str_output.string.should =~ /hello world/
|
377
|
+
|
378
|
+
class Command1 < Pry::CommandBase
|
379
|
+
command "goodbye", "" do
|
380
|
+
output.puts "goodbye world"
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
str_output = StringIO.new
|
385
|
+
|
386
|
+
Pry.new(:input => InputTester.new("goodbye"), :output => str_output, :commands => Command1).rep
|
387
|
+
str_output.string.should =~ /goodbye world/
|
388
|
+
|
389
|
+
Object.remove_const(:Command0)
|
390
|
+
Object.remove_const(:Command1)
|
391
|
+
end
|
392
|
+
|
393
|
+
it 'should inherit "help" command from Pry::CommandBase' do
|
394
|
+
class Command2 < Pry::CommandBase
|
395
|
+
command "h", "h command" do
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
Command2.commands.keys.size.should == 2
|
400
|
+
Command2.commands.keys.include?("help").should == true
|
401
|
+
Command2.commands.keys.include?("h").should == true
|
402
|
+
|
403
|
+
Object.remove_const(:Command2)
|
404
|
+
end
|
405
|
+
|
406
|
+
it 'should inherit commands from Pry::Commands' do
|
407
|
+
class Command3 < Pry::Commands
|
408
|
+
command "v" do
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
Command3.commands.include?("nesting").should == true
|
413
|
+
Command3.commands.include?("jump-to").should == true
|
414
|
+
Command3.commands.include?("cd").should == true
|
415
|
+
Command3.commands.include?("v").should == true
|
416
|
+
|
417
|
+
Object.remove_const(:Command3)
|
418
|
+
end
|
419
|
+
|
420
|
+
it 'should alias a command with another command' do
|
421
|
+
class Command6 < Pry::CommandBase
|
422
|
+
alias_command "help2", "help"
|
423
|
+
end
|
424
|
+
|
425
|
+
Command6.commands["help2"].should == Command6.commands["help"]
|
426
|
+
# str_output = StringIO.new
|
427
|
+
# Pry.new(:input => InputTester.new("run_v"), :output => str_output, :commands => Command3).rep
|
428
|
+
# str_output.string.should =~ /v command/
|
429
|
+
|
430
|
+
Object.remove_const(:Command6)
|
431
|
+
end
|
432
|
+
|
433
|
+
it 'should change description of a command using desc' do
|
434
|
+
|
435
|
+
class Command7 < Pry::Commands
|
436
|
+
end
|
437
|
+
|
438
|
+
orig = Command7.commands["help"][:description]
|
439
|
+
|
440
|
+
class Command7
|
441
|
+
desc "help", "blah"
|
442
|
+
end
|
443
|
+
|
444
|
+
Command7.commands["help"][:description].should.not == orig
|
445
|
+
Command7.commands["help"][:description].should == "blah"
|
446
|
+
|
447
|
+
Object.remove_const(:Command7)
|
448
|
+
end
|
449
|
+
|
450
|
+
it 'should run a command from within a command' do
|
451
|
+
class Command01 < Pry::Commands
|
452
|
+
command "v" do
|
453
|
+
output.puts "v command"
|
454
|
+
end
|
455
|
+
|
456
|
+
command "run_v" do
|
457
|
+
run "v"
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
str_output = StringIO.new
|
462
|
+
Pry.new(:input => InputTester.new("run_v"), :output => str_output, :commands => Command01).rep
|
463
|
+
str_output.string.should =~ /v command/
|
464
|
+
|
465
|
+
Object.remove_const(:Command01)
|
466
|
+
end
|
467
|
+
|
468
|
+
it 'should enable an inherited method to access opts and output and target, due to instance_exec' do
|
469
|
+
class Command3 < Pry::Commands
|
470
|
+
command "v" do
|
471
|
+
output.puts "#{target.eval('self')}"
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
class Command4 < Command3
|
476
|
+
end
|
477
|
+
|
478
|
+
str_output = StringIO.new
|
479
|
+
Pry.new(:print => proc {}, :input => InputTester.new("v"),
|
480
|
+
:output => str_output, :commands => Command4).rep("john")
|
481
|
+
str_output.string.chomp.should == "john"
|
482
|
+
|
483
|
+
Object.remove_const(:Command3)
|
484
|
+
Object.remove_const(:Command4)
|
485
|
+
end
|
486
|
+
|
487
|
+
it 'should import commands from another command object' do
|
488
|
+
class Command3 < Pry::CommandBase
|
489
|
+
import_from Pry::Commands, "status", "jump-to"
|
490
|
+
end
|
491
|
+
|
492
|
+
str_output = StringIO.new
|
493
|
+
Pry.new(:print => proc {}, :input => InputTester.new("status"),
|
494
|
+
:output => str_output, :commands => Command3).rep("john")
|
495
|
+
str_output.string.should =~ /Status:/
|
496
|
+
|
497
|
+
Object.remove_const(:Command3)
|
498
|
+
end
|
499
|
+
|
500
|
+
it 'should delete some inherited commands when using delete method' do
|
501
|
+
class Command3 < Pry::Commands
|
502
|
+
command "v" do
|
503
|
+
end
|
504
|
+
|
505
|
+
delete "show_doc", "show_method"
|
506
|
+
delete "ls"
|
507
|
+
end
|
508
|
+
|
509
|
+
Command3.commands.include?("nesting").should == true
|
510
|
+
Command3.commands.include?("jump-to").should == true
|
511
|
+
Command3.commands.include?("cd").should == true
|
512
|
+
Command3.commands.include?("v").should == true
|
513
|
+
Command3.commands.include?("show_doc").should == false
|
514
|
+
Command3.commands.include?("show_method").should == false
|
515
|
+
Command3.commands.include?("ls").should == false
|
516
|
+
|
517
|
+
Object.remove_const(:Command3)
|
518
|
+
end
|
519
|
+
|
520
|
+
it 'should override some inherited commands' do
|
521
|
+
class Command3 < Pry::Commands
|
522
|
+
command "jump-to" do
|
523
|
+
output.puts "jump-to the music"
|
524
|
+
end
|
525
|
+
|
526
|
+
command "help" do
|
527
|
+
output.puts "help to the music"
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
# suppress evaluation output
|
532
|
+
Pry.print = proc {}
|
533
|
+
|
534
|
+
str_output = StringIO.new
|
535
|
+
Pry.new(:input => InputTester.new("jump-to"), :output => str_output, :commands => Command3).rep
|
536
|
+
str_output.string.chomp.should == "jump-to the music"
|
537
|
+
|
538
|
+
str_output = StringIO.new
|
539
|
+
Pry.new(:input => InputTester.new("help"), :output => str_output, :commands => Command3).rep
|
540
|
+
str_output.string.chomp.should == "help to the music"
|
541
|
+
|
542
|
+
Object.remove_const(:Command3)
|
543
|
+
|
544
|
+
Pry.reset_defaults
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
it "should set the print default, and the default should be overridable" do
|
549
|
+
new_print = proc { |out, value| out.puts value }
|
550
|
+
Pry.print = new_print
|
551
|
+
|
552
|
+
Pry.new.print.should == Pry.print
|
553
|
+
str_output = StringIO.new
|
554
|
+
Pry.new(:input => InputTester.new("\"test\""), :output => str_output).rep
|
555
|
+
str_output.string.should == "test\n"
|
556
|
+
|
557
|
+
str_output = StringIO.new
|
558
|
+
Pry.new(:input => InputTester.new("\"test\""), :output => str_output,
|
559
|
+
:print => proc { |out, value| out.puts value.reverse }).rep
|
560
|
+
str_output.string.should == "tset\n"
|
561
|
+
|
562
|
+
Pry.new.print.should == Pry.print
|
563
|
+
str_output = StringIO.new
|
564
|
+
Pry.new(:input => InputTester.new("\"test\""), :output => str_output).rep
|
565
|
+
str_output.string.should == "test\n"
|
566
|
+
end
|
567
|
+
|
568
|
+
describe "pry return values" do
|
569
|
+
it 'should return the target object' do
|
570
|
+
Pry.start(self, :input => StringIO.new("exit"), :output => Pry::NullOutput).should == self
|
571
|
+
end
|
572
|
+
|
573
|
+
it 'should return the parameter given to exit' do
|
574
|
+
Pry.start(self, :input => StringIO.new("exit 10"), :output => Pry::NullOutput).should == 10
|
575
|
+
end
|
576
|
+
|
577
|
+
it 'should return the parameter (multi word string) given to exit' do
|
578
|
+
Pry.start(self, :input => StringIO.new("exit \"john mair\""), :output => Pry::NullOutput).should == "john mair"
|
579
|
+
end
|
580
|
+
|
581
|
+
it 'should return the parameter (function call) given to exit' do
|
582
|
+
Pry.start(self, :input => StringIO.new("exit 'abc'.reverse"), :output => Pry::NullOutput).should == 'cba'
|
583
|
+
end
|
584
|
+
|
585
|
+
it 'should return the parameter (self) given to exit' do
|
586
|
+
Pry.start("carl", :input => StringIO.new("exit self"), :output => Pry::NullOutput).should == "carl"
|
587
|
+
end
|
588
|
+
end
|
589
|
+
|
590
|
+
describe "prompts" do
|
591
|
+
it 'should set the prompt default, and the default should be overridable (single prompt)' do
|
592
|
+
new_prompt = proc { "test prompt> " }
|
593
|
+
Pry.prompt = new_prompt
|
594
|
+
|
595
|
+
Pry.new.prompt.should == Pry.prompt
|
596
|
+
Pry.new.select_prompt(true, 0).should == "test prompt> "
|
597
|
+
Pry.new.select_prompt(false, 0).should == "test prompt> "
|
598
|
+
|
599
|
+
new_prompt = proc { "A" }
|
600
|
+
pry_tester = Pry.new(:prompt => new_prompt)
|
601
|
+
pry_tester.prompt.should == new_prompt
|
602
|
+
pry_tester.select_prompt(true, 0).should == "A"
|
603
|
+
pry_tester.select_prompt(false, 0).should == "A"
|
604
|
+
|
605
|
+
Pry.new.prompt.should == Pry.prompt
|
606
|
+
Pry.new.select_prompt(true, 0).should == "test prompt> "
|
607
|
+
Pry.new.select_prompt(false, 0).should == "test prompt> "
|
608
|
+
end
|
609
|
+
|
610
|
+
it 'should set the prompt default, and the default should be overridable (multi prompt)' do
|
611
|
+
new_prompt = [proc { "test prompt> " }, proc { "test prompt* " }]
|
612
|
+
Pry.prompt = new_prompt
|
613
|
+
|
614
|
+
Pry.new.prompt.should == Pry.prompt
|
615
|
+
Pry.new.select_prompt(true, 0).should == "test prompt> "
|
616
|
+
Pry.new.select_prompt(false, 0).should == "test prompt* "
|
617
|
+
|
618
|
+
new_prompt = [proc { "A" }, proc { "B" }]
|
619
|
+
pry_tester = Pry.new(:prompt => new_prompt)
|
620
|
+
pry_tester.prompt.should == new_prompt
|
621
|
+
pry_tester.select_prompt(true, 0).should == "A"
|
622
|
+
pry_tester.select_prompt(false, 0).should == "B"
|
623
|
+
|
624
|
+
Pry.new.prompt.should == Pry.prompt
|
625
|
+
Pry.new.select_prompt(true, 0).should == "test prompt> "
|
626
|
+
Pry.new.select_prompt(false, 0).should == "test prompt* "
|
627
|
+
end
|
628
|
+
end
|
629
|
+
|
630
|
+
it 'should set the hooks default, and the default should be overridable' do
|
631
|
+
Pry.input = InputTester.new("exit")
|
632
|
+
Pry.hooks = {
|
633
|
+
:before_session => proc { |out,_| out.puts "HELLO" },
|
634
|
+
:after_session => proc { |out,_| out.puts "BYE" }
|
635
|
+
}
|
636
|
+
|
637
|
+
str_output = StringIO.new
|
638
|
+
Pry.new(:output => str_output).repl
|
639
|
+
str_output.string.should =~ /HELLO/
|
640
|
+
str_output.string.should =~ /BYE/
|
641
|
+
|
642
|
+
Pry.input.rewind
|
643
|
+
|
644
|
+
str_output = StringIO.new
|
645
|
+
Pry.new(:output => str_output,
|
646
|
+
:hooks => {
|
647
|
+
:before_session => proc { |out,_| out.puts "MORNING" },
|
648
|
+
:after_session => proc { |out,_| out.puts "EVENING" }
|
649
|
+
}
|
650
|
+
).repl
|
651
|
+
|
652
|
+
str_output.string.should =~ /MORNING/
|
653
|
+
str_output.string.should =~ /EVENING/
|
654
|
+
|
655
|
+
# try below with just defining one hook
|
656
|
+
Pry.input.rewind
|
657
|
+
str_output = StringIO.new
|
658
|
+
Pry.new(:output => str_output,
|
659
|
+
:hooks => {
|
660
|
+
:before_session => proc { |out,_| out.puts "OPEN" }
|
661
|
+
}
|
662
|
+
).repl
|
663
|
+
|
664
|
+
str_output.string.should =~ /OPEN/
|
665
|
+
|
666
|
+
Pry.input.rewind
|
667
|
+
str_output = StringIO.new
|
668
|
+
Pry.new(:output => str_output,
|
669
|
+
:hooks => {
|
670
|
+
:after_session => proc { |out,_| out.puts "CLOSE" }
|
671
|
+
}
|
672
|
+
).repl
|
673
|
+
|
674
|
+
str_output.string.should =~ /CLOSE/
|
675
|
+
|
676
|
+
Pry.reset_defaults
|
677
|
+
end
|
678
|
+
end
|
679
|
+
end
|
680
|
+
end
|
681
|
+
end
|