pry 0.8.4pre1 → 0.9.0pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/.gitignore +1 -0
  2. data/README.markdown +1 -1
  3. data/Rakefile +11 -5
  4. data/TODO +28 -2
  5. data/bin/pry +5 -9
  6. data/examples/example_basic.rb +2 -4
  7. data/examples/example_command_override.rb +2 -5
  8. data/examples/example_commands.rb +1 -4
  9. data/examples/example_hooks.rb +2 -5
  10. data/examples/example_image_edit.rb +4 -8
  11. data/examples/example_input.rb +1 -4
  12. data/examples/example_input2.rb +1 -4
  13. data/examples/example_output.rb +1 -4
  14. data/examples/example_print.rb +2 -5
  15. data/examples/example_prompt.rb +2 -5
  16. data/examples/helper.rb +6 -0
  17. data/lib/pry.rb +61 -4
  18. data/lib/pry/command_context.rb +10 -9
  19. data/lib/pry/command_processor.rb +29 -68
  20. data/lib/pry/command_set.rb +79 -28
  21. data/lib/pry/commands.rb +10 -121
  22. data/lib/pry/completion.rb +30 -29
  23. data/lib/pry/config.rb +93 -0
  24. data/lib/pry/default_commands/basic.rb +37 -0
  25. data/lib/pry/default_commands/context.rb +15 -15
  26. data/lib/pry/default_commands/documentation.rb +49 -48
  27. data/lib/pry/default_commands/easter_eggs.rb +1 -20
  28. data/lib/pry/default_commands/gems.rb +32 -41
  29. data/lib/pry/default_commands/input.rb +95 -19
  30. data/lib/pry/default_commands/introspection.rb +54 -60
  31. data/lib/pry/default_commands/ls.rb +2 -2
  32. data/lib/pry/default_commands/shell.rb +29 -39
  33. data/lib/pry/extended_commands/experimental.rb +48 -0
  34. data/lib/pry/extended_commands/user_command_api.rb +22 -0
  35. data/lib/pry/helpers.rb +1 -0
  36. data/lib/pry/helpers/base_helpers.rb +9 -106
  37. data/lib/pry/helpers/command_helpers.rb +96 -59
  38. data/lib/pry/helpers/text.rb +83 -0
  39. data/lib/pry/plugins.rb +79 -0
  40. data/lib/pry/pry_class.rb +96 -111
  41. data/lib/pry/pry_instance.rb +87 -55
  42. data/lib/pry/version.rb +1 -1
  43. data/test/helper.rb +56 -7
  44. data/test/test_command_processor.rb +99 -0
  45. data/test/{test_commandset.rb → test_command_set.rb} +18 -12
  46. data/test/test_default_commands.rb +59 -0
  47. data/test/test_default_commands/test_context.rb +64 -0
  48. data/test/test_default_commands/test_documentation.rb +31 -0
  49. data/test/test_default_commands/test_input.rb +157 -0
  50. data/test/test_default_commands/test_introspection.rb +146 -0
  51. data/test/test_pry.rb +430 -313
  52. metadata +25 -9
  53. data/lib/pry/hooks.rb +0 -17
  54. data/lib/pry/print.rb +0 -16
  55. data/lib/pry/prompts.rb +0 -31
@@ -2,12 +2,13 @@ require "pry/command_processor.rb"
2
2
 
3
3
  class Pry
4
4
 
5
- # The list of configuration options.
6
- CONFIG_OPTIONS = [:input, :output, :commands, :print,
7
- :exception_handler, :prompt, :hooks,
8
- :custom_completions]
9
-
10
- attr_accessor *CONFIG_OPTIONS
5
+ attr_accessor :input
6
+ attr_accessor :output
7
+ attr_accessor :commands
8
+ attr_accessor :print
9
+ attr_accessor :exception_handler
10
+ attr_accessor :hooks
11
+ attr_accessor :custom_completions
11
12
 
12
13
  # Returns the target binding for the session. Note that altering this
