pry 0.9.7.4 → 0.9.8pre2

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.
Files changed (49) hide show
  1. data/.gitignore +1 -3
  2. data/README.markdown +3 -1
  3. data/Rakefile +48 -31
  4. data/bin/pry +2 -80
  5. data/lib/pry.rb +17 -20
  6. data/lib/pry/cli.rb +152 -0
  7. data/lib/pry/command_processor.rb +13 -0
  8. data/lib/pry/command_set.rb +102 -9
  9. data/lib/pry/config.rb +28 -6
  10. data/lib/pry/default_commands/context.rb +9 -8
  11. data/lib/pry/default_commands/documentation.rb +55 -13
  12. data/lib/pry/default_commands/easter_eggs.rb +1 -1
  13. data/lib/pry/default_commands/input.rb +25 -25
  14. data/lib/pry/default_commands/introspection.rb +19 -18
  15. data/lib/pry/default_commands/ls.rb +23 -38
  16. data/lib/pry/default_commands/shell.rb +47 -15
  17. data/lib/pry/helpers/command_helpers.rb +28 -6
  18. data/lib/pry/helpers/options_helpers.rb +7 -4
  19. data/lib/pry/helpers/text.rb +23 -3
  20. data/lib/pry/history.rb +55 -17
  21. data/lib/pry/history_array.rb +2 -0
  22. data/lib/pry/hooks.rb +108 -0
  23. data/lib/pry/indent.rb +9 -5
  24. data/lib/pry/method.rb +99 -50
  25. data/lib/pry/plugins.rb +10 -2
  26. data/lib/pry/pry_class.rb +48 -20
  27. data/lib/pry/pry_instance.rb +106 -91
  28. data/lib/pry/version.rb +1 -1
  29. data/lib/pry/wrapped_module.rb +73 -0
  30. data/man/pry.1 +195 -0
  31. data/man/pry.1.html +204 -0
  32. data/man/pry.1.ronn +141 -0
  33. data/pry.gemspec +21 -24
  34. data/test/helper.rb +12 -3
  35. data/test/test_cli.rb +78 -0
  36. data/test/test_command_set.rb +193 -1
  37. data/test/test_default_commands/test_context.rb +19 -4
  38. data/test/test_default_commands/test_input.rb +2 -2
  39. data/test/test_default_commands/test_introspection.rb +63 -6
  40. data/test/test_default_commands/test_ls.rb +8 -35
  41. data/test/test_default_commands/test_shell.rb +36 -1
  42. data/test/test_hooks.rb +175 -0
  43. data/test/test_indent.rb +2 -0
  44. data/test/test_method.rb +10 -0
  45. data/test/test_pry.rb +35 -34
  46. data/test/test_pry_history.rb +24 -24
  47. data/test/test_syntax_checking.rb +47 -0
  48. data/test/test_wrapped_module.rb +71 -0
  49. metadata +40 -34
@@ -2,9 +2,9 @@ require 'helper'
2
2
 
3
3
  describe "Pry::DefaultCommands::Context" do
4
4
  describe "exit-all" do
5
- it 'should break out of the repl loop of Pry instance (returning target of session)' do
5
+ it 'should break out of the repl loop of Pry instance and return nil' do
6
6
  redirect_pry_io(InputTester.new("exit-all"), StringIO.new) do
7
- Pry.new.repl(0).should == 0
7
+ Pry.new.repl(0).should == nil
8
8
  end
9
9
  end
10
10
 
@@ -31,6 +31,21 @@ describe "Pry::DefaultCommands::Context" do
31
31
  end
32
32
  end
33
33
 
34
+ describe "whereami" do
35
+ it 'should work with methods that have been undefined' do
36
+ class Cor
37
+ def blimey!
38
+ Cor.send :undef_method, :blimey!
39
+ # using [.] so the regex doesn't match itself
40
+ mock_pry(binding, 'whereami').should =~ /self[.]blimey!/
41
+ end
42
+ end
43
+
44
+ Cor.new.blimey!
45
+ Object.remove_const(:Cor)
46
+ end
47
+ end
48
+
34
49
  describe "exit" do
