Module: Command::DSL::Argument
- Included in:
- AlternatingArgument, ArgumentDecorator, CommandDefinition
- Defined in:
- lib/command-set/dsl.rb
Overview
The meta-programmatic machinery to create arguments quickly. Includes methods such that argument classes can register themselves into the DSL. Much of this module is unfortunately obtuse - it’s designed so that argument types can be easily extended, which makes the actual DSL trickier to document.
Ultimately, arguments are governed by their basic type (which descends from Argument) and the ArgumentDecorator objects that wrap it.
Within a Command#setup or CommandSet#command block, you can make decorator and argument calls like:
optional.named.string_argument :person, "A Person"
Which will create a StringArgument and wrap it in the NamedArgument and OptionalArgument ArgumentDecorators. This sounds confusing, but the upshot is that the person
argument can be omitted, but if it’s included, it must be preceded with the argument’s name: “person” like so:
> command person judson
Which will assign “judson” to the person
argument for the command.
:include: doc/argumentDSL
Defined Under Namespace
Classes: SubjectDeferral
Constant Summary collapse
- @@decorator_map =
{}
- @@argmap =
{}
- @@shorthand_map =
{}
Class Method Summary collapse
-
.argument_typemap ⇒ Object
:nodoc:.
-
.document ⇒ Object
Generates rdoc ready documentation of the decorator and argument methods created by #register calls.
-
.register_argument(klass, shorthand, type = nil) ⇒ Object
The Argument#register method calls back to this, which creates methods like
funky_argument
that are responsible for embedding the actual arguments in the Commands they’re declared for. -
.register_decorator(klass, method) ⇒ Object
The ArgumentDecorator#register method calls back to this, so that decorators can quickly register a method to wrap an argument with themselves.
Instance Method Summary collapse
-
#alternating_argument(name = nil, &block) ⇒ Object
(also: #alternating)
Sugar for creating an alternating argument.
-
#argument(arg, *values, &get_values) ⇒ Object
The basic argument definition.
-
#create(name, basis) ⇒ Object
The method used to instantiate arguments based on their values.
-
#create_decorator(&block) ⇒ Object
When an ArgumentDecorator calls self.register, this method is aliased with the name the decorator passes It takes care of instantiating the decorator such that it’s available to decorate the eventual argument.
-
#named_optionals ⇒ Object
:nodoc:.
-
#special_argument(name, values = nil, &get_values) ⇒ Object
This method functions analogously to create_decorator, except it works for arguments, not decorators.
-
#subject ⇒ Object
Returns a SubjectDeferral Ultimately, this allows you to reference and base an argument on a value in the subject.
Class Method Details
.argument_typemap ⇒ Object
:nodoc:
296 297 298 |
# File 'lib/command-set/dsl.rb', line 296 def self.argument_typemap #:nodoc: @@argmap end |
.document ⇒ Object
Generates rdoc ready documentation of the decorator and argument methods created by #register calls. Output is included in this module’s documentation. Also useful if you want to document your own argument class’ contributions. Try something like:
> ruby -r"lib/command-set/arguments.rb" -e "puts Command::DSL::Argument::document"
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
# File 'lib/command-set/dsl.rb', line 251 def self.document docs = <<-EOD There are two kinds of methods available for #{self.name}. First there are decorators. They mark up arguments with extra meaning, like being optional. The second are actual argument creation calls, which are shorthand for something like argument FiddlyArgument {} In general, you'll use these something like decorator.decorator.shorthand_argument "name" For instance named.optional.file_argument "config" Decorator methods, and the classes they add: EOD @@decorator_map.each_pair do |method, klass| docs += "+#{method}+:: #{klass.name.sub("Command::","")}\n" end docs += <<-EOD The shorthand argument methods are: EOD @@shorthand_map.to_a.sort.each do |method, klass| docs += "+#{method}+:: #{klass.name.sub("Command::","")}\n" end docs += <<-EOD Don't forget about #alternating_argument and #argument itself! EOD indent = /^\s+/.match(docs)[0] docs.gsub!(/^#{indent}/, "") return docs end |
.register_argument(klass, shorthand, type = nil) ⇒ Object
The Argument#register method calls back to this, which creates methods like funky_argument
that are responsible for embedding the actual arguments in the Commands they’re declared for.
234 235 236 237 238 239 240 241 242 243 |
# File 'lib/command-set/dsl.rb', line 234 def self.register_argument(klass, shorthand, type=nil) unless type.nil? or not Class === type or @@argmap.has_key?(type) @@argmap[type]=klass end method_name = shorthand + "_argument" @@shorthand_map[method_name] = klass alias_method method_name, :special_argument end |
.register_decorator(klass, method) ⇒ Object
The ArgumentDecorator#register method calls back to this, so that decorators can quickly register a method to wrap an argument with themselves.
224 225 226 227 |
# File 'lib/command-set/dsl.rb', line 224 def self.register_decorator(klass, method) @@decorator_map[method] = klass alias_method method, :create_decorator end |
Instance Method Details
#alternating_argument(name = nil, &block) ⇒ Object Also known as: alternating
Sugar for creating an alternating argument. Basically, an alternating argument is a series of arguments, any of which could be set. They either need to be of distinct types, or use named
to distinguish between them.
354 355 356 357 |
# File 'lib/command-set/dsl.rb', line 354 def alternating_argument(name=nil, &block) arg = AlternatingArgument.new(self, &block) arg.name(name) end |
#argument(arg, *values, &get_values) ⇒ Object
The basic argument definition. If arg
is an Argument object, it’ll be used - which means that you can explicitly create and argument and embed it. Otherwise, the values of values
or get_values
will be used to create the argument
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 |
# File 'lib/command-set/dsl.rb', line 323 def argument(arg, *values, &get_values) name = nil argument = nil if(::Command::Argument === arg) name = arg.name argument = arg elsif(Class === arg and ::Command::Argument > arg) argument = arg.new(values[0], get_values||values[1]) else name = arg argument = create(name, get_values||values.first) end return self.(argument) end |
#create(name, basis) ⇒ Object
The method used to instantiate arguments based on their values. Searches all registered Argument classes, from children up, until one admits to being able to create arguments based on the value.
364 365 366 367 368 369 370 371 372 |
# File 'lib/command-set/dsl.rb', line 364 def create(name, basis) @@argmap.keys.sort{|r,l|(r>l)?1:-1}.each do |type| #Check child classes first if type === basis return @@argmap[type].new(name, basis) end end raise TypeError, "Don't know how to base an argument " + "on #{basis.class}" end |
#create_decorator(&block) ⇒ Object
When an ArgumentDecorator calls self.register, this method is aliased with the name the decorator passes It takes care of instantiating the decorator such that it’s available to decorate the eventual argument.
Don’t look to closely at the source. It does bad things.
305 306 307 308 |
# File 'lib/command-set/dsl.rb', line 305 def create_decorator(&block) me = /:in `([^']*)/.match(caller(0)[0])[1] return ArgumentDecorator.new(self, @@decorator_map[me], &block) end |
#named_optionals ⇒ Object
:nodoc:
374 375 376 |
# File 'lib/command-set/dsl.rb', line 374 def named_optionals #:nodoc: raise NotImplementedException end |
#special_argument(name, values = nil, &get_values) ⇒ Object
This method functions analogously to create_decorator, except it works for arguments, not decorators. It’s worth looking at as the call signature for all funky_argument
style calls.
313 314 315 316 317 |
# File 'lib/command-set/dsl.rb', line 313 def special_argument(name, values=nil, &get_values) me = /:in `([^']*)/.match(caller(0)[0])[1] argument = @@shorthand_map[me].new(name, get_values||values) return self.(argument) end |
#subject ⇒ Object
Returns a SubjectDeferral Ultimately, this allows you to reference and base an argument on a value in the subject. Check this out:
number_argument :which_little_pig subject.pigs {|pigs| 1..pigs.length}
When that argument is evaluated, the pigs (is_a? Array) field of the subject will get turned into a range: from 1 to it’s length.
346 347 348 |
# File 'lib/command-set/dsl.rb', line 346 def subject return SubjectDeferral.new end |