pry 0.9.8.2-i386-mingw32 → 0.9.8.3-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 (38) hide show
  1. data/CHANGELOG +8 -0
  2. data/README.markdown +20 -13
  3. data/Rakefile +1 -1
  4. data/lib/pry.rb +1 -2
  5. data/lib/pry/command.rb +88 -2
  6. data/lib/pry/command_set.rb +15 -85
  7. data/lib/pry/commands.rb +12 -8
  8. data/lib/pry/default_commands/cd.rb +58 -0
  9. data/lib/pry/default_commands/commands.rb +62 -0
  10. data/lib/pry/default_commands/context.rb +48 -165
  11. data/lib/pry/default_commands/editing.rb +385 -0
  12. data/lib/pry/default_commands/help.rb +127 -0
  13. data/lib/pry/default_commands/hist.rb +116 -0
  14. data/lib/pry/default_commands/{shell.rb → input_and_output.rb} +137 -15
  15. data/lib/pry/default_commands/introspection.rb +79 -232
  16. data/lib/pry/default_commands/ls.rb +4 -2
  17. data/lib/pry/default_commands/{basic.rb → misc.rb} +1 -14
  18. data/lib/pry/default_commands/navigating_pry.rb +114 -0
  19. data/lib/pry/helpers/base_helpers.rb +15 -3
  20. data/lib/pry/helpers/command_helpers.rb +16 -0
  21. data/lib/pry/history.rb +12 -4
  22. data/lib/pry/method.rb +2 -2
  23. data/lib/pry/pry_class.rb +7 -1
  24. data/lib/pry/pry_instance.rb +6 -0
  25. data/lib/pry/rbx_path.rb +6 -18
  26. data/lib/pry/version.rb +1 -1
  27. data/pry.gemspec +8 -8
  28. data/test/helper.rb +8 -0
  29. data/test/test_command.rb +256 -2
  30. data/test/test_command_integration.rb +2 -13
  31. data/test/test_command_set.rb +13 -23
  32. data/test/test_default_commands/test_help.rb +57 -0
  33. data/test/test_default_commands/test_introspection.rb +23 -0
  34. data/test/test_pry.rb +11 -0
  35. metadata +13 -9
  36. data/lib/pry/default_commands/documentation.rb +0 -209
  37. data/lib/pry/default_commands/input.rb +0 -247
  38. data/test/test_default_commands.rb +0 -58