13
14
  # attribute will not change the target binding.
@@ -18,22 +19,56 @@ class Pry
18
19
  # @param [Hash] options The optional configuration parameters.
19
20
  # @option options [#readline] :input The object to use for input.
20
21
  # @option options [#puts] :output The object to use for output.
21
- # @option options [Pry::CommandBase] :commands The object to use for commands. (see commands.rb)
22
- # @option options [Hash] :hooks The defined hook Procs (see hooks.rb)
23
- # @option options [Array<Proc>] :default_prompt The array of Procs to use for the prompts. (see prompts.rb)
22
+ # @option options [Pry::CommandBase] :commands The object to use for commands.
23
+ # @option options [Hash] :hooks The defined hook Procs
24
+ # @option options [Array<Proc>] :prompt The array of Procs to use for the prompts.
24
25
  # @option options [Proc] :print The Proc to use for the 'print'
25
26
  # component of the REPL. (see print.rb)
26
27
  def initialize(options={})
28
+ refresh(options)
29
+ @command_processor = CommandProcessor.new(self)
30
+ end
27
31
 
28
- default_options = {}
29
- CONFIG_OPTIONS.each { |v| default_options[v] = Pry.send(v) }
30
- default_options.merge!(options)
32
+ # Refresh the Pry instance settings from the Pry class.
33
+ # Allows options to be specified to override settings from Pry class.
34
+ # @param [Hash] options The options to override Pry class settings
35
+ # for this instance.
36
+ def refresh(options={})
37
+ defaults = {}
38
+ attributes = [
39
+ :input, :output, :commands, :print,
40
+ :exception_handler, :hooks, :custom_completions,
41
+ :prompt
42
+ ]
43
+
44
+ attributes.each do |attribute|
45
+ defaults[attribute] = Pry.send attribute
46
+ end
31
47
 
32
- CONFIG_OPTIONS.each do |key|
33
- send "#{key}=", default_options[key]
48
+ defaults.merge!(options).each do |key, value|
49
+ send "#{key}=", value
34
50
  end
51
+ true
52
+ end
35
53
 
36
- @command_processor = CommandProcessor.new(self)
54
+ # The current prompt.
55
+ # This is the prompt at the top of the prompt stack.
56
+ #
57
+ # @example
58
+ # self.prompt = Pry::SIMPLE_PROMPT
59
+ # self.prompt # => Pry::SIMPLE_PROMPT
60
+ #
61
+ # @return [Array<Proc>] Current prompt.
62
+ def prompt
63
+ prompt_stack.last
64
+ end
65
+
66
+ def prompt=(new_prompt)
67
+ if prompt_stack.empty?
68
+ push_prompt new_prompt
69
+ else
70
+ prompt_stack[-1] = new_prompt
71
+ end
37
72
  end
38
73
 
39
74
  # Get nesting data.
@@ -50,6 +85,11 @@ class Pry
50
85
  self.class.nesting = v
51
86
  end
52
87
 
88
+ # @return [Boolean] Whether top-level session has ended.
89
+ def finished_top_level_session?
90
+ nesting.empty?
91
+ end
92
+
53
93
  # Return parent of current Pry session.
54
94
  # @return [Pry] The parent of the current Pry session.
55
95
  def parent
@@ -71,8 +111,8 @@ class Pry
71
111
  Pry.active_instance = self
72
112
 
73
113
  # Make sure special locals exist
74
- target.eval("_pry_ = ::Pry.active_instance")
75
- target.eval("_ = ::Pry.last_result")
114
+ set_active_instance(target)
115
+ set_last_result(Pry.last_result, target)
76
116
  self.session_target = target
77
117
  end
78
118
 
@@ -91,6 +131,8 @@ class Pry
91
131
  throw :breakout, break_data
92
132
  end
93
133
 
134
+ save_history if Pry.config.history.save && finished_top_level_session?
135
+
94
136
  return_value
95
137
  end
96
138
 