35
50
  it 'should pop a binding with exit' do
36
51
  b = Pry.binding_for(:outer)
@@ -44,7 +59,7 @@ describe "Pry::DefaultCommands::Context" do
44
59
  end
45
60
 
46
61
  it 'should break out of the repl loop of Pry instance when binding_stack has only one binding with exit' do
47
- Pry.start(0, :input => StringIO.new("exit")).should == 0
62
+ Pry.start(0, :input => StringIO.new("exit")).should == nil
48
63
  end
49
64
 
50
65
  it 'should break out of the repl loop of Pry instance when binding_stack has only one binding with exit, and return user-given value' do
@@ -127,7 +142,7 @@ describe "Pry::DefaultCommands::Context" do
127
142
  end
128
143
 
129
144
  it 'should break out of the repl loop of Pry instance when binding_stack has only one binding with cd ..' do
130
- Pry.start(0, :input => StringIO.new("cd ..")).should == 0
145
+ Pry.start(0, :input => StringIO.new("cd ..")).should == nil
131
146
  end
132
147
 
133
148
  it 'should break out to outer-most session with cd /' do
@@ -154,7 +154,7 @@ describe "Pry::DefaultCommands::Input" do
154
154
  b = binding
155
155
  b.eval('x = "\"hello\""')
156
156
  redirect_pry_io(InputTester.new("play x", "exit-all"), str_output = StringIO.new) do
157
- Pry.start b, :hooks => {}
157
+ Pry.start b, :hooks => Pry::Hooks.new
158
158
  end
159
159
  str_output.string.should =~ /hello/
160
160
  end
@@ -163,7 +163,7 @@ describe "Pry::DefaultCommands::Input" do
163
163
  b = binding
164
164
  b.eval('x = "\"hello\"\n\"goodbye\"\n\"love\""')
165
165
  redirect_pry_io(InputTester.new("play x --lines 1", "exit-all"), str_output = StringIO.new) do
166
- Pry.start b, :hooks => {}
166
+ Pry.start b, :hooks => Pry::Hooks.new
167
167
  end
168
168
  str_output.string.should =~ /hello/
169
169
  str_output.string.should.not =~ /love/
@@ -48,7 +48,7 @@ describe "Pry::DefaultCommands::Introspection" do
48
48
  end
49
49
 
50
50
  it "should reload the file if it is a ruby file" do
51
- tf = Tempfile.new(["tmp", ".rb"])
51
+ tf = Tempfile.new(["pry", ".rb"])
52
52
  path = tf.path
53
53
 
54
54
  mock_pry("edit #{path}", "$rand").should =~ /#{@rand}/
@@ -57,7 +57,7 @@ describe "Pry::DefaultCommands::Introspection" do
57
57
  end
58
58
 
59
59
  it "should not reload the file if it is not a ruby file" do
60
- tf = Tempfile.new(["tmp", ".py"])
60
+ tf = Tempfile.new(["pry", ".py"])
61
61
  path = tf.path
62
62
 
63
63
  mock_pry("edit #{path}", "$rand").should.not =~ /#{@rand}/
@@ -66,7 +66,7 @@ describe "Pry::DefaultCommands::Introspection" do
66
66
  end
67
67
 
68
68
  it "should not reload a ruby file if -n is given" do
69
- tf = Tempfile.new(["tmp", ".rb"])
69
+ tf = Tempfile.new(["pry", ".rb"])
70
70
  path = tf.path
71
71
 
72
72
  mock_pry("edit -n #{path}", "$rand").should.not =~ /#{@rand}/
@@ -75,7 +75,7 @@ describe "Pry::DefaultCommands::Introspection" do
75
75
  end
76
76
 
77
77
  it "should reload a non-ruby file if -r is given" do