@@ -0,0 +1,127 @@
1
+ class Pry
2
+ module DefaultCommands
3
+ Help = Pry::CommandSet.new do
4
+ create_command "help" do |cmd|
5
+ description "Show a list of commands. Type `help <foo>` for information about <foo>."
6
+
7
+ banner <<-BANNER
8
+ Usage: help [ COMMAND ]
9
+
10
+ With no arguments, help lists all the available commands in the current
11
+ command-set along with their description.
12
+
13
+ When given a command name as an argument, shows the help for that command.
14
+ BANNER
15
+
16
+ # We only want to show commands that have descriptions, so that the
17
+ # easter eggs don't show up.
18
+ def visible_commands
19
+ visible = {}
20
+ commands.each do |key, command|
21
+ visible[key] = command if command.description && !command.description.empty?
22
+ end
23
+ visible
24
+ end
25
+
26
+ # Get a hash of available commands grouped by the "group" name.
27
+ def command_groups
28
+ visible_commands.values.group_by(&:group)
29
+ end
30
+
31
+ def process
32
+ if args.empty?
33
+ display_index(command_groups)
34
+ else
35
+ display_search(args.first)
36
+ end
37
+ end
38
+
39
+ # Display the index view, with headings and short descriptions per command.
40
+ #
41
+ # @param Hash[String => Array[Commands]]
42
+ def display_index(groups)
43
+ help_text = []
44
+
45
+ groups.keys.sort_by(&method(:group_sort_key)).each do |key|
46
+ commands = groups[key].sort_by{ |command| command.options[:listing].to_s }
47
+
48
+ unless commands.empty?
49
+ help_text << "#{text.bold(key)}\n" + commands.map do |command|
50
+ " #{command.options[:listing].to_s.ljust(18)} #{command.description}"
51
+ end.join("\n")
52
+ end
53
+ end
54
+
55
+ stagger_output(help_text.join("\n\n"))
56
+ end
57
+
58
+ # Display help for an individual command or group.
59
+ #
60
+ # @param String The string to search for.
61
+ def display_search(search)
62
+ if command = command_set.find_command_for_help(search)
63
+ display_command(command)
64
+ else
65
+ groups = search_hash(search, command_groups)
66
+
67
+ if groups.size > 0
68
+ display_index(groups)
69
+ return
70
+ end
71
+
72
+ filtered = search_hash(search, visible_commands)
73
+ raise CommandError, "No help found for '#{args.first}'" if filtered.empty?
74
+
75
+ if filtered.size == 1
76
+ display_command(filtered.values.first)
77
+ else
78
+ display_index({"'#{search}' commands" => filtered.values})
79
+ end
80
+ end
81
+ end
82
+
83
+ # Display help for an individual command.
84
+ #
85
+ # @param [Pry::Command]
86
+ def display_command(command)
87
+ stagger_output command.new.help
88
+ end
89
+
90
+ # Find a subset of a hash that matches the user's search term.
91
+ #
92
+ # If there's an exact match a Hash of one element will be returned,
93
+ # otherwise a sub-Hash with every key that matches the search will
94
+ # be returned.
95
+ #
96
+ # @param [String] the search term
97
+ # @param [Hash] the hash to search
98
+ def search_hash(search, hash)
99
+ matching = {}
100
+
101
+ hash.each_pair do |key, value|
102
+ next unless key.is_a?(String)
103
+ if normalize(key) == normalize(search)
104
+ return {key => value}
105
+ elsif normalize(key).start_with?(normalize(search))
106
+ matching[key] = value
107
+ end
108
+ end
109
+
110
+ matching
111
+ end
112
+
113
+ # Clean search terms to make it easier to search group names
114
+ #
115
+ # @param String
116
+ # @return String
117
+ def normalize(key)
118
+ key.downcase.gsub(/pry\W+/, '')
119
+ end
120
+
121
+ def group_sort_key(group_name)
122
+ [%w(Help Context Editing Introspection Input_and_output Navigating_pry Gems Basic Commands).index(group_name.gsub(' ', '_')) || 99, group_name]
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,116 @@
1
+ class Pry
2
+ module DefaultCommands
3
+ Hist = Pry::CommandSet.new do
4
+
5
+ create_command "hist", "Show and replay Readline history. Aliases: history" do
6
+ group "Editing"
7
+ banner <<-USAGE
8
+ Usage: hist
9
+ hist --head N
10
+ hist --tail N
11
+ hist --show START..END
12
+ hist --grep PATTERN
13
+ hist --clear
14
+ hist --replay START..END
15
+ hist --save [START..END] FILE
16
+ USAGE
17
+
18
+ def options(opt)
19
+ opt.on :H, :head, "Display the first N items.", :optional => true, :as => Integer
20
+ opt.on :T, :tail, "Display the last N items.", :optional => true, :as => Integer
21
+ opt.on :s, :show, "Show the given range of lines.", :optional => true, :as => Range
22
+ opt.on :G, :grep, "Show lines matching the given pattern.", true, :as => String
23
+ opt.on :c, :clear, "Clear the current session's history."
24
+ opt.on :r, :replay, "Replay a line or range of lines.", true, :as => Range
25
+ opt.on :save, "Save history to a file.", true, :as => Range
26
+
27
+ opt.on :e, :'exclude-pry', "Exclude Pry commands from the history."
28
+ opt.on :n, :'no-numbers', "Omit line numbers."
29
+ opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
30
+ end
31
+
32
+ def process
33
+ @history = Pry::Code(Pry.history.to_a)
34
+
35
+ @history = case
36
+ when opts.present?(:head)
37
+ @history.between(1, opts[:head] || 10)
38
+ when opts.present?(:tail)
39
+ @history.between(-(opts[:tail] || 10), -1)
40
+ when opts.present?(:show)
41
+ @history.between(opts[:show])
42
+ else
43
+ @history
44
+ end
45
+
46
+ if opts.present?(:grep)
47
+ @history = @history.grep(opts[:grep])
48
+ end
49
+
50
+ if opts.present?(:'exclude-pry')
51
+ @history = @history.select { |l, ln| !command_set.valid_command?(l) }
52
+ end
53
+
54
+ if opts.present?(:save)
55
+ process_save
56
+ elsif opts.present?(:clear)
57
+ process_clear
58
+ elsif opts.present?(:replay)
59
+ process_replay
60
+ else
61
+ process_display
62
+ end
63
+ end
64
+
65
+ def process_display
66
+ unless opts.present?(:'no-numbers')
67
+ @history = @history.with_line_numbers
68
+ end
69
+
70
+ render_output(@history, opts)
71
+ end
72
+
73
+ def process_save
74
+ case opts[:save]
75
+ when Range
76
+ @history = @history.between(opts[:save])
77
+
78
+ unless args.first
79
+ raise CommandError, "Must provide a file name."
80
+ end
81
+
82
+ file_name = File.expand_path(args.first)
83
+ when String
84
+ file_name = File.expand_path(opts[:save])
85
+ end
86
+
87
+ output.puts "Saving history in #{file_name}..."
88
+
89
+ File.open(file_name, 'w') { |f| f.write(@history.to_s) }
90
+
91
+ output.puts "History saved."
92
+ end
93
+
94
+ def process_clear
95
+ Pry.history.clear
96
+ output.puts "History cleared."
97
+ end
98
+
99
+ def process_replay
100
+ @history = @history.between(opts[:r])
101
+
102
+ _pry_.input_stack.push _pry_.input
103
+ _pry_.input = StringIO.new(@history.raw)
104
+ # eval_string << "#{@history.raw}\n"
105
+ # run "show-input" unless _pry_.complete_expression?(eval_string)
106
+ end
107
+ end
108
+
109
+ alias_command "history", "hist"
110
+
111
+
112
+
113
+
114
+ end
115
+ end
116
+ end
@@ -1,9 +1,10 @@
1
+ require 'tempfile'
2
+
1
3
  class Pry
