pry 0.9.8pre2-i386-mingw32 → 0.9.8pre3-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.
@@ -8,41 +8,6 @@ class Pry
8
8
  # This class is used to create sets of commands. Commands can be imported from
9
9
  # different sets, aliased, removed, etc.
10
10
  class CommandSet
11
- class Command < Struct.new(:name, :description, :options, :block)
12
-
13
- def call(context, *args)
14
- context.command_name = options[:listing]
15
-
16
- if stub_block = options[:stub_info]
17
- context.instance_eval(&stub_block)
18
- else
19
- ret = context.instance_exec(*correct_arg_arity(block.arity, args), &block)
20
- if options[:keep_retval]
21
- ret
22
- else
23
- Pry::CommandContext::VOID_VALUE
24
- end
25
- end
26
- end
27
-
28
- private
29
- def correct_arg_arity(arity, args)
30
- case arity <=> 0
31
- when -1
32
- args
33
- when 0
34
- []
35
- when 1
36
- # another jruby hack
37
- if Pry::Helpers::BaseHelpers.jruby?
38
- args[0..(arity - 1)]
39
- else
40
- args.values_at 0..(arity - 1)
41
- end
42
- end
43
- end
44
- end
45
-
46
11
  include Enumerable
47
12
  include Pry::Helpers::BaseHelpers
48
13
 
@@ -117,29 +82,42 @@ class Pry
117
82
  # # pry(main)> help number
118
83
  # # number-N regex command
119
84
  def command(name, description="No description.", options={}, &block)
85
+ options = default_options(name).merge!(options)
120
86
 
121
- options = {
122
- :requires_gem => [],
123
- :keep_retval => false,
124
- :argument_required => false,
125
- :interpolate => true,
126
- :shellwords => true,
127
- :listing => name,
128
- :use_prefix => true
129
- }.merge!(options)
130
-
131
- unless command_dependencies_met? options
132
- gems_needed = Array(options[:requires_gem])
133
- gems_not_installed = gems_needed.select { |g| !gem_installed?(g) }
87
+ commands[name] = Pry::BlockCommand.subclass(name, description, options, helper_module, &block)
88
+ end
134
89
 
135
- options[:stub_info] = proc do
136
- output.puts "\nThe command '#{name}' is #{Helpers::Text.bold("unavailable")} because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}"
137
- output.puts "-"
138
- output.puts "Type `install-command #{name}` to install the required gems and activate this command."
139
- end
140
- end
90
+ # Defines a new Pry command class.
91
+ #
92
+ # @param [String, Regexp] name The name of the command. Can be
93
+ # Regexp as well as String.
94
+ # @param [String] description A description of the command.
95
+ # @param [Hash] options The optional configuration parameters, see {#command}
96
+ # @param &Block The class body's definition.
97
+ #
98
+ # @example
99
+ # Pry::Commands.command_class "echo", "echo's the input", :shellwords => false do
100
+ # def options(opt)
101
+ # opt.banner "Usage: echo [-u | -d] <string to echo>"
102
+ # opt.on :u, :upcase, "ensure the output is all upper-case"
103
+ # opt.on :d, :downcase, "ensure the output is all lower-case"
104
+ # end
105
+ #
106
+ # def process
107
+ # raise Pry::CommandError, "-u and -d makes no sense" if opts.present?(:u) && opts.present?(:d)
108
+ # result = args.join(" ")
109
+ # result.downcase! if opts.present?(:downcase)
110
+ # result.upcase! if opts.present?(:upcase)
111
+ # output.puts result
112
+ # end
113
+ # end
114
+ #
115
+ def command_class(name, description="No description.", options={}, &block)
116
+ options = default_options(name).merge!(options)
141
117
 
142
- commands[name] = Command.new(name, description, options, block)
118
+ commands[name] = Pry::ClassCommand.subclass(name, description, options, helper_module, &block)
119
+ commands[name].class_eval(&block)
120
+ commands[name]
143
121
  end
144
122
 
145
123
  # Execute a block of code before a command is invoked. The block also
@@ -153,13 +131,7 @@ class Pry
153
131
  # end