78
- tf = Tempfile.new(["tmp", ".pryrc"])
78
+ tf = Tempfile.new(["pry", ".pryrc"])
79
79
  path = tf.path
80
80
 
81
81
  mock_pry("edit -r #{path}", "$rand").should =~ /#{@rand}/
@@ -87,7 +87,7 @@ describe "Pry::DefaultCommands::Introspection" do
87
87
 
88
88
  describe "with --ex" do
89
89
  before do
90
- @tf = Tempfile.new(["tmp", ".rb"])
90
+ @tf = Tempfile.new(["pry", ".rb"])
91
91
  @path = @tf.path
92
92
  @tf << "1\n2\nraise RuntimeError"
93
93
  @tf.flush
@@ -254,6 +254,10 @@ describe "Pry::DefaultCommands::Introspection" do
254
254
  str_output.string.should =~ /def sample/
255
255
  end
256
256
 
257
+ it 'should output help' do
258
+ mock_pry('show-method -h').should =~ /Usage: show-method/
259
+ end
260
+
257
261
  it 'should output a method\'s source with line numbers' do
258
262
  str_output = StringIO.new
259
263
  redirect_pry_io(InputTester.new("show-method -l sample_method", "exit-all"), str_output) do
@@ -316,6 +320,59 @@ describe "Pry::DefaultCommands::Introspection" do
316
320
  str_output.string.should =~ /Mr flibble/
317
321
  end
318
322
 
323
+ it "should find instance methods with -M" do
324
+ c = Class.new{ def moo; "ve over!"; end }
325
+ mock_pry(binding, "cd c","show-method -M moo").should =~ /ve over/
326
+ end
327
+
328
+ it "should not find instance methods with -m" do
329
+ c = Class.new{ def moo; "ve over!"; end }
330
+ mock_pry(binding, "cd c", "show-method -m moo").should =~ /could not be found/
331
+ end
332
+
333
+ it "should find normal methods with -m" do
334
+ c = Class.new{ def self.moo; "ve over!"; end }
335
+ mock_pry(binding, "cd c", "show-method -m moo").should =~ /ve over/
336
+ end
337
+
338
+ it "should not find normal methods with -M" do
339
+ c = Class.new{ def self.moo; "ve over!"; end }
340
+ mock_pry(binding, "cd c", "show-method -M moo").should =~ /could not be found/
341
+ end
342
+
343
+ it "should find normal methods with no -M or -m" do
344
+ c = Class.new{ def self.moo; "ve over!"; end }
345
+ mock_pry(binding, "cd c", "show-method moo").should =~ /ve over/
346
+ end
347
+
348
+ it "should find instance methods with no -M or -m" do
349
+ c = Class.new{ def moo; "ve over!"; end }
350
+ mock_pry(binding, "cd c", "show-method moo").should =~ /ve over/
351
+ end
352
+
353
+ it "should find super methods" do
354
+ class Foo
355
+ def foo(*bars)
356
+ :super_wibble
357
+ end
358
+ end
359
+ o = Foo.new
360
+ Object.remove_const(:Foo)
361
+ def o.foo(*bars)
362
+ :wibble
363
+ end
364
+
365
+ mock_pry(binding, "show-method --super o.foo").should =~ /:super_wibble/
366
+
367
+ end
368
+
369
+ it "should not raise an exception when a non-extant super method is requested" do
370
+ o = Object.new
371
+ def o.foo(*bars); end
372
+
373
+ mock_pry(binding, "show-method --super o.foo").should =~ /'self.foo' has no super method/
374
+ end
375
+
319
376
  # dynamically defined method source retrieval is only supported in
320
377
  # 1.9 - where Method#source_location is native
321
378
  if RUBY_VERSION =~ /1.9/
@@ -364,7 +421,7 @@ describe "Pry::DefaultCommands::Introspection" do
364
421
  describe "edit-method" do
365
422
  describe "on a method defined in a file" do
366
423
  before do