2
4
  module DefaultCommands
3
5
 
4
- Shell = Pry::CommandSet.new do
5
-
6
- command(/\.(.*)/, "All text following a '.' is forwarded to the shell.", :listing => ".<shell command>", :use_prefix => false) do |cmd|
6
+ InputAndOutput = Pry::CommandSet.new do
7
+ command(/\.(.*)/, "All text following a '.' is forwarded to the shell.", :listing => ".<shell command>", :use_prefix => false, :takes_block => true) do |cmd|
7
8
  if cmd =~ /^cd\s+(.+)/i
8
9
  dest = $1
9
10
  begin
@@ -12,7 +13,13 @@ class Pry
12
13
  raise CommandError, "No such directory: #{dest}"
13
14
  end
14
15
  else
15
- Pry.config.system.call(output, cmd, _pry_)
16
+ pass_block(cmd)
17
+
18
+ if command_block
19
+ command_block.call `#{cmd}`
20
+ else
21
+ Pry.config.system.call(output, cmd, _pry_)
22
+ end
16
23
  end
17
24
  end
18
25
 
@@ -30,6 +37,122 @@ class Pry
30
37
  end
31
38
  alias_command "file-mode", "shell-mode"
32
39
 
40
+ create_command "gist", "Gist a method or expression history to github.", :requires_gem => "gist", :shellwords => false do
41
+ banner <<-USAGE
42
+ Usage: gist [OPTIONS] [METH]
43
+ Gist method (doc or source) or input expression to github.
44
+ Ensure the `gist` gem is properly working before use. http://github.com/defunkt/gist for instructions.
45
+ e.g: gist -m my_method
46
+ e.g: gist -d my_method
47
+ e.g: gist -i 1..10
48
+ e.g: gist -c show-method
49
+ e.g: gist -m hello_world --lines 2..-2
50
+ USAGE
51
+
52
+ attr_accessor :content
53
+ attr_accessor :code_type
54
+
55
+ def setup
56
+ require 'gist'
57
+ self.content = ""
58
+ self.code_type = :ruby
59
+ end
60
+
61
+ def options(opt)
62
+ opt.on :m, :method, "Gist a method's source.", true do |meth_name|
63
+ meth = get_method_or_raise(meth_name, target, {})
64
+ self.content << meth.source
65
+ self.code_type = meth.source_type
66
+ end
67
+ opt.on :d, :doc, "Gist a method's documentation.", true do |meth_name|
68
+ meth = get_method_or_raise(meth_name, target, {})
69
+ text.no_color do
70
+ self.content << process_comment_markup(meth.doc, self.code_type)
71
+ end
72
+ self.code_type = :plain
73
+ end
74
+ opt.on :c, :command, "Gist a command's source.", true do |command_name|
75
+ command = find_command(command_name)
76
+ block = Pry::Method.new(find_command(command_name).block)
77
+ self.content << block.source
78
+ end
79
+ opt.on :f, :file, "Gist a file.", true do |file|
80
+ self.content << File.read(File.expand_path(file))
81
+ end
82
+ opt.on :p, :public, "Create a public gist (default: false)", :default => false
83
+ opt.on :l, :lines, "Only gist a subset of lines.", :optional => true, :as => Range, :default => 1..-1
84
+ opt.on :i, :in, "Gist entries from Pry's input expression history. Takes an index or range.", :optional => true,
85
+ :as => Range, :default => -5..-1 do |range|
86
+ range = convert_to_range(range)
87
+ input_expressions = _pry_.input_array[range] || []
88
+ Array(input_expressions).each_with_index do |code, index|
89
+ corrected_index = index + range.first
90
+ if code && code != ""
91
+ self.content << code
92
+ if code !~ /;\Z/
93
+ self.content << "#{comment_expression_result_for_gist(Pry.config.gist.inspecter.call(_pry_.output_array[corrected_index]))}"
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ def process
101
+ perform_gist
102
+ end
103
+
104
+ def perform_gist
105
+ type_map = { :ruby => "rb", :c => "c", :plain => "plain" }
106
+
107
+ if self.content =~ /\A\s*\z/
108
+ raise CommandError, "Found no code to gist."
109
+ end
110
+
111
+ # prevent Gist from exiting the session on error
112
+ begin
113
+ extname = opts.present?(:file) ? ".#{gist_file_extension(opts[:f])}" : ".#{type_map[self.code_type]}"
114
+
115
+ if opts.present?(:lines)
116
+ self.content = restrict_to_lines(content, opts[:l])
117
+ end
118
+
119
+ link = Gist.write([:extension => extname,
120
+ :input => self.content],
121
+ !opts[:p])
122
+ rescue SystemExit
123
+ end
124
+
125
+ if link
126
+ Gist.copy(link)
127
+ output.puts "Gist created at #{link} and added to clipboard."
128
+ end
129
+ end
130
+
131
+ def gist_file_extension(file_name)
132
+ file_name.split(".").last
133
+ end
134
+
135
+ def convert_to_range(n)
136
+ if !n.is_a?(Range)
137
+ (n..n)
138
+ else
139
+ n
140
+ end
141
+ end
142
+
143
+ def comment_expression_result_for_gist(result)
144
+ content = ""
145
+ result.lines.each_with_index do |line, index|
146
+ if index == 0
147
+ content << "# => #{line}"
148
+ else
149
+ content << "# #{line}"
150
+ end
151
+ end
152
+ content
153
+ end
154
+ end
155
+
33
156
  create_command "save-file", "Export to a file using content from the REPL." do
