pry 0.9.4pre1-i386-mswin32 → 0.9.4pre2-i386-mswin32

Sign up to get free protection for your applications and to get access to all the features.
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