Module: Boson::Scientist
Overview
Scientist wraps around and redefines an object’s method to give it the following features:
-
Methods can take shell command input with options or receive its normal arguments. See the Commandification section.
-
Methods have a slew of global options available. See OptionCommand for an explanation of basic global options.
The main methods Scientist provides are redefine_command() for redefining an object’s method with a Command object and commandify() for redefining with a hash of method attributes. Note that for an object’s method to be redefined correctly, its last argument must expect a hash.
Commandification
Take for example this basic method/command with an options definition:
:level=>:numeric, :verbose=>:boolean
def foo(*args)
args
end
When Scientist wraps around foo(), it can take arguments normally or as a shell command:
foo 'one', 'two', :verbose=>true # normal call
foo 'one two -v' # commandline call
Both calls return: ['one', 'two', {:verbose=>true}]
Non-string arguments can be passed as well:
foo Object, 'two', :level=>1
foo Object, 'two -l1'
Both calls return: [Object, 'two', {:level=>1}]
Defined Under Namespace
Classes: Error
Instance Attribute Summary collapse
-
#global_options ⇒ Object
Returns the value of attribute global_options.
Instance Method Summary collapse
-
#after_parse ⇒ Object
Hook method available after parse in translate_args.
-
#analyze(obj, command, args, &block) ⇒ Object
Runs a command given its object and arguments.
-
#commandify(obj, hash) ⇒ Object
A wrapper around redefine_command that doesn’t depend on a Command object.
-
#during_analyze(&block) ⇒ Object
Overridable method called during analyze.
-
#object_methods(obj) ⇒ Object
Returns hash of methods for an object.
-
#option_command(cmd = @command) ⇒ Object
option command for given command.
-
#redefine_command(obj, command) ⇒ Object
Redefines an object’s method with a Command of the same name.
-
#redefine_command_block(obj, command) ⇒ Object
The actual method which redefines a command’s original method.
Instance Attribute Details
#global_options ⇒ Object
Returns the value of attribute global_options.
38 39 40 |
# File 'lib/boson/scientist.rb', line 38 def @global_options end |
Instance Method Details
#after_parse ⇒ Object
Hook method available after parse in translate_args
119 |
# File 'lib/boson/scientist.rb', line 119 def after_parse; end |
#analyze(obj, command, args, &block) ⇒ Object
Runs a command given its object and arguments
103 104 105 106 107 108 109 110 111 |
# File 'lib/boson/scientist.rb', line 103 def analyze(obj, command, args, &block) @global_options, @command, @original_args = {}, command, args.dup @args = translate_args(obj, args) return run_help_option(@command) if @global_options[:help] during_analyze(&block) rescue OptionParser::Error, Error raise if Boson.in_shell warn "Error: #{$!}" end |
#commandify(obj, hash) ⇒ Object
A wrapper around redefine_command that doesn’t depend on a Command object. Rather you simply pass a hash of command attributes (see Command.new) or command methods and let OpenStruct mock a command. The only required attribute is :name, though to get any real use you should define :options and :arg_size (default is ‘*’). Example:
>> def checkit(*args); args; end
=> nil
>> Boson::Scientist.commandify(self, :name=>'checkit', :options=>{:verbose=>:boolean, :num=>:numeric})
=> ['checkit']
# regular ruby method
>> checkit 'one', 'two', :num=>13, :verbose=>true
=> ["one", "two", {:num=>13, :verbose=>true}]
# commandline ruby method
>> checkit 'one two -v -n=13'
=> ["one", "two", {:num=>13, :verbose=>true}]
69 70 71 72 73 74 75 76 |
# File 'lib/boson/scientist.rb', line 69 def commandify(obj, hash) raise ArgumentError, ":name required" unless hash[:name] hash[:arg_size] ||= '*' hash[:has_splat_args?] = true if hash[:arg_size] == '*' fake_cmd = OpenStruct.new(hash) fake_cmd.option_parser ||= OptionParser.new(fake_cmd. || {}) redefine_command(obj, fake_cmd) end |
#during_analyze(&block) ⇒ Object
Overridable method called during analyze
114 115 116 |
# File 'lib/boson/scientist.rb', line 114 def during_analyze(&block) process_result call_original_command(@args, &block) end |
#object_methods(obj) ⇒ Object
Returns hash of methods for an object
93 94 95 |
# File 'lib/boson/scientist.rb', line 93 def object_methods(obj) @object_methods[obj] ||= {} end |
#option_command(cmd = @command) ⇒ Object
option command for given command
98 99 100 |
# File 'lib/boson/scientist.rb', line 98 def option_command(cmd=@command) @option_commands[cmd] ||= OptionCommand.new(cmd) end |
#redefine_command(obj, command) ⇒ Object
Redefines an object’s method with a Command of the same name.
44 45 46 47 48 49 50 51 52 |
# File 'lib/boson/scientist.rb', line 44 def redefine_command(obj, command) cmd_block = redefine_command_block(obj, command) @no_option_commands << command if command..nil? [command.name, command.alias].compact.each {|e| obj.singleton_class.send(:define_method, e, cmd_block) } rescue Error warn "Error: #{$!.}" end |
#redefine_command_block(obj, command) ⇒ Object
The actual method which redefines a command’s original method
79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/boson/scientist.rb', line 79 def redefine_command_block(obj, command) object_methods(obj)[command.name] ||= begin obj.method(command.name) rescue NameError raise Error, "No method exists to redefine command '#{command.name}'." end lambda {|*args| Scientist.analyze(obj, command, args) {|args| Scientist.object_methods(obj)[command.name].call(*args) } } end |