34
157
  banner <<-USAGE
35
158
  Usage: save-file [OPTIONS] [FILE]
@@ -130,13 +253,13 @@ class Pry
130
253
 
131
254
  def process
132
255
  handler = case
133
- when opts.present?(:ex)
134
- method :process_ex
135
- when opts.present?(:in)
136
- method :process_in
137
- else
138
- method :process_file
139
- end
256
+ when opts.present?(:ex)
257
+ method :process_ex
258
+ when opts.present?(:in)
259
+ method :process_in
260
+ else
261
+ method :process_file
262
+ end
140
263
 
141
264
  output = handler.call do |code|
142
265
  code.code_type = opts[:type] || :ruby
@@ -183,8 +306,8 @@ class Pry
183
306
  HEADER
184
307
 
185
308
  code = yield(Pry::Code.from_file(ex_file).
186
- between(start_line, end_line).
187
- with_marker(ex_line))
309
+ between(start_line, end_line).
310
+ with_marker(ex_line))
188
311
 
189
312
  "#{header}#{code}"
190
313
  end
@@ -233,8 +356,7 @@ class Pry
233
356
  code
234
357
  end
235
358
  end
236
- end
237
359
 
360
+ end
238
361
  end
239
362
  end
240
-
@@ -5,8 +5,80 @@ class Pry
5
5
 
