pry 0.9.6.2 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.gitignore +6 -0
  2. data/CHANGELOG +19 -1
  3. data/CONTRIBUTORS +22 -16
  4. data/Rakefile +12 -6
  5. data/bin/pry +15 -12
  6. data/lib/pry.rb +39 -28
  7. data/lib/pry/command_context.rb +1 -0
  8. data/lib/pry/command_processor.rb +9 -2
  9. data/lib/pry/command_set.rb +7 -0
  10. data/lib/pry/config.rb +8 -0
  11. data/lib/pry/default_commands/basic.rb +7 -10
  12. data/lib/pry/default_commands/context.rb +36 -26
  13. data/lib/pry/default_commands/documentation.rb +31 -123
  14. data/lib/pry/default_commands/gems.rb +9 -4
  15. data/lib/pry/default_commands/input.rb +21 -11
  16. data/lib/pry/default_commands/introspection.rb +79 -88
  17. data/lib/pry/default_commands/ls.rb +165 -176
  18. data/lib/pry/default_commands/shell.rb +8 -8
  19. data/lib/pry/extended_commands/experimental.rb +1 -5
  20. data/lib/pry/extended_commands/user_command_api.rb +17 -5
  21. data/lib/pry/helpers.rb +1 -0
  22. data/lib/pry/helpers/base_helpers.rb +5 -1
  23. data/lib/pry/helpers/command_helpers.rb +22 -241
  24. data/lib/pry/helpers/options_helpers.rb +58 -0
  25. data/lib/pry/helpers/text.rb +10 -4
  26. data/lib/pry/history.rb +1 -1
  27. data/lib/pry/indent.rb +205 -0
  28. data/lib/pry/method.rb +412 -0
  29. data/lib/pry/pry_class.rb +56 -15
  30. data/lib/pry/pry_instance.rb +63 -16
  31. data/lib/pry/rbx_method.rb +20 -0
  32. data/lib/pry/rbx_path.rb +34 -0
  33. data/lib/pry/version.rb +1 -1
  34. data/pry.gemspec +16 -16
  35. data/test/helper.rb +8 -4
  36. data/test/test_command_helpers.rb +1 -69
  37. data/test/test_command_set.rb +29 -28
  38. data/test/test_default_commands/test_documentation.rb +23 -10
  39. data/test/test_default_commands/test_introspection.rb +58 -13
  40. data/test/test_default_commands/test_ls.rb +148 -0
  41. data/test/test_indent.rb +234 -0
  42. data/test/test_input_stack.rb +13 -0
  43. data/test/test_method.rb +291 -0
  44. data/test/test_pry.rb +10 -1
  45. metadata +82 -65
@@ -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
- target = target()
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 1] [METH 2] [METH N]
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
- next if opts.help?
21
+ raise Pry::CommandError, "No documentation found." if meth.doc.nil? || meth.doc.empty?
32
22
 
33
- args = [nil] if args.empty?
34
- args.each do |method_name|
35
- meth_name = method_name
36
- if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
37
- output.puts "Invalid method name: #{meth_name}. Type `show-doc --help` for help"
38
- next
39
- end
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 = Slop.parse!(args) do |opt|
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 "Method Information:"
90
- output.puts "--"
91
- output.puts "Name: " + meth_name
92
- output.puts "Owner: " + (meth.owner.to_s ? meth.owner.to_s : "Unknown")
93
- output.puts "Visibility: " + method_visibility(meth).to_s
94
- output.puts "Type: " + (meth.is_a?(Method) ? "Bound" : "Unbound")
95
- output.puts "Arity: " + meth.arity.to_s
96
- output.puts "Method Signature: " + signature_for(meth)
97
-
98
- output.puts "Source location: " + (meth.source_location ? meth.source_location.join(":") : "Not found.")
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 = Slop.parse!(args) do |opt|
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, code_type = code_and_code_type_for(meth)
78
+ content = meth.source
79
+ code_type = meth.source_type
136
80
  else
137
- content, code_type = doc_and_code_type_for(meth)
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
- output.puts "Insufficient permissions to install `#{text.green gem}`"
13
+ raise CommandError, "Insufficient permissions to install `#{text.green gem}`."
13
14
  rescue Gem::GemNotFoundException
14
- output.puts "Gem `#{text.green gem}` not found."
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
- spec ? Dir.chdir(spec.full_gem_path) : output.puts("Gem `#{gem}` not found.")
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.white gem} (#{versions.join ', '})"
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
- next output.puts "No input to amend." if eval_string.empty?
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
- if (meth = get_method_object(meth_name, target, {})).nil?
81
- output.puts "Invalid method name: #{meth_name}."
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(code.each_line.to_a[range]).join
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
- next output.puts "No such file: #{opts[:f]}" if !File.exists?(file_name)
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
- next output.puts "Error: no input to play command" if !args.first
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
- next output.puts "Must provide a file name." if !args.first
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
- target = target()
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 1] [METH 2] [METH N]
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
- next if opts.help?
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
- code, code_type = code_and_code_type_for(meth)
43
- next if !code
44
-
45
- output.puts make_header(meth, code_type, code)
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
- render_output(opts.flood?, start_line, code)
59
- code
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
- output.puts "You must provide a command name."
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
- code, _ = code_and_code_type_for(block)
95
- next if !code
74
+ next unless block.source
75
+ set_file_and_dir_locals(block.source_file)
96
76
 
97
- output.puts make_header(block, :ruby, code)
77
+ output.puts make_header(block)
78
+ output.puts
98
79
 
99
80
  if Pry.color
100
- code = CodeRay.scan(code, :ruby).term
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.source_location ? block.source_location.last : 1
88
+ start_line = block.source_line || 1
106
89
  end
107
90
 
108
- render_output(opts.flood?, opts.l? ? block.source_location.last : false, code)
91
+ render_output(opts.flood?, opts.l? ? block.source_line : false, code)
109
92
  code
110
93
  else
111
- output.puts "No such command: #{command_name}."
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.in?, !args.empty?].count(true) > 1
137
- next output.puts "Only one of --ex, --temp, --in and FILE may be specified"
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
- next output.puts "No Exception found." if _pry_.last_exception.nil?
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 && is_core_rbx_path?(ex_file)
182
- file_name = rbx_convert_path_to_full(ex_file)
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 = Slop.parse!(args) do |opt|
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
- output.puts "Error: No editor set!"
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
- meth_name = args.shift
244
- meth_name, target, type = get_method_attributes(meth_name, target, opts.to_hash(true))
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
- if meth.nil?
248
- output.puts "Invalid method name: #{meth_name}."
249
- next
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
- next output.puts "Error: Pry can only patch methods created with the `def` keyword."
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
- Pry.new(:input => StringIO.new(File.read(f.path))).rep(meth.owner)
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 is_a_c_method?(meth)
272
- output.puts "Error: Can't edit a C method."
252
+ if meth.source_type == :c
253
+ raise CommandError, "Can't edit a C method."
273
254
  else
274
- file, line = path_line_for(meth)
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