Module: Clio::Commandable
- Defined in:
- lib/clio/commandable.rb
Overview
Commandable Mixin
The Commandable mixin is a very quick and and easy way to make almost any class usable via a command line interface. It simply uses writer methods as option setters, and the first command line argument as the method to call, with the subsequent arguments passed to the method.
The only limitation of this approach (besides the weak control of the process) is that required options must be specified with the key=value notation.
class X
include Clio::Commandable
attr_accessor :quiet
def bread(*args)
["BREAD", quiet, *args]
end
def butter(*args)
["BUTTER", quiet, *args]
end
end
x = X.new
x.execute_command("butter yum")
=> ["BUTTER", nil, "yum"]
x.execute_command("bread --quiet")
=> ["BUTTER", true]
Commandable also defines #command_missing and #option_missing, which you can override to provide suitable results.
TODO: Maybe command_missing is redundant, and method_missing would suffice?
Class Method Summary collapse
- .parse(obj, argv) ⇒ Object
- .parse_equal(obj, opt, argv) ⇒ Object
- .parse_flags(obj, opt, args) ⇒ Object
- .parse_option(obj, opt, argv) ⇒ Object
- .run(obj, argv = ARGV) ⇒ Object
Instance Method Summary collapse
-
#command_missing ⇒ Object
This is the fallback subcommand.
-
#execute_command(argv = ARGV) ⇒ Object
Used to invoke the command.
-
#option_missing(opt, *argv) ⇒ Object
Override option_missing if needed.
Class Method Details
.parse(obj, argv) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/clio/commandable.rb', line 86 def parse(obj, argv) case argv when String require 'shellwords' argv = Shellwords.shellwords(argv) else argv = argv.dup end argv = argv.dup args, opts, i = [], {}, 0 while argv.size > 0 case opt = argv.shift when /=/ parse_equal(obj, opt, argv) when /^--/ parse_option(obj, opt, argv) when /^-/ parse_flags(obj, opt, argv) else args << opt end end return args end |
.parse_equal(obj, opt, argv) ⇒ Object
113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/clio/commandable.rb', line 113 def parse_equal(obj, opt, argv) if md = /^[-]*(.*?)=(.*?)$/.match(opt) x, v = md[1], md[2] else raise ArgumentError, "#{x}" end if obj.respond_to?("#{x}=") # TODO: to_b if 'true' or 'false' ? obj.send("#{x}=",v) else obj.option_missing(x, v) # argv? end end |
.parse_flags(obj, opt, args) ⇒ Object
138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/clio/commandable.rb', line 138 def parse_flags(obj, opt, args) x = opt[1..-1] c = 0 x.split(//).each do |k| if obj.respond_to?("#{k}=") obj.send("#{k}=",true) else obj.option_missing(x, argv) end end end |
.parse_option(obj, opt, argv) ⇒ Object
128 129 130 131 132 133 134 135 |
# File 'lib/clio/commandable.rb', line 128 def parse_option(obj, opt, argv) x = opt[2..-1] if obj.respond_to?("#{x}=") obj.send("#{x}=",true) else obj.option_missing(x, argv) end end |
.run(obj, argv = ARGV) ⇒ Object
69 70 71 72 73 74 75 76 77 |
# File 'lib/clio/commandable.rb', line 69 def run(obj, argv=ARGV) args = parse(obj, argv) subcmd = args.shift if subcmd && !obj.respond_to?("#{subcmd}=") obj.send(subcmd, *args) else obj.command_missing end end |
Instance Method Details
#command_missing ⇒ Object
This is the fallback subcommand. Override this to provide a fallback when no command is given on the commandline.
54 55 56 |
# File 'lib/clio/commandable.rb', line 54 def command_missing raise NoCommandError end |
#execute_command(argv = ARGV) ⇒ Object
Used to invoke the command.
48 49 50 |
# File 'lib/clio/commandable.rb', line 48 def execute_command(argv=ARGV) Commandable.run(self, argv) end |
#option_missing(opt, *argv) ⇒ Object
Override option_missing if needed. This receives the name of the option and the remaining arguments list. It must consume any argument it uses from the (begining of) the list.
63 64 65 |
# File 'lib/clio/commandable.rb', line 63 def option_missing(opt, *argv) raise NoOptionError, opt end |