154
132
  def before_command(name, &block)
155
133
  cmd = find_command_by_name_or_listing(name)
156
- prev_block = cmd.block
157
-
158
- wrapper_block = proc do |*args|
159
- instance_exec(*args, &block)
160
- instance_exec(*args, &prev_block)
161
- end
162
- cmd.block = wrapper_block
134
+ cmd.hooks[:before].unshift block
163
135
  end
164
136
 
165
137
  # Execute a block of code after a command is invoked. The block also
@@ -173,13 +145,7 @@ class Pry
173
145
  # end
174
146
  def after_command(name, &block)
175
147
  cmd = find_command_by_name_or_listing(name)
176
- prev_block = cmd.block
177
-
178
- wrapper_block = proc do |*args|
179
- instance_exec(*args, &prev_block)
180
- instance_exec(*args, &block)
181
- end
182
- cmd.block = wrapper_block
148
+ cmd.hooks[:after] << block
183
149
  end
184
150
 
185
151
  def each &block
@@ -267,27 +233,6 @@ class Pry
267
233
  commands.delete(cmd.name)
268
234
  end
269
235
 
270
- # Runs a command.
271
- # @param [Object] context Object which will be used as self during the
272
- # command.
273
- # @param [String] name Name of the command to be run
274
- # @param [Array<Object>] args Arguments passed to the command
275
- # @raise [NoCommandError] If the command is not defined in this set
276
- def run_command(context, name, *args)
277
- context.extend helper_module
278
- command = commands[name]
279
-
280
- if command.nil?
281
- raise NoCommandError.new(name, self)
282
- end
283
-
284
- if command.options[:argument_required] && args.empty?
285
- puts "The command '#{command.name}' requires an argument."
286
- else
287
- command.call context, *args
288
- end
289
- end
290
-
291
236
  # Sets or gets the description for a command (replacing the old
292
237
  # description). Returns current description if no description
293
238
  # parameter provided.
@@ -328,7 +273,58 @@ class Pry
328
273
  commands.keys
329
274
  end
330
275
 
276
+ # Find a command that matches the given line
277
+ #
278
+ # @param [String] the line that may be a command invocation
279
+ # @return [Pry::Command, nil]
280
+ def find_command(val)
281
+ commands.values.detect{ |c| c.matches?(val) }
282
+ end
283
+
284
+ # Is the given line a command invocation?
285
+ #
286
+ # @param [String]
287
+ # @return [Boolean]
288
+ def valid_command?(val)
289
+ !!find_command(val)
290
+ end
291
+
292
+ # Process the given line to see whether it needs executing as a command.
293
+ #
294
+ # @param String the line to execute
295
+ # @param Hash the context to execute the commands with
296
+ # @return CommandSet::Result
297
+ #
298
+ def process_line(val, context={})
299
+ if command = find_command(val)
300
+ context = context.merge(:command_set => self)
301
+ retval = command.new(context).process_line(val)
302
+ Result.new(true, retval)
303
+ else
304
+ Result.new(false)
305
+ end
306
+ end
307
+
308
+ # @nodoc used for testing
309
+ def run_command(context, name, *args)
310
+ command = commands[name] or raise NoCommandError.new(name, self)
311
+ command.new(context).call_safely(*args)
312
+ end
313
+
331
314
  private
315
+
316
+ def default_options(name)
317
+ {
318
+ :requires_gem => [],
319
+ :keep_retval => false,
320
+ :argument_required => false,
321
+ :interpolate => true,
322
+ :shellwords => true,
323
+ :listing => name,
324
+ :use_prefix => true
325
+ }
326
+ end
327
+
332
328
  def define_default_commands
333
329
 
334
330
  command "help", "This menu." do |cmd|
@@ -345,7 +341,7 @@ class Pry
345
341
  stagger_output(help_text)
346
342
  else
347
343
  if command = find_command(cmd)
348
- output.puts command.description
344
+ output.puts command.new.help
349
345
  else
350
346
  output.puts "No info for command: #{cmd}"
351
347
  end
