pry 0.9.4pre1-i386-mingw32 → 0.9.4pre2-i386-mingw32

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 (39) hide show
  1. data/CHANGELOG +23 -0
  2. data/CONTRIBUTORS +13 -11
  3. data/README.markdown +2 -0
  4. data/Rakefile +16 -2
  5. data/TODO +8 -0
  6. data/lib/pry.rb +58 -9
  7. data/lib/pry/command_context.rb +11 -0
  8. data/lib/pry/command_processor.rb +43 -6
  9. data/lib/pry/command_set.rb +14 -4
  10. data/lib/pry/completion.rb +5 -5
  11. data/lib/pry/config.rb +6 -2
  12. data/lib/pry/default_commands/context.rb +83 -35
  13. data/lib/pry/default_commands/documentation.rb +37 -31
  14. data/lib/pry/default_commands/easter_eggs.rb +5 -0
  15. data/lib/pry/default_commands/input.rb +13 -10
  16. data/lib/pry/default_commands/introspection.rb +54 -40
  17. data/lib/pry/default_commands/shell.rb +9 -5
  18. data/lib/pry/helpers/base_helpers.rb +16 -5
  19. data/lib/pry/helpers/command_helpers.rb +41 -17
  20. data/lib/pry/helpers/text.rb +2 -1
  21. data/lib/pry/history.rb +61 -0
  22. data/lib/pry/plugins.rb +19 -8
  23. data/lib/pry/pry_class.rb +25 -62
  24. data/lib/pry/pry_instance.rb +105 -120
  25. data/lib/pry/version.rb +1 -1
  26. data/pry.gemspec +15 -14
  27. data/test/helper.rb +31 -0
  28. data/test/test_command_set.rb +7 -2
  29. data/test/test_completion.rb +7 -3
  30. data/test/test_default_commands/test_context.rb +185 -1
  31. data/test/test_default_commands/test_documentation.rb +10 -0
  32. data/test/test_default_commands/test_input.rb +16 -11
  33. data/test/test_default_commands/test_introspection.rb +10 -0
  34. data/test/test_default_commands/test_shell.rb +18 -0
  35. data/test/test_pry.rb +189 -40
  36. data/test/test_pry_history.rb +13 -13
  37. data/test/test_pry_output.rb +44 -0
  38. data/test/test_special_locals.rb +35 -0
  39. metadata +182 -173
data/CHANGELOG CHANGED
@@ -8,6 +8,29 @@
8
8
  * show-doc and stat now display method visibility (update WIKI)
9
9
  * got rid of warnings caused by stricter ruby 1.9.3 rules
10
10
  * remove interpolation of command names and fix interpolation error messag (update WIKI) (thanks ryanf!)
11
+ * 'nested sessions' now use binding stacks (so each instance manages its own collection of bindings without spawning other instances)
12
+ * changed `exit` command so that it now called Kernel#exit (after saving history)
13
+ * 'quit' now behaves like 'exit-all' (and aliased to exit-all) - it breaks out of the repl loop and sets empties the binding_stack
14
+ * 'cd ..' just pops a binding off the binding_stack with special behaviour when only one binding in stack - it breaks out of the repl loop
15
+ * added switch-to command (like jump-to but doesnt unwind the stack)
16
+ * show-method and show-doc now accept multiple method names
17
+ * control_d hook added (Pry.config.control_d_handler)
18
+ * behaviour of ^d is now to break out of current expr if in multi-line expr, or break out of current context if nested, or break out of pry repl loop if at top-level
19
+ * can no longer interpolate command name itself e.g #{x}-#{y} where x = "show" and y = "doc"
20
+ * ^C no longer captured
21
+ * got rid of Pry.active_instance, Pry.last_exception and friends.
22
+ * also special locals now shared among bindings in a pry instance (i.e _ex_ (and friends) re-injected into new binding entered with 'cd')
23
+ * renamed inp and out to _in_ and _out_ (to avoid collisions with actual locals in debugging scope)
24
+ * added third parameter to prompts, the pry instance itself (_pry) see https://github.com/pry/pry/issues/233 for why it's important
25
+ * cd behaviour when no args performs the same as `cd /`
26
+ * commands with keep_retval can now return nil (to suppress output now return 'void' instead)
27
+ * Pry::CommandProcessor::Result introduced
28
+ * Pry.view_clip() modified to be more robust and properly display Class#name
29
+ * edit command when invoked with no args now works like edit -t
30
+ * when edit is invoked (with no args or with -t) inside a multi-line expression input buffer, it dumps that buffer into a temp file and takes you to it
31
+ * got rid of Pry#null_input? since all that was needed was eval_string.empty?
32
+ * cd command now supports complex syntax: cd ../@y/y/../z
33
+ * JRuby is no longer a 2nd class citizen, almost full JRuby support, passing 100% tests
11
34
 