6
6
  Introspection = Pry::CommandSet.new do
7
7
 
8
+ create_command "show-doc", "Show the comments above METH. Aliases: \?", :shellwords => false do |*args|
9
+ banner <<-BANNER
10
+ Usage: show-doc [OPTIONS] [METH]
11
+ Show the comments above method METH. Tries instance methods first and then methods by default.
12
+ e.g show-doc hello_method
13
+ BANNER
14
+
15
+ def options(opt)
16
+ method_options(opt)
17
+ opt.on :l, "line-numbers", "Show line numbers."
18
+ opt.on :b, "base-one", "Show line numbers but start numbering at 1 (useful for `amend-line` and `play` commands)."
19
+ opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
20
+ end
21
+
22
+ def process
23
+ meth = method_object
24
+ raise Pry::CommandError, "No documentation found." if meth.doc.nil? || meth.doc.empty?
25
+
26
+ doc = process_comment_markup(meth.doc, meth.source_type)
27
+ output.puts make_header(meth, doc)
28
+ output.puts "#{text.bold("Owner:")} #{meth.owner || "N/A"}"
29
+ output.puts "#{text.bold("Visibility:")} #{meth.visibility}"
30
+ output.puts "#{text.bold("Signature:")} #{meth.signature}"
31
+ output.puts
32
+
33
+ if opts.present?(:b) || opts.present?(:l)
34
+ doc = Code.new(doc, start_line, :text).
35
+ with_line_numbers(true)
36
+ end
37
+
38
+ render_output(doc, opts)
39
+ end
40
+
41
+ def start_line
42
+ if opts.present?(:'base-one')
43
+ 1
44
+ else
45
+ (method_object.source_line - method_object.doc.lines.count) || 1
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ alias_command "?", "show-doc"
52
+
53
+ create_command "stat", "View method information and set _file_ and _dir_ locals.", :shellwords => false do |*args|
54
+ banner <<-BANNER
55
+ Usage: stat [OPTIONS] [METH]
56
+ Show method information for method METH and set _file_ and _dir_ locals.
57
+ e.g: stat hello_method
58
+ BANNER
59
+
60
+ def options(opt)
61
+ method_options(opt)
62
+ end
63
+
64
+ def process
65
+ meth = method_object
66
+ output.puts unindent <<-EOS
67
+ Method Information:
68
+ --
69
+ Name: #{meth.name}
70
+ Owner: #{meth.owner ? meth.owner : "Unknown"}
71
+ Visibility: #{meth.visibility}
72
+ Type: #{meth.is_a?(::Method) ? "Bound" : "Unbound"}
73
+ Arity: #{meth.arity}
74
+ Method Signature: #{meth.signature}
75
+ Source Location: #{meth.source_location ? meth.source_location.join(":") : "Not found."}
76
+ EOS
77
+ end
78
+ end
79
+
8
80
  create_command "show-method" do
9
- description "Show the source for METH. Type `show-method --help` for more info. Aliases: $, show-source"
81
+ description "Show the source for METH. Aliases: $, show-source"
10
82
 
11
83
  banner <<-BANNER
12
84
  Usage: show-method [OPTIONS] [METH]
@@ -62,7 +134,7 @@ class Pry
62
134
  alias_command "show-source", "show-method"
63
135
  alias_command "$", "show-method"
64
136
 
65
- command "show-command", "Show the source for CMD. Type `show-command --help` for more info." do |*args|
137
+ command "show-command", "Show the source for CMD." do |*args|
66
138
  target = target()
67
139
 
68
140
  opts = Slop.parse!(args) do |opt|
@@ -103,244 +175,19 @@ class Pry
103
175
  end
104
176
  end
105
177
 
106
- create_command "edit" do
107
- description "Invoke the default editor on a file. Type `edit --help` for more info"
108
-
178
+ create_command "ri", "View ri documentation. e.g `ri Array#each`" do
109
179
  banner <<-BANNER
