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.
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 +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
- 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