pry 0.8.0pre9-i386-mswin32 → 0.8.1-i386-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,18 +1,18 @@
1
1
  class Pry
2
2
  class Commands < CommandBase
3
- module CommandHelpers
3
+ module CommandHelpers
4
4
 
5
5
  private
6
6
 
7
7
  def try_to_load_pry_doc
8
8
 
9
- # YARD crashes on rbx, so do not require it
9
+ # YARD crashes on rbx, so do not require it
10
10
  if !Object.const_defined?(:RUBY_ENGINE) || RUBY_ENGINE !~ /rbx/
11
11
  require "pry-doc"
12
12
  end
13
13
  rescue LoadError
14
14
  end
15
-
15
+
16
16
  def meth_name_from_binding(b)
17
17
  meth_name = b.eval('__method__')
18
18
  if [:__script__, nil, :__binding__, :__binding_impl__].include?(meth_name)
@@ -29,7 +29,7 @@ class Pry
29
29
  target.eval("_file_ = $_file_temp")
30
30
  target.eval("_dir_ = $_dir_temp")
31
31
  end
32
-
32
+
33
33
  def add_line_numbers(lines, start_line)
34
34
  line_array = lines.each_line.to_a
35
35
  line_array.each_with_index.map do |line, idx|
@@ -110,7 +110,7 @@ class Pry
110
110
  if !meth_name
111
111
  return nil
112
112
  end
113
-
113
+
114
114
  if options[:M]
115
115
  target.eval("instance_method(:#{meth_name})")
116
116
  elsif options[:m]
@@ -127,15 +127,16 @@ class Pry
127
127
  end
128
128
  end
129
129
  end
130
-
130
+
131
131
  def make_header(meth, code_type, content)
132
- file, line = meth.source_location
133
132
  num_lines = "Number of lines: #{bold(content.each_line.count.to_s)}"
134
133
  case code_type
135
134
  when :ruby
135
+ file, line = meth.source_location
136
136
  "\n#{bold('From:')} #{file} @ line #{line}:\n#{num_lines}\n\n"
137
137
  else
138
- "\n#{bold('From:')} Ruby Core (C Method):\n#{num_lines}\n\n"
138
+ file = Pry::MethodInfo.info_for(meth).file
139
+ "\n#{bold('From:')} #{file} in Ruby Core (C Method):\n#{num_lines}\n\n"
139
140
  end
140
141
  end
141
142
 
@@ -146,11 +147,11 @@ class Pry
146
147
  def should_use_pry_doc?(meth)
147
148
  Pry.has_pry_doc && is_a_c_method?(meth)
148
149
  end
149
-
150
+
150
151
  def code_type_for(meth)
151
152
  # only C methods
152
153
  if should_use_pry_doc?(meth)
153
- info = Pry::MethodInfo.info_for(meth)
154
+ info = Pry::MethodInfo.info_for(meth)
154
155
  if info && info.source
155
156
  code_type = :c
156
157
  else
@@ -168,7 +169,7 @@ class Pry
168
169
  end
169
170
  code_type
170
171
  end
171
-
172
+
172
173
  def file_map
173
174
  {
174
175
  [".c", ".h"] => :c,
@@ -187,7 +188,7 @@ class Pry
187
188
  ".json" => :json
188
189
  }
189
190
  end
190
-
191
+
191
192
  def syntax_highlight_by_file_type_or_specified(contents, file_name, file_type)
192
193
  _, language_detected = file_map.find do |k, v|
193
194
  Array(k).any? do |matcher|
@@ -204,7 +205,7 @@ class Pry
204
205
  def normalized_line_number(line_number, total_lines)
205
206
  line_number < 0 ? line_number + total_lines : line_number
206
207
  end
207
-
208
+
208
209
  # returns the file content between the lines and the normalized
209
210
  # start and end line numbers.
210
211
  def read_between_the_lines(file_name, start_line, end_line)
@@ -274,6 +275,29 @@ class Pry
274
275
  code.sub /\A\s*\/\*.*?\*\/\s*/m, ''
275
276
  end
276
277
 
278
+ def prompt(message, options="Yn")
279
+ opts = options.scan(/./)
280
+ optstring = opts.join("/") # case maintained
281
+ defaults = opts.select{|o| o.upcase == o }
282
+ opts = opts.map{|o| o.downcase}
283
+
284
+ raise "Error: Too many default values for the prompt: #{default.inspect}" if defaults.size > 1
285
+
286
+ default = defaults.first
287
+
288
+ loop do
289
+ response = Pry.input.readline("#{message} (#{optstring}) ").downcase
290
+ case response
291
+ when *opts
292
+ return response
293
+ when ""
294
+ return default.downcase
295
+ else
296
+ output.puts " |_ Invalid option: #{response.inspect}. Try again."
297
+ end
298
+ end
299
+ end
300
+
277
301
  end
278
302
  end
279
303
  end
@@ -6,15 +6,15 @@ class Pry
6
6
  SYSTEM_COMMAND_REGEX = /^#{Regexp.escape(SYSTEM_COMMAND_DELIMITER)}(.*)/
7
7
 
8
8
  extend Forwardable
9
-
9
+
10
10
  attr_accessor :pry_instance
11
-
11
+
12
12
  def initialize(pry_instance)
13
13
  @pry_instance = pry_instance
14
14
  end
15
15
 
16
16
  def_delegators :@pry_instance, :commands, :nesting, :output
17
-
17
+
18
18
  # Is the string a command valid?
19
19
  # @param [String] val The string passed in from the Pry prompt.
20
20
  # @return [Boolean] Whether the string is a valid command.
@@ -59,21 +59,31 @@ class Pry
59
59
  def execute_system_command(val, target)
60
60
  SYSTEM_COMMAND_REGEX =~ val