@@ -151,22 +193,19 @@ class Pry
151
193
  Readline.completion_proc = Pry::InputCompleter.build_completion_proc target, instance_eval(&custom_completions)
152
194
  end
153
195
 
154
- # save the pry instance to active_instance
155
- Pry.active_instance = self
156
- target.eval("_pry_ = ::Pry.active_instance")
157
-
158
196
  @last_result_is_exception = false
197
+ set_active_instance(target)
198
+ expr = r(target)
159
199
 
160
- # eval the expression and save to last_result
161
- # Do not want __FILE__, __LINE__ here because we need to distinguish
162
- # (eval) methods for show-method and friends.
163
- # This also sets the `_` local for the session.
164
- set_last_result(target.eval(r(target)), target)
200
+ Pry.line_buffer.push(*expr.each_line)
201
+ set_last_result(target.eval(expr, Pry.eval_path, Pry.current_line), target)
165
202
  rescue SystemExit => e
166
203
  exit
167
204
  rescue Exception => e
168
205
  @last_result_is_exception = true
169
206
  set_last_exception(e, target)
207
+ ensure
208
+ Pry.current_line += expr.each_line.count if expr
170
209
  end
171
210
 
172
211
  # Perform a read.
@@ -175,18 +214,19 @@ class Pry
175
214
  # Ruby expression is received.
176
215
  # Pry commands are also accepted here and operate on the target.
177
216
  # @param [Object, Binding] target The receiver of the read.
217
+ # @param [String] eval_string Optionally Prime `eval_string` with a start value.
178
218
  # @return [String] The Ruby expression.
179
219
  # @example
180
220
  # Pry.new.r(Object.new)
181
- def r(target=TOPLEVEL_BINDING)
221
+ def r(target=TOPLEVEL_BINDING, eval_string="")
182
222
  target = Pry.binding_for(target)
183
223
  @suppress_output = false
184
- eval_string = ""
185
224
 
186
225
  val = ""
187
226
  loop do
188
227
  val = retrieve_line(eval_string, target)
189
228
  process_line(val, eval_string, target)
229
+
190
230
  break if valid_expression?(eval_string)
191
231
  end
192
232
 
@@ -195,7 +235,7 @@ class Pry
195
235
  eval_string
196
236
  end
197
237
 
198
- # FIXME should delete this method? it's exposing an implementation detail!
238
+ # Output the result or pass to an exception handler (if result is an exception).
199
239
  def show_result(result)
200
240
  if last_result_is_exception?
201
241
  exception_handler.call output, result
@@ -264,6 +304,14 @@ class Pry
264
304
  target.eval("_ex_ = ::Pry.last_exception")
265
305
  end
266
306
 
307
+ # Set the active instance for a session.
308
+ # This method should not need to be invoked directly.
309
+ # @param [Binding] target The binding to set `_ex_` on.
310
+ def set_active_instance(target)
311
+ Pry.active_instance = self
312
+ target.eval("_pry_ = ::Pry.active_instance")
313
+ end
314
+
267
315
  # @return [Boolean] True if the last result is an exception that was raised,
268
316
  # as opposed to simply an instance of Exception (like the result of
269
317
  # Exception.new)
@@ -291,7 +339,7 @@ class Pry
291
339
  end
292
340
 
293
341
  rescue EOFError
294
- self.input = Readline
342
+ self.input = Pry.input
295
343
  ""
296
344
  end
297
345
  end
@@ -305,6 +353,14 @@ class Pry
305
353
  !@suppress_output || last_result_is_exception?
306
354
  end
307
355
 
356
+ # Save readline history to a file.
357
+ def save_history
358
+ history_file = File.expand_path(Pry.config.history.file)
359
+ File.open(history_file, 'w') do |f|
360
+ f.write Readline::HISTORY.to_a.join("\n")
361
+ end
362
+ end
363
+
308
364
  # Returns the appropriate prompt to use.
309
365
  # This method should not need to be invoked directly.
310
366
  # @param [Boolean] first_line Whether this is the first line of input