@@ -355,10 +351,9 @@ class Pry
355
351
  command "install-command", "Install a disabled command." do |name|
356
352
  require 'rubygems/dependency_installer' unless defined? Gem::DependencyInstaller
357
353
  command = find_command(name)
358
- stub_info = command.options[:stub_info]
359
354
 
360
- if !stub_info
361
- output.puts "Not a command stub. Nothing to do."
355
+ if command_dependencies_met?(command.options)
356
+ output.puts "Dependencies for #{command.name} are met. Nothing to do."
362
357
  next
363
358
  end
364
359
 
@@ -391,9 +386,31 @@ class Pry
391
386
  end
392
387
  next if gem_install_failed
393
388
 
394
- command.options.delete :stub_info
395
389
  output.puts "Installation of `#{name}` successful! Type `help #{name}` for information"
396
390
  end
397
391
  end
398
392
  end
393
+
394
+ # Wraps the return result of process_commands, indicates if the
395
+ # result IS a command and what kind of command (e.g void)
396
+ class Result
397
+ attr_reader :retval
398
+
399
+ def initialize(is_command, retval = nil)
400
+ @is_command, @retval = is_command, retval
401
+ end
402
+
403
+ # Is the result a command?
404
+ # @return [Boolean]
405
+ def command?
406
+ @is_command
407
+ end
408
+
409
+ # Is the result a command and if it is, is it a void command?
410
+ # (one that does not return a value)
411
+ # @return [Boolean]
412
+ def void_command?
413
+ retval == Command::VOID_VALUE
414
+ end
415
+ end
399
416
  end
@@ -3,124 +3,196 @@ class Pry
3
3
 
4
4
  Documentation = Pry::CommandSet.new do
5
5
 
6
- command "ri", "View ri documentation. e.g `ri Array#each`" do |*args|
7
- run ".ri", *args
6
+ command_class "ri", "View ri documentation. e.g `ri Array#each`" do
7
+ banner <<-BANNER
8
+ Usage: ri [spec]
9
+ e.g. ri Array#each
10
+
11
+ Relies on the ri executable being available. See also: show-doc.
12
+ BANNER
13
+
14
+ def process
15
+ run ".ri", *args
16
+ end
8
17
  end
9
18
 
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|
12
- opt.banner unindent <<-USAGE
13
- Usage: show-doc [OPTIONS] [METH]
14
- Show the comments above method METH. Tries instance methods first and then methods by default.
15
- e.g show-doc hello_method
16
- USAGE
19
+ command_class "show-doc", "Show the comments above METH. Type `show-doc --help` for more info. Aliases: \?", :shellwords => false do |*args|
20
+ banner <<-BANNER
21
+ Usage: show-doc [OPTIONS] [METH]
22
+ Show the comments above method METH. Tries instance methods first and then methods by default.
23
+ e.g show-doc hello_method
24
+ BANNER
17
25
 
26
+ def options(opt)
27
+ method_options(opt)
18
28
  opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
19
29
  end
20
30
 
21
- raise Pry::CommandError, "No documentation found." if meth.doc.nil? || meth.doc.empty?
22
-
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.present?(:flood), false, doc)
31
+ def process
32
+ meth = method_object
33
+ raise Pry::CommandError, "No documentation found." if meth.doc.nil? || meth.doc.empty?
34
+
35
+ doc = process_comment_markup(meth.doc, meth.source_type)
36
+ output.puts make_header(meth, doc)
37
+ output.puts "#{text.bold("Owner:")} #{meth.owner || "N/A"}"
38
+ output.puts "#{text.bold("Visibility:")} #{meth.visibility}"
39
+ output.puts "#{text.bold("Signature:")} #{meth.signature}"
40
+ output.puts
41
+ render_output(opts.present?(:flood), false, doc)
42
+ end
30
43
  end
31
44
 
32
45
  alias_command "?", "show-doc"
33
46
 
