pry 0.9.6.2-i386-mingw32 → 0.9.7-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.
- data/.gitignore +6 -0
- data/CHANGELOG +19 -1
- data/CONTRIBUTORS +22 -16
- data/Rakefile +12 -6
- data/bin/pry +15 -12
- data/lib/pry.rb +39 -28
- data/lib/pry/command_context.rb +1 -0
- data/lib/pry/command_processor.rb +9 -2
- data/lib/pry/command_set.rb +7 -0
- data/lib/pry/config.rb +8 -0
- data/lib/pry/default_commands/basic.rb +7 -10
- data/lib/pry/default_commands/context.rb +36 -26
- data/lib/pry/default_commands/documentation.rb +31 -123
- data/lib/pry/default_commands/gems.rb +9 -4
- data/lib/pry/default_commands/input.rb +21 -11
- data/lib/pry/default_commands/introspection.rb +79 -88
- data/lib/pry/default_commands/ls.rb +165 -176
- data/lib/pry/default_commands/shell.rb +8 -8
- data/lib/pry/extended_commands/experimental.rb +1 -5
- data/lib/pry/extended_commands/user_command_api.rb +17 -5
- data/lib/pry/helpers.rb +1 -0
- data/lib/pry/helpers/base_helpers.rb +5 -1
- data/lib/pry/helpers/command_helpers.rb +22 -241
- data/lib/pry/helpers/options_helpers.rb +58 -0
- data/lib/pry/helpers/text.rb +10 -4
- data/lib/pry/history.rb +1 -1
- data/lib/pry/indent.rb +205 -0
- data/lib/pry/method.rb +412 -0
- data/lib/pry/pry_class.rb +56 -15
- data/lib/pry/pry_instance.rb +63 -16
- data/lib/pry/rbx_method.rb +20 -0
- data/lib/pry/rbx_path.rb +34 -0
- data/lib/pry/version.rb +1 -1
- data/pry.gemspec +16 -16
- data/test/helper.rb +8 -4
- data/test/test_command_helpers.rb +1 -69
- data/test/test_command_set.rb +29 -28
- data/test/test_default_commands/test_documentation.rb +23 -10
- data/test/test_default_commands/test_introspection.rb +58 -13
- data/test/test_default_commands/test_ls.rb +148 -0
- data/test/test_indent.rb +234 -0
- data/test/test_input_stack.rb +13 -0
- data/test/test_method.rb +291 -0
- data/test/test_pry.rb +10 -1
- metadata +88 -71
@@ -7,103 +7,60 @@ class Pry
|
|
7
7
|
run ".ri", *args
|
8
8
|
end
|
9
9
|
|
10
|
-
command "show-doc", "Show the comments above METH. Type `show-doc --help` for more info. Aliases: \?" do |*args|
|
11
|
-
|
12
|
-
|
13
|
-
opts = Slop.parse!(args) do |opt|
|
10
|
+
command "show-doc", "Show the comments above METH. Type `show-doc --help` for more info. Aliases: \?", :shellwords => false do |*args|
|
11
|
+
opts, meth = parse_options!(args, :method_object) do |opt|
|
14
12
|
opt.banner unindent <<-USAGE
|
15
|
-
Usage: show-doc [OPTIONS] [METH
|
13
|
+
Usage: show-doc [OPTIONS] [METH]
|
16
14
|
Show the comments above method METH. Tries instance methods first and then methods by default.
|
17
15
|
e.g show-doc hello_method
|
18
16
|
USAGE
|
19
17
|
|
20
|
-
opt.on :M, "instance-methods", "Operate on instance methods."
|
21
|
-
opt.on :m, :methods, "Operate on methods."
|
22
|
-
opt.on :c, :context, "Select object context to run under.", true do |context|
|
23
|
-
target = Pry.binding_for(target.eval(context))
|
24
|
-
end
|
25
18
|
opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
|
26
|
-
opt.on :h, :help, "This message." do
|
27
|
-
output.puts opt
|
28
|
-
end
|
29
19
|
end
|
30
20
|
|
31
|
-
|
21
|
+
raise Pry::CommandError, "No documentation found." if meth.doc.nil? || meth.doc.empty?
|
32
22
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
doc, code_type = doc_and_code_type_for(meth)
|
42
|
-
next if !doc
|
43
|
-
|
44
|
-
next output.puts("No documentation found.") if doc.empty?
|
45
|
-
doc = process_comment_markup(doc, code_type)
|
46
|
-
output.puts make_header(meth, code_type, doc)
|
47
|
-
output.puts "#{text.bold("visibility: ")} #{method_visibility(meth).to_s}"
|
48
|
-
output.puts "#{text.bold("signature: ")} #{signature_for(meth)}"
|
49
|
-
output.puts
|
50
|
-
render_output(opts.flood?, false, doc)
|
51
|
-
doc
|
52
|
-
end
|
23
|
+
doc = process_comment_markup(meth.doc, meth.source_type)
|
24
|
+
output.puts make_header(meth, doc)
|
25
|
+
output.puts "#{text.bold("Owner:")} #{meth.owner || "N/A"}"
|
26
|
+
output.puts "#{text.bold("Visibility:")} #{meth.visibility}"
|
27
|
+
output.puts "#{text.bold("Signature:")} #{meth.signature}"
|
28
|
+
output.puts
|
29
|
+
render_output(opts.flood?, false, doc)
|
53
30
|
end
|
54
31
|
|
55
32
|
alias_command "?", "show-doc"
|
56
33
|
|
57
|
-
command "stat", "View method information and set _file_ and _dir_ locals. Type `stat --help` for more info." do |*args|
|
34
|
+
command "stat", "View method information and set _file_ and _dir_ locals. Type `stat --help` for more info.", :shellwords => false do |*args|
|
58
35
|
target = target()
|
59
36
|
|
60
|
-
opts =
|
37
|
+
opts, meth = parse_options!(args, :method_object) do |opt|
|
61
38
|
opt.banner unindent <<-USAGE
|
62
39
|
Usage: stat [OPTIONS] [METH]
|
63
40
|
Show method information for method METH and set _file_ and _dir_ locals.
|
64
41
|
e.g: stat hello_method
|
65
42
|
USAGE
|
66
|
-
|
67
|
-
opt.on :M, "instance-methods", "Operate on instance methods."
|
68
|
-
opt.on :m, :methods, "Operate on methods."
|
69
|
-
opt.on :c, :context, "Select object context to run under.", true do |context|
|
70
|
-
target = Pry.binding_for(target.eval(context))
|
71
|
-
end
|
72
|
-
opt.on :h, :help, "This message" do
|
73
|
-
output.puts opt
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
next if opts.help?
|
78
|
-
|
79
|
-
meth_name = args.shift
|
80
|
-
if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
|
81
|
-
output.puts "Invalid method name: #{meth_name}. Type `stat --help` for help"
|
82
|
-
next
|
83
|
-
end
|
84
|
-
|
85
|
-
if !is_a_c_method?(meth) && !is_a_dynamically_defined_method?(meth)
|
86
|
-
set_file_and_dir_locals(path_line_for(meth).first)
|
87
43
|
end
|
88
44
|
|
89
|
-
output.puts
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
45
|
+
output.puts unindent <<-EOS
|
46
|
+
Method Information:
|
47
|
+
--
|
48
|
+
Name: #{meth.name}
|
49
|
+
Owner: #{meth.owner ? meth.owner : "Unknown"}
|
50
|
+
Visibility: #{meth.visibility}
|
51
|
+
Type: #{meth.is_a?(::Method) ? "Bound" : "Unbound"}
|
52
|
+
Arity: #{meth.arity}
|
53
|
+
Method Signature: #{meth.signature}
|
54
|
+
Source Location: #{meth.source_location ? meth.source_location.join(":") : "Not found."}
|
55
|
+
EOS
|
99
56
|
end
|
100
57
|
|
101
|
-
command "gist-method", "Gist a method to github. Type `gist-method --help` for more info.", :requires_gem => "gist" do |*args|
|
58
|
+
command "gist-method", "Gist a method to github. Type `gist-method --help` for more info.", :requires_gem => "gist", :shellwords => false do |*args|
|
102
59
|
require 'gist'
|
103
60
|
|
104
61
|
target = target()
|
105
62
|
|
106
|
-
opts =
|
63
|
+
opts, meth = parse_options!(args, :method_object) do |opt|
|
107
64
|
opt.banner unindent <<-USAGE
|
108
65
|
Usage: gist-method [OPTIONS] [METH]
|
109
66
|
Gist the method (doc or source) to github.
|
@@ -112,29 +69,18 @@ class Pry
|
|
112
69
|
e.g: gist -d my_method
|
113
70
|
USAGE
|
114
71
|
|
115
|
-
opt.on :m, :method, "Gist a method's source."
|
116
72
|
opt.on :d, :doc, "Gist a method's documentation."
|
117
73
|
opt.on :p, :private, "Create a private gist (default: true)", :default => true
|
118
|
-
opt.on :h, :help, "This message" do
|
119
|
-
output.puts opt
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
next if opts.help?
|
124
|
-
|
125
|
-
# This needs to be extracted into its own method as it's shared
|
126
|
-
# by show-method and show-doc and stat commands
|
127
|
-
meth_name = args.shift
|
128
|
-
if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
|
129
|
-
output.puts "Invalid method name: #{meth_name}. Type `gist-method --help` for help"
|
130
|
-
next
|
131
74
|
end
|
132
75
|
|
133
76
|
type_map = { :ruby => "rb", :c => "c", :plain => "plain" }
|
134
77
|
if !opts.doc?
|
135
|
-
content
|
78
|
+
content = meth.source
|
79
|
+
code_type = meth.source_type
|
136
80
|
else
|
137
|
-
content
|
81
|
+
content = meth.doc
|
82
|
+
code_type = meth.source_type
|
83
|
+
|
138
84
|
text.no_color do
|
139
85
|
content = process_comment_markup(content, code_type)
|
140
86
|
end
|
@@ -147,44 +93,6 @@ class Pry
|
|
147
93
|
|
148
94
|
output.puts "Gist created at #{link}"
|
149
95
|
end
|
150
|
-
|
151
|
-
helpers do
|
152
|
-
|
153
|
-
# paraphrased from awesome_print gem
|
154
|
-
def signature_for(method)
|
155
|
-
if method.respond_to?(:parameters)
|
156
|
-
|
157
|
-
args = method.parameters.inject([]) do |arr, (type, name)|
|
158
|
-
name ||= (type == :block ? 'block' : "arg#{arr.size + 1}")
|
159
|
-
arr << case type
|
160
|
-
when :req then name.to_s
|
161
|
-
when :opt, :rest then "*#{name}"
|
162
|
-
when :block then "&#{name}"
|
163
|
-
else '?'
|
164
|
-
end
|
165
|
-
end
|
166
|
-
else
|
167
|
-
args = (1..method.arity.abs).map { |i| "arg#{i}" }
|
168
|
-
args[-1] = "*#{args[-1]}" if method.arity < 0
|
169
|
-
end
|
170
|
-
|
171
|
-
"#{method.name}(#{args.join(', ')})"
|
172
|
-
end
|
173
|
-
|
174
|
-
def method_visibility(meth)
|
175
|
-
if meth.owner.public_instance_methods.include? meth.name
|
176
|
-
:public
|
177
|
-
elsif meth.owner.protected_instance_methods.include? meth.name
|
178
|
-
:protected
|
179
|
-
elsif meth.owner.private_instance_methods.include? meth.name
|
180
|
-
:private
|
181
|
-
else
|
182
|
-
:none
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
96
|
end
|
188
|
-
|
189
97
|
end
|
190
98
|
end
|
@@ -4,14 +4,15 @@ class Pry
|
|
4
4
|
Gems = Pry::CommandSet.new do
|
5
5
|
|
6
6
|
command "gem-install", "Install a gem and refresh the gem cache.", :argument_required => true do |gem|
|
7
|
+
require 'rubygems/dependency_installer' unless defined? Gem::DependencyInstaller
|
7
8
|
begin
|
8
9
|
destination = File.writable?(Gem.dir) ? Gem.dir : Gem.user_dir
|
9
10
|
installer = Gem::DependencyInstaller.new :install_dir => destination
|
10
11
|
installer.install gem
|
11
12
|
rescue Errno::EACCES
|
12
|
-
|
13
|
+
raise CommandError, "Insufficient permissions to install `#{text.green gem}`."
|
13
14
|
rescue Gem::GemNotFoundException
|
14
|
-
|
15
|
+
raise CommandError, "Gem `#{text.green gem}` not found."
|
15
16
|
else
|
16
17
|
Gem.refresh
|
17
18
|
output.puts "Gem `#{text.green gem}` installed."
|
@@ -21,7 +22,11 @@ class Pry
|
|
21
22
|
command "gem-cd", "Change working directory to specified gem's directory.", :argument_required => true do |gem|
|
22
23
|
specs = Gem::Specification.respond_to?(:each) ? Gem::Specification.find_all_by_name(gem) : Gem.source_index.find_name(gem)
|
23
24
|
spec = specs.sort { |a,b| Gem::Version.new(b.version) <=> Gem::Version.new(a.version) }.first
|
24
|
-
|
25
|
+
if spec
|
26
|
+
Dir.chdir(spec.full_gem_path)
|
27
|
+
else
|
28
|
+
raise CommandError, "Gem `#{gem}` not found."
|
29
|
+
end
|
25
30
|
end
|
26
31
|
|
27
32
|
command "gem-list", "List/search installed gems. (Optional parameter: a regexp to limit the search)" do |pattern|
|
@@ -41,7 +46,7 @@ class Pry
|
|
41
46
|
index == 0 ? text.bright_green(spec.version.to_s) : text.green(spec.version.to_s)
|
42
47
|
end
|
43
48
|
|
44
|
-
output.puts "#{text.
|
49
|
+
output.puts "#{text.default gem} (#{versions.join ', '})"
|
45
50
|
end
|
46
51
|
end
|
47
52
|
|
@@ -33,7 +33,10 @@ class Pry
|
|
33
33
|
end
|
34
34
|
|
35
35
|
next if opts.h?
|
36
|
-
|
36
|
+
|
37
|
+
if eval_string.empty?
|
38
|
+
raise CommandError, "No input to amend."
|
39
|
+
end
|
37
40
|
|
38
41
|
replacement_line = "" if !replacement_line
|
39
42
|
input_array = eval_string.each_line.to_a
|
@@ -77,20 +80,20 @@ class Pry
|
|
77
80
|
|
78
81
|
if opts.m?
|
79
82
|
meth_name = opts[:m]
|
80
|
-
|
81
|
-
|
82
|
-
next
|
83
|
-
end
|
84
|
-
code, _ = code_and_code_type_for(meth)
|
85
|
-
next if !code
|
83
|
+
meth = get_method_or_raise(meth_name, target, {}, :omit_help)
|
84
|
+
next unless meth.source
|
86
85
|
|
87
86
|
range = opts.l? ? one_index_range_or_number(opts[:l]) : (0..-1)
|
88
87
|
range = (0..-2) if opts.o?
|
89
88
|
|
90
|
-
eval_string << Array(
|
89
|
+
eval_string << Array(meth.source.each_line.to_a[range]).join
|
91
90
|
elsif opts.f?
|
92
91
|
file_name = File.expand_path(opts[:f])
|
93
|
-
|
92
|
+
|
93
|
+
if !File.exists?(file_name)
|
94
|
+
raise CommandError, "No such file: #{opts[:f]}"
|
95
|
+
end
|
96
|
+
|
94
97
|
text_array = File.readlines(file_name)
|
95
98
|
range = opts.l? ? one_index_range_or_number(opts[:l]) : (0..-1)
|
96
99
|
range = (0..-2) if opts.o?
|
@@ -98,7 +101,10 @@ class Pry
|
|
98
101
|
_pry_.input_stack << _pry_.input
|
99
102
|
_pry_.input = StringIO.new(Array(text_array[range]).join)
|
100
103
|
else
|
101
|
-
|
104
|
+
if !args.first
|
105
|
+
raise CommandError, "No input to play command."
|
106
|
+
end
|
107
|
+
|
102
108
|
code = target.eval(args.first)
|
103
109
|
|
104
110
|
range = opts.l? ? one_index_range_or_number(opts[:l]) : (0..-1)
|
@@ -242,7 +248,11 @@ class Pry
|
|
242
248
|
case opts["save"]
|
243
249
|
when Range
|
244
250
|
hist_array = Array(history[opts["save"]])
|
245
|
-
|
251
|
+
|
252
|
+
if !args.first
|
253
|
+
raise CommandError, "Must provide a file name."
|
254
|
+
end
|
255
|
+
|
246
256
|
file_name = File.expand_path(args.first)
|
247
257
|
when String
|
248
258
|
hist_array = history
|
@@ -5,59 +5,40 @@ class Pry
|
|
5
5
|
|
6
6
|
Introspection = Pry::CommandSet.new do
|
7
7
|
|
8
|
-
command "show-method", "Show the source for METH. Type `show-method --help` for more info. Aliases: $, show-source" do |*args|
|
9
|
-
|
10
|
-
|
11
|
-
opts = Slop.parse!(args) do |opt|
|
8
|
+
command "show-method", "Show the source for METH. Type `show-method --help` for more info. Aliases: $, show-source", :shellwords => false do |*args|
|
9
|
+
opts, meth = parse_options!(args, :method_object) do |opt|
|
12
10
|
opt.banner unindent <<-USAGE
|
13
|
-
Usage: show-method [OPTIONS] [METH
|
11
|
+
Usage: show-method [OPTIONS] [METH]
|
14
12
|
Show the source for method METH. Tries instance methods first and then methods by default.
|
15
13
|
e.g: show-method hello_method
|
16
14
|
USAGE
|
17
15
|
|
18
16
|
opt.on :l, "line-numbers", "Show line numbers."
|
19
17
|
opt.on :b, "base-one", "Show line numbers but start numbering at 1 (useful for `amend-line` and `play` commands)."
|
20
|
-
|
21
|
-
opt.on :M, "instance-methods", "Operate on instance methods."
|
22
|
-
opt.on :m, :methods, "Operate on methods."
|
23
18
|
opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
|
24
|
-
opt.on :c, :context, "Select object context to run under.", true do |context|
|
25
|
-
target = Pry.binding_for(target.eval(context))
|
26
|
-
end
|
27
|
-
opt.on :h, :help, "This message." do
|
28
|
-
output.puts opt
|
29
|
-
end
|
30
19
|
end
|
31
20
|
|
32
|
-
|
33
|
-
|
34
|
-
args = [nil] if args.empty?
|
35
|
-
args.each do |method_name|
|
36
|
-
meth_name = method_name
|
37
|
-
if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
|
38
|
-
output.puts "Invalid method name: #{meth_name}. Type `show-method --help` for help"
|
39
|
-
next
|
40
|
-
end
|
21
|
+
raise CommandError, "Could not find method source" unless meth.source
|
41
22
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
if Pry.color
|
47
|
-
code = CodeRay.scan(code, code_type).term
|
48
|
-
end
|
49
|
-
|
50
|
-
start_line = false
|
51
|
-
if opts.l?
|
52
|
-
start_line = meth.source_location ? meth.source_location.last : 1
|
53
|
-
end
|
54
|
-
|
55
|
-
start_line = opts.b? ? 1 : start_line
|
23
|
+
output.puts make_header(meth)
|
24
|
+
output.puts "#{text.bold("Owner:")} #{meth.owner || "N/A"}"
|
25
|
+
output.puts "#{text.bold("Visibility:")} #{meth.visibility}"
|
26
|
+
output.puts
|
56
27
|
|
28
|
+
if Pry.color
|
29
|
+
code = CodeRay.scan(meth.source, meth.source_type).term
|
30
|
+
else
|
31
|
+
code = meth.source
|
32
|
+
end
|
57
33
|
|
58
|
-
|
59
|
-
|
34
|
+
start_line = false
|
35
|
+
if opts.b?
|
36
|
+
start_line = 1
|
37
|
+
elsif opts.l?
|
38
|
+
start_line = meth.source_line || 1
|
60
39
|
end
|
40
|
+
|
41
|
+
render_output(opts.flood?, start_line, code)
|
61
42
|
end
|
62
43
|
|
63
44
|
alias_command "show-source", "show-method"
|
@@ -84,31 +65,33 @@ class Pry
|
|
84
65
|
|
85
66
|
command_name = args.shift
|
86
67
|
if !command_name
|
87
|
-
|
88
|
-
next
|
68
|
+
raise CommandError, "You must provide a command name."
|
89
69
|
end
|
90
70
|
|
91
71
|
if find_command(command_name)
|
92
|
-
block = find_command(command_name).block
|
72
|
+
block = Pry::Method.new(find_command(command_name).block)
|
93
73
|
|
94
|
-
|
95
|
-
|
74
|
+
next unless block.source
|
75
|
+
set_file_and_dir_locals(block.source_file)
|
96
76
|
|
97
|
-
output.puts make_header(block
|
77
|
+
output.puts make_header(block)
|
78
|
+
output.puts
|
98
79
|
|
99
80
|
if Pry.color
|
100
|
-
code = CodeRay.scan(
|
81
|
+
code = CodeRay.scan(block.source, :ruby).term
|
82
|
+
else
|
83
|
+
code = block.source
|
101
84
|
end
|
102
85
|
|
103
86
|
start_line = false
|
104
87
|
if opts.l?
|
105
|
-
start_line = block.
|
88
|
+
start_line = block.source_line || 1
|
106
89
|
end
|
107
90
|
|
108
|
-
render_output(opts.flood?, opts.l? ? block.
|
91
|
+
render_output(opts.flood?, opts.l? ? block.source_line : false, code)
|
109
92
|
code
|
110
93
|
else
|
111
|
-
|
94
|
+
raise CommandError, "No such command: #{command_name}."
|
112
95
|
end
|
113
96
|
end
|
114
97
|
|
@@ -133,8 +116,8 @@ class Pry
|
|
133
116
|
end
|
134
117
|
next if opts.h?
|
135
118
|
|
136
|
-
if [opts.ex?, opts.t?, opts.
|
137
|
-
|
119
|
+
if [opts.ex?, opts.t?, opts.i?, !args.empty?].count(true) > 1
|
120
|
+
raise CommandError, "Only one of --ex, --temp, --in and FILE may be specified."
|
138
121
|
end
|
139
122
|
|
140
123
|
# edit of local code, eval'd within pry.
|
@@ -173,21 +156,29 @@ class Pry
|
|
173
156
|
# edit of remote code, eval'd at top-level
|
174
157
|
else
|
175
158
|
if opts.ex?
|
176
|
-
|
159
|
+
if _pry_.last_exception.nil?
|
160
|
+
raise CommandError, "No exception found."
|
161
|
+
end
|
162
|
+
|
177
163
|
ex = _pry_.last_exception
|
178
164
|
bt_index = opts[:ex].to_i
|
179
165
|
|
180
166
|
ex_file, ex_line = ex.bt_source_location_for(bt_index)
|
181
|
-
if ex_file &&
|
182
|
-
file_name =
|
167
|
+
if ex_file && RbxPath.is_core_path?(ex_file)
|
168
|
+
file_name = RbxPath.convert_path_to_full(ex_file)
|
183
169
|
else
|
184
170
|
file_name = ex_file
|
185
171
|
end
|
186
172
|
|
187
173
|
line = ex_line
|
188
|
-
next output.puts "Exception has no associated file." if file_name.nil?
|
189
|
-
next output.puts "Cannot edit exceptions raised in REPL." if Pry.eval_path == file_name
|
190
174
|
|
175
|
+
if file_name.nil?
|
176
|
+
raise CommandError, "Exception has no associated file."
|
177
|
+
end
|
178
|
+
|
179
|
+
if Pry.eval_path == file_name
|
180
|
+
raise CommandError, "Cannot edit exceptions raised in REPL."
|
181
|
+
end
|
191
182
|
else
|
192
183
|
# break up into file:line
|
193
184
|
file_name = File.expand_path(args.first)
|
@@ -208,10 +199,10 @@ class Pry
|
|
208
199
|
end
|
209
200
|
end
|
210
201
|
|
211
|
-
command "edit-method", "Edit a method. Type `edit-method --help` for more info." do |*args|
|
202
|
+
command "edit-method", "Edit a method. Type `edit-method --help` for more info.", :shellwords => false do |*args|
|
212
203
|
target = target()
|
213
204
|
|
214
|
-
opts =
|
205
|
+
opts, meth = parse_options!(args, :method_object) do |opt|
|
215
206
|
opt.banner unindent <<-USAGE
|
216
207
|
Usage: edit-method [OPTIONS] [METH]
|
217
208
|
Edit the method METH in an editor.
|
@@ -219,60 +210,49 @@ class Pry
|
|
219
210
|
e.g: edit-method hello_method
|
220
211
|
USAGE
|
221
212
|
|
222
|
-
opt.on :M, "instance-methods", "Operate on instance methods."
|
223
|
-
opt.on :m, :methods, "Operate on methods."
|
224
213
|
opt.on :n, "no-reload", "Do not automatically reload the method's file after editing."
|
225
214
|
opt.on "no-jump", "Do not fast forward editor to first line of method."
|
226
215
|
opt.on :p, :patch, "Instead of editing the method's file, try to edit in a tempfile and apply as a monkey patch."
|
227
|
-
opt.on :c, :context, "Select object context to run under.", true do |context|
|
228
|
-
target = Pry.binding_for(target.eval(context))
|
229
|
-
end
|
230
216
|
opt.on :h, :help, "This message." do
|
231
217
|
output.puts opt
|
232
218
|
end
|
233
219
|
end
|
234
220
|
|
235
|
-
next if opts.help?
|
236
|
-
|
237
221
|
if !Pry.config.editor
|
238
|
-
|
239
|
-
output.puts "Ensure that #{text.bold("Pry.config.editor")} is set to your editor of choice."
|
240
|
-
next
|
222
|
+
raise CommandError, "No editor set!\nEnsure that #{text.bold("Pry.config.editor")} is set to your editor of choice."
|
241
223
|
end
|
242
224
|
|
243
|
-
|
244
|
-
|
245
|
-
meth = get_method_object_from_target(meth_name, target, type)
|
225
|
+
if opts.p? || meth.dynamically_defined?
|
226
|
+
lines = meth.source.lines.to_a
|
246
227
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
end
|
251
|
-
|
252
|
-
if opts.p? || is_a_dynamically_defined_method?(meth)
|
253
|
-
code, _ = code_and_code_type_for(meth)
|
254
|
-
|
255
|
-
lines = code.lines.to_a
|
256
|
-
if lines[0] =~ /^def [^( \n]+/
|
257
|
-
lines[0] = "def #{meth_name}#{$'}"
|
228
|
+
if ((original_name = meth.original_name) &&
|
229
|
+
lines[0] =~ /^def (?:.*?\.)?#{original_name}(?=[\(\s;]|$)/)
|
230
|
+
lines[0] = "def #{original_name}#{$'}"
|
258
231
|
else
|
259
|
-
|
232
|
+
raise CommandError, "Pry can only patch methods created with the `def` keyword."
|
260
233
|
end
|
261
234
|
|
262
235
|
temp_file do |f|
|
263
236
|
f.puts lines.join
|
264
237
|
f.flush
|
265
238
|
invoke_editor(f.path, 0)
|
266
|
-
|
239
|
+
|
240
|
+
if meth.alias?
|
241
|
+
with_method_transaction(original_name, meth.owner) do
|
242
|
+
Pry.new(:input => StringIO.new(File.read(f.path))).rep(meth.owner)
|
243
|
+
Pry.binding_for(meth.owner).eval("alias #{meth.name} #{original_name}")
|
244
|
+
end
|
245
|
+
else
|
246
|
+
Pry.new(:input => StringIO.new(File.read(f.path))).rep(meth.owner)
|
247
|
+
end
|
267
248
|
end
|
268
249
|
next
|
269
250
|
end
|
270
251
|
|
271
|
-
if
|
272
|
-
|
252
|
+
if meth.source_type == :c
|
253
|
+
raise CommandError, "Can't edit a C method."
|
273
254
|
else
|
274
|
-
file, line =
|
275
|
-
set_file_and_dir_locals(file)
|
255
|
+
file, line = meth.source_file, meth.source_line
|
276
256
|
|
277
257
|
invoke_editor(file, opts["no-jump"] ? 0 : line)
|
278
258
|
silence_warnings do
|
@@ -281,6 +261,17 @@ class Pry
|
|
281
261
|
end
|
282
262
|
end
|
283
263
|
|
264
|
+
helpers do
|
265
|
+
def with_method_transaction(meth_name, target=TOPLEVEL_BINDING)
|
266
|
+
target = Pry.binding_for(target)
|
267
|
+
temp_name = "__pry_#{meth_name}__"
|
268
|
+
|
269
|
+
target.eval("alias #{temp_name} #{meth_name}")
|
270
|
+
yield
|
271
|
+
target.eval("alias #{meth_name} #{temp_name}")
|
272
|
+
target.eval("undef #{temp_name}")
|
273
|
+
end
|
274
|
+
end
|
284
275
|
end
|
285
276
|
end
|
286
277
|
end
|