pry 0.6.7 → 0.6.8
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/CHANGELOG +5 -0
- data/LICENSE +25 -25
- data/README.markdown +11 -2
- data/Rakefile +1 -1
- data/bin/pry +5 -4
- data/examples/example_basic.rb +17 -17
- data/examples/example_command_override.rb +35 -35
- data/examples/example_commands.rb +39 -39
- data/examples/example_hooks.rb +12 -12
- data/examples/example_image_edit.rb +71 -71
- data/examples/example_input.rb +10 -10
- data/examples/example_input2.rb +32 -32
- data/examples/example_output.rb +14 -14
- data/examples/example_print.rb +9 -9
- data/examples/example_prompt.rb +12 -12
- data/lib/pry/command_base.rb +150 -150
- data/lib/pry/commands.rb +43 -4
- data/lib/pry/completion.rb +202 -202
- data/lib/pry/core_extensions.rb +55 -55
- data/lib/pry/hooks.rb +19 -8
- data/lib/pry/pry_class.rb +37 -4
- data/lib/pry/pry_instance.rb +3 -3
- data/lib/pry/version.rb +1 -1
- data/test/test.rb +725 -681
- data/test/test_helper.rb +46 -38
- data/test/testrc +2 -0
- metadata +91 -59
data/lib/pry/commands.rb
CHANGED
@@ -27,6 +27,44 @@ class Pry
|
|
27
27
|
remove_first_word = lambda do |text|
|
28
28
|
text.split.drop(1).join(' ')
|
29
29
|
end
|
30
|
+
|
31
|
+
command "whereami", "Show the code context for the session." do
|
32
|
+
file = target.eval('__FILE__')
|
33
|
+
line_num = target.eval('__LINE__')
|
34
|
+
klass = target.eval('self.class')
|
35
|
+
|
36
|
+
meth_name = meth_name_from_binding.call(target)
|
37
|
+
if !meth_name
|
38
|
+
output.puts "Cannot find containing method. Did you remember to use \`binding.pry\` ?"
|
39
|
+
next
|
40
|
+
end
|
41
|
+
|
42
|
+
check_for_dynamically_defined_method.call(file)
|
43
|
+
|
44
|
+
output.puts "--\nFrom #{file} @ line #{line_num} in #{klass}##{meth_name}:\n--"
|
45
|
+
|
46
|
+
# This method inspired by http://rubygems.org/gems/ir_b
|
47
|
+
File.open(file).each_with_index do |line, index|
|
48
|
+
line_n = index + 1
|
49
|
+
next unless line_n > (line_num - 6)
|
50
|
+
break if line_n > (line_num + 5)
|
51
|
+
if line_n == line_num
|
52
|
+
code =" =>#{line_n.to_s.rjust(3)}: #{line.chomp}"
|
53
|
+
if Pry.color
|
54
|
+
code = CodeRay.scan(code, :ruby).term
|
55
|
+
end
|
56
|
+
output.puts code
|
57
|
+
code
|
58
|
+
else
|
59
|
+
code = "#{line_n.to_s.rjust(6)}: #{line.chomp}"
|
60
|
+
if Pry.color
|
61
|
+
code = CodeRay.scan(code, :ruby).term
|
62
|
+
end
|
63
|
+
output.puts code
|
64
|
+
code
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
30
68
|
|
31
69
|
command "!", "Clear the input buffer. Useful if the parsing process goes wrong and you get stuck in the read loop." do
|
32
70
|
output.puts "Input buffer cleared!"
|
@@ -37,11 +75,12 @@ class Pry
|
|
37
75
|
Pry.start(target)
|
38
76
|
end
|
39
77
|
|
40
|
-
command "exit-program", "End the current program. Aliases: quit-program" do
|
78
|
+
command "exit-program", "End the current program. Aliases: quit-program, !!!" do
|
41
79
|
exit
|
42
80
|
end
|
43
81
|
|
44
82
|
alias_command "quit-program", "exit-program", ""
|
83
|
+
alias_command "!!!", "exit-program", ""
|
45
84
|
|
46
85
|
command "toggle-color", "Toggle syntax highlighting." do
|
47
86
|
Pry.color = !Pry.color
|
@@ -262,7 +301,7 @@ Shows local and instance variables by default.
|
|
262
301
|
next
|
263
302
|
end
|
264
303
|
|
265
|
-
contents = File.read(file_name)
|
304
|
+
contents = File.read(File.expand_path(file_name))
|
266
305
|
output.puts contents
|
267
306
|
contents
|
268
307
|
end
|
@@ -301,10 +340,10 @@ e.g: eval-file -c self "hello.rb"
|
|
301
340
|
old_constants = Object.constants
|
302
341
|
if options[:c]
|
303
342
|
target_self = target.eval('self')
|
304
|
-
target.eval(File.read(file_name))
|
343
|
+
target.eval(File.read(File.expand_path(file_name)))
|
305
344
|
output.puts "--\nEval'd '#{file_name}' in the `#{target_self}` context."
|
306
345
|
else
|
307
|
-
TOPLEVEL_BINDING.eval(File.read(file_name))
|
346
|
+
TOPLEVEL_BINDING.eval(File.read(File.expand_path(file_name)))
|
308
347
|
output.puts "--\nEval'd '#{file_name}' at top-level."
|
309
348
|
end
|
310
349
|
new_constants = Object.constants - old_constants
|
data/lib/pry/completion.rb
CHANGED
@@ -1,202 +1,202 @@
|
|
1
|
-
# taken from irb
|
2
|
-
|
3
|
-
require "readline"
|
4
|
-
|
5
|
-
class Pry
|
6
|
-
|
7
|
-
# Implements tab completion for Readline in Pry
|
8
|
-
module InputCompleter
|
9
|
-
|
10
|
-
if Readline.respond_to?("basic_word_break_characters=")
|
11
|
-
Readline.basic_word_break_characters= " \t\n\"\\'`><=;|&{("
|
12
|
-
end
|
13
|
-
|
14
|
-
Readline.completion_append_character = nil
|
15
|
-
|
16
|
-
ReservedWords = [
|
17
|
-
"BEGIN", "END",
|
18
|
-
"alias", "and",
|
19
|
-
"begin", "break",
|
20
|
-
"case", "class",
|
21
|
-
"def", "defined", "do",
|
22
|
-
"else", "elsif", "end", "ensure",
|
23
|
-
"false", "for",
|
24
|
-
"if", "in",
|
25
|
-
"module",
|
26
|
-
"next", "nil", "not",
|
27
|
-
"or",
|
28
|
-
"redo", "rescue", "retry", "return",
|
29
|
-
"self", "super",
|
30
|
-
"then", "true",
|
31
|
-
"undef", "unless", "until",
|
32
|
-
"when", "while",
|
33
|
-
"yield",
|
34
|
-
]
|
35
|
-
|
36
|
-
Operators = ["%", "&", "*", "**", "+", "-", "/",
|
37
|
-
"<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>",
|
38
|
-
"[]", "[]=", "^", "!", "!=", "!~"]
|
39
|
-
|
40
|
-
# Return a new completion proc for use by Readline.
|
41
|
-
# @param [Binding] target The current binding context.
|
42
|
-
# @param [Array<String>] commands The array of Pry commands.
|
43
|
-
def self.build_completion_proc(target, commands=[""])
|
44
|
-
proc do |input|
|
45
|
-
bind = target
|
46
|
-
|
47
|
-
case input
|
48
|
-
when /^(\/[^\/]*\/)\.([^.]*)$/
|
49
|
-
# Regexp
|
50
|
-
receiver = $1
|
51
|
-
message = Regexp.quote($2)
|
52
|
-
|
53
|
-
candidates = Regexp.instance_methods.collect{|m| m.to_s}
|
54
|
-
select_message(receiver, message, candidates)
|
55
|
-
|
56
|
-
when /^([^\]]*\])\.([^.]*)$/
|
57
|
-
# Array
|
58
|
-
receiver = $1
|
59
|
-
message = Regexp.quote($2)
|
60
|
-
|
61
|
-
candidates = Array.instance_methods.collect{|m| m.to_s}
|
62
|
-
select_message(receiver, message, candidates)
|
63
|
-
|
64
|
-
when /^([^\}]*\})\.([^.]*)$/
|
65
|
-
# Proc or Hash
|
66
|
-
receiver = $1
|
67
|
-
message = Regexp.quote($2)
|
68
|
-
|
69
|
-
candidates = Proc.instance_methods.collect{|m| m.to_s}
|
70
|
-
candidates |= Hash.instance_methods.collect{|m| m.to_s}
|
71
|
-
select_message(receiver, message, candidates)
|
72
|
-
|
73
|
-
when /^(:[^:.]*)$/
|
74
|
-
# Symbol
|
75
|
-
if Symbol.respond_to?(:all_symbols)
|
76
|
-
sym = $1
|
77
|
-
candidates = Symbol.all_symbols.collect{|s| ":" + s.id2name}
|
78
|
-
candidates.grep(/^#{sym}/)
|
79
|
-
else
|
80
|
-
[]
|
81
|
-
end
|
82
|
-
|
83
|
-
when /^::([A-Z][^:\.\(]*)$/
|
84
|
-
# Absolute Constant or class methods
|
85
|
-
receiver = $1
|
86
|
-
candidates = Object.constants.collect{|m| m.to_s}
|
87
|
-
candidates.grep(/^#{receiver}/).collect{|e| "::" + e}
|
88
|
-
|
89
|
-
when /^([A-Z].*)::([^:.]*)$/
|
90
|
-
# Constant or class methods
|
91
|
-
receiver = $1
|
92
|
-
message = Regexp.quote($2)
|
93
|
-
begin
|
94
|
-
candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind)
|
95
|
-
candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind)
|
96
|
-
rescue Exception
|
97
|
-
candidates = []
|
98
|
-
end
|
99
|
-
candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e}
|
100
|
-
|
101
|
-
when /^(:[^:.]+)\.([^.]*)$/
|
102
|
-
# Symbol
|
103
|
-
receiver = $1
|
104
|
-
message = Regexp.quote($2)
|
105
|
-
|
106
|
-
candidates = Symbol.instance_methods.collect{|m| m.to_s}
|
107
|
-
select_message(receiver, message, candidates)
|
108
|
-
|
109
|
-
when /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)\.([^.]*)$/
|
110
|
-
# Numeric
|
111
|
-
receiver = $1
|
112
|
-
message = Regexp.quote($5)
|
113
|
-
|
114
|
-
begin
|
115
|
-
candidates = eval(receiver, bind).methods.collect{|m| m.to_s}
|
116
|
-
rescue Exception
|
117
|
-
candidates = []
|
118
|
-
end
|
119
|
-
select_message(receiver, message, candidates)
|
120
|
-
|
121
|
-
when /^(-?0x[0-9a-fA-F_]+)\.([^.]*)$/
|
122
|
-
# Numeric(0xFFFF)
|
123
|
-
receiver = $1
|
124
|
-
message = Regexp.quote($2)
|
125
|
-
|
126
|
-
begin
|
127
|
-
candidates = eval(receiver, bind).methods.collect{|m| m.to_s}
|
128
|
-
rescue Exception
|
129
|
-
candidates = []
|
130
|
-
end
|
131
|
-
select_message(receiver, message, candidates)
|
132
|
-
|
133
|
-
when /^(\$[^.]*)$/
|
134
|
-
regmessage = Regexp.new(Regexp.quote($1))
|
135
|
-
candidates = global_variables.collect{|m| m.to_s}.grep(regmessage)
|
136
|
-
|
137
|
-
when /^([^."].*)\.([^.]*)$/
|
138
|
-
# variable
|
139
|
-
receiver = $1
|
140
|
-
message = Regexp.quote($2)
|
141
|
-
|
142
|
-
gv = eval("global_variables", bind).collect{|m| m.to_s}
|
143
|
-
lv = eval("local_variables", bind).collect{|m| m.to_s}
|
144
|
-
cv = eval("self.class.constants", bind).collect{|m| m.to_s}
|
145
|
-
|
146
|
-
if (gv | lv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver
|
147
|
-
# foo.func and foo is local var. OR
|
148
|
-
# Foo::Bar.func
|
149
|
-
begin
|
150
|
-
candidates = eval("#{receiver}.methods", bind).collect{|m| m.to_s}
|
151
|
-
rescue Exception
|
152
|
-
candidates = []
|
153
|
-
end
|
154
|
-
else
|
155
|
-
# func1.func2
|
156
|
-
candidates = []
|
157
|
-
ObjectSpace.each_object(Module){|m|
|
158
|
-
begin
|
159
|
-
name = m.name
|
160
|
-
rescue Exception
|
161
|
-
name = ""
|
162
|
-
end
|
163
|
-
next if name != "IRB::Context" and
|
164
|
-
/^(IRB|SLex|RubyLex|RubyToken)/ =~ name
|
165
|
-
candidates.concat m.instance_methods(false).collect{|x| x.to_s}
|
166
|
-
}
|
167
|
-
candidates.sort!
|
168
|
-
candidates.uniq!
|
169
|
-
end
|
170
|
-
select_message(receiver, message, candidates)
|
171
|
-
|
172
|
-
when /^\.([^.]*)$/
|
173
|
-
# unknown(maybe String)
|
174
|
-
|
175
|
-
receiver = ""
|
176
|
-
message = Regexp.quote($1)
|
177
|
-
|
178
|
-
candidates = String.instance_methods(true).collect{|m| m.to_s}
|
179
|
-
select_message(receiver, message, candidates)
|
180
|
-
|
181
|
-
else
|
182
|
-
candidates = eval("methods | private_methods | local_variables | self.class.constants", bind).collect{|m| m.to_s}
|
183
|
-
|
184
|
-
(candidates|ReservedWords|commands).grep(/^#{Regexp.quote(input)}/)
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
def self.select_message(receiver, message, candidates)
|
190
|
-
candidates.grep(/^#{message}/).collect do |e|
|
191
|
-
case e
|
192
|
-
when /^[a-zA-Z_]/
|
193
|
-
receiver + "." + e
|
194
|
-
when /^[0-9]/
|
195
|
-
when *Operators
|
196
|
-
#receiver + " " + e
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
1
|
+
# taken from irb
|
2
|
+
|
3
|
+
require "readline"
|
4
|
+
|
5
|
+
class Pry
|
6
|
+
|
7
|
+
# Implements tab completion for Readline in Pry
|
8
|
+
module InputCompleter
|
9
|
+
|
10
|
+
if Readline.respond_to?("basic_word_break_characters=")
|
11
|
+
Readline.basic_word_break_characters= " \t\n\"\\'`><=;|&{("
|
12
|
+
end
|
13
|
+
|
14
|
+
Readline.completion_append_character = nil
|
15
|
+
|
16
|
+
ReservedWords = [
|
17
|
+
"BEGIN", "END",
|
18
|
+
"alias", "and",
|
19
|
+
"begin", "break",
|
20
|
+
"case", "class",
|
21
|
+
"def", "defined", "do",
|
22
|
+
"else", "elsif", "end", "ensure",
|
23
|
+
"false", "for",
|
24
|
+
"if", "in",
|
25
|
+
"module",
|
26
|
+
"next", "nil", "not",
|
27
|
+
"or",
|
28
|
+
"redo", "rescue", "retry", "return",
|
29
|
+
"self", "super",
|
30
|
+
"then", "true",
|
31
|
+
"undef", "unless", "until",
|
32
|
+
"when", "while",
|
33
|
+
"yield",
|
34
|
+
]
|
35
|
+
|
36
|
+
Operators = ["%", "&", "*", "**", "+", "-", "/",
|
37
|
+
"<", "<<", "<=", "<=>", "==", "===", "=~", ">", ">=", ">>",
|
38
|
+
"[]", "[]=", "^", "!", "!=", "!~"]
|
39
|
+
|
40
|
+
# Return a new completion proc for use by Readline.
|
41
|
+
# @param [Binding] target The current binding context.
|
42
|
+
# @param [Array<String>] commands The array of Pry commands.
|
43
|
+
def self.build_completion_proc(target, commands=[""])
|
44
|
+
proc do |input|
|
45
|
+
bind = target
|
46
|
+
|
47
|
+
case input
|
48
|
+
when /^(\/[^\/]*\/)\.([^.]*)$/
|
49
|
+
# Regexp
|
50
|
+
receiver = $1
|
51
|
+
message = Regexp.quote($2)
|
52
|
+
|
53
|
+
candidates = Regexp.instance_methods.collect{|m| m.to_s}
|
54
|
+
select_message(receiver, message, candidates)
|
55
|
+
|
56
|
+
when /^([^\]]*\])\.([^.]*)$/
|
57
|
+
# Array
|
58
|
+
receiver = $1
|
59
|
+
message = Regexp.quote($2)
|
60
|
+
|
61
|
+
candidates = Array.instance_methods.collect{|m| m.to_s}
|
62
|
+
select_message(receiver, message, candidates)
|
63
|
+
|
64
|
+
when /^([^\}]*\})\.([^.]*)$/
|
65
|
+
# Proc or Hash
|
66
|
+
receiver = $1
|
67
|
+
message = Regexp.quote($2)
|
68
|
+
|
69
|
+
candidates = Proc.instance_methods.collect{|m| m.to_s}
|
70
|
+
candidates |= Hash.instance_methods.collect{|m| m.to_s}
|
71
|
+
select_message(receiver, message, candidates)
|
72
|
+
|
73
|
+
when /^(:[^:.]*)$/
|
74
|
+
# Symbol
|
75
|
+
if Symbol.respond_to?(:all_symbols)
|
76
|
+
sym = $1
|
77
|
+
candidates = Symbol.all_symbols.collect{|s| ":" + s.id2name}
|
78
|
+
candidates.grep(/^#{sym}/)
|
79
|
+
else
|
80
|
+
[]
|
81
|
+
end
|
82
|
+
|
83
|
+
when /^::([A-Z][^:\.\(]*)$/
|
84
|
+
# Absolute Constant or class methods
|
85
|
+
receiver = $1
|
86
|
+
candidates = Object.constants.collect{|m| m.to_s}
|
87
|
+
candidates.grep(/^#{receiver}/).collect{|e| "::" + e}
|
88
|
+
|
89
|
+
when /^([A-Z].*)::([^:.]*)$/
|
90
|
+
# Constant or class methods
|
91
|
+
receiver = $1
|
92
|
+
message = Regexp.quote($2)
|
93
|
+
begin
|
94
|
+
candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind)
|
95
|
+
candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind)
|
96
|
+
rescue Exception
|
97
|
+
candidates = []
|
98
|
+
end
|
99
|
+
candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e}
|
100
|
+
|
101
|
+
when /^(:[^:.]+)\.([^.]*)$/
|
102
|
+
# Symbol
|
103
|
+
receiver = $1
|
104
|
+
message = Regexp.quote($2)
|
105
|
+
|
106
|
+
candidates = Symbol.instance_methods.collect{|m| m.to_s}
|
107
|
+
select_message(receiver, message, candidates)
|
108
|
+
|
109
|
+
when /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)\.([^.]*)$/
|
110
|
+
# Numeric
|
111
|
+
receiver = $1
|
112
|
+
message = Regexp.quote($5)
|
113
|
+
|
114
|
+
begin
|
115
|
+
candidates = eval(receiver, bind).methods.collect{|m| m.to_s}
|
116
|
+
rescue Exception
|
117
|
+
candidates = []
|
118
|
+
end
|
119
|
+
select_message(receiver, message, candidates)
|
120
|
+
|
121
|
+
when /^(-?0x[0-9a-fA-F_]+)\.([^.]*)$/
|
122
|
+
# Numeric(0xFFFF)
|
123
|
+
receiver = $1
|
124
|
+
message = Regexp.quote($2)
|
125
|
+
|
126
|
+
begin
|
127
|
+
candidates = eval(receiver, bind).methods.collect{|m| m.to_s}
|
128
|
+
rescue Exception
|
129
|
+
candidates = []
|
130
|
+
end
|
131
|
+
select_message(receiver, message, candidates)
|
132
|
+
|
133
|
+
when /^(\$[^.]*)$/
|
134
|
+
regmessage = Regexp.new(Regexp.quote($1))
|
135
|
+
candidates = global_variables.collect{|m| m.to_s}.grep(regmessage)
|
136
|
+
|
137
|
+
when /^([^."].*)\.([^.]*)$/
|
138
|
+
# variable
|
139
|
+
receiver = $1
|
140
|
+
message = Regexp.quote($2)
|
141
|
+
|
142
|
+
gv = eval("global_variables", bind).collect{|m| m.to_s}
|
143
|
+
lv = eval("local_variables", bind).collect{|m| m.to_s}
|
144
|
+
cv = eval("self.class.constants", bind).collect{|m| m.to_s}
|
145
|
+
|
146
|
+
if (gv | lv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver
|
147
|
+
# foo.func and foo is local var. OR
|
148
|
+
# Foo::Bar.func
|
149
|
+
begin
|
150
|
+
candidates = eval("#{receiver}.methods", bind).collect{|m| m.to_s}
|
151
|
+
rescue Exception
|
152
|
+
candidates = []
|
153
|
+
end
|
154
|
+
else
|
155
|
+
# func1.func2
|
156
|
+
candidates = []
|
157
|
+
ObjectSpace.each_object(Module){|m|
|
158
|
+
begin
|
159
|
+
name = m.name
|
160
|
+
rescue Exception
|
161
|
+
name = ""
|
162
|
+
end
|
163
|
+
next if name != "IRB::Context" and
|
164
|
+
/^(IRB|SLex|RubyLex|RubyToken)/ =~ name
|
165
|
+
candidates.concat m.instance_methods(false).collect{|x| x.to_s}
|
166
|
+
}
|
167
|
+
candidates.sort!
|
168
|
+
candidates.uniq!
|
169
|
+
end
|
170
|
+
select_message(receiver, message, candidates)
|
171
|
+
|
172
|
+
when /^\.([^.]*)$/
|
173
|
+
# unknown(maybe String)
|
174
|
+
|
175
|
+
receiver = ""
|
176
|
+
message = Regexp.quote($1)
|
177
|
+
|
178
|
+
candidates = String.instance_methods(true).collect{|m| m.to_s}
|
179
|
+
select_message(receiver, message, candidates)
|
180
|
+
|
181
|
+
else
|
182
|
+
candidates = eval("methods | private_methods | local_variables | self.class.constants", bind).collect{|m| m.to_s}
|
183
|
+
|
184
|
+
(candidates|ReservedWords|commands).grep(/^#{Regexp.quote(input)}/)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def self.select_message(receiver, message, candidates)
|
190
|
+
candidates.grep(/^#{message}/).collect do |e|
|
191
|
+
case e
|
192
|
+
when /^[a-zA-Z_]/
|
193
|
+
receiver + "." + e
|
194
|
+
when /^[0-9]/
|
195
|
+
when *Operators
|
196
|
+
#receiver + " " + e
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|