367
- @tempfile = Tempfile.new(['tmp', '*.rb'])
424
+ @tempfile = Tempfile.new(['pry', '*.rb'])
368
425
  @tempfile.puts <<-EOS
369
426
  module A
370
427
  def a
@@ -1,38 +1,5 @@
1
1
  require 'helper'
2
2
  describe "ls" do
3
- describe "class_name" do
4
- extend Pry::DefaultCommands::Ls.helper_module
5
- it "should use the name of the class if it exists" do
6
- class_name(Object).should == "Object"
7
- end
8
-
9
- it "should use the name of the module if it exists" do
10
- class_name(Kernel).should == "Kernel"
11
- end
12
-
13
- it "should use Foo.self for singleton classes of classes" do
14
- class_name(class << Object; self; end).should == "Object.self"
15
- end
16
-
17
- it "should use Foo.self for singleton methods of modules" do
18
- class_name(class << Kernel; self; end).should == "Kernel.self"
19
- end
20
-
21
- it "should default to the .to_s if that's not possible" do
22
- cls = Class.new
23
- class_name(cls).should == cls.to_s
24
- end
25
-
26
- it "should default to .to_s.self" do
27
- cls = Class.new
28
- class_name(class << cls; self; end).should == "#{cls.to_s}.self"
29
- end
30
-
31
- it "should just be self for singleton classes of normal objects" do
32
- class_name(class << "hi"; self; end).should == "self"
33
- end
34
- end
35
-
36
3
  describe "below ceiling" do
37
4
  it "should stop before Object by default" do
38
5
  mock_pry("cd Class.new{ def goo; end }.new", "ls").should.not =~ /Object/
@@ -55,7 +22,13 @@ describe "ls" do
55
22
  end
56
23
  end
57
24
 
58
- describe "methods" do
25
+ describe "help" do
26
+ it 'should show help with -h' do
27
+ mock_pry("ls -h").should =~ /Usage: ls/
28
+ end
29
+ end
30
+
31
+ describe "methods" do
59
32
  it "should show public methods by default" do
60
33
  mock_pry("ls Class.new{ def goo; end }.new").should =~ /goo/
61
34
  end
@@ -77,7 +50,7 @@ describe "ls" do
77
50
  it "should work for objects with an overridden method method" do
78
51
  require 'net/http'
79
52
  # This doesn't actually touch the network, promise!
80
- mock_pry("ls Net::HTTP::Get.new('localhost')").should =~ /Net::HTTPGenericRequest methods/
53
+ mock_pry("ls Net::HTTP::Get.new('localhost')").should =~ /Net::HTTPGenericRequest#methods/
81
54
  end
82
55
  end
83
56
 
@@ -9,6 +9,41 @@ describe "Pry::DefaultCommands::Shell" do
9
9
  end
10
10
  end
11
11
 
12
+ describe "with --in" do
13
+ it 'should display the last few expressions with indices' do
14
+ output = mock_pry("10", "20", "cat --in")
15
+ output.should =~ /^1:/
16
+ output.should =~ /^ 10/
17
+ output.should =~ /^2:/
18
+ output.should =~ /^ 20/
19
+ end
20
+ end
21
+
22
+ describe "with --in 1" do
23
+ it 'should display the first expression with no index' do
24
+ output = mock_pry("10", "20", "cat --in 1")
25
+ output.should.not =~ /^\d+:/
26
+ output.should =~ /^10/
27
+ end
28
+ end
29
+
30
+ describe "with --in -1" do
31
+ it 'should display the last expression with no index' do
32
+ output = mock_pry("10", "20", "cat --in -1")
33
+ output.should.not =~ /^\d+:/
34
+ output.should =~ /^20/
35
+ end
36
+ end
37
+
38
+ describe "with --in 1..2" do
39
+ it 'should display the given range with indices, omitting nils' do
40
+ output = mock_pry("10", "20", "cat --ex", ":hello", "cat --in 1..4")
41
+ output.should =~ /^1:/
42
+ output.should.not =~ /^3:/
43
+ output.should =~ /^ :hello/
44
+ end
45
+ end
46
+
12
47
  # this doesnt work so well on rbx due to differences in backtrace
