1
0
Fork 0
mirror of https://github.com/pry/pry.git synced 2022-11-09 12:35:05 -05:00

Remove parse_options! API

Having classy commands means it's much easier to implement, so we just
require those instead.
This commit is contained in:
Conrad Irwin 2011-12-31 15:57:50 +00:00
parent 80d50c9bb4
commit bb48077241
7 changed files with 143 additions and 143 deletions

View file

@ -211,6 +211,13 @@ class Pry
# necessary, you can also override {setup} which will be called before {options}, for example to
# require any gems your command needs to run, or to set up state.
class ClassCommand < Command
class << self
def banner(arg=nil)
@banner = arg if arg
@banner || description
end
end
attr_accessor :opts
attr_accessor :args
@ -242,6 +249,7 @@ class Pry
# Return an instance of Slop that can parse the options that this command accepts.
def slop
Slop.new do |opt|
opt.banner(unindent(self.class.banner))
options(opt)
opt.on(:h, :help, "Show this message.")
end
@ -274,7 +282,6 @@ class Pry
# end
def options(opt); end
# The actual body of your command should go here.
#
# The {opts} mehod can be called to get the options that Slop has passed,

View file

@ -115,7 +115,7 @@ class Pry
def command_class(name, description="No description.", options={}, &block)
options = default_options(name).merge!(options)
commands[name] = Pry::ClassCommand.subclass(name, description, options, helper_module)
commands[name] = Pry::ClassCommand.subclass(name, description, options, helper_module, &block)
commands[name].class_eval(&block)
commands[name]
end

View file

@ -3,56 +3,72 @@ class Pry
Documentation = Pry::CommandSet.new do
command "ri", "View ri documentation. e.g `ri Array#each`" do |*args|
run ".ri", *args
command_class "ri", "View ri documentation. e.g `ri Array#each`" do
banner <<-BANNER
Usage: ri [spec]
e.g. ri Array#each
Relies on the ri executable being available. See also: show-doc.
BANNER
def process
run ".ri", *args
end
end
command "show-doc", "Show the comments above METH. Type `show-doc --help` for more info. Aliases: \?", :shellwords => false do |*args|
opts, meth = parse_options!(args, :method_object) do |opt|
opt.banner unindent <<-USAGE
Usage: show-doc [OPTIONS] [METH]
Show the comments above method METH. Tries instance methods first and then methods by default.
e.g show-doc hello_method
USAGE
command_class "show-doc", "Show the comments above METH. Type `show-doc --help` for more info. Aliases: \?", :shellwords => false do |*args|
banner <<-BANNER
Usage: show-doc [OPTIONS] [METH]
Show the comments above method METH. Tries instance methods first and then methods by default.
e.g show-doc hello_method
BANNER
def options(opt)
method_options(opt)
opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
end
raise Pry::CommandError, "No documentation found." if meth.doc.nil? || meth.doc.empty?
def process
meth = method_object
raise Pry::CommandError, "No documentation found." if meth.doc.nil? || meth.doc.empty?
doc = process_comment_markup(meth.doc, meth.source_type)
output.puts make_header(meth, doc)
output.puts "#{text.bold("Owner:")} #{meth.owner || "N/A"}"
output.puts "#{text.bold("Visibility:")} #{meth.visibility}"
output.puts "#{text.bold("Signature:")} #{meth.signature}"
output.puts
render_output(opts.present?(:flood), false, doc)
doc = process_comment_markup(meth.doc, meth.source_type)
output.puts make_header(meth, doc)
output.puts "#{text.bold("Owner:")} #{meth.owner || "N/A"}"
output.puts "#{text.bold("Visibility:")} #{meth.visibility}"
output.puts "#{text.bold("Signature:")} #{meth.signature}"
output.puts
render_output(opts.present?(:flood), false, doc)
end
end
alias_command "?", "show-doc"
command "stat", "View method information and set _file_ and _dir_ locals. Type `stat --help` for more info.", :shellwords => false do |*args|
target = target()
opts, meth = parse_options!(args, :method_object) do |opt|
opt.banner unindent <<-USAGE
command_class "stat", "View method information and set _file_ and _dir_ locals. Type `stat --help` for more info.", :shellwords => false do |*args|
banner <<-BANNER
Usage: stat [OPTIONS] [METH]
Show method information for method METH and set _file_ and _dir_ locals.
e.g: stat hello_method
USAGE
BANNER
def options(opt)
method_options(opt)
end
output.puts unindent <<-EOS
Method Information:
--
Name: #{meth.name}
Owner: #{meth.owner ? meth.owner : "Unknown"}
Visibility: #{meth.visibility}
Type: #{meth.is_a?(::Method) ? "Bound" : "Unbound"}
Arity: #{meth.arity}
Method Signature: #{meth.signature}
Source Location: #{meth.source_location ? meth.source_location.join(":") : "Not found."}
EOS
def process
meth = method_object
output.puts unindent <<-EOS
Method Information:
--
Name: #{meth.name}
Owner: #{meth.owner ? meth.owner : "Unknown"}
Visibility: #{meth.visibility}
Type: #{meth.is_a?(::Method) ? "Bound" : "Unbound"}
Arity: #{meth.arity}
Method Signature: #{meth.signature}
Source Location: #{meth.source_location ? meth.source_location.join(":") : "Not found."}
EOS
end
end
command_class "gist", "Gist a method or expression history to github. Type `gist --help` for more info.", :requires_gem => "gist", :shellwords => false do