12
35
  */7/2011 version 0.9.3
13
36
  * cat --ex (cats 5 lines above and below line in file where exception was raised)
@@ -1,11 +1,13 @@
1
- 547 John Mair <jrmair@gmail.com>
2
- 76 Rob Gleeson <rob@flowof.info>
3
- 46 Lee Jarvis <lee@jarvis.co>
4
- 46 Mon ouïe <mon.ouie@gmail.com>
5
- 18 David Palm <dpalm@elctech.com>
6
- 13 epitron <chris@ill-logic.com>
7
- 8 Conrad Irwin <conrad.irwin@gmail.com>
8
- 6 Ryan Fitzgerald <rwfitzge@gmail.com>
9
- 2 Eric Christopherson <echristopherson@gmail.com>
10
- 2 Xavier Shay <xavier@rhnh.net>
11
- 1 Josh Cheek <josh.cheek@gmail.com>
1
+ 564 John Mair
2
+ 76 Rob Gleeson
3
+ 50 Lee Jarvis
4
+ 46 Mon ouïe
5
+ 18 David Palm
6
+ 13 epitron
7
+ 8 Conrad Irwin
8
+ 6 Ryan Fitzgerald
9
+ 2 Darrick Wiebe
10
+ 2 Xavier Shay
11
+ 2 Eric Christopherson
12
+ 1 Josh Cheek
13
+ 1 Tim Pope
@@ -6,6 +6,8 @@ _Get to the code_
6
6
 
7
7
  **Note that JRuby is not yet supported in this release, but will be
8
8
  soon.**