110
- Usage: edit [--no-reload|--reload] [--line LINE] [--temp|--ex|FILE[:LINE]|--in N]
111
-
112
- Open a text editor. When no FILE is given, edits the pry input buffer.
113
- Ensure Pry.config.editor is set to your editor of choice.
114
-
115
- e.g: `edit sample.rb`
116
- e.g: `edit sample.rb --line 105`
117
- e.g: `edit --ex`
180
+ Usage: ri [spec]
181
+ e.g. ri Array#each
118
182
 
119
- https://github.com/pry/pry/wiki/Editor-integration#wiki-Edit_command
183
+ Relies on the ri executable being available. See also: show-doc.
120
184
  BANNER
121
185
 
122
- def options(opt)
123
- opt.on :e, :ex, "Open the file that raised the most recent exception (_ex_.file)", :optional => true, :as => Integer
124
- opt.on :i, :in, "Open a temporary file containing the Nth line of _in_. N may be a range.", :optional => true, :as => Range, :default => -1..-1
125
- opt.on :t, :temp, "Open an empty temporary file"
126
- opt.on :l, :line, "Jump to this line in the opened file", true, :as => Integer
127
- opt.on :n, :"no-reload", "Don't automatically reload the edited code"
128
- opt.on :c, :"current", "Open the current __FILE__ and at __LINE__ (as returned by `whereami`)."
129
- opt.on :r, :reload, "Reload the edited code immediately (default for ruby files)"
130
- end
131
-
132
186
  def process
133
- if [opts.present?(:ex), opts.present?(:temp), opts.present?(:in), !args.empty?].count(true) > 1
134
- raise CommandError, "Only one of --ex, --temp, --in and FILE may be specified."
135
- end
136
-
137
- if !opts.present?(:ex) && !opts.present?(:current) && args.empty?
138
- # edit of local code, eval'd within pry.
139
- process_local_edit
140
- else
141
- # edit of remote code, eval'd at top-level
142
- process_remote_edit
143
- end
144
- end
145
-
146
- def process_i
147
- case opts[:i]
148
- when Range
149
- (_pry_.input_array[opts[:i]] || []).join
150
- when Fixnum
151
- _pry_.input_array[opts[:i]] || ""
152
- else
153
- return output.puts "Not a valid range: #{opts[:i]}"
154
- end
155
- end
156
-
157
- def process_local_edit
158
- content = case
159
- when opts.present?(:temp)
160
- ""
161
- when opts.present?(:in)
162
- process_i
163
- when eval_string.strip != ""
164
- eval_string
165
- else
166
- _pry_.input_array.reverse_each.find{ |x| x && x.strip != "" } || ""
167
- end
168
-
169
- line = content.lines.count
170
-
171
- temp_file do |f|
172
- f.puts(content)
173
- f.flush
174
- invoke_editor(f.path, line)
175
- if !opts.present?(:'no-reload') && !Pry.config.disable_auto_reload
176
- silence_warnings do
177
- eval_string.replace(File.read(f.path))
178
- end
179
- end
180
- end
181
- end
182
-
183
- def process_remote_edit
184
- if opts.present?(:ex)
185
- if _pry_.last_exception.nil?
186
- raise CommandError, "No exception found."
187
- end
188
-
189
- ex = _pry_.last_exception
190
- bt_index = opts[:ex].to_i
191
-
192
- ex_file, ex_line = ex.bt_source_location_for(bt_index)
193
- if ex_file && RbxPath.is_core_path?(ex_file)
194
- file_name = RbxPath.convert_path_to_full(ex_file)
195
- else
196
- file_name = ex_file
197
- end
198
-
199
- line = ex_line
200
-
201
- if file_name.nil?
202
- raise CommandError, "Exception has no associated file."
203
- end
204
-
205
- if Pry.eval_path == file_name
206
- raise CommandError, "Cannot edit exceptions raised in REPL."
207
- end
208
- elsif opts.present?(:current)
209
- file_name = target.eval("__FILE__")
210
- line = target.eval("__LINE__")
211
- else
212
-
213
- # break up into file:line
214
- file_name = File.expand_path(args.first)
215
- line = file_name.sub!(/:(\d+)$/, "") ? $1.to_i : 1
216
- end
217
-
218
- if not_a_real_file?(file_name)
219
- raise CommandError, "#{file_name} is not a valid file name, cannot edit!"
220
- end
221
-
222
- line = opts[:l].to_i if opts.present?(:line)
223
-
224
- invoke_editor(file_name, line)
225
- set_file_and_dir_locals(file_name)
226
-
227
- if opts.present?(:reload) || ((opts.present?(:ex) || file_name.end_with?(".rb")) && !opts.present?(:'no-reload')) && !Pry.config.disable_auto_reload
228
- silence_warnings do
229
- TOPLEVEL_BINDING.eval(File.read(file_name), file_name)
230
- end
231
- end
187
+ run ".ri", *args
232
188
  end
