pry 0.9.0pre3-java → 0.9.4pre2-java
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/.gitignore +1 -0
- data/CHANGELOG +84 -6
- data/CONTRIBUTORS +13 -0
- data/README.markdown +23 -183
- data/Rakefile +22 -19
- data/TODO +36 -6
- data/bin/pry +12 -1
- data/lib/pry.rb +60 -12
- data/lib/pry/command_context.rb +21 -0
- data/lib/pry/command_processor.rb +62 -16
- data/lib/pry/command_set.rb +25 -11
- data/lib/pry/commands.rb +0 -3
- data/lib/pry/completion.rb +6 -6
- data/lib/pry/config.rb +25 -5
- data/lib/pry/default_commands/basic.rb +27 -6
- data/lib/pry/default_commands/context.rb +84 -35
- data/lib/pry/default_commands/documentation.rb +69 -31
- data/lib/pry/default_commands/easter_eggs.rb +5 -0
- data/lib/pry/default_commands/input.rb +193 -56
- data/lib/pry/default_commands/introspection.rb +98 -50
- data/lib/pry/default_commands/ls.rb +51 -21
- data/lib/pry/default_commands/shell.rb +57 -13
- data/lib/pry/extended_commands/experimental.rb +0 -32
- data/lib/pry/extended_commands/user_command_api.rb +33 -2
- data/lib/pry/helpers/base_helpers.rb +30 -10
- data/lib/pry/helpers/command_helpers.rb +75 -16
- data/lib/pry/helpers/text.rb +12 -11
- data/lib/pry/history.rb +61 -0
- data/lib/pry/plugins.rb +23 -12
- data/lib/pry/pry_class.rb +51 -50
- data/lib/pry/pry_instance.rb +129 -119
- data/lib/pry/version.rb +1 -1
- data/pry.gemspec +46 -0
- data/test/helper.rb +37 -3
- data/test/test_command_processor.rb +62 -19
- data/test/test_command_set.rb +40 -2
- data/test/test_completion.rb +27 -0
- data/test/test_default_commands/test_context.rb +185 -1
- data/test/test_default_commands/test_documentation.rb +10 -0
- data/test/test_default_commands/test_input.rb +207 -11
- data/test/test_default_commands/test_introspection.rb +20 -1
- data/test/test_default_commands/test_shell.rb +18 -0
- data/test/test_pry.rb +261 -45
- data/test/test_pry_history.rb +82 -0
- data/test/test_pry_output.rb +44 -0
- data/test/test_special_locals.rb +35 -0
- metadata +185 -159
data/lib/pry/helpers/text.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
class Pry
|
2
2
|
module Helpers
|
3
3
|
|
4
|
-
# The methods defined on {Text} are available to custom commands via {Pry::CommandContext#text}.
|
4
|
+
# The methods defined on {Text} are available to custom commands via {Pry::CommandContext#text}.
|
5
5
|
module Text
|
6
|
-
|
7
|
-
COLORS =
|
6
|
+
|
7
|
+
COLORS =
|
8
8
|
{
|
9
9
|
"black" => 0,
|
10
10
|
"red" => 1,
|
@@ -18,7 +18,7 @@ class Pry
|
|
18
18
|
}
|
19
19
|
|
20
20
|
class << self
|
21
|
-
|
21
|
+
|
22
22
|
COLORS.each_pair do |color, value|
|
23
23
|
define_method color do |text|
|
24
24
|
Pry.color ? "\033[0;#{30+value}m#{text}\033[0m" : text.to_s
|
@@ -31,7 +31,7 @@ class Pry
|
|
31
31
|
|
32
32
|
alias_method :grey, :bright_black
|
33
33
|
alias_method :gray, :bright_black
|
34
|
-
|
34
|
+
|
35
35
|
|
36
36
|
# Remove any color codes from _text_.
|
37
37
|
#
|
@@ -41,11 +41,11 @@ class Pry
|
|
41
41
|
text.to_s.gsub(/\e\[.*?(\d)+m/ , '')
|
42
42
|
end
|
43
43
|
|
44
|
-
# Returns _text_ as bold text for use on a terminal.
|
44
|
+
# Returns _text_ as bold text for use on a terminal.
|
45
45
|
# _Pry.color_ must be true for this method to perform any transformations.
|
46
46
|
#
|
47
47
|
# @param [String, #to_s] text
|
48
|
-
# @return [String] _text_
|
48
|
+
# @return [String] _text_
|
49
49
|
def bold text
|
50
50
|
Pry.color ? "\e[1m#{text}\e[0m" : text.to_s
|
51
51
|
end
|
@@ -63,15 +63,16 @@ class Pry
|
|
63
63
|
end
|
64
64
|
|
65
65
|
# Returns _text_ in a numbered list, beginning at _offset_.
|
66
|
-
#
|
66
|
+
#
|
67
67
|
# @param [#each_line] text
|
68
68
|
# @param [Fixnum] offset
|
69
69
|
# @return [String]
|
70
|
-
def with_line_numbers
|
70
|
+
def with_line_numbers(text, offset, color=:blue)
|
71
71
|
lines = text.each_line.to_a
|
72
|
+
max_width = (offset + lines.count).to_s.length
|
72
73
|
lines.each_with_index.map do |line, index|
|
73
|
-
adjusted_index = index + offset
|
74
|
-
"#{self.
|
74
|
+
adjusted_index = (index + offset).to_s.rjust(max_width)
|
75
|
+
"#{self.send(color, adjusted_index)}: #{line}"
|
75
76
|
end.join
|
76
77
|
end
|
77
78
|
end
|
data/lib/pry/history.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
class Pry
|
2
|
+
# The History class is responsible for maintaining the user's input history, both
|
3
|
+
# internally and within Readline::HISTORY.
|
4
|
+
class History
|
5
|
+
def initialize
|
6
|
+
@history = []
|
7
|
+
@saved_lines = 0
|
8
|
+
end
|
9
|
+
|
10
|
+
# Loads a file's contents into the input history.
|
11
|
+
# @param [String] filename
|
12
|
+
# @return [Integer] The number of lines loaded
|
13
|
+
def load(filename)
|
14
|
+
File.foreach(filename) do |line|
|
15
|
+
Readline::HISTORY << line.chomp
|
16
|
+
@history << line.chomp
|
17
|
+
end
|
18
|
+
@saved_lines = @history.length
|
19
|
+
end
|
20
|
+
|
21
|
+
# Appends input history from this session to a file.
|
22
|
+
# @param [String] filename
|
23
|
+
# @return [Integer] The number of lines saved
|
24
|
+
def save(filename)
|
25
|
+
history_to_save = @history[@saved_lines..-1]
|
26
|
+
File.open(filename, 'a') do |f|
|
27
|
+
history_to_save.each { |ln| f.puts ln }
|
28
|
+
end
|
29
|
+
@saved_lines = @history.length
|
30
|
+
history_to_save.length
|
31
|
+
end
|
32
|
+
|
33
|
+
# Adds a line to the input history, ignoring blank and duplicate lines.
|
34
|
+
# @param [String] line
|
35
|
+
# @return [String] The same line that was passed in
|
36
|
+
def push(line)
|
37
|
+
unless line.empty? || (@history.last && line.strip == @history.last.strip)
|
38
|
+
Readline::HISTORY << line
|
39
|
+
@history << line
|
40
|
+
end
|
41
|
+
line
|
42
|
+
end
|
43
|
+
alias << push
|
44
|
+
|
45
|
+
# Clears all history. Anything the user entered before this point won't be
|
46
|
+
# saved, but anything they put in afterwards will still be appended to the
|
47
|
+
# history file on exit.
|
48
|
+
def clear
|
49
|
+
Readline::HISTORY.shift until Readline::HISTORY.empty?
|
50
|
+
@history = []
|
51
|
+
@saved_lines = 0
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns an Array containing all stored history.
|
55
|
+
# @return [Array<String>] An Array containing all lines of history loaded
|
56
|
+
# or entered by the user in the current session.
|
57
|
+
def to_a
|
58
|
+
@history.dup
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/pry/plugins.rb
CHANGED
@@ -1,33 +1,44 @@
|
|
1
1
|
class Pry
|
2
2
|
class PluginManager
|
3
3
|
PRY_PLUGIN_PREFIX = /^pry-/
|
4
|
-
PluginNotFound = Class.new(LoadError)
|
5
4
|
|
6
|
-
|
5
|
+
# Placeholder when no associated gem found, displays warning
|
6
|
+
class NoPlugin
|
7
|
+
def initialize(name)
|
8
|
+
@name = name
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(*args)
|
12
|
+
$stderr.puts "Warning: The plugin '#{@name}' was not found! (no gem found)"
|
13
|
+
end
|
14
|
+
end
|
7
15
|
|
8
16
|
class Plugin
|
9
|
-
attr_accessor :name, :gem_name, :enabled, :active
|
17
|
+
attr_accessor :name, :gem_name, :enabled, :spec, :active
|
10
18
|
|
11
|
-
def initialize(name, gem_name, enabled)
|
12
|
-
@name, @gem_name, @enabled = name, gem_name, enabled
|
19
|
+
def initialize(name, gem_name, spec, enabled)
|
20
|
+
@name, @gem_name, @enabled, @spec = name, gem_name, enabled, spec
|
13
21
|
end
|
14
22
|
|
15
|
-
# Disable a plugin.
|
23
|
+
# Disable a plugin. (prevents plugin from being loaded, cannot
|
24
|
+
# disable an already activated plugin)
|
16
25
|
def disable!
|
17
26
|
self.enabled = false
|
18
27
|
end
|
19
28
|
|
20
|
-
# Enable a plugin.
|
29
|
+
# Enable a plugin. (does not load it immediately but puts on
|
30
|
+
# 'white list' to be loaded)
|
21
31
|
def enable!
|
22
32
|
self.enabled = true
|
23
33
|
end
|
24
34
|
|
25
|
-
# Activate the plugin (require the gem
|
35
|
+
# Activate the plugin (require the gem - enables/loads the
|
36
|
+
# plugin immediately at point of call, even if plugin is disabled)
|
26
37
|
def activate!
|
27
38
|
begin
|
28
|
-
require gem_name
|
39
|
+
require gem_name if !active?
|
29
40
|
rescue LoadError
|
30
|
-
|
41
|
+
$stderr.puts "Warning: The plugin '#{gem_name}' was not found! (gem found but could not be loaded)"
|
31
42
|
end
|
32
43
|
self.active = true
|
33
44
|
self.enabled = true
|
@@ -47,7 +58,7 @@ class Pry
|
|
47
58
|
(Gem::Specification.respond_to?(:each) ? Gem::Specification : Gem.source_index.find_name('')).each do |gem|
|
48
59
|
next if gem.name !~ PRY_PLUGIN_PREFIX
|
49
60
|
plugin_name = gem.name.split('-', 2).last
|
50
|
-
@plugins << Plugin.new(plugin_name, gem.name, true) if !gem_located?(gem.name)
|
61
|
+
@plugins << Plugin.new(plugin_name, gem.name, gem, true) if !gem_located?(gem.name)
|
51
62
|
end
|
52
63
|
@plugins
|
53
64
|
end
|
@@ -55,7 +66,7 @@ class Pry
|
|
55
66
|
# @return [Hash] A hash with all plugin names (minus the 'pry-') as
|
56
67
|
# keys and Plugin objects as values.
|
57
68
|
def plugins
|
58
|
-
h =
|
69
|
+
h = Hash.new { |_, key| NoPlugin.new(key) }
|
59
70
|
@plugins.each do |plugin|
|
60
71
|
h[plugin.name] = plugin
|
61
72
|
end
|
data/lib/pry/pry_class.rb
CHANGED
@@ -18,26 +18,6 @@ class Pry
|
|
18
18
|
def_delegators delagatee, *names.map { |v| "#{v}=" }
|
19
19
|
end
|
20
20
|
|
21
|
-
# Get nesting data.
|
22
|
-
# This method should not need to be accessed directly.
|
23
|
-
# @return [Array] The unparsed nesting information.
|
24
|
-
attr_reader :nesting
|
25
|
-
|
26
|
-
# Get last value evaluated by Pry.
|
27
|
-
# This method should not need to be accessed directly.
|
28
|
-
# @return [Object] The last result.
|
29
|
-
attr_accessor :last_result
|
30
|
-
|
31
|
-
# Get last exception raised.
|
32
|
-
# This method should not need to be accessed directly.
|
33
|
-
# @return [Exception] The last exception.
|
34
|
-
attr_accessor :last_exception
|
35
|
-
|
36
|
-
# Get the active Pry instance that manages the active Pry session.
|
37
|
-
# This method should not need to be accessed directly.
|
38
|
-
# @return [Pry] The active Pry instance.
|
39
|
-
attr_accessor :active_instance
|
40
|
-
|
41
21
|
# Get/Set the Proc that defines extra Readline completions (on top
|
42
22
|
# of the ones defined for IRB).
|
43
23
|
# @return [Proc] The Proc that defines extra Readline completions (on top
|
@@ -45,10 +25,6 @@ class Pry
|
|
45
25
|
# Pry.custom_completions = proc { Dir.entries('.') }
|
46
26
|
attr_accessor :custom_completions
|
47
27
|
|
48
|
-
# Value returned by last executed Pry command.
|
49
|
-
# @return [Object] The command value
|
50
|
-
attr_accessor :cmd_ret_value
|
51
|
-
|
52
28
|
# @return [Fixnum] The current input line.
|
53
29
|
attr_accessor :current_line
|
54
30
|
|
@@ -62,9 +38,15 @@ class Pry
|
|
62
38
|
# @return [OpenStruct] Return Pry's config object.
|
63
39
|
attr_accessor :config
|
64
40
|
|
41
|
+
# @return [History] Return Pry's line history object.
|
42
|
+
attr_accessor :history
|
43
|
+
|
65
44
|
# @return [Boolean] Whether Pry was activated from the command line.
|
66
45
|
attr_accessor :cli
|
67
46
|
|
47
|
+
# @return [Fixnum] The number of active Pry sessions.
|
48
|
+
attr_accessor :active_sessions
|
49
|
+
|
68
50
|
# plugin forwardables
|
69
51
|
def_delegators :@plugin_manager, :plugins, :load_plugins, :locate_plugins
|
70
52
|
|
@@ -82,6 +64,13 @@ class Pry
|
|
82
64
|
end
|
83
65
|
end
|
84
66
|
|
67
|
+
# Load any Ruby files specified with the -r flag on the command line.
|
68
|
+
def self.load_requires
|
69
|
+
Pry.config.requires.each do |file|
|
70
|
+
require file
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
85
74
|
# Start a Pry REPL.
|
86
75
|
# This method also loads the files specified in `Pry::RC_FILES` the
|
87
76
|
# first time it is invoked.
|
@@ -97,7 +86,8 @@ class Pry
|
|
97
86
|
# multiple times per each new session (i.e in debugging)
|
98
87
|
load_rc if Pry.config.should_load_rc
|
99
88
|
load_plugins if Pry.config.plugins.enabled
|
100
|
-
|
89
|
+
load_requires if Pry.config.should_load_requires
|
90
|
+
load_history if Pry.config.history.should_load
|
101
91
|
|
102
92
|
@initial_session = false
|
103
93
|
end
|
@@ -121,18 +111,32 @@ class Pry
|
|
121
111
|
# @param obj The object to view.
|
122
112
|
# @param max_size The maximum number of chars before clipping occurs.
|
123
113
|
# @return [String] The string representation of `obj`.
|
124
|
-
def self.view_clip(obj,
|
125
|
-
if obj.
|
114
|
+
def self.view_clip(obj, max_length = 60)
|
115
|
+
if obj.kind_of?(Module) && obj.name && obj.name != "" && obj.name.to_s.length <= max_length
|
116
|
+
obj.name.to_s
|
117
|
+
elsif obj.inspect.length <= max_length
|
126
118
|
obj.inspect
|
127
|
-
else
|
119
|
+
else
|
128
120
|
"#<#{obj.class}:%#x>" % (obj.object_id << 1)
|
129
121
|
end
|
122
|
+
|
123
|
+
rescue
|
124
|
+
"unknown"
|
130
125
|
end
|
131
126
|
|
132
127
|
# Load Readline history if required.
|
133
128
|
def self.load_history
|
134
|
-
history_file
|
135
|
-
|
129
|
+
Pry.history.load(history_file) if File.exists?(history_file)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Save new lines of Readline history if required.
|
133
|
+
def self.save_history
|
134
|
+
Pry.history.save(history_file)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Get the full path of the history_path for pry.
|
138
|
+
def self.history_file
|
139
|
+
File.expand_path(Pry.config.history.file)
|
136
140
|
end
|
137
141
|
|
138
142
|
# @return [Boolean] Whether this is the first time a Pry session has
|
@@ -172,9 +176,9 @@ class Pry
|
|
172
176
|
|
173
177
|
def self.default_editor_for_platform
|
174
178
|
if RUBY_PLATFORM =~ /mswin|mingw/
|
175
|
-
ENV['
|
179
|
+
ENV['VISUAL'] || ENV['EDITOR'] || "notepad"
|
176
180
|
else
|
177
|
-
ENV['
|
181
|
+
ENV['VISUAL'] || ENV['EDITOR'] || "nano"
|
178
182
|
end
|
179
183
|
end
|
180
184
|
|
@@ -190,16 +194,23 @@ class Pry
|
|
190
194
|
config.pager = true
|
191
195
|
config.editor = default_editor_for_platform
|
192
196
|
config.should_load_rc = true
|
197
|
+
config.disable_auto_reload = false
|
198
|
+
config.command_prefix = ""
|
193
199
|
|
194
200
|
config.plugins ||= OpenStruct.new
|
195
201
|
config.plugins.enabled = true
|
196
202
|
config.plugins.strict_loading = true
|
197
203
|
|
204
|
+
config.requires ||= []
|
205
|
+
config.should_load_requires = true
|
206
|
+
|
198
207
|
config.history ||= OpenStruct.new
|
199
|
-
config.history.
|
200
|
-
config.history.
|
208
|
+
config.history.should_save = true
|
209
|
+
config.history.should_load = true
|
201
210
|
config.history.file = File.expand_path("~/.pry_history")
|
202
211
|
|
212
|
+
config.control_d_handler = DEFAULT_CONTROL_D_HANDLER
|
213
|
+
|
203
214
|
config.memory_size = 100
|
204
215
|
end
|
205
216
|
|
@@ -211,32 +222,22 @@ class Pry
|
|
211
222
|
|
212
223
|
self.custom_completions = DEFAULT_CUSTOM_COMPLETIONS
|
213
224
|
self.cli = false
|
214
|
-
self.current_line =
|
215
|
-
self.line_buffer = []
|
225
|
+
self.current_line = 1
|
226
|
+
self.line_buffer = [""]
|
216
227
|
self.eval_path = "(pry)"
|
228
|
+
self.active_sessions = 0
|
217
229
|
end
|
218
230
|
|
219
231
|
# Basic initialization.
|
220
232
|
def self.init
|
221
233
|
@plugin_manager ||= PluginManager.new
|
222
|
-
|
223
234
|
self.config ||= Config.new
|
235
|
+
self.history ||= History.new
|
236
|
+
|
224
237
|
reset_defaults
|
225
238
|
locate_plugins
|
226
239
|
end
|
227
240
|
|
228
|
-
@nesting = []
|
229
|
-
def @nesting.level
|
230
|
-
last.is_a?(Array) ? last.first : nil
|
231
|
-
end
|
232
|
-
|
233
|
-
# Return all active Pry sessions.
|
234
|
-
# @return [Array<Pry>] Active Pry sessions.
|
235
|
-
def self.sessions
|
236
|
-
# last element in nesting array is the pry instance
|
237
|
-
nesting.map(&:last)
|
238
|
-
end
|
239
|
-
|
240
241
|
# Return a `Binding` object for `target` or return `target` if it is
|
241
242
|
# already a `Binding`.
|
242
243
|
# In the case where `target` is top-level then return `TOPLEVEL_BINDING`
|
@@ -246,7 +247,7 @@ class Pry
|
|
246
247
|
if target.is_a?(Binding)
|
247
248
|
target
|
248
249
|
else
|
249
|
-
if
|
250
|
+
if TOPLEVEL_BINDING.eval('self') == target
|
250
251
|
TOPLEVEL_BINDING
|
251
252
|
else
|
252
253
|
target.__binding__
|
data/lib/pry/pry_instance.rb
CHANGED
@@ -10,10 +10,15 @@ class Pry
|
|
10
10
|
attr_accessor :hooks
|
11
11
|
attr_accessor :custom_completions
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
attr_accessor :
|
13
|
+
attr_accessor :binding_stack
|
14
|
+
|
15
|
+
attr_accessor :last_result
|
16
|
+
attr_accessor :last_exception
|
17
|
+
attr_accessor :last_file
|
18
|
+
attr_accessor :last_dir
|
19
|
+
|
20
|
+
attr_reader :input_array
|
21
|
+
attr_reader :output_array
|
17
22
|
|
18
23
|
# Create a new `Pry` object.
|
19
24
|
# @param [Hash] options The optional configuration parameters.
|
@@ -28,6 +33,7 @@ class Pry
|
|
28
33
|
refresh(options)
|
29
34
|
|
30
35
|
@command_processor = CommandProcessor.new(self)
|
36
|
+
@binding_stack = []
|
31
37
|
end
|
32
38
|
|
33
39
|
# Refresh the Pry instance settings from the Pry class.
|
@@ -73,6 +79,18 @@ class Pry
|
|
73
79
|
end
|
74
80
|
end
|
75
81
|
|
82
|
+
# Injects a local variable into the provided binding.
|
83
|
+
# @param [String] name The name of the local to inject.
|
84
|
+
# @param [Object] value The value to set the local to.
|
85
|
+
# @param [Binding] b The binding to set the local on.
|
86
|
+
# @return [Object] The value the local was set to.
|
87
|
+
def inject_local(name, value, b)
|
88
|
+
Thread.current[:__pry_local__] = value
|
89
|
+
b.eval("#{name} = Thread.current[:__pry_local__]")
|
90
|
+
ensure
|
91
|
+
Thread.current[:__pry_local__] = nil
|
92
|
+
end
|
93
|
+
|
76
94
|
# @return [Integer] The maximum amount of objects remembered by the inp and
|
77
95
|
# out arrays. Defaults to 100.
|
78
96
|
def memory_size
|
@@ -84,32 +102,6 @@ class Pry
|
|
84
102
|
@output_array = Pry::HistoryArray.new(size)
|
85
103
|
end
|
86
104
|
|
87
|
-
# Get nesting data.
|
88
|
-
# This method should not need to be accessed directly.
|
89
|
-
# @return [Array] The unparsed nesting information.
|
90
|
-
def nesting
|
91
|
-
self.class.nesting
|
92
|
-
end
|
93
|
-
|
94
|
-
# Set nesting data.
|
95
|
-
# This method should not need to be accessed directly.
|
96
|
-
# @param v nesting data.
|
97
|
-
def nesting=(v)
|
98
|
-
self.class.nesting = v
|
99
|
-
end
|
100
|
-
|
101
|
-
# @return [Boolean] Whether top-level session has ended.
|
102
|
-
def finished_top_level_session?
|
103
|
-
nesting.empty?
|
104
|
-
end
|
105
|
-
|
106
|
-
# Return parent of current Pry session.
|
107
|
-
# @return [Pry] The parent of the current Pry session.
|
108
|
-
def parent
|
109
|
-
idx = Pry.sessions.index(self)
|
110
|
-
Pry.sessions[idx - 1] if idx && idx > 0
|
111
|
-
end
|
112
|
-
|
113
105
|
# Execute the hook `hook_name`, if it is defined.
|
114
106
|
# @param [Symbol] hook_name The hook to execute
|
115
107
|
# @param [Array] args The arguments to pass to the hook.
|
@@ -117,41 +109,53 @@ class Pry
|
|
117
109
|
hooks[hook_name].call(*args, &block) if hooks[hook_name]
|
118
110
|
end
|
119
111
|
|
112
|
+
# Make sure special locals exist at start of session
|
113
|
+
def initialize_special_locals(target)
|
114
|
+
inject_local("_in_", @input_array, target)
|
115
|
+
inject_local("_out_", @output_array, target)
|
116
|
+
inject_local("_pry_", self, target)
|
117
|
+
inject_local("_ex_", nil, target)
|
118
|
+
inject_local("_file_", nil, target)
|
119
|
+
inject_local("_dir_", nil, target)
|
120
|
+
|
121
|
+
# without this line we get 1 test failure, ask Mon_Ouie
|
122
|
+
set_last_result(nil, target)
|
123
|
+
inject_local("_", nil, target)
|
124
|
+
end
|
125
|
+
private :initialize_special_locals
|
126
|
+
|
127
|
+
def inject_special_locals(target)
|
128
|
+
inject_local("_in_", @input_array, target)
|
129
|
+
inject_local("_out_", @output_array, target)
|
130
|
+
inject_local("_pry_", self, target)
|
131
|
+
inject_local("_ex_", self.last_exception, target)
|
132
|
+
inject_local("_file_", self.last_file, target)
|
133
|
+
inject_local("_dir_", self.last_dir, target)
|
134
|
+
inject_local("_", self.last_result, target)
|
135
|
+
end
|
136
|
+
|
120
137
|
# Initialize the repl session.
|
121
138
|
# @param [Binding] target The target binding for the session.
|
122
139
|
def repl_prologue(target)
|
123
140
|
exec_hook :before_session, output, target
|
124
|
-
|
125
|
-
|
126
|
-
# Make sure special locals exist
|
127
|
-
target.eval("inp = ::Pry.active_instance.instance_eval { @input_array }")
|
128
|
-
target.eval("out = ::Pry.active_instance.instance_eval { @output_array }")
|
141
|
+
initialize_special_locals(target)
|
129
142
|
|
130
|
-
set_active_instance(target)
|
131
143
|
@input_array << nil # add empty input so inp and out match
|
132
|
-
set_last_result(Pry.last_result, target)
|
133
144
|
|
134
|
-
|
145
|
+
Pry.active_sessions += 1
|
146
|
+
binding_stack.push target
|
135
147
|
end
|
136
148
|
|
137
149
|
# Clean-up after the repl session.
|
138
150
|
# @param [Binding] target The target binding for the session.
|
139
151
|
# @return [Object] The return value of the repl session (if one exists).
|
140
|
-
def repl_epilogue(target,
|
141
|
-
nesting.pop
|
152
|
+
def repl_epilogue(target, break_data)
|
142
153
|
exec_hook :after_session, output, target
|
143
154
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
if nesting_level != break_level
|
149
|
-
throw :breakout, break_data
|
150
|
-
end
|
151
|
-
|
152
|
-
save_history if Pry.config.history.save && finished_top_level_session?
|
153
|
-
|
154
|
-
return_value
|
155
|
+
Pry.active_sessions -= 1
|
156
|
+
binding_stack.pop
|
157
|
+
Pry.save_history if Pry.config.history.should_save && Pry.active_sessions == 0
|
158
|
+
break_data
|
155
159
|
end
|
156
160
|
|
157
161
|
# Start a read-eval-print-loop.
|
@@ -168,18 +172,13 @@ class Pry
|
|
168
172
|
|
169
173
|
repl_prologue(target)
|
170
174
|
|
171
|
-
# cannot rely on nesting.level as
|
172
|
-
# nesting.level changes with new sessions
|
173
|
-
nesting_level = nesting.size
|
174
|
-
|
175
175
|
break_data = catch(:breakout) do
|
176
|
-
nesting.push [nesting.size, target_self, self]
|
177
176
|
loop do
|
178
|
-
rep(
|
177
|
+
rep(binding_stack.last)
|
179
178
|
end
|
180
179
|
end
|
181
180
|
|
182
|
-
return_value = repl_epilogue(target,
|
181
|
+
return_value = repl_epilogue(target, break_data)
|
183
182
|
return_value || target_self
|
184
183
|
end
|
185
184
|
|
@@ -211,29 +210,18 @@ class Pry
|
|
211
210
|
Readline.completion_proc = Pry::InputCompleter.build_completion_proc target, instance_eval(&custom_completions)
|
212
211
|
end
|
213
212
|
|
214
|
-
#
|
215
|
-
|
216
|
-
|
217
|
-
target.eval("inp = ::Pry.active_instance.instance_eval { @input_array }")
|
218
|
-
target.eval("out = ::Pry.active_instance.instance_eval { @output_array }")
|
219
|
-
|
220
|
-
@last_result_is_exception = false
|
221
|
-
set_active_instance(target)
|
213
|
+
# It's not actually redundant to inject them continually as we may have
|
214
|
+
# moved into the scope of a new Binding (e.g the user typed `cd`)
|
215
|
+
inject_special_locals(target)
|
222
216
|
|
223
217
|
code = r(target)
|
224
218
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
rescue SystemExit => e
|
229
|
-
exit
|
230
|
-
rescue Exception => e
|
231
|
-
@last_result_is_exception = true
|
232
|
-
@output_array << e
|
219
|
+
result = set_last_result(target.eval(code, Pry.eval_path, Pry.current_line), target)
|
220
|
+
result
|
221
|
+
rescue RescuableException => e
|
233
222
|
set_last_exception(e, target)
|
234
223
|
ensure
|
235
|
-
|
236
|
-
Pry.current_line += code.each_line.count if code
|
224
|
+
update_input_history(code)
|
237
225
|
end
|
238
226
|
|
239
227
|
# Perform a read.
|
@@ -258,7 +246,7 @@ class Pry
|
|
258
246
|
break if valid_expression?(eval_string)
|
259
247
|
end
|
260
248
|
|
261
|
-
@suppress_output = true if eval_string =~ /;\Z/ ||
|
249
|
+
@suppress_output = true if eval_string =~ /;\Z/ || eval_string.empty?
|
262
250
|
|
263
251
|
eval_string
|
264
252
|
end
|
@@ -270,14 +258,19 @@ class Pry
|
|
270
258
|
else
|
271
259
|
print.call output, result
|
272
260
|
end
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
261
|
+
rescue RescuableException => e
|
262
|
+
# Being uber-paranoid here, given that this exception arose because we couldn't
|
263
|
+
# serialize something in the user's program, let's not assume we can serialize
|
264
|
+
# the exception either.
|
265
|
+
begin
|
266
|
+
output.puts "output error: #{e.inspect}"
|
267
|
+
rescue RescuableException => e
|
268
|
+
if last_result_is_exception?
|
269
|
+
output.puts "output error: failed to show exception"
|
270
|
+
else
|
271
|
+
output.puts "output error: failed to show result"
|
272
|
+
end
|
273
|
+
end
|
281
274
|
end
|
282
275
|
|
283
276
|
# Read a line of input and check for ^d, also determine prompt to use.
|
@@ -289,28 +282,40 @@ class Pry
|
|
289
282
|
current_prompt = select_prompt(eval_string.empty?, target.eval('self'))
|
290
283
|
val = readline(current_prompt)
|
291
284
|
|
292
|
-
# exit session if we receive EOF character
|
285
|
+
# exit session if we receive EOF character (^D)
|
293
286
|
if !val
|
294
|
-
output.puts
|
295
|
-
|
287
|
+
output.puts ""
|
288
|
+
Pry.config.control_d_handler.call(eval_string, self)
|
289
|
+
""
|
290
|
+
else
|
291
|
+
val
|
296
292
|
end
|
297
|
-
|
298
|
-
val
|
299
293
|
end
|
300
294
|
|
301
295
|
# Process the line received.
|
302
296
|
# This method should not need to be invoked directly.
|
303
297
|
# @param [String] val The line to process.
|
304
298
|
# @param [String] eval_string The cumulative lines of input.
|
305
|
-
# @
|
299
|
+
# @param [Binding] target The target of the Pry session.
|
306
300
|
def process_line(val, eval_string, target)
|
307
|
-
val
|
308
|
-
|
301
|
+
result = @command_processor.process_commands(val, eval_string, target)
|
302
|
+
|
303
|
+
# set a temporary (just so we can inject the value we want into eval_string)
|
304
|
+
Thread.current[:__pry_cmd_result__] = result
|
309
305
|
|
310
|
-
if
|
311
|
-
|
306
|
+
# note that `result` wraps the result of command processing; if a
|
307
|
+
# command was matched and invoked then `result.command?` returns true,
|
308
|
+
# otherwise it returns false.
|
309
|
+
if result.command? && !result.void_command?
|
310
|
+
|
311
|
+
# the command that was invoked was non-void (had a return value) and so we make
|
312
|
+
# the value of the current expression equal to the return value
|
313
|
+
# of the command.
|
314
|
+
eval_string.replace "Thread.current[:__pry_cmd_result__].retval\n"
|
312
315
|
else
|
313
|
-
|
316
|
+
# only commands should have an empty `val`
|
317
|
+
# so this ignores their result
|
318
|
+
eval_string << "#{val.rstrip}\n" if !val.empty?
|
314
319
|
end
|
315
320
|
end
|
316
321
|
|
@@ -319,9 +324,10 @@ class Pry
|
|
319
324
|
# @param [Object] result The result.
|
320
325
|
# @param [Binding] target The binding to set `_` on.
|
321
326
|
def set_last_result(result, target)
|
322
|
-
|
327
|
+
@last_result_is_exception = false
|
323
328
|
@output_array << result
|
324
|
-
|
329
|
+
|
330
|
+
self.last_result = result
|
325
331
|
end
|
326
332
|
|
327
333
|
# Set the last exception for a session.
|
@@ -329,16 +335,29 @@ class Pry
|
|
329
335
|
# @param [Exception] ex The exception.
|
330
336
|
# @param [Binding] target The binding to set `_ex_` on.
|
331
337
|
def set_last_exception(ex, target)
|
332
|
-
|
333
|
-
|
338
|
+
class << ex
|
339
|
+
attr_accessor :file, :line
|
340
|
+
end
|
341
|
+
|
342
|
+
ex.backtrace.first =~ /(.*):(\d+)/
|
343
|
+
ex.file, ex.line = $1, $2.to_i
|
344
|
+
|
345
|
+
@last_result_is_exception = true
|
346
|
+
@output_array << ex
|
347
|
+
|
348
|
+
self.last_exception = ex
|
334
349
|
end
|
335
350
|
|
336
|
-
#
|
351
|
+
# Update Pry's internal state after evalling code.
|
337
352
|
# This method should not need to be invoked directly.
|
338
|
-
# @param [
|
339
|
-
def
|
340
|
-
|
341
|
-
|
353
|
+
# @param [String] code The code we just eval'd
|
354
|
+
def update_input_history(code)
|
355
|
+
# Always push to the @input_array as the @output_array is always pushed to.
|
356
|
+
@input_array << code
|
357
|
+
if code
|
358
|
+
Pry.line_buffer.push(*code.each_line)
|
359
|
+
Pry.current_line += code.each_line.count
|
360
|
+
end
|
342
361
|
end
|
343
362
|
|
344
363
|
# @return [Boolean] True if the last result is an exception that was raised,
|
@@ -355,10 +374,9 @@ class Pry
|
|
355
374
|
def readline(current_prompt="> ")
|
356
375
|
|
357
376
|
if input == Readline
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
input.readline(current_prompt, true)
|
377
|
+
line = input.readline(current_prompt, false)
|
378
|
+
Pry.history << line.dup if line
|
379
|
+
line
|
362
380
|
else
|
363
381
|
begin
|
364
382
|
if input.method(:readline).arity == 1
|
@@ -382,14 +400,6 @@ class Pry
|
|
382
400
|
!@suppress_output || last_result_is_exception?
|
383
401
|
end
|
384
402
|
|
385
|
-
# Save readline history to a file.
|
386
|
-
def save_history
|
387
|
-
history_file = File.expand_path(Pry.config.history.file)
|
388
|
-
File.open(history_file, 'w') do |f|
|
389
|
-
f.write Readline::HISTORY.to_a.join("\n")
|
390
|
-
end
|
391
|
-
end
|
392
|
-
|
393
403
|
# Returns the appropriate prompt to use.
|
394
404
|
# This method should not need to be invoked directly.
|
395
405
|
# @param [Boolean] first_line Whether this is the first line of input
|
@@ -399,9 +409,9 @@ class Pry
|
|
399
409
|
def select_prompt(first_line, target_self)
|
400
410
|
|
401
411
|
if first_line
|
402
|
-
Array(prompt).first.call(target_self,
|
412
|
+
Array(prompt).first.call(target_self, binding_stack.size - 1, self)
|
403
413
|
else
|
404
|
-
Array(prompt).last.call(target_self,
|
414
|
+
Array(prompt).last.call(target_self, binding_stack.size - 1, self)
|
405
415
|
end
|
406
416
|
end
|
407
417
|
|