13
48
  # so we currently skip rbx until we figure out a workaround
14
49
  describe "with --ex" do
@@ -86,7 +121,7 @@ describe "Pry::DefaultCommands::Shell" do
86
121
  it 'each successive cat --ex should show the next level of backtrace, and going past the final level should return to the first' do
87
122
  temp_files = []
88
123
  3.times do |i|
89
- temp_files << Tempfile.new(['tmp', '*.rb'])
124
+ temp_files << Tempfile.new(['pry', '*.rb'])
90
125
  temp_files.last << "bt number #{i}"
91
126
  temp_files.last.flush
92
127
  end
@@ -0,0 +1,175 @@
1
+ require 'helper'
2
+
3
+ describe Pry::Hooks do
4
+ before do
5
+ @hooks = Pry::Hooks.new
6
+ end
7
+
8
+ describe "adding a new hook" do
9
+ it 'should not execute hook while adding it' do
10
+ run = false
11
+ @hooks.add_hook(:test_hook, :my_name) { run = true }
12
+ run.should == false
13
+ end
14
+
15
+ it 'should not allow adding of a hook with a duplicate name' do
16
+ @hooks.add_hook(:test_hook, :my_name) {}
17
+
18
+ lambda { @hooks.add_hook(:test_hook, :my_name) {} }.should.raise ArgumentError
19
+ end
20
+
21
+ it 'should create a new hook with a block' do
22
+ @hooks.add_hook(:test_hook, :my_name) { }
23
+ @hooks.hook_count(:test_hook).should == 1
24
+ end
25
+
26
+ it 'should create a new hook with a callable' do
27
+ @hooks.add_hook(:test_hook, :my_name, proc { })
28
+ @hooks.hook_count(:test_hook).should == 1
29
+ end
30
+
31
+ it 'should use block if given both block and callable' do
32
+ run = false
33
+ foo = false
34
+ @hooks.add_hook(:test_hook, :my_name, proc { foo = true }) { run = true }
35
+ @hooks.hook_count(:test_hook).should == 1
36
+ @hooks.exec_hook(:test_hook)
37
+ run.should == true
38
+ foo.should == false
39
+ end
40
+
41
+ it 'should raise if not given a block or any other object' do
42
+ lambda { @hooks.add_hook(:test_hook, :my_name) }.should.raise ArgumentError
43
+ end
44
+
45
+ it 'should create multiple hooks for an event' do
46
+ @hooks.add_hook(:test_hook, :my_name) {}
47
+ @hooks.add_hook(:test_hook, :my_name2) {}
48
+ @hooks.hook_count(:test_hook).should == 2
49
+ end
50
+
51
+ it 'should return a count of 0 for an empty hook' do
52
+ @hooks.hook_count(:test_hook).should == 0
53
+ end
54
+ end
55
+
56
+ describe "getting hooks" do
57
+ describe "get_hook" do
58
+ it 'should return the correct requested hook' do
59
+ run = false
60
+ fun = false
61
+ @hooks.add_hook(:test_hook, :my_name) { run = true }
62
+ @hooks.add_hook(:test_hook, :my_name2) { fun = true }
63
+ @hooks.get_hook(:test_hook, :my_name).call
64
+ run.should == true
65
+ fun.should == false
66
+ end
67
+
68
+ it 'should return nil if hook does not exist' do
69
+ @hooks.get_hook(:test_hook, :my_name).should == nil
70
+ end
71
+ end
72
+
73
+ describe "get_hooks" do
74
+ it 'should return a hash of hook names/hook functions for an event' do
75
+ hook1 = proc { 1 }
76
+ hook2 = proc { 2 }
77
+ @hooks.add_hook(:test_hook, :my_name1, hook1)
78
+ @hooks.add_hook(:test_hook, :my_name2, hook2)
79
+ hash = @hooks.get_hooks(:test_hook)
80
+ hash.size.should == 2
81
+ hash[:my_name1].should == hook1
82
+ hash[:my_name2].should == hook2
83
+ end
84
+
85
+ it 'should return an empty hash if no hooks defined' do
86
+ @hooks.get_hooks(:test_hook).should == {}
87
+ end
88
+ end
89
+ end
90
+
91
+ describe "clearing all hooks for an event" do
92
+ it 'should clear all hooks' do
93
+ @hooks.add_hook(:test_hook, :my_name) { }
94
+ @hooks.add_hook(:test_hook, :my_name2) { }
95
+ @hooks.add_hook(:test_hook, :my_name3) { }
96
+ @hooks.clear(:test_hook)
97
+ @hooks.hook_count(:test_hook).should == 0
98
+ end
99
+ end
100
+
101
+ describe "deleting a hook" do
102
+ it 'should successfully delete a hook' do
103
+ @hooks.add_hook(:test_hook, :my_name) {}
104
+ @hooks.delete_hook(:test_hook, :my_name)
105
+ @hooks.hook_count(:test_hook).should == 0
106
+ end
107
+
108
+ it 'should return the deleted hook' do
109
+ run = false
110
+ @hooks.add_hook(:test_hook, :my_name) { run = true }
111
+ @hooks.delete_hook(:test_hook, :my_name).call
112
+ run.should == true
113
+ end
114
+
115
+ it 'should return nil if hook does not exist' do
116
+ @hooks.delete_hook(:test_hook, :my_name).should == nil
117
+ end
118
+ end
119
+
120
+ describe "executing a hook" do
121
+ it 'should execute block hook' do
122
+ run = false
123
+ @hooks.add_hook(:test_hook, :my_name) { run = true }
124
+ @hooks.exec_hook(:test_hook)
125
+ run.should == true
126
+ end
127
+
128
+ it 'should execute proc hook' do
129
+ run = false
130
+ @hooks.add_hook(:test_hook, :my_name, proc { run = true })
131
+ @hooks.exec_hook(:test_hook)
132
+ run.should == true
133
+ end
134
+
135
+ it 'should execute a general callable hook' do
136
+ callable = Object.new.tap do |obj|
137
+ obj.instance_variable_set(:@test_var, nil)
138
+ class << obj
139
+ attr_accessor :test_var
140
+ def call() @test_var = true; end
141
+ end
142
+ end
143
+
144
+ @hooks.add_hook(:test_hook, :my_name, callable)
145
+ @hooks.exec_hook(:test_hook)
146
+ callable.test_var.should == true
147
+ end
148
+
149
+ it 'should execute all hooks for an event if more than one is defined' do
150
+ x = nil
151
+ y = nil
152
+ @hooks.add_hook(:test_hook, :my_name1) { y = true }
153
+ @hooks.add_hook(:test_hook, :my_name2) { x = true }
154
+ @hooks.exec_hook(:test_hook)
155
+ x.should == true
156
+ y.should == true
157
+ end
158
+
159
+ it 'should execute hooks in order' do
160
+ array = []
161
+ @hooks.add_hook(:test_hook, :my_name1) { array << 1 }
162
+ @hooks.add_hook(:test_hook, :my_name2) { array << 2 }
163
+ @hooks.add_hook(:test_hook, :my_name3) { array << 3 }
164
+ @hooks.exec_hook(:test_hook)
165
+ array.should == [1, 2, 3]
166
+ end
167
+
168
+ it 'return value of exec_hook should be that of last executed hook' do
169
+ @hooks.add_hook(:test_hook, :my_name1) { 1 }
170
+ @hooks.add_hook(:test_hook, :my_name2) { 2 }
171
+ @hooks.add_hook(:test_hook, :my_name3) { 3 }
172
+ @hooks.exec_hook(:test_hook).should == 3
173
+ end
174
+ end
175
+ end