lib/tap/app/api.rb in tap-0.19.0 vs lib/tap/app/api.rb in tap-1.3.0
- old
+ new
@@ -1,7 +1,6 @@
-require 'configurable'
-require 'tap/signals/help'
+require 'tap/app'
module Tap
class App
# Api implements the application interface described in the
@@ -28,11 +27,11 @@
# subclass. The parser is also setup to print usage (using the desc
# for the subclass) and exit for the '-h' and '--help' options.
#
# The parse method uses parser by default, so subclasses can simply
# modify parser and ensure parse still works correctly.
- def parser
+ def parser(app)
opts = ConfigParser.new
unless configurations.empty?
opts.separator "configurations:"
opts.add(configurations)
@@ -40,38 +39,48 @@
end
opts.separator "options:"
# add option to print help
- opts.on("-h", "--help", "Print this help") do
- puts "#{self}#{desc.empty? ? '' : ' -- '}#{desc.to_s}"
- puts help
- puts opts
- exit
+ opts.on("--help", "Print this help") do
+ lines = ["#{self}#{desc.empty? ? '' : ' -- '}#{desc.to_s}"]
+ lines << help
+ lines << "usage: tap #{to_s.underscore} #{respond_to?(:args) ? args : nil}"
+ lines << nil
+ lines << opts
+ raise lines.join("\n")
end
opts
end
+ def parse(argv=ARGV, app=Tap::App.current, &block)
+ parse!(argv.dup, app, &block)
+ end
+
# Parses the argv into an instance of self. Internally parse parses
# an argh then calls build, but there is no requirement that this
# occurs in subclasses.
- def parse(argv=ARGV, app=Tap::App.instance)
- parse!(argv.dup, app)
- end
-
- # Same as parse, but removes arguments destructively.
- def parse!(argv=ARGV, app=Tap::App.instance)
- parser = self.parser
- argv = parser.parse!(argv, :add_defaults => false)
+ #
+ # Returns the instance. If a block is given, the instance and any
+ # remaining arguments will be yielded to it.
+ def parse!(argv=ARGV, app=Tap::App.current)
+ parser = self.parser(app)
+ args = parser.parse!(argv, :add_defaults => false)
+ obj = build(convert_to_spec(parser, args), app)
- [build({'config' => parser.nested_config}, app), argv]
+ if block_given?
+ yield(obj, args)
+ else
+ parser.warn_ignored_args(args)
+ obj
+ end
end
-
+
# Returns an instance of self. By default build calls new with the
# configurations specified by spec['config'], and app.
- def build(spec={}, app=Tap::App.instance)
+ def build(spec={}, app=Tap::App.current)
new(spec['config'] || {}, app)
end
# Returns a help string that formats the desc documentation.
def help
@@ -83,21 +92,27 @@
lines.push(line)
end
lines.join("\n")
end
+
+ protected
+
+ def convert_to_spec(parser, args)
+ {'config' => parser.nested_config}
+ end
end
include Configurable
include Signals
- signal :help, :class => Help, :bind => nil # signals help
+ define_signal :help, Help # signals help
- # The App receiving self during enq
+ # The app for self
attr_reader :app
- def initialize(config={}, app=Tap::App.instance)
+ def initialize(config={}, app=Tap::App.current)
@app = app
initialize_config(config)
end
# By default associations returns nil.
@@ -106,10 +121,16 @@
# By default to_spec returns a hash like {'config' => config} where
# config is a stringified representation of the configurations for self.
def to_spec
config = self.config.to_hash {|hash, key, value| hash[key.to_s] = value }
- {'config' => config}
+ config.empty? ? {} : {'config' => config}
+ end
+
+ # Provides an abbreviated version of the default inspect, with only the
+ # class, object_id, and configurations listed.
+ def inspect
+ "#<#{self.class.to_s}:#{object_id} #{config.to_hash.inspect} >"
end
end
end
end
\ No newline at end of file