9
+
10
+ **Please** [DONATE](http://www.pledgie.com/campaigns/15899) to the Pry project - Pry was a **huge** amount of work and every donation received is encouraging and supports Pry's continued development!
9
11
 
10
12
  [Skip to the website (recommended)](http://pry.github.com) <br />
11
13
  [Skip to the wiki](https://github.com/pry/pry/wiki)
data/Rakefile CHANGED
@@ -22,8 +22,8 @@ def apply_spec_defaults(s)
22
22
  s.test_files = `git ls-files -- test/*`.split("\n")
23
23
  s.add_dependency("ruby_parser",">=2.0.5")
24
24
  s.add_dependency("coderay",">=0.9.8")
25
- s.add_dependency("slop","~>1.9.0")
26
- s.add_dependency("method_source",">=0.6.0")
25
+ s.add_dependency("slop","~>2.1.0")
26
+ s.add_dependency("method_source",">=0.6.5")
27
27
  s.add_development_dependency("bacon",">=1.1.0")
28
28
  s.add_development_dependency("open4", "~>1.0.1")
29
29
  end
@@ -62,6 +62,20 @@ namespace :ruby do
62
62
  end
63
63
  end
64
64
 
65
+ namespace :jruby do
66
+ spec = Gem::Specification.new do |s|
67
+ apply_spec_defaults(s)
68
+ s.add_dependency("spoon", ">=0.0.1")
69
+ s.platform = "java"
70
+ end
71
+
72
+ Rake::GemPackageTask.new(spec) do |pkg|
73
+ pkg.need_zip = false
74
+ pkg.need_tar = false
75
+ end
76
+ end
77
+
78
+
65
79
  [:mingw32, :mswin32].each do |v|
66
80
  namespace v do
67
81
  spec = Gem::Specification.new do |s|
data/TODO CHANGED
@@ -12,6 +12,14 @@
12
12
  * fix history saving (should not save all of Readline::HISTORY, but only what changed)
13
13
  * prevent blank lines going to Readline::HISTORY
14
14
  * ensure that cat --ex emulates the `whereami` format - includes line numbers and formatted the same, etc
15
+ * rename inp and out to _inp_ and _out_ otherwise than can overwrite locals by those names when debugging (not good)
16
+ * add source file to stat command
17
+ * make plugins use hash instead of array
18
+ * ensure edit -t has 'edit' alias (no parameters) and dumps eval_string into buffer
19
+ * whitelist exceptions
20
+ * hooks system
21
+ * jruby shell command support
22
+ *
15
23
 
16
24
  0.9.3
17
25
  * hist command now excludes last line of input (the command invocation itself)
data/lib/pry.rb CHANGED
@@ -19,11 +19,20 @@ class Pry
19
19
 
20
20
  # The default prints
21
21
  DEFAULT_PRINT = proc do |output, value|
22
- begin
23
- Helpers::BaseHelpers.stagger_output("=> #{Helpers::BaseHelpers.colorize_code(value.pretty_inspect)}", output)
24
- rescue NoMethodError
25
- output.puts "=> unknown"
22
+ stringified = begin
23
+ value.pretty_inspect
24
+ rescue RescuableException => ex
25
+ nil
26
+ end
27
+
28
+ unless String === stringified
29
+ # Read the class name off of the singleton class to provide a default inspect.
30
+ klass = (class << value; self; end).ancestors.first
31
+ stringified = "#<#{klass}:0x#{value.__id__.to_s(16)}>"
32
+ Helpers::BaseHelpers.stagger_output("output error: #{ex.inspect}", output) if ex
26
33
  end
34
+
35
+ Helpers::BaseHelpers.stagger_output("=> #{Helpers::BaseHelpers.colorize_code(stringified)}", output)
27
36
  end
28
37
 
29
38
  # Will only show the first line of the backtrace
@@ -34,7 +43,7 @@ class Pry
34
43
 
35
44
  # The default prompt; includes the target and nesting level
36
45
  DEFAULT_PROMPT = [
37
- proc { |target_self, nest_level|
46
+ proc { |target_self, nest_level, _|
38
47
  if nest_level == 0
39
48
  "pry(#{Pry.view_clip(target_self)})> "
40
49
  else
@@ -42,23 +51,62 @@ class Pry
42
51
  end
43
52
  },
44
53
 
45
- proc { |target_self, nest_level|
54
+ proc { |target_self, nest_level, _|
46
55
  if nest_level == 0
47
56
  "pry(#{Pry.view_clip(target_self)})* "
48
57
  else
49
58
  "pry(#{Pry.view_clip(target_self)}):#{Pry.view_clip(nest_level)}* "
50
59
  end
51
60
  }
52
- ]
61
+ ]
62
+ # Deal with the ^D key being pressed, different behaviour in
63
+ # different cases:
64
+ # 1) In an expression - behave like `!` command (clear input buffer)
65
+ # 2) At top-level session - behave like `exit command (break out of repl loop)
66
+ # 3) In a nested session - behave like `cd ..` (pop a binding)
67
+ DEFAULT_CONTROL_D_HANDLER = proc do |eval_string, _pry_|
68
+ if !eval_string.empty?
69
+ # clear input buffer
70
+ eval_string.replace("")
71
+ elsif _pry_.binding_stack.one?
72
+ # ^D at top-level breaks out of loop
73
+ _pry_.binding_stack.clear
74
+ throw(:breakout)
75
+ else
76
+ # otherwise just pops a binding
77
+ _pry_.binding_stack.pop
78
+ end
79
+ end
53
80
 
54
81
  # A simple prompt - doesn't display target or nesting level
55
82
  SIMPLE_PROMPT = [proc { ">> " }, proc { " | " }]
56
83
 
57
84
  SHELL_PROMPT = [
58
- proc { |target_self, _| "pry #{Pry.view_clip(target_self)}:#{Dir.pwd} $ " },
59
- proc { |target_self, _| "pry #{Pry.view_clip(target_self)}:#{Dir.pwd} * " }
85
+ proc { |target_self, _, _| "pry #{Pry.view_clip(target_self)}:#{Dir.pwd} $ " },
86
+ proc { |target_self, _, _| "pry #{Pry.view_clip(target_self)}:#{Dir.pwd} * " }
60
87
  ]
61
88
 
89
+ # As a REPL, we often want to catch any unexpected exceptions that may have
90
+ # been raised; however we don't want to go overboard and prevent the user
91
+ # from exiting Pry when they want to.
92
+ module RescuableException
93
+ def self.===(exception)
94
+ case exception
95
+ # Catch when the user hits ^C (Interrupt < SignalException), and assume
96
+ # that they just wanted to stop the in-progress command (just like bash etc.)
97
+ when Interrupt
98
+ true
99
+ # Don't catch signals (particularly not SIGTERM) as these are unlikely to be
100
+ # intended for pry itself. We should also make sure that Kernel#exit works.
101
+ when SystemExit, SignalException
102
+ false
103
+ # All other exceptions will be caught.
104
+ else
105
+ true
106
+ end
107
+ end
108
+ end
109
+
62
110
  end
63
111
 
64
112
  require "method_source"
@@ -82,6 +130,7 @@ end
82
130
  require "pry/version"
83
131
  require "pry/history_array"
84
132
  require "pry/helpers"
133
+ require "pry/history"
85
134
  require "pry/command_set"
86
135
  require "pry/commands"
87
136
  require "pry/command_context"
@@ -2,6 +2,13 @@ class Pry
2
2
  # Command contexts are the objects runing each command.
3
3
  # Helper modules can be mixed into this class.
4
4
  class CommandContext
5
+
6
+ # represents a void return value for a command
7
+ VOID_VALUE = Object.new
8
+
9
+ # give it a nice inspect
10
+ def VOID_VALUE.inspect() "void" end
11
+
5
12
  attr_accessor :output
6
13
  attr_accessor :target
7
14
  attr_accessor :captures
@@ -34,6 +41,10 @@ class Pry
34
41
  Pry::Helpers::Text
35
42
  end
36
43
 
44
+ def void
45
+ VOID_VALUE
46
+ end
47
+
37
48
  include Pry::Helpers::BaseHelpers
38
49
  include Pry::Helpers::CommandHelpers
39
50
  end
@@ -2,6 +2,36 @@ require 'forwardable'
2
2
 
3
3
  class Pry
4
4
  class CommandProcessor
5
+
6
+ # Wraps the return result of process_commands, indicates if the
7
+ # result IS a command and what kind of command (e.g void)
8
+ class Result
9
+ attr_reader :retval
10
+
11
+ def initialize(is_command, keep_retval = false, retval = nil)
12
+ @is_command, @keep_retval, @retval = is_command, keep_retval, retval
13
+ end
14
+
15
+ # Is the result a command?
16
+ # @return [Boolean]
17
+ def command?
18
+ @is_command
19
+ end
20
+
21
+ # Is the result a command and if it is, is it a void command?
22
+ # (one that does not return a value)
23
+ # @return [Boolean]
24
+ def void_command?
25
+ (command? && !keep_retval?) || retval == CommandContext::VOID_VALUE
26
+ end
27
+
28
+ # Is the return value kept for this command? (i.e :keep_retval => true)
29
+ # @return [Boolean]
30
+ def keep_retval?
31
+ @keep_retval
32
+ end
33
+ end
34
+
5
35
  extend Forwardable
6
36
 
7
37
  attr_accessor :pry_instance
@@ -10,7 +40,7 @@ class Pry
10
40
  @pry_instance = pry_instance
11
41
  end
12
42
 
13
- def_delegators :@pry_instance, :commands, :nesting, :output
43
+ def_delegators :@pry_instance, :commands, :output
14
44
 
15
45
  # Is the string a valid command?
16
46
  # @param [String] val The string passed in from the Pry prompt.
@@ -80,11 +110,17 @@ class Pry
80
110
  # @param [String] eval_string The cumulative lines of input for
81
111
  # multi-line input.
82
112
  # @param [Binding] target The receiver of the commands.
113
+ # @return [Pry::CommandProcessor::Result] A wrapper object
114
+ # containing info about the result of the command processing
115
+ # (indicating whether it is a command and if it is what kind of
116
+ # command it is.
83
117
  def process_commands(val, eval_string, target)
84
118
 
85
- # no command was matched, so return to caller
86
119
  command, captures, pos = command_matched(val, target)
87
- return if !command
120
+
121
+ # no command was matched, so return to caller
122
+ return Result.new(false) if !command
123
+
88
124
  arg_string = val[pos..-1]
89
125
 
90
126
  # remove the one leading space if it exists
@@ -96,12 +132,13 @@ class Pry
96
132
  :val => val,
97
133
  :arg_string => arg_string,
98
134
  :eval_string => eval_string,
99
- :nesting => nesting,
100
135
  :commands => commands.commands,
101
136
  :captures => captures
102
137
  }
103
138
 
104
- execute_command(target, command.name, options, *(captures + args))
139
+ ret = execute_command(target, command.name, options, *(captures + args))
140
+
141
+ Result.new(true, command.options[:keep_retval], ret)
105
142
  end
106
143
 
107
144
  # Execute a Pry command.
@@ -110,6 +147,7 @@ class Pry
110
147
  # @param [String] command The name of the command to be run.
111
148
  # @param [Hash] options The options to set on the Commands object.
112
149
  # @param [Array] args The command arguments.
150
+ # @return [Object] The value returned by the command
113
151
  def execute_command(target, command, options, *args)
114
152
  context = CommandContext.new
115
153
 
@@ -127,7 +165,6 @@ class Pry
127
165
 
128
166
  ret = commands.run_command(context, command, *args)
129
167
 
130
- # Tick, tock, im getting rid of this shit soon.
131
168
  options[:val].replace("")
132
169
 
133
170
  ret
@@ -15,7 +15,11 @@ class Pry
15
15
  context.instance_eval(&stub_block)
16
16
  else
17
17
  ret = context.instance_exec(*correct_arg_arity(block.arity, args), &block)
18
- ret if options[:keep_retval]
18
+ if options[:keep_retval]
19
+ ret
20
+ else
21
+ Pry::CommandContext::VOID_VALUE
22
+ end
19
23
  end
20
24
  end
21
25
 
@@ -24,9 +28,15 @@ class Pry
24
28
  case arity <=> 0
25
29
  when -1
26
30
  args
27
- when 1, 0
28
- # Keep 1.8 happy
29
- args.values_at 0..(arity - 1)
31
+ when 0
32
+ []
33
+ when 1
34
+ # another jruby hack
35
+ if Pry::Helpers::BaseHelpers.jruby?
36
+ args[0..(arity - 1)]
37
+ else
38
+ args.values_at 0..(arity - 1)
39
+ end
30
40
  end
31
41
  end
32
42
  end
@@ -94,7 +94,7 @@ class Pry
94
94
  begin
95
95
  candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind)
96
96
  candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind)
97
- rescue Exception
97
+ rescue RescuableException
98
98
  candidates = []
99
99
  end
100
100
  candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e}