@@ -326,30 +382,6 @@ class Pry
326
382
  end
327
383
  private :prompt_stack
328
384
 
329
- # The current prompt, this is the prompt at the top of the prompt stack.
330
- # @return [Array<Proc>] Current prompt.
331
- # @example
332
- # push_prompt(Pry::SIMPLE_PROMPT)
333
- # prompt # => Pry::SIMPLE_PROMPT
334
- def prompt
335
- prompt_stack.last
336
- end
337
-
338
- # Replaces the current prompt with the new prompt.
339
- # Does not change the rest of the prompt stack.
340
- # @param [Array<Proc>] new_prompt
341
- # @return [Array<Proc>] new_prompt
342
- # @example
343
- # pry.prompt = Pry::SIMPLE_PROMPT # => Pry::SIMPLE_PROMPT
344
- # pry.prompt # => Pry::SIMPLE_PROMPT
345
- def prompt=(new_prompt)
346
- if prompt_stack.empty?
347
- push_prompt new_prompt
348
- else
349
- prompt_stack[-1] = new_prompt
350
- end
351
- end
352
-
353
385
  # Pushes the current prompt onto a stack that it can be restored from later.
354
386
  # Use this if you wish to temporarily change the prompt.
355
387
  # @param [Array<Proc>] new_prompt
@@ -374,7 +406,7 @@ class Pry
374
406
  # pry.pop_prompt # => prompt1
375
407
  # pry.pop_prompt # => prompt1
376
408
  def pop_prompt
377
- if prompt_stack.size > 1 then prompt_stack.pop else prompt end
409
+ prompt_stack.size > 1 ? prompt_stack.pop : prompt
378
410
  end
379
411
 
380
412
  if RUBY_VERSION =~ /1.9/ && RUBY_ENGINE == "ruby"
@@ -1,3 +1,3 @@
1
1
  class Pry
2
- VERSION = "0.8.4pre1"
2
+ VERSION = "0.9.0pre1"
3
3
  end
@@ -7,21 +7,70 @@ require 'bacon'
7
7
 
8
8
  # Ensure we do not execute any rc files
9
9
  Pry::RC_FILES.clear
10
- Pry.color = false
11
- Pry.should_load_rc = false
12
-
13
- class Module
14
- public :remove_const
15
- end
16
10
 
11
+ # in case the tests call reset_defaults, ensure we reset them to
12
+ # amended (test friendly) values
17
13
  class << Pry
18
14
  alias_method :orig_reset_defaults, :reset_defaults
19
15
  def reset_defaults
20
16
  orig_reset_defaults
17
+
21
18
  Pry.color = false
19
+ Pry.pager = false
20
+ Pry.config.should_load_rc = false
21
+ Pry.config.plugins.enabled = false
22
+ Pry.config.history.load = false
23
+ Pry.config.history.save = false
22
24
  end
23
25
  end
24
26
 
27
+ Pry.reset_defaults
28
+
29
+ # sample doc
30
+ def sample_method
31
+ :sample
32
+ end
33
+
34
+ def redirect_pry_io(new_in, new_out)
35
+ old_in = Pry.input
36
+ old_out = Pry.output
37
+
38
+ Pry.input = new_in
39
+ Pry.output = new_out
40
+ begin
41
+ yield
42
+ ensure
43
+ Pry.input = old_in
44
+ Pry.output = old_out
45
+ end
46
+ end
47
+
48
+ def redirect_global_pry_input(new_io)
49
+ old_io = Pry.input
50
+ Pry.input = new_io
51
+ begin
52
+ yield
53
+ ensure
54
+ Pry.input = old_io
55
+ end
56
+ end
57
+
58
+ def redirect_global_pry_output(new_io)
59
+ old_io = Pry.output
60
+ Pry.output = new_io
61
+ begin
62
+ yield
63
+ ensure
64
+ Pry.output = old_io
65
+ end
66
+ end
67
+
68
+ class Module
69
+ public :remove_const
70
+ public :remove_method
71
+ end
72
+
73
+
25
74
  class InputTester