233
189
  end
234
190
 
235
- create_command "edit-method" do
236
- description "Edit a method. Type `edit-method --help` for more info."
237
-
238
- banner <<-BANNER
239
- Usage: edit-method [OPTIONS] [METH]
240
-
241
- Edit the method METH in an editor.
242
- Ensure Pry.config.editor is set to your editor of choice.
243
-
244
- e.g: `edit-method hello_method`
245
- e.g: `edit-method Pry#rep`
246
- e.g: `edit-method`
247
-
248
- https://github.com/pry/pry/wiki/Editor-integration#wiki-Edit_method
249
- BANNER
250
-
251
- command_options :shellwords => false
252
-
253
- def options(opt)
254
- method_options(opt)
255
- opt.on :n, "no-reload", "Do not automatically reload the method's file after editing."
256
- opt.on "no-jump", "Do not fast forward editor to first line of method."
257
- opt.on :p, :patch, "Instead of editing the method's file, try to edit in a tempfile and apply as a monkey patch."
258
- end
259
-
260
- def process
261
- if !Pry.config.editor
262
- raise CommandError, "No editor set!\nEnsure that #{text.bold("Pry.config.editor")} is set to your editor of choice."
263
- end
264
-
265
- begin
266
- @method = method_object
267
- rescue NonMethodContextError => err
268
- end
269
-
270
- if opts.present?(:patch) || (@method && @method.dynamically_defined?)
271
- if err
272
- raise err # can't patch a non-method
273
- end
274
-
275
- process_patch
276
- else
277
- if err && !File.exist?(target.eval('__FILE__'))
278
- raise err # can't edit a non-file
279
- end
280
-
281
- process_file
282
- end
283
- end
284
-
285
- def process_patch
286
- lines = @method.source.lines.to_a
287
-
288
- if ((original_name = @method.original_name) &&
289
- lines[0] =~ /^def (?:.*?\.)?#{original_name}(?=[\(\s;]|$)/)
290
- lines[0] = "def #{original_name}#{$'}"
291
- else
292
- raise CommandError, "Pry can only patch methods created with the `def` keyword."
293
- end
294
-
295
- temp_file do |f|
296
- f.puts lines.join
297
- f.flush
298
- invoke_editor(f.path, 0)
299
-
300
- if @method.alias?
301
- with_method_transaction(original_name, @method.owner) do
302
- Pry.new(:input => StringIO.new(File.read(f.path))).rep(@method.owner)
303
- Pry.binding_for(@method.owner).eval("alias #{@method.name} #{original_name}")
304
- end
305
- else
306
- Pry.new(:input => StringIO.new(File.read(f.path))).rep(@method.owner)
307
- end
308
- end
309
- end
310
-
311
- def process_file
312
- file, line = extract_file_and_line
313
-
314
- invoke_editor(file, opts["no-jump"] ? 0 : line)
315
- silence_warnings do
316
- load file unless opts.present?(:'no-reload') || Pry.config.disable_auto_reload
317
- end
318
- end
319
-
320
- protected
321
- def extract_file_and_line
322
- if @method
323
- if @method.source_type == :c
324
- raise CommandError, "Can't edit a C method."
325
- else
326
- [@method.source_file, @method.source_line]
327
- end
328
- else
329
- [target.eval('__FILE__'), target.eval('__LINE__')]
330
- end
331
- end
332
-
333
- def with_method_transaction(meth_name, target=TOPLEVEL_BINDING)
334
- target = Pry.binding_for(target)
335
- temp_name = "__pry_#{meth_name}__"
336
-
337
- target.eval("alias #{temp_name} #{meth_name}")
338
- yield
339
- target.eval("alias #{meth_name} #{temp_name}")
340
- ensure
341
- target.eval("undef #{temp_name}") rescue nil
342
- end
343
- end
344
191
  end
345
192
  end
346
193
  end