34
- command "stat", "View method information and set _file_ and _dir_ locals. Type `stat --help` for more info.", :shellwords => false do |*args|
35
- target = target()
36
-
37
- opts, meth = parse_options!(args, :method_object) do |opt|
38
- opt.banner unindent <<-USAGE
47
+ command_class "stat", "View method information and set _file_ and _dir_ locals. Type `stat --help` for more info.", :shellwords => false do |*args|
48
+ banner <<-BANNER
39
49
  Usage: stat [OPTIONS] [METH]
40
50
  Show method information for method METH and set _file_ and _dir_ locals.
41
51
  e.g: stat hello_method
42
- USAGE
43
- end
44
-
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
52
+ BANNER
53
+
54
+ def options(opt)
55
+ method_options(opt)
56
+ end
57
+
58
+ def process
59
+ meth = method_object
60
+ output.puts unindent <<-EOS
61
+ Method Information:
62
+ --
63
+ Name: #{meth.name}
64
+ Owner: #{meth.owner ? meth.owner : "Unknown"}
65
+ Visibility: #{meth.visibility}
66
+ Type: #{meth.is_a?(::Method) ? "Bound" : "Unbound"}
67
+ Arity: #{meth.arity}
68
+ Method Signature: #{meth.signature}
69
+ Source Location: #{meth.source_location ? meth.source_location.join(":") : "Not found."}
70
+ EOS
71
+ end
56
72
  end
57
73
 
58
- command "gist", "Gist a method or expression history to github. Type `gist --help` for more info.", :requires_gem => "gist", :shellwords => false do |*args|
59
- require 'gist'
74
+ command_class "gist", "Gist a method or expression history to github. Type `gist --help` for more info.", :requires_gem => "gist", :shellwords => false do
75
+ attr_accessor :content
76
+ attr_accessor :code_type
77
+ attr_accessor :input_ranges
60
78
 
61
- target = target()
79
+ def setup
80
+ require 'gist'
81
+ end
62
82
 
63
- opts = parse_options!(args) do |opt|
83
+ def options(opt)
64
84
  opt.banner unindent <<-USAGE
65
- Usage: gist [OPTIONS] [METH]
66
- Gist method (doc or source) or input expression to github.
67
- Ensure the `gist` gem is properly working before use. http://github.com/defunkt/gist for instructions.
68
- e.g: gist -m my_method
69
- e.g: gist -d my_method
70
- e.g: gist -i 1..10
71
- USAGE
85
+ Usage: gist [OPTIONS] [METH]
86
+ Gist method (doc or source) or input expression to github.
87
+ Ensure the `gist` gem is properly working before use. http://github.com/defunkt/gist for instructions.
88
+ e.g: gist -m my_method
89
+ e.g: gist -d my_method
90
+ e.g: gist -i 1..10
91
+ USAGE
72
92
 
73
93
  opt.on :d, :doc, "Gist a method's documentation.", true
74
94
  opt.on :m, :method, "Gist a method's source.", true
95
+ opt.on :f, :file, "Gist a file.", true
75
96
  opt.on :p, :public, "Create a public gist (default: false)", :default => false
76
- opt.on :i, :in, "Gist entries from Pry's input expression history. Takes an index or range.", :optional => true, :as => Range, :default => -5..-1
97
+ opt.on :l, :lines, "Only gist a subset of lines (only works with -m and -f)", :optional => true, :as => Range, :default => 1..-1
98
+ opt.on :i, :in, "Gist entries from Pry's input expression history. Takes an index or range.", :optional => true,
99
+ :as => Range, :default => -5..-1 do |range|
100
+ input_ranges << absolute_index_range(range, _pry_.input_array.length)
101
+ end
77
102
  end
78
103
 