26
75
  def initialize(*actions)
27
76
  @orig_actions = actions.dup
@@ -47,7 +96,7 @@ class Pry
47
96
  end
48
97
 
49
98
 
50
- CommandTester = Pry::CommandSet.new :test do
99
+ CommandTester = Pry::CommandSet.new do
51
100
  command "command1", "command 1 test" do
52
101
  output.puts "command1"
53
102
  end
@@ -0,0 +1,99 @@
1
+ require 'helper'
2
+
3
+ describe "Pry::CommandProcessor" do
4
+
5
+ before do
6
+ @pry = Pry.new
7
+ @pry.commands = Pry::CommandSet.new
8
+ @command_processor = Pry::CommandProcessor.new(@pry)
9
+ end
10
+
11
+ after do
12
+ @pry.commands = Pry::CommandSet.new
13
+ end
14
+
15
+ it 'should correctly match a simple string command' do
16
+ @pry.commands.command("test-command") {}
17
+ command, captures, pos = @command_processor.command_matched "test-command"
18
+
19
+ command.name.should == "test-command"
20
+ captures.should == []
21
+ pos.should == "test-command".length
22
+ end
23
+
24
+ it 'should correctly match a simple string command with parameters' do
25
+ @pry.commands.command("test-command") { |arg|}
26
+ command, captures, pos = @command_processor.command_matched "test-command hello"
27
+
28
+ command.name.should == "test-command"
29
+ captures.should == []
30
+ pos.should == "test-command".length
31
+ end
32
+
33
+ it 'should not match when the relevant command does not exist' do
34
+ command, captures, pos = @command_processor.command_matched "test-command"
35
+
36
+ command.should == nil
37
+ captures.should == nil
38
+ end
39
+
40
+ it 'should correctly match a regex command' do
41
+ @pry.commands.command(/rue(.?)/) { }
42
+ command, captures, pos = @command_processor.command_matched "rue hello"
43
+
44
+ command.name.should == /rue(.?)/
45
+ captures.should == [""]
46
+ pos.should == 3
47
+ end
48
+
49
+ it 'should correctly match a regex command and extract the capture groups' do
50
+ @pry.commands.command(/rue(.?)/) { }
51
+ command, captures, pos = @command_processor.command_matched "rue5 hello"
52
+
53
+ command.name.should == /rue(.?)/
54
+ captures.should == ["5"]
55
+ pos.should == 4
56
+ end
57
+
58
+ it 'should correctly match a string command with spaces in its name' do
59
+ @pry.commands.command("test command") {}
60
+ command, captures, pos = @command_processor.command_matched "test command"
61
+
62
+ command.name.should == "test command"
63
+ captures.should == []
64
+ pos.should == command.name.length
65
+ end
66
+
67
+ it 'should correctly match a string command with spaces in its name with parameters' do
68
+ @pry.commands.command("test command") {}
69
+ command, captures, pos = @command_processor.command_matched "test command param1 param2"
70
+
71
+ command.name.should == "test command"
72
+ captures.should == []
73
+ pos.should == command.name.length
74
+ end
75
+
76
+ it 'should correctly match a regex command with spaces in its name' do
77
+ regex_command_name = /test\s+(.+)\s+command/
78
+ @pry.commands.command(regex_command_name) {}
79
+
80
+ sample_text = "test friendship command"
81
+ command, captures, pos = @command_processor.command_matched sample_text
82
+
83
+ command.name.should == regex_command_name
84
+ captures.should == ["friendship"]
85
+ pos.should == sample_text.size
86
+ end
87
+
88
+ it 'should correctly match a complex regex command' do
89
+ regex_command_name = /\.(.*)/
90
+ @pry.commands.command(regex_command_name) {}
91
+
92
+ sample_text = ".cd ~/pry"
93
+ command, captures, pos = @command_processor.command_matched sample_text
94
+
95
+ command.name.should == regex_command_name
96
+ captures.should == ["cd ~/pry"]
97
+ pos.should == sample_text.size
98
+ end
99
+ end
@@ -2,11 +2,7 @@ require 'helper'
2
2
 