61
61
  cmd = interpolate_string($1, target)
62
-
62
+
63
63
  if cmd =~ /^cd\s+(.+)/i
64
64
  begin
65
- Dir.chdir(File.expand_path($1))
65
+ @@cd_history ||= []
66
+ if $1 == "-"
67
+ dest = @@cd_history.pop || Dir.pwd
68
+ else
69
+ dest = File.expand_path($1)
70
+ end
71
+
72
+ @@cd_history << Dir.pwd
73
+ Dir.chdir(dest)
66
74
  rescue Errno::ENOENT
67
- output.puts "No such directory: #{$1}"
75
+ output.puts "No such directory: #{dest}"
68
76
  end
69
77
  else
70
- system(cmd)
78
+ if !system(cmd)
79
+ output.puts "Error: there was a problem executing system command: #{cmd}"
80
+ end
71
81
  end
72
82
 
73
83
  # Tick, tock, im getting rid of this shit soon.
74
84
  val.replace("")
75
85
  end
76
-
86
+
77
87
  # Determine whether a Pry command was matched and return command data
78
88
  # and argument string.
79
89
  # This method should not need to be invoked directly.
@@ -114,7 +124,7 @@ class Pry
114
124
  args = args_string ? Shellwords.shellwords(args_string) : []
115
125
  action = cmd_data[:action]
116
126
  keep_retval = cmd_data[:keep_retval]