79
- type_map = { :ruby => "rb", :c => "c", :plain => "plain" }
80
- if opts.present?(:in)
81
- code_type = :ruby
82
- content = ""
83
- normalized_range = absolute_index_range(opts[:i], _pry_.input_array.length)
84
- input_items = _pry_.input_array[normalized_range] || []
85
-
86
- input_items.each_with_index.map do |code, index|
87
- corrected_index = index + normalized_range.first
88
- if code && code != ""
89
- content << code
90
- content << "#{comment_expression_result_for_gist(Pry.config.gist.inspecter.call(_pry_.output_array[corrected_index]))}" if code !~ /;\Z/
104
+ def process
105
+ if opts.present?(:in)
106
+ in_option
107
+ elsif opts.present?(:file)
108
+ file_option
109
+ elsif opts.present?(:doc)
110
+ doc_option
111
+ elsif opts.present?(:method)
112
+ method_option
113
+ end
114
+
115
+ perform_gist
116
+ end
117
+
118
+ def in_option
119
+ self.code_type = :ruby
120
+ self.content = ""
121
+
122
+ input_ranges.each do |range|
123
+ input_expressions = _pry_.input_array[range] || []
124
+ input_expressions.each_with_index.map do |code, index|
125
+ corrected_index = index + range.first
126
+ if code && code != ""
127
+ self.content << code
128
+ if code !~ /;\Z/
129
+ self.content << "#{comment_expression_result_for_gist(Pry.config.gist.inspecter.call(_pry_.output_array[corrected_index]))}"
130
+ end
131
+ end
91
132
  end
92
133
  end
93
- elsif opts.present?(:doc)
134
+ end
135
+
136
+ def file_option
137
+ whole_file = File.read(File.expand_path(opts[:f]))
138
+ if opts.present?(:lines)
139
+ self.content = restrict_to_lines(whole_file, opts[:l])
140
+ else
141
+ self.content = whole_file
142
+ end
143
+ end
144
+
145
+ def doc_option
94
146
  meth = get_method_or_raise(opts[:d], target, {})
95
- content = meth.doc
96
- code_type = meth.source_type
147
+ self.content = meth.doc
148
+ self.code_type = meth.source_type
97
149
 
98
150
  text.no_color do
99
- content = process_comment_markup(content, code_type)
151
+ self.content = process_comment_markup(self.content, self.code_type)
100
152
  end
101
- code_type = :plain
102
- elsif opts.present?(:method)
153
+ self.code_type = :plain
154
+ end
155
+
156
+ def method_option
103
157
  meth = get_method_or_raise(opts[:m], target, {})
104
- content = meth.source
105
- code_type = meth.source_type
158
+ method_source = meth.source
159
+ if opts.present?(:lines)
160
+ self.content = restrict_to_lines(method_source, opts[:l])
161
+ else
162
+ self.content = method_source
163
+ end
164
+
165
+ self.code_type = meth.source_type
106
166
  end
107
167
 
108
- # prevent Gist from exiting the session on error
109
- begin
110
- link = Gist.write([:extension => ".#{type_map[code_type]}",
111
- :input => content],
112
- !opts[:p])
113
- rescue SystemExit
168
+ def perform_gist
169
+ type_map = { :ruby => "rb", :c => "c", :plain => "plain" }
170
+
171
+ # prevent Gist from exiting the session on error
172
+ begin
173
+ extname = opts.present?(:file) ? ".#{gist_file_extension(opts[:f])}" : ".#{type_map[self.code_type]}"
174
+
175
+ link = Gist.write([:extension => extname,
176
+ :input => self.content],
177
+ !opts[:p])
178
+ rescue SystemExit
179
+ end
180
+
181
+ if link
182
+ Gist.copy(link)
183
+ output.puts "Gist created at #{link} and added to clipboard."
184
+ end
114
185
  end
115
186
 
116
- if link
117
- Gist.copy(link)
118
- output.puts "Gist created at #{link} and added to clipboard."
187
+ def restrict_to_lines(content, lines)
188
+ line_range = one_index_range(lines)
189
+ content.lines.to_a[line_range].join
119
190
  end
120
- end
121
191
 
192
+ def gist_file_extension(file_name)
193
+ file_name.split(".").last
194
+ end
122
195
 
123
- helpers do
124
196
  def comment_expression_result_for_gist(result)
125
197
  content = ""
126
198
  result.lines.each_with_index do |line, index|
@@ -133,8 +205,7 @@ class Pry
133
205
  content
134
206
  end
135
207
  end
136
-
137
-
138
208
  end
139
209
  end
140
210
  end
211
+