3
3
  describe Pry::CommandSet do
4
4
  before do
5
- @set = Pry::CommandSet.new(:some_name)
6
- end
7
-
8
- it 'should use the name specified at creation' do
9
- @set.name.should == :some_name
5
+ @set = Pry::CommandSet.new
10
6
  end
11
7
 
12
8
  it 'should call the block used for the command when it is called' do
@@ -35,7 +31,7 @@ describe Pry::CommandSet do
35
31
  @set.run_command true, 'foo'
36
32
  end
37
33
 
38
- it 'should raise an error when calling an undefined comand' do
34
+ it 'should raise an error when calling an undefined command' do
39
35
  @set.command('foo') {}
40
36
  lambda {
41
37
  @set.run_command nil, 'bar'
@@ -54,7 +50,7 @@ describe Pry::CommandSet do
54
50
  it 'should be able to import some commands from other sets' do
55
51
  run = false
56
52
 
57
- other_set = Pry::CommandSet.new :foo do
53
+ other_set = Pry::CommandSet.new do
58
54
  command('foo') { run = true }
59
55
  command('bar') {}
60
56
  end
@@ -72,7 +68,7 @@ describe Pry::CommandSet do
72
68
  it 'should be able to import a whole set' do
73
69
  run = []
74
70
 
75
- other_set = Pry::CommandSet.new :foo do
71
+ other_set = Pry::CommandSet.new do
76
72
  command('foo') { run << true }
77
73
  command('bar') { run << true }
78
74
  end
@@ -88,7 +84,7 @@ describe Pry::CommandSet do
88
84
  run = false
89
85
  @set.command('foo') { run = true }
90
86
 
91
- Pry::CommandSet.new(:other, @set).run_command nil, 'foo'
87
+ Pry::CommandSet.new(@set).run_command nil, 'foo'
92
88
  run.should == true
93
89
  end
94
90
 
@@ -139,7 +135,7 @@ describe Pry::CommandSet do
139
135
  Pry::CommandContext.new.should.not.respond_to :my_helper
140
136
  end
141
137
 
142
- it 'should not recreate a new heler module when helpers is called' do
138
+ it 'should not recreate a new helper module when helpers is called' do
143
139
  @set.command('foo') do
144
140
  should.respond_to :my_helper
145
141
  should.respond_to :my_other_helper
@@ -157,7 +153,7 @@ describe Pry::CommandSet do
157
153
  end
158
154
 
159
155
  it 'should import helpers from imported sets' do
160
- imported_set = Pry::CommandSet.new :test do
156
+ imported_set = Pry::CommandSet.new do
161
157
  helpers do
162
158
  def imported_helper_method; end
163
159
  end
@@ -169,7 +165,7 @@ describe Pry::CommandSet do
169
165
  end
170
166
 
171
167
  it 'should import helpers even if only some commands are imported' do
172
- imported_set = Pry::CommandSet.new :test do
168
+ imported_set = Pry::CommandSet.new do
173
169
  helpers do
174
170
  def imported_helper_method; end
175
171
  end
@@ -181,4 +177,14 @@ describe Pry::CommandSet do
181
177
  @set.command('foo') { should.respond_to :imported_helper_method }
182
178
  @set.run_command(Pry::CommandContext.new, 'foo')
183
179
  end
180
+
181
+ it 'should provide a :listing for a command that defaults to its name' do
182
+ @set.command 'foo', "" do;end
183
+ @set.commands['foo'].options[:listing].should == 'foo'
184
+ end
185
+
186
+ it 'should provide a :listing for a command that differs from its name' do
187
+ @set.command 'foo', "", :listing => 'bar' do;end
188
+ @set.commands['foo'].options[:listing].should == 'bar'
189
+ end
184
190
  end