117
-
127
+
118
128
  options = {
119
129
  :val => val,
120
130
  :eval_string => eval_string,
@@ -157,7 +167,7 @@ class Pry
157
167
 
158
168
  # Tick, tock, im getting rid of this shit soon.
159
169
  options[:val].clear
160
-
170
+
161
171
  ret_val
162
172
  end
163
173
  end
@@ -2,6 +2,8 @@ direc = File.dirname(__FILE__)
2
2
 
3
3
  require "optparse"
4
4
  require "method_source"
5
+ require 'slop'
6
+ require 'rubygems/dependency_installer'
5
7
  require "#{direc}/command_base"
6
8
  require "#{direc}/pry_instance"
7
9
  require "#{direc}/command_helpers"
@@ -23,31 +25,30 @@ class Pry
23
25
  Pry.start(target)
24
26
  end
25
27
 
26
- # this cannot be accessed, it's just for help purposed.
28
+ # this cannot be accessed, it's just for help purposes.
27
29
  command ".<shell command>", "All text following a '.' is forwarded to the shell." do
28
30
  end
29
31
 
30
- command "hist", "Show and replay Readline history" do |*args|
31
- require 'slop'
32
+ command "hist", "Show and replay Readline history. Type `hist --help` for more info." do |*args|
33
+ hist_array = Readline::HISTORY.to_a
34
+
32
35
  if args.empty?
33
- text = add_line_numbers(Readline::HISTORY.to_a.join("\n"), 0)
36
+ text = add_line_numbers(hist_array.join("\n"), 0)
34
37
  stagger_output(text)
35
38
  next
36
39
  end
37
40
 
38
- opts = Slop.parse(args) do
39
- banner "Usage: hist [-rSTART..END]"
40
- on :r, :replay, 'The line (or range of lines) to replay.', true, :as => Range do |r|
41
- options[:r].argument_value = r.to_i if r.is_a?(String)
41
+ opts = Slop.parse(args) do |opt|
42
+ opt.banner "Usage: hist [--replay START..END]\nView and replay history\ne.g hist --replay 2..8"
43
+ opt.on :r, :replay, 'The line (or range of lines) to replay.', true, :as => Range
44
+ opt.on :h, :help, 'Show this message.', :tail => true do
45
+ output.puts opt.help
42
46
  end
43
- on :h, :help, 'Show this message.', :tail => true do
44
- output.puts help
45
- end
46
47
  end
47
48
 
48
49
  next if opts.h?
49
50
 
50
- actions = Array(Readline::HISTORY.to_a[opts[:r]]).join("\n") + "\n"
51
+ actions = Array(hist_array[opts[:replay]]).join("\n") + "\n"
51
52
  Pry.active_instance.input = StringIO.new(actions)
52
53
  end
53
54
 
@@ -58,46 +59,67 @@ class Pry
58
59
  alias_command "quit-program", "exit-program", ""
59
60
  alias_command "!!!", "exit-program", ""
60
61
 
62
+ command "gem-install", "Install a gem and refresh the gem cache." do |gem_name|
63
+ gem_home = Gem.instance_variable_get(:@gem_home)
64
+ output.puts "Attempting to install gem: #{bold(gem_name)}"
65
+
66
+ begin
67
+ if File.writable?(gem_home)
68
+ Gem::DependencyInstaller.new.install(gem_name)
69
+ output.puts "Gem #{bold(gem_name)} successfully installed."
70
+ else
71
+ if system("sudo gem install #{gem_name}")
72
+ output.puts "Gem #{bold(gem_name)} successfully installed."
73
+ else
74
+ output.puts "Gem #{bold(gem_name)} could not be installed."
75
+ next
76
+ end
77
+ end
78
+ rescue Gem::GemNotFoundException
79
+ output.puts "Required Gem: #{bold(gem_name)} not found."
80
+ next
81
+ end
82
+
83
+ Gem.refresh
84
+ output.puts "Refreshed gem cache."
85
+ end
86
+
61
87
  command "ri", "View ri documentation. e.g `ri Array#each`" do |*args|
62
- run target, ".ri", *args
88
+ run ".ri", *args
63
89
  end
64
90
 
65
- command "stat", "View method information and set _file_ and _dir_ locals" do |*args|
66
- options = {}
91
+ command "stat", "View method information and set _file_ and _dir_ locals. Type `stat --help` for more info." do |*args|
67
92
  target = target()
68
- meth_name = nil
69
-
70
- OptionParser.new do |opts|
71
- opts.banner = %{Usage: stat [OPTIONS] [METH]
72
- Show method information for method METH and set _file_ and _dir_ locals.
93
+
94
+ opts = Slop.parse!(args) do |opts|
95
+ opts.banner %{Usage: stat [OPTIONS] [METH]
96
+ Show method information for method METH and set _file_ and _dir_ locals.
73
97
  e.g: stat hello_method
74
98
  --
75
99
  }
76
- opts.on("-M", "--instance-methods", "Operate on instance methods.") do
77
- options[:M] = true
78
- end
79
-
80
- opts.on("-m", "--methods", "Operate on methods.") do
81
- options[:m] = true
82
- end
83
-
84
- opts.on("-c", "--context CONTEXT", "Select object context to run under.") do |context|
100
+ opts.on :M, "instance-methods", "Operate on instance methods."
101
+ opts.on :m, :methods, "Operate on methods."
102
+ opts.on :c, :context, "Select object context to run under.", true do |context|
85
103
  target = Pry.binding_for(target.eval(context))
86
104
  end
87
-
88
- opts.on_tail("-h", "--help", "This message.") do
105
+ opts.on :h, :help, "This message" do
89
106
  output.puts opts
90
- options[:h] = true
91
107
  end
92
- end.order(args) do |v|
93
- meth_name = v
94
108
  end
95
109
 
96
- next if options[:h]
97
-
98
- meth_name = meth_name_from_binding(target) if !meth_name
110
+ next if opts.help?
99
111
 
100
- if (meth = get_method_object(meth_name, target, options)).nil?
112
+ meth_name = args.shift
113
+ if meth_name
114
+ if meth_name =~ /\A([^\.\#]+)[\.\#](.+)\z/ && !opts.context?
115
+ context, meth_name = $1, $2
116
+ target = Pry.binding_for(target.eval(context))
117
+ end
118
+ else
119
+ meth_name = meth_name_from_binding(target)
120
+ end
121
+
122
+ if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
101
123
  output.puts "Invalid method name: #{meth_name}. Type `stat --help` for help"
102
124
  next
103
125
  end
@@ -108,50 +130,59 @@ e.g: stat hello_method
108
130
 
109
131
  output.puts make_header(meth, code_type, code)
110
132
  output.puts bold("Method Name: ") + meth_name
133
+ output.puts bold("Method Owner: ") + (meth.owner.to_s ? meth.owner.to_s : "Unknown")
111
134
  output.puts bold("Method Language: ") + code_type.to_s.capitalize
112
135
  output.puts bold("Method Type: ") + (meth.is_a?(Method) ? "Bound" : "Unbound")
113
136
  output.puts bold("Method Arity: ") + meth.arity.to_s
137
+
138
+ name_map = { :req => "Required:", :opt => "Optional:", :rest => "Rest:" }
139
+ if meth.respond_to?(:parameters)
140
+ output.puts bold("Method Parameters: ") + meth.parameters.group_by(&:first).
141
+ map { |k, v| "#{name_map[k]} #{v.map { |kk, vv| vv ? vv.to_s : "noname" }.join(", ")}" }.join(". ")
142
+ end
114
143
  output.puts bold("Comment length: ") + (doc.empty? ? 'No comment.' : (doc.lines.count.to_s + ' lines.'))
115
144
  end
116
145
 
117
- command "gist-method", "Gist a method to github.", :requires_gem => "gist" do |*args|
118
- options = {}
119
- meth_name = nil
146
+ command "gist-method", "Gist a method to github. Type `gist-method --help` for more info.", :requires_gem => "gist" do |*args|
147
+ target = target()
120
148
 
121
- OptionParser.new do |opts|
149
+ opts = Slop.parse!(args) do |opts|
122
150
  opts.banner = %{Usage: gist-method [OPTIONS] [METH]
123
151
  Gist the method (doc or source) to github.
152
+ Ensure the `gist` gem is properly working before use. http://github.com/defunkt/gist for instructions.
124
153
  e.g: gist -m my_method
125
154
  e.g: gist -d my_method
126
155
  --
127
156
  }
128
- opts.on("-m", "--method", "Gist a method's source.") do |line|
129
- options[:m] = true
130
- end
131
-
132
- opts.on("-d", "--doc", "Gist a method's documentation.") do
133
- options[:d] = true
134
- end
135
-
136
- opts.on_tail("-h", "--help", "This message.") do
157
+ opts.on :m, :method, "Gist a method's source."
158
+ opts.on :d, :doc, "Gist a method's documentation."
159
+ opts.on :p, :private, "Create a private gist (default: true)", :default => true
160
+ opts.on :h, :help, "This message" do
137
161
  output.puts opts
138
- options[:h] = true
139
162
  end
140
- end.order(args) do |v|
141
- meth_name = v
142
163
  end
143
164
 
144
- next if options[:h]
145
-
146
- meth_name = meth_name_from_binding(target) if !meth_name
165
+ next if opts.help?
147
166
 
148
- if (meth = get_method_object(meth_name, target, options)).nil?
167
+ # This needs to be extracted into its own method as it's shared
168
+ # by show-method and show-doc and stat commands
169
+ meth_name = args.shift
170
+ if meth_name
171
+ if meth_name =~ /\A([^\.\#]+)[\.\#](.+)\z/
172
+ context, meth_name = $1, $2
173
+ target = Pry.binding_for(target.eval(context))
174
+ end
175
+ else
176
+ meth_name = meth_name_from_binding(target)
177
+ end
178
+
179
+ if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
149
180
  output.puts "Invalid method name: #{meth_name}. Type `gist-method --help` for help"
150
181
  next
151
182
  end
152
183
 
153
184
  type_map = { :ruby => "rb", :c => "c", :plain => "plain" }
154
- if !options[:d]
185
+ if !opts.doc?
155
186
  content, code_type = code_and_code_type_for(meth)
156
187
  else
157
188
  content, code_type = doc_and_code_type_for(meth)
@@ -160,8 +191,8 @@ e.g: gist -d my_method
160
191
  end
161
192
  code_type = :plain
162
193
  end
163
-
164
- IO.popen("gist -p -t #{type_map[code_type]} -", "w") do |gist|
194
+
195
+ IO.popen("gist#{' -p' if opts.p?} -t #{type_map[code_type]} -", "w") do |gist|
165
196
  gist.puts content
166
197
  end
167
198
  end
@@ -189,22 +220,22 @@ e.g: gist -d my_method
189
220
 
190
221
  command "shell-mode", "Toggle shell mode. Bring in pwd prompt and file completion." do
191
222
  case Pry.active_instance.prompt
192
- when Pry::FILE_PROMPT
223
+ when Pry::SHELL_PROMPT
193
224
  Pry.active_instance.prompt = Pry::DEFAULT_PROMPT
194
225
  Pry.active_instance.custom_completions = Pry::DEFAULT_CUSTOM_COMPLETIONS
195
226
  else
196
- Pry.active_instance.prompt = Pry::FILE_PROMPT
227
+ Pry.active_instance.prompt = Pry::SHELL_PROMPT
197
228
  Pry.active_instance.custom_completions = Pry::FILE_COMPLETIONS
198
229
  Readline.completion_proc = Pry::InputCompleter.build_completion_proc target,
199
230
  Pry.active_instance.instance_eval(&Pry::FILE_COMPLETIONS)
200
- end
231
+ end
201
232
  end
202
233
 
203
234
  alias_command "file-mode", "shell-mode", ""
204
235
 
205
- command "nesting", "Show nesting information." do
236
+ command "nesting", "Show nesting information." do
206
237
  nesting = opts[:nesting]
207
-
238
+
208
239
  output.puts "Nesting status:"
209
240
  output.puts "--"
210
241
  nesting.each do |level, obj|
@@ -218,7 +249,7 @@ e.g: gist -d my_method
218
249
 
219
250
  command "status", "Show status information." do
220
251
  nesting = opts[:nesting]
221
-
252
+
222
253
  output.puts "Status:"
223
254
  output.puts "--"
224
255
  output.puts "Receiver: #{Pry.view_clip(target.eval('self'))}"
@@ -232,7 +263,53 @@ e.g: gist -d my_method
232
263
  output.puts "Last result: #{Pry.view(Pry.last_result)}"
233
264
  end
234
265
 
235
- command "whereami", "Show the code context for the session. Shows AROUND lines around the invocation line. AROUND defaults to 5 lines. " do |num|
266
+
267
+ command "req", "Requires gem(s). No need for quotes! (If the gem isn't installed, it will ask if you want to install it.)" do |*gems|
268
+ gems = gems.join(' ').gsub(',', '').split(/\s+/)
269
+ gems.each do |gem|
270
+ begin
271
+ if require gem
272
+ output.puts "#{bright_yellow(gem)} loaded"
273
+ else
274
+ output.puts "#{bright_white(gem)} already loaded"
275
+ end
276
+
277
+ rescue LoadError => e
278
+
279
+ if gem_installed? gem
280
+ output.puts e.inspect
281
+ else
282
+ output.puts "#{bright_red(gem)} not found"
283
+ if prompt("Install the gem?") == "y"
284
+ run "gem-install", gem
285
+ end
286
+ end
287
+
288
+ end # rescue
289
+ end # gems.each
290
+ end
291
+
292
+
293
+ command "gem-list", "List/search installed gems. (Optional parameter: a regexp to limit the search)" do |arg|
294
+ gems = Gem.source_index.gems.values.group_by(&:name)
295
+ if arg
296
+ query = Regexp.new(arg, Regexp::IGNORECASE)
297
+ gems = gems.select { |gemname, specs| gemname =~ query }
298
+ end
299
+
300
+ gems.each do |gemname, specs|
301
+ versions = specs.map(&:version).sort.reverse.map(&:to_s)
302
+ versions = ["<bright_green>#{versions.first}</bright_green>"] +
303
+ versions[1..-1].map{|v| "<green>#{v}</green>" }
304
+
305
+ gemname = highlight(gemname, query) if query
306
+ result = "<white>#{gemname} <grey>(#{versions.join ', '})</grey>"
307
+ output.puts colorize(result)
308
+ end
309
+ end
310
+
311
+
312
+ command "whereami", "Show the code context for the session. (whereami <n> shows <n> extra lines of code around the invocation line. Default: 5)" do |num|
236
313
  file = target.eval('__FILE__')
237
314
  line_num = target.eval('__LINE__')
238
315
  klass = target.eval('self.class')
@@ -246,14 +323,14 @@ e.g: gist -d my_method
246
323
  meth_name = meth_name_from_binding(target)
247
324
  meth_name = "N/A" if !meth_name
248
325
 
249
- if file =~ /(\(.*\))|<.*>/ || file == ""
326
+ if file =~ /(\(.*\))|<.*>/ || file == "" || file == "-e"
250
327
  output.puts "Cannot find local context. Did you use `binding.pry` ?"
251
328
  next
252
329
  end
253
-
254
- set_file_and_dir_locals(file)
330
+
331
+ set_file_and_dir_locals(file)
255
332
  output.puts "\n#{bold('From:')} #{file} @ line #{line_num} in #{klass}##{meth_name}:\n\n"
256
-
333
+
257
334
  # This method inspired by http://rubygems.org/gems/ir_b
258
335
  File.open(file).each_with_index do |line, index|
259
336
  line_n = index + 1
@@ -276,25 +353,24 @@ e.g: gist -d my_method
276
353
  end
277
354
  end
278
355
  end
279
-
356
+
280
357
  command "version", "Show Pry version." do
281
358
  output.puts "Pry version: #{Pry::VERSION} on Ruby #{RUBY_VERSION}."
282
359
  end
283
-
284
- command "exit-all", "End all nested Pry sessions. Accepts optional return value. Aliases: !@" do
360
+
361
+ command "exit-all", "End all nested Pry sessions. Accepts optional return value. Aliases: !!@" do
285
362
  str = remove_first_word(opts[:val])
286
363
  throw(:breakout, [0, target.eval(str)])
287
364
  end
288
365
 
289
- alias_command "!@", "exit-all", ""
366
+ alias_command "!!@", "exit-all", ""
290
367
 
291
368
  command "ls", "Show the list of vars and methods in the current scope. Type `ls --help` for more info." do |*args|
292
369
  options = {}
293
-
294
370
  # Set target local to the default -- note that we can set a different target for
295
371
  # ls if we like: e.g ls my_var
296
372
  target = target()
297
-
373
+
298
374
  OptionParser.new do |opts|
299
375
  opts.banner = %{Usage: ls [OPTIONS] [VAR]\n\
300
376
  List information about VAR (the current context by default).
@@ -304,7 +380,7 @@ Shows local and instance variables by default.
304
380
  opts.on("-g", "--globals", "Display global variables.") do
305
381
  options[:g] = true
306
382
  end
307
-
383
+
308
384
  opts.on("-c", "--constants", "Display constants.") do
309
385
  options[:c] = true
310
386
  end
@@ -313,15 +389,15 @@ Shows local and instance variables by default.
313
389
  options[:l] = true
314
390
  end
315
391
 
316
- opts.on("-i", "--ivars", "Display instance variables.") do
392
+ opts.on("-i", "--ivars", "Display instance variables.") do
317
393
  options[:i] = true
318
394
  end
319
395
 
320
- opts.on("-k", "--class-vars", "Display class variables.") do
396
+ opts.on("-k", "--class-vars", "Display class variables.") do
321
397
  options[:k] = true
322
- end
398
+ end
323
399
 
324
- opts.on("-m", "--methods", "Display methods (public methods by default).") do
400
+ opts.on("-m", "--methods", "Display methods (public methods by default).") do
325
401
  options[:m] = true
326
402
  end
327
403
 
@@ -329,34 +405,42 @@ Shows local and instance variables by default.
329
405
  options[:M] = true
330
406
  end
331
407
 
332
- opts.on("-P", "--public", "Display public methods (with -m).") do
408
+ opts.on("-P", "--public", "Display public methods (with -m).") do
333
409
  options[:P] = true
334
410
  end
335
411
 
336
- opts.on("-r", "--protected", "Display protected methods (with -m).") do
412
+ opts.on("-r", "--protected", "Display protected methods (with -m).") do
337
413
  options[:r] = true
338
- end
414
+ end
339
415
 
340
- opts.on("-p", "--private", "Display private methods (with -m).") do
416
+ opts.on("-p", "--private", "Display private methods (with -m).") do
341
417
  options[:p] = true
342
418
  end
343
419
 
344
- opts.on("-j", "--just-singletons", "Display just the singleton methods (with -m).") do
420
+ opts.on("-j", "--just-singletons", "Display just the singleton methods (with -m).") do
345
421
  options[:j] = true
346
- end
422
+ end
347
423
 
348
- opts.on("-s", "--super", "Include superclass entries (relevant to constant and methods options).") do
424
+ opts.on("-s", "--super", "Include superclass entries (relevant to constant and methods options).") do
349
425
  options[:s] = true
350
426
  end
351
-
427
+
352
428
  opts.on("-a", "--all", "Display all types of entries.") do
353
429
  options[:a] = true
354
430
  end
355
431
 
356
- opts.on("-v", "--verbose", "Verbose ouput.") do
432
+ opts.on("-v", "--verbose", "Verbose ouput.") do
357
433
  options[:v] = true
358
434
  end
359
435
 
436
+ opts.on("-f", "--flood", "Do not use a pager to view text longer than one screen.") do
437
+ options[:f] = true
438
+ end
439
+
440
+ opts.on("--grep REG", "Regular expression to be used.") do |reg|
441
+ options[:grep] = Regexp.new(reg)
442
+ end
443
+
360
444
  opts.on_tail("-h", "--help", "Show this message.") do
361
445
  output.puts opts
362
446
  options[:h] = true
@@ -374,18 +458,21 @@ Shows local and instance variables by default.
374
458
  :l => true,
375
459
  :i => true,
376
460
  :k => true
377
- }) if options.empty? || (options.size == 1 && options[:v])
461
+ }) if options.empty? || (options.size == 1 && options[:v]) || (options.size == 1 && options[:grep])
462
+
463
+ options[:grep] = // if !options[:grep]
464
+
378
465
 
379
466
  # Display public methods by default if -m or -M switch is used.
380
467
  options[:P] = true if (options[:m] || options[:M]) && !(options[:p] || options[:r] || options[:j])
381
-
468
+
382
469
  info = {}
383
470
  target_self = target.eval('self')
384
471
 
385
472
  # ensure we have a real boolean and not a `nil` (important when
386
473
  # interpolating in the string)
387
474
  options[:s] = !!options[:s]
388
-
475
+
389
476
  # Numbers (e.g 0, 1, 2) are for ordering the hash values in Ruby 1.8
390
477
  i = -1
391
478
 
@@ -400,7 +487,7 @@ Shows local and instance variables by default.
400
487
  end, i += 1] if options[:k] || options[:a]
401
488
 
402
489
  info["global variables"] = [Array(target.eval("global_variables")).sort, i += 1] if options[:g] || options[:a]
403
-
490
+
404
491
  info["public methods"] = [Array(target.eval("public_methods(#{options[:s]})")).uniq.sort, i += 1] if (options[:m] && options[:P]) || options[:a]
405
492
 
406
493
  info["protected methods"] = [Array(target.eval("protected_methods(#{options[:s]})")).sort, i += 1] if (options[:m] && options[:r]) || options[:a]
@@ -408,52 +495,77 @@ Shows local and instance variables by default.
408
495
  info["private methods"] = [Array(target.eval("private_methods(#{options[:s]})")).sort, i += 1] if (options[:m] && options[:p]) || options[:a]
409
496
 
410
497
  info["just singleton methods"] = [Array(target.eval("methods(#{options[:s]})")).sort, i += 1] if (options[:m] && options[:j]) || options[:a]
411
-
498
+
412
499
  info["public instance methods"] = [Array(target.eval("public_instance_methods(#{options[:s]})")).uniq.sort, i += 1] if target_self.is_a?(Module) && ((options[:M] && options[:P]) || options[:a])
413
500
 
414
501
  info["protected instance methods"] = [Array(target.eval("protected_instance_methods(#{options[:s]})")).uniq.sort, i += 1] if target_self.is_a?(Module) && ((options[:M] && options[:r]) || options[:a])
415
502
 
416
503
  info["private instance methods"] = [Array(target.eval("private_instance_methods(#{options[:s]})")).uniq.sort, i += 1] if target_self.is_a?(Module) && ((options[:M] && options[:p]) || options[:a])
417
-
504
+
418
505
  # dealing with 1.8/1.9 compatibility issues :/
419
506
  csuper = options[:s]
420
507
  if Module.method(:constants).arity == 0
421
508
  csuper = nil
422
509
  end
423
-
510
+
424
511
  info["constants"] = [Array(target_self.is_a?(Module) ? target.eval("constants(#{csuper})") :
425
512
  target.eval("self.class.constants(#{csuper})")).uniq.sort, i += 1] if options[:c] || options[:a]
426
513
 
514
+ text = ""
515
+
427
516
  # verbose output?
428
517
  if options[:v]
429
-
430
518
  # verbose
519
+
431
520
  info.sort_by { |k, v| v.last }.each do |k, v|
432
521
  if !v.first.empty?
433
- output.puts "#{k}:\n--"
522
+ text << "#{k}:\n--\n"
523
+ filtered_list = v.first.grep options[:grep]
434
524
  if Pry.color
435
- output.puts CodeRay.scan(Pry.view(v.first), :ruby).term
525
+ text << CodeRay.scan(Pry.view(filtered_list), :ruby).term + "\n"
436
526
  else
437
- output.puts Pry.view(v.first)
527
+ text << Pry.view(filtered_list) + "\n"
438
528
  end
439
- output.puts
529
+ text << "\n\n"
440
530
  end
441
531
  end
442
532
 
533
+ if !options[:f]
534
+ stagger_output(text)
535
+ else
536
+ output.puts text
537
+ end
538
+
443
539
  # plain
444
540
  else
445
541
  list = info.values.sort_by(&:last).map(&:first).inject(&:+)
542
+ list = list.grep(options[:grep]) if list
446
543
  list.uniq! if list
447
544
  if Pry.color
448
- output.puts CodeRay.scan(Pry.view(list), :ruby).term
545
+ text << CodeRay.scan(Pry.view(list), :ruby).term + "\n"
546
+ else
547
+ text << Pry.view(list) + "\n"
548
+ end
549
+ if !options[:f]
550
+ stagger_output(text)
449
551
  else
450
- output.puts Pry.view(list)
552
+ output.puts text
451
553
  end
452
554
  list
453
555
  end
454
556
  end
455
557
 
456
- command "cat-file", "Show output of file FILE. Type `cat-file --help` for more information." do |*args|
558
+ command "lls", "List local files using 'ls'" do |*args|
559
+ cmd = ".ls"
560
+ cmd << " --color=always" if Pry.color
561
+ run cmd, *args
562
+ end
563
+
564
+ command "lcd", "Change the current (working) directory" do |*args|
565
+ run ".cd", *args
566
+ end
567
+
568
+ command "cat", "Show output of file FILE. Type `cat --help` for more information." do |*args|
457
569
  options= {}
458
570
  file_name = nil
459
571
  start_line = 0
@@ -461,9 +573,9 @@ Shows local and instance variables by default.
461
573
  file_type = nil
462
574
 
463
575
  OptionParser.new do |opts|
464
- opts.banner = %{Usage: cat-file [OPTIONS] FILE
576
+ opts.banner = %{Usage: cat [OPTIONS] FILE
465
577
  Cat a file. Defaults to displaying whole file. Syntax highlights file if type is recognized.
466
- e.g: cat-file hello.rb
578
+ e.g: cat hello.rb
467
579
  --
468
580
  }
469
581
  opts.on("-l", "--line-numbers", "Show line numbers.") do |line|
@@ -482,11 +594,11 @@ e.g: cat-file hello.rb
482
594
  file_type = type.to_sym
483
595
  end
484
596
 
485
- opts.on("-f", "--flood", "Do not use a pager to view text longer than one screen.") do
597
+ opts.on("-f", "--flood", "Do not use a pager to view text longer than one screen.") do
486
598
  options[:f] = true
487
599
  end
488
600
 
489
- opts.on_tail("-h", "--help", "This message.") do
601
+ opts.on_tail("-h", "--help", "This message.") do
490
602
  output.puts opts
491
603
  options[:h] = true
492
604
  end
@@ -495,7 +607,7 @@ e.g: cat-file hello.rb
495
607
  end
496
608
 
497
609
  next if options[:h]
498
-
610
+
499
611
  if !file_name
500
612
  output.puts "Must provide a file name."
501
613
  next
@@ -516,7 +628,7 @@ e.g: cat-file hello.rb
516
628
  options = {}
517
629
  target = target()
518
630
  file_name = nil
519
-
631
+
520
632
  OptionParser.new do |opts|
521
633
  opts.banner = %{Usage: eval-file [OPTIONS] FILE
522
634
  Eval a Ruby script at top-level or in the specified context. Defaults to top-level.
@@ -528,7 +640,7 @@ e.g: eval-file -c self "hello.rb"
528
640
  target = Pry.binding_for(target.eval(context))
529
641
  end
530
642
 
531
- opts.on_tail("-h", "--help", "This message.") do
643
+ opts.on_tail("-h", "--help", "This message.") do
532
644
  output.puts opts
533
645
  options[:h] = true
534
646
  end
@@ -556,73 +668,57 @@ e.g: eval-file -c self "hello.rb"
556
668
 
557
669
  new_constants = Object.constants - old_constants
558
670
  output.puts "Brought in the following top-level constants: #{new_constants.inspect}" if !new_constants.empty?
559
- end
560
-
561
- command "cat", "Show output of VAR.inspect. Aliases: inspect" do |obj|
562
- if !obj
563
- output.puts "Must provide an object to inspect."
564
- next
565
- end
566
-
567
- output.puts Pry.view(target.eval("#{obj}"))
568
671
  end
569
672
 
570
- alias_command "inspect", "cat", ""
571
-
572
673
  command "cd", "Start a Pry session on VAR (use `cd ..` to go back and `cd /` to return to Pry top-level)", :keep_retval => true do |obj|
573
674
  if !obj
574
675
  output.puts "Must provide an object."
575
676
  next
576
677
  end
577
-
678
+
578
679
  throw(:breakout, opts[:nesting].level) if obj == ".."
579
680
 
580
- if obj == "/"
681
+ if obj == "/"
581
682
  throw(:breakout, 1) if opts[:nesting].level > 0
582
683
  next
583
- end
684
+ end
584
685
 
585
686
  Pry.start target.eval("#{obj}")
586
687
  end
587
688
 
588
689
  command "show-doc", "Show the comments above METH. Type `show-doc --help` for more info. Aliases: \?" do |*args|
589
- options = {}
590
690
  target = target()
591
- meth_name = nil
592
-
593
- OptionParser.new do |opts|
594
- opts.banner = %{Usage: show-doc [OPTIONS] [METH]
691
+
692
+ opts = Slop.parse!(args) do |opts|
693
+ opts.banner %{Usage: show-doc [OPTIONS] [METH]
595
694
  Show the comments above method METH. Tries instance methods first and then methods by default.
596
695
  e.g show-doc hello_method
597
696
  --
598
697
  }
599
- opts.on("-M", "--instance-methods", "Operate on instance methods.") do
600
- options[:M] = true
601
- end
602
-
603
- opts.on("-m", "--methods", "Operate on methods.") do
604
- options[:m] = true
605
- end
606
-
607
- opts.on("-c", "--context CONTEXT", "Select object context to run under.") do |context|
698
+ opts.on :M, "instance-methods", "Operate on instance methods."
699
+ opts.on :m, :methods, "Operate on methods."
700
+ opts.on :c, :context, "Select object context to run under.", true do |context|
608
701
  target = Pry.binding_for(target.eval(context))
609
702
  end
610
-
611
- opts.on("-f", "--flood", "Do not use a pager to view text longer than one screen.") do
612
- options[:f] = true
613
- end
614
-
615
- opts.on_tail("-h", "--help", "This message.") do
703
+ opts.on :f, :flood, "Do not use a pager to view text longer than one screen."
704
+ opts.on :h, :help, "This message." do
616
705
  output.puts opts
617
- options[:h] = true
618
706
  end
619
- end.order(args) do |v|
620
- meth_name = v
621
707
  end
622
708
 
623
- next if options[:h]
709
+ next if opts.help?
710
+
711
+ meth_name = args.shift
712
+ if meth_name
713
+ if meth_name =~ /\A([^\.\#]+)[\.\#](.+)\z/ && !opts.context?
714
+ context, meth_name = $1, $2
715
+ target = Pry.binding_for(target.eval(context))
716
+ end
717
+ else
718
+ meth_name = meth_name_from_binding(target)
719
+ end
624
720
 
625
- if (meth = get_method_object(meth_name, target, options)).nil?
721
+ if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
626
722
  output.puts "Invalid method name: #{meth_name}. Type `show-doc --help` for help"
627
723
  next
628
724
  end
@@ -631,65 +727,55 @@ e.g show-doc hello_method
631
727
  next if !doc
632
728
 
633
729
  next output.puts("No documentation found.") if doc.empty?
634
-
730
+
635
731
  doc = process_comment_markup(doc, code_type)
636
-
732
+
637
733
  output.puts make_header(meth, code_type, doc)
638
734
 
639
- render_output(options[:f], false, doc)
735
+ render_output(opts.flood?, false, doc)
640
736
  doc
641
737
  end
642
738
 
643
739
  alias_command "?", "show-doc", ""
644
740
 
645
741
  command "show-method", "Show the source for METH. Type `show-method --help` for more info. Aliases: $, show-source" do |*args|
646
- options = {}
647
742
  target = target()
648
- meth_name = nil
649
-
650
- OptionParser.new do |opts|
651
- opts.banner = %{Usage: show-method [OPTIONS] [METH]
743
+
744
+ opts = Slop.parse!(args) do |opts|
745
+ opts.banner %{Usage: show-method [OPTIONS] [METH]
652
746
  Show the source for method METH. Tries instance methods first and then methods by default.
653
747
  e.g: show-method hello_method
654
748
  --
655
749
  }
656
- opts.on("-l", "--line-numbers", "Show line numbers.") do |line|
657
- options[:l] = true
658
- end
659
-
660
- opts.on("-M", "--instance-methods", "Operate on instance methods.") do
661
- options[:M] = true
662
- end
663
-
664
- opts.on("-m", "--methods", "Operate on methods.") do
665
- options[:m] = true
666
- end
667
-
668
- opts.on("-f", "--flood", "Do not use a pager to view text longer than one screen.") do
669
- options[:f] = true
670
- end
671
-
672
- opts.on("-c", "--context CONTEXT", "Select object context to run under.") do |context|
750
+ opts.on :l, "line-numbers", "Show line numbers."
751
+ opts.on :M, "instance-methods", "Operate on instance methods."
752
+ opts.on :m, :methods, "Operate on methods."
753
+ opts.on :f, :flood, "Do not use a pager to view text longer than one screen."
754
+ opts.on :c, :context, "Select object context to run under.", true do |context|
673
755
  target = Pry.binding_for(target.eval(context))
674
756
  end
675
-
676
- opts.on_tail("-h", "--help", "This message.") do
757
+ opts.on :h, :help, "This message." do
677
758
  output.puts opts
678
- options[:h] = true
679
759
  end
680
- end.order(args) do |v|
681
- meth_name = v
682
760
  end
683
761
 
684
- next if options[:h]
762
+ next if opts.help?
685
763
 
686
- meth_name = meth_name_from_binding(target) if !meth_name
764
+ meth_name = args.shift
765
+ if meth_name
766
+ if meth_name =~ /\A([^\.\#]+)[\.\#](.+)\z/ && !opts.context?
767
+ context, meth_name = $1, $2
768
+ target = Pry.binding_for(target.eval(context))
769
+ end
770
+ else
771
+ meth_name = meth_name_from_binding(target)
772
+ end
687
773
 
688
- if (meth = get_method_object(meth_name, target, options)).nil?
774
+ if (meth = get_method_object(meth_name, target, opts.to_hash(true))).nil?
689
775
  output.puts "Invalid method name: #{meth_name}. Type `show-method --help` for help"
690
776
  next
691
777
  end
692
-
778
+
693
779
  code, code_type = code_and_code_type_for(meth)
694
780
  next if !code
695
781
 
@@ -699,11 +785,11 @@ e.g: show-method hello_method
699
785
  end
700
786
 
701
787
  start_line = false
702
- if options[:l]
788
+ if opts.l?
703
789
  start_line = meth.source_location ? meth.source_location.last : 1
704
790
  end
705
-
706
- render_output(options[:f], start_line, code)
791
+
792
+ render_output(opts.flood?, start_line, code)
707
793
  code
708
794
  end
709
795
 
@@ -714,10 +800,10 @@ e.g: show-method hello_method
714
800
  options = {}
715
801
  target = target()
716
802
  command_name = nil
717
-
803
+
718
804
  OptionParser.new do |opts|
719
805
  opts.banner = %{Usage: show-command [OPTIONS] [CMD]
720
- Show the source for command CMD.
806
+ Show the source for command CMD.
721
807
  e.g: show-command show-method
722
808
  --
723
809
  }
@@ -725,11 +811,11 @@ e.g: show-command show-method
725
811
  options[:l] = true
726
812
  end
727
813
 
728
- opts.on("-f", "--flood", "Do not use a pager to view text longer than one screen.") do
814
+ opts.on("-f", "--flood", "Do not use a pager to view text longer than one screen.") do
729
815
  options[:f] = true
730
816
  end
731
817
 
732
- opts.on_tail("-h", "--help", "This message.") do
818
+ opts.on_tail("-h", "--help", "This message.") do
733
819
  output.puts opts
734
820
  options[:h] = true
735
821
  end
@@ -743,7 +829,7 @@ e.g: show-command show-method
743
829
  output.puts "You must provide a command name."
744
830
  next
745
831
  end
746
-
832
+
747
833
  if commands[command_name]
748
834
  meth = commands[command_name][:action]
749
835
 
@@ -764,7 +850,7 @@ e.g: show-command show-method
764
850
  output.puts "No such command: #{command_name}."
765
851
  end
766
852
  end
767
-
853
+
768
854
  command "jump-to", "Jump to a Pry session further up the stack, exiting all sessions below." do |break_level|
769
855
  break_level = break_level.to_i
770
856
  nesting = opts[:nesting]
@@ -780,7 +866,7 @@ e.g: show-command show-method
780
866
  end
781
867
  end
782
868
 
783
- command "exit", "End the current Pry session. Accepts optional return value. Aliases: quit, back" do
869
+ command "exit", "End the current Pry session. Accepts optional return value. Aliases: quit, back" do
784
870
  str = remove_first_word(opts[:val])
785
871
  throw(:breakout, [opts[:nesting].level, target.eval(str)])
786
872
  end
@@ -825,7 +911,7 @@ Wait for the early owl.
825
911
  output.puts text
826
912
  text
827
913
  end
828
-
914
+
829
915
  command "cohen-poem", "" do
830
916
  text = %{
831
917
  --
@@ -843,7 +929,7 @@ and so small between the thin pines
843
929
  on these enormous landscapes,
844
930
  that if you turn your head
845
931
  they are lost for hours.
846
- -- Leonard Cohen
932
+ -- Leonard Cohen
847
933
  }
848
934
  output.puts text
849
935
  text