View file

@ -5,40 +5,44 @@ class Pry
Introspection = Pry::CommandSet.new do
command "show-method", "Show the source for METH. Type `show-method --help` for more info. Aliases: $, show-source", :shellwords => false do |*args|
opts, meth = parse_options!(args, :method_object) do |opt|
opt.banner unindent <<-USAGE
Usage: show-method [OPTIONS] [METH]
Show the source for method METH. Tries instance methods first and then methods by default.
e.g: show-method hello_method
USAGE
command_class "show-method", "Show the source for METH. Type `show-method --help` for more info. Aliases: $, show-source", :shellwords => false do |*args|
banner <<-BANNER
Usage: show-method [OPTIONS] [METH]
Show the source for method METH. Tries instance methods first and then methods by default.
e.g: show-method hello_method
BANNER
def options(opt)
method_options(opt)
opt.on :l, "line-numbers", "Show line numbers."
opt.on :b, "base-one", "Show line numbers but start numbering at 1 (useful for `amend-line` and `play` commands)."
opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
end
raise CommandError, "Could not find method source" unless meth.source
def process
meth = method_object
raise CommandError, "Could not find method source" unless meth.source
output.puts make_header(meth)
output.puts "#{text.bold("Owner:")} #{meth.owner || "N/A"}"
output.puts "#{text.bold("Visibility:")} #{meth.visibility}"
output.puts
output.puts make_header(meth)
output.puts "#{text.bold("Owner:")} #{meth.owner || "N/A"}"
output.puts "#{text.bold("Visibility:")} #{meth.visibility}"
output.puts
if Pry.color
code = CodeRay.scan(meth.source, meth.source_type).term
else
code = meth.source
if Pry.color
code = CodeRay.scan(meth.source, meth.source_type).term
else
code = meth.source
end
start_line = false
if opts.present?(:'base-one')
start_line = 1
elsif opts.present?(:'line-numbers')
start_line = meth.source_line || 1
end
render_output(opts.present?(:flood), start_line, code)
end
start_line = false
if opts.present?(:'base-one')
start_line = 1
elsif opts.present?(:'line-numbers')
start_line = meth.source_line || 1
end
render_output(opts.present?(:flood), start_line, code)
end
alias_command "show-source", "show-method"
@ -199,64 +203,63 @@ class Pry
end
end
command "edit-method", "Edit a method. Type `edit-method --help` for more info.", :shellwords => false do |*args|
target = target()
command_class "edit-method", "Edit a method. Type `edit-method --help` for more info.", :shellwords => false do |*args|
opts, meth = parse_options!(args, :method_object) do |opt|
opt.banner unindent <<-USAGE
def options(opt)
opt.banner unindent <<-BANNER
Usage: edit-method [OPTIONS] [METH]
Edit the method METH in an editor.
Ensure #{text.bold("Pry.config.editor")} is set to your editor of choice.
e.g: edit-method hello_method
USAGE
BANNER
method_options(opt)
opt.on :n, "no-reload", "Do not automatically reload the method's file after editing."
opt.on "no-jump", "Do not fast forward editor to first line of method."
opt.on :p, :patch, "Instead of editing the method's file, try to edit in a tempfile and apply as a monkey patch."
opt.on :h, :help, "This message." do
output.puts opt.help
end
end
if !Pry.config.editor
raise CommandError, "No editor set!\nEnsure that #{text.bold("Pry.config.editor")} is set to your editor of choice."
end
if opts.present?(:patch) || meth.dynamically_defined?
lines = meth.source.lines.to_a
if ((original_name = meth.original_name) &&
lines[0] =~ /^def (?:.*?\.)?#{original_name}(?=[\(\s;]|$)/)
lines[0] = "def #{original_name}#{$'}"
else
raise CommandError, "Pry can only patch methods created with the `def` keyword."
def process
meth = method_object
if !Pry.config.editor
raise CommandError, "No editor set!\nEnsure that #{text.bold("Pry.config.editor")} is set to your editor of choice."
end
temp_file do |f|
f.puts lines.join
f.flush
invoke_editor(f.path, 0)
if opts.present?(:patch) || meth.dynamically_defined?
lines = meth.source.lines.to_a
if meth.alias?
with_method_transaction(original_name, meth.owner) do
Pry.new(:input => StringIO.new(File.read(f.path))).rep(meth.owner)
Pry.binding_for(meth.owner).eval("alias #{meth.name} #{original_name}")
end
if ((original_name = meth.original_name) &&
lines[0] =~ /^def (?:.*?\.)?#{original_name}(?=[\(\s;]|$)/)
lines[0] = "def #{original_name}#{$'}"
else
Pry.new(:input => StringIO.new(File.read(f.path))).rep(meth.owner)
raise CommandError, "Pry can only patch methods created with the `def` keyword."
end
temp_file do |f|
f.puts lines.join
f.flush
invoke_editor(f.path, 0)
if meth.alias?
with_method_transaction(original_name, meth.owner) do
Pry.new(:input => StringIO.new(File.read(f.path))).rep(meth.owner)
Pry.binding_for(meth.owner).eval("alias #{meth.name} #{original_name}")
end
else
Pry.new(:input => StringIO.new(File.read(f.path))).rep(meth.owner)
end
end
return
end
next
end
if meth.source_type == :c
raise CommandError, "Can't edit a C method."
else
file, line = meth.source_file, meth.source_line
if meth.source_type == :c
raise CommandError, "Can't edit a C method."
else
file, line = meth.source_file, meth.source_line
invoke_editor(file, opts["no-jump"] ? 0 : line)
silence_warnings do
load file if !opts.present?(:'no-jump') && !Pry.config.disable_auto_reload
invoke_editor(file, opts["no-jump"] ? 0 : line)
silence_warnings do
load file if !opts.present?(:'no-jump') && !Pry.config.disable_auto_reload
end
end
end
end

View file

@ -33,8 +33,6 @@ class Pry
opt.on :i, "ivars", "Show instance variables (in blue) and class variables (in bright blue)"
opt.on :G, "grep", "Filter output by regular expression", :optional => false
opt.on :h, "help", "Show help"
end
def process

View file

@ -3,54 +3,20 @@ class Pry
module OptionsHelpers
module_function
# Use Slop to parse the arguments given.
#
# @param [Array] args The options are stripped out by Slop.
# @param [*Symbol] extras Extra features you want returned.
# @param [&Block] used to add custom arguments to Slop.
#
# @option [Extra] :method_object Returns a method object.
#
# @return Slop::Options iff you don't pass any extras.
# @return [Array] If you do pass extras, an array is returned where the first argument is the
# Slop::Options object, and the remainder are the extras you requested in order.
#
def parse_options!(args, *extras, &block)
opts = Slop.parse!(args) do |opt|
extras.each{ |extra| send(:"add_#{extra}_options", opt) }
yield opt
opt.on :h, :help, "This message" do
output.puts opt.help
throw :command_done
end
end
if extras.empty?
opts
else
[opts] + extras.map{ |extra| send(:"process_#{extra}_options", args, opts) }
end
end
# Add the method object options to an unused Slop instance.
def add_method_object_options(opt)
# Add method options to the Slop instance
def method_options(opt)
@method_target = target
opt.on :M, "instance-methods", "Operate on instance methods."
opt.on :m, :methods, "Operate on methods."
opt.on :s, :super, "Select the 'super' method. Can be repeated to traverse the ancestors."
opt.on :s, :super, "Select the 'super' method. Can be repeated to traverse the ancestors.", :as => :count
opt.on :c, :context, "Select object context to run under.", true do |context|
@method_target = Pry.binding_for(target.eval(context))
end
end
# Add the derived :method_object option to a used Slop instance.
def process_method_object_options(args, opts)
# TODO: de-hack when we upgrade Slop: https://github.com/injekt/slop/pull/30
opts.options[:super].force_argument_value opts.options[:super].count if opts.present?(:super)
get_method_or_raise(args.empty? ? nil : args.join(" "), @method_target,
# Get the method object parsed by the slop instance
def method_object
@method_object ||= get_method_or_raise(args.empty? ? nil : args.join(" "), @method_target,
:super => opts[:super],
:instance => opts.present?(:'instance-methods') && !opts.present?(:'methods'),
:methods => opts.present?(:'methods') && !opts.present?(:'instance-methods')

View file

@ -125,6 +125,16 @@ describe "Pry::Command" do
mock_command(cmd, %w(--help)).output.should =~ /Total Perspective Vortex/
end
it 'should use the banner provided' do
cmd = @set.command_class 'deep-thought', "The second-best computer ever" do
banner <<-BANNER
Who's merest operational parameters, I am not worthy to compute.
BANNER
end
mock_command(cmd, %w(--help)).output.should =~ /Who\'s merest/
end
end