@@ -114,7 +114,7 @@ class Pry
114
114
 
115
115
  begin
116
116
  candidates = eval(receiver, bind).methods.collect{|m| m.to_s}
117
- rescue Exception
117
+ rescue RescuableException
118
118
  candidates = []
119
119
  end
120
120
  select_message(receiver, message, candidates)
@@ -126,7 +126,7 @@ class Pry
126
126
 
127
127
  begin
128
128
  candidates = eval(receiver, bind).methods.collect{|m| m.to_s}
129
- rescue Exception
129
+ rescue RescuableException
130
130
  candidates = []
131
131
  end
132
132
  select_message(receiver, message, candidates)
@@ -149,7 +149,7 @@ class Pry
149
149
  # Foo::Bar.func
150
150
  begin
151
151
  candidates = eval("#{receiver}.methods", bind).collect{|m| m.to_s}
152
- rescue Exception
152
+ rescue RescuableException
153
153
  candidates = []
154
154
  end
155
155
  else
@@ -158,7 +158,7 @@ class Pry
158
158
  ObjectSpace.each_object(Module){|m|
159
159
  begin
160
160
  name = m.name.to_s
161
- rescue Exception
161
+ rescue RescuableException
162
162
  name = ""
163
163
  end
164
164
  next if name != "IRB::Context" and
@@ -51,9 +51,9 @@ class Pry
51
51
  # return value of that callable invocation is used as the exact
52
52
  # shell command to invoke the editor.
53
53
  # @example String
54
- # Pry.editor = "emacsclient"
54
+ # Pry.config.editor = "emacsclient"
55
55
  # @example Callable
56
- # Pry.editor = proc { |file, line| "emacsclient #{file} +#{line}" }
56
+ # Pry.config.editor = proc { |file, line| "emacsclient #{file} +#{line}" }
57
57
  # @return [String, #call]
58
58
  attr_accessor :editor
59
59
 
@@ -107,6 +107,10 @@ class Pry
107
107
 
108
108
  # @return [Integer] Amount of results that will be stored into out
109
109
  attr_accessor :memory_size
110
+
111
+ # @return [Proc] The proc that manages ^D presses in the REPL.
112
+ # The proc is passed the current eval_string and the current pry instance.
113
+ attr_accessor :control_d_handler
110
114
  end
111
115
  end
112
116
 
@@ -6,75 +6,122 @@ class Pry
6
6
  Context = Pry::CommandSet.new do
7
7
  import Ls
8
8
 
9
- 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|
10
- case obj
11
- when nil
12
- output.puts "Must provide an object."
13
- next
14
- when ".."
15
- throw(:breakout, opts[:nesting].level)
16
- when "/"
17
- throw(:breakout, 1) if opts[:nesting].level > 0
18
- next
19
- when "::"
20
- TOPLEVEL_BINDING.pry
21
- next
9
+ command "cd", "Move into a new context (use `cd ..` to go back and `cd /` to return to Pry top-level). Complex syntax (e.g cd ../@x/y) also supported." do |obj|
10
+ path = arg_string.split(/\//)
11
+ stack = _pry_.binding_stack.dup
12
+
13
+ # special case when we only get a single "/", return to root
14
+ stack = [stack.first] if path.empty?
15
+
16
+ resolve_failure = false
17
+ path.each do |context|
18
+ begin
19
+ case context.chomp
20
+ when ""
21
+ stack = [stack.first]
22
+ when "::"
23
+ stack.push(TOPLEVEL_BINDING)
24
+ when "."
25
+ next
26
+ when ".."
27
+ if stack.one?
28
+ _pry_.binding_stack.clear
29
+ throw(:breakout)
30
+ else
31
+ stack.pop
32
+ end
33
+ else
34
+ stack.push(Pry.binding_for(stack.last.eval(context)))
35
+ end
36
+
37
+ rescue RescuableException
38
+ output.puts "Bad object path: #{arg_string}. Failed trying to resolve: #{context}"
39
+ resolve_failure = true
40
+ end
41
+ end
42
+
43
+ next if resolve_failure
44
+
45
+ _pry_.binding_stack = stack
46
+ end
47
+
48
+ command "switch-to", "Start a new sub-session on a binding in the current stack (numbered by nesting)." do |selection|
49
+ selection = selection.to_i
50
+
51
+ if selection < 0 || selection > _pry_.binding_stack.size - 1
52
+ output.puts "Invalid binding index #{selection} - use `nesting` command to view valid indices."
22
53
  else
23
- Pry.start target.eval(arg_string)
54
+ Pry.start(_pry_.binding_stack[selection])
24
55
  end
25
56
  end
26
57
 
27
58
  command "nesting", "Show nesting information." do
28
- nesting = opts[:nesting]
29
-
30
59
  output.puts "Nesting status:"
31
60
  output.puts "--"
32
- nesting.each do |level, obj|
61
+ _pry_.binding_stack.each_with_index do |obj, level|
33
62
  if level == 0
34
- output.puts "#{level}. #{Pry.view_clip(obj)} (Pry top level)"
63
+ output.puts "#{level}. #{Pry.view_clip(obj.eval('self'))} (Pry top level)"
35
64
  else
36
- output.puts "#{level}. #{Pry.view_clip(obj)}"
65
+ output.puts "#{level}. #{Pry.view_clip(obj.eval('self'))}"
37
66
  end
38
67
  end
39
68
  end
40
69
 
41
- command "jump-to", "Jump to a Pry session further up the stack, exiting all sessions below." do |break_level|
70
+ command "jump-to", "Jump to a binding further up the stack, popping all bindings below." do |break_level|
42
71
  break_level = break_level.to_i
43
- nesting = opts[:nesting]
72
+ nesting_level = _pry_.binding_stack.size - 1
44
73
 
45
74
  case break_level
46
- when nesting.level
47
- output.puts "Already at nesting level #{nesting.level}"
48
- when (0...nesting.level)
49
- throw(:breakout, break_level + 1)
75
+ when nesting_level
76
+ output.puts "Already at nesting level #{nesting_level}"
77
+ when (0...nesting_level)
78
+ _pry_.binding_stack.slice!(break_level + 1, _pry_.binding_stack.size)
79
+
50
80
  else
51
- max_nest_level = nesting.level - 1
81
+ max_nest_level = nesting_level - 1
52
82
  output.puts "Invalid nest level. Must be between 0 and #{max_nest_level}. Got #{break_level}."
53
83
  end
54
84
  end
55
85
 
56
- command "exit", "End the current Pry session. Accepts optional return value. Aliases: quit, back" do
57
- throw(:breakout, [opts[:nesting].level, target.eval(arg_string)])
86
+ command "exit-all", "End the current Pry session (popping all bindings) and returning to caller. Accepts optional return value. Aliases: !!@" do
87
+ # clear the binding stack
88
+ _pry_.binding_stack.clear
89
+
90
+ # break out of the repl loop
91
+ throw(:breakout, target.eval(arg_string))
58
92
  end
59
93
 
60
- alias_command "quit", "exit", ""
61
- alias_command "back", "exit", ""
94
+ alias_command "!!@", "exit-all", ""
95
+
96
+ command "exit", "Pop the current binding and return to the one immediately prior. Note this does NOT exit the program. Aliases: quit", :keep_retval => true do
97
+ if _pry_.binding_stack.one?
98
+ # when breaking out of top-level then behave like `exit-all`
99
+ _pry_.binding_stack.clear
100
+ throw(:breakout, target.eval(arg_string))
101
+ else
102
+ # otherwise just pop a binding
103
+ popped_object = _pry_.binding_stack.pop.eval('self')
62
104
 
63
- command "exit-all", "End all nested Pry sessions. Accepts optional return value. Aliases: !!@" do
64
- throw(:breakout, [0, target.eval(arg_string)])
105
+ # return a user-specified value if given
106
+ if !arg_string.empty?
107
+ target.eval(arg_string)
108
+ else
109
+ popped_object
110
+ end
111
+ end
65
112
  end
66
113
 
67
- alias_command "!!@", "exit-all", ""
114
+ alias_command "quit", "exit", ""
68
115
 
69
116
  command "exit-program", "End the current program. Aliases: quit-program, !!!" do
70
117
  Pry.save_history if Pry.config.history.should_save
71
- exit
118
+ Kernel.exit target.eval(arg_string).to_i
72
119
  end
73
120
 
74
121
  alias_command "quit-program", "exit-program", ""
75
122
  alias_command "!!!", "exit-program", ""
76
123
 
77
- command "!pry", "Start a Pry session on current self; this even works mid-expression." do
124
+ command "!pry", "Start a Pry session on current self; this even works mid multi-line expression." do
78
125
  target.pry
79
126
  end
80
127
 
@@ -100,6 +147,7 @@ class Pry
100
147
  set_file_and_dir_locals(file)
101
148
  output.puts "\n#{text.bold('From:')} #{file} @ line #{line_num} in #{klass}##{meth_name}:\n\n"
102
149
 
150
+
103
151
  # This method inspired by http://rubygems.org/gems/ir_b
104
152
  File.open(file).each_with_index do |line, index|
105
153
  line_n = index + 1