yacl 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/HISTORY.rdoc +5 -0
- data/LICENSE +16 -0
- data/Manifest.txt +48 -0
- data/README.rdoc +55 -0
- data/Rakefile +308 -0
- data/example/myapp-simple/bin/myapp +16 -0
- data/example/myapp-simple/config/database.yml +8 -0
- data/example/myapp-simple/config/host.yml +2 -0
- data/example/myapp-simple/config/pipeline.yml +1 -0
- data/example/myapp-simple/lib/myapp.rb +53 -0
- data/example/myapp/bin/myapp +17 -0
- data/example/myapp/bin/myapp-job +10 -0
- data/example/myapp/config/database.yml +8 -0
- data/example/myapp/config/httpserver.yml +3 -0
- data/example/myapp/config/pipeline.yml +1 -0
- data/example/myapp/lib/myapp.rb +6 -0
- data/example/myapp/lib/myapp/cli.rb +92 -0
- data/example/myapp/lib/myapp/defaults.rb +28 -0
- data/example/myapp/lib/myapp/job.rb +56 -0
- data/lib/yacl.rb +12 -0
- data/lib/yacl/define.rb +9 -0
- data/lib/yacl/define/cli.rb +7 -0
- data/lib/yacl/define/cli/options.rb +97 -0
- data/lib/yacl/define/cli/parser.rb +112 -0
- data/lib/yacl/define/cli/runner.rb +82 -0
- data/lib/yacl/define/defaults.rb +58 -0
- data/lib/yacl/define/plan.rb +197 -0
- data/lib/yacl/loader.rb +80 -0
- data/lib/yacl/loader/env.rb +103 -0
- data/lib/yacl/loader/yaml_dir.rb +137 -0
- data/lib/yacl/loader/yaml_file.rb +102 -0
- data/lib/yacl/properties.rb +144 -0
- data/lib/yacl/simple.rb +52 -0
- data/spec/data/yaml_dir/database.yml +8 -0
- data/spec/data/yaml_dir/httpserver.yml +3 -0
- data/spec/define/cli/options_spec.rb +47 -0
- data/spec/define/cli/parser_spec.rb +64 -0
- data/spec/define/cli/runner_spec.rb +57 -0
- data/spec/define/defaults_spec.rb +24 -0
- data/spec/define/plan_spec.rb +77 -0
- data/spec/loader/env_spec.rb +32 -0
- data/spec/loader/yaml_dir_spec.rb +43 -0
- data/spec/loader/yaml_file_spec.rb +80 -0
- data/spec/loader_spec.rb +16 -0
- data/spec/properties_spec.rb +60 -0
- data/spec/simple_spec.rb +85 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/version_spec.rb +8 -0
- metadata +207 -0
@@ -0,0 +1 @@
|
|
1
|
+
dir: /tmp/foo/bar
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'yacl'
|
2
|
+
module MyApp
|
3
|
+
# This is a simplier version of 'myapp' example where we use a DSL instead of
|
4
|
+
# explicit classes. Under hte covers, this creats classes that do the same as
|
5
|
+
# the explicit version.
|
6
|
+
#
|
7
|
+
# For simpler cases where you want to put all of this together this may make
|
8
|
+
# more sense.
|
9
|
+
class Application < ::Yacl::Simple
|
10
|
+
|
11
|
+
# This defines a MyApp::Application::Defaults class. This class is also
|
12
|
+
# available via MyApp::Application.defaults
|
13
|
+
defaults do
|
14
|
+
default 'archive.uri' , 'http://archive.example.com'
|
15
|
+
default 'messaging.uri' , 'kestrel://messaging1.example.com:2229/'
|
16
|
+
default 'messaging.queue', 'pending'
|
17
|
+
default 'system' , 'main'
|
18
|
+
default 'timelimit' , '10'
|
19
|
+
end
|
20
|
+
|
21
|
+
# This defines a MyApp::Application::Parser class. This class is also
|
22
|
+
# available via MyApp::Application.parser
|
23
|
+
parser do
|
24
|
+
banner "myapp [options]+"
|
25
|
+
opt 'pipeline.dir', :long => 'pipeline-dir', :short => 'd', :description => "The pipeline directory we are using", :cast => :string
|
26
|
+
opt 'config.dir' , :long => 'config-dir', :short => 'c', :description => "The directory to load configuration from", :cast => :string
|
27
|
+
opt 'timelimit' , :long => 'time-limit', :short => 't', :description => "The amount of time to run for", :cast => :integer
|
28
|
+
opt 'system' , :long => 'system', :short => 's', :description => "The system setting", :cast => :string
|
29
|
+
opt 'debug' , :long => 'debug', :sortt => 'D', :description => "Turn on debugging", :cast => :boolean
|
30
|
+
end
|
31
|
+
|
32
|
+
# This defines a MyApp::Application::Plan class. This class is also
|
33
|
+
# available via MyApp::Application.plan
|
34
|
+
plan do
|
35
|
+
try MyApp::Application.parser
|
36
|
+
try Yacl::Loader::Env, :prefix => 'MY_APP'
|
37
|
+
try Yacl::Loader::YamlDir, :parameter => 'config.dir'
|
38
|
+
try MyApp::Application.defaults
|
39
|
+
|
40
|
+
on_error do |exception|
|
41
|
+
$stderr.puts "ERROR: #{exception}"
|
42
|
+
$stderr.puts "Try --help for help"
|
43
|
+
exit 1
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# This is the method that will be run when it is executed on the
|
48
|
+
# commandline.
|
49
|
+
def run
|
50
|
+
puts properties.map.inspect
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# load path munging so the example works from a git checkout, do not do this
|
4
|
+
# in your program
|
5
|
+
$: << File.expand_path( "../../../../lib", __FILE__ ) # yacl library
|
6
|
+
$: << File.expand_path( "../../lib", __FILE__ ) # lib dir of this sample app
|
7
|
+
require 'rubygems'
|
8
|
+
|
9
|
+
#------------------------------------------------------------------------------
|
10
|
+
# This would be the top level commandline entry point for your program. Feel
|
11
|
+
# free to have multiple of them if that is what your situation requires.
|
12
|
+
#------------------------------------------------------------------------------
|
13
|
+
|
14
|
+
require 'myapp'
|
15
|
+
require 'myapp/cli'
|
16
|
+
|
17
|
+
MyApp::Cli::Runner.go( ARGV, ENV )
|
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#------------------------------------------------------------------------------
|
4
|
+
# This would be a top-level entrypoint into your system that was not commandline
|
5
|
+
# based. Think loaded by some other framework. Maybe a Torquebox Job or a
|
6
|
+
# Resqueue Job or something that was more static.
|
7
|
+
#------------------------------------------------------------------------------
|
8
|
+
|
9
|
+
require 'myapp'
|
10
|
+
MyApp::Job::ForSomething.new( "pipeline.dir" => "/over/there" )
|
@@ -0,0 +1 @@
|
|
1
|
+
dir: /tmp/foo/bar
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'myapp/defaults'
|
2
|
+
module MyApp
|
3
|
+
# In this example I am encapsulating everything that has to do with a
|
4
|
+
# commandline program within the Cli module. For this example, there is one
|
5
|
+
# and only one commandline program.
|
6
|
+
module Cli
|
7
|
+
|
8
|
+
# The Commandline options for our program. This maps the commandline
|
9
|
+
# options, given in the :long and :short style for consistency in
|
10
|
+
# commandline functionalyt to their property names which have a dotten
|
11
|
+
# notation and make property access consistent throughout the program.
|
12
|
+
#
|
13
|
+
# These Options are to be used by the Parser class.
|
14
|
+
class Options < Yacl::Define::Cli::Options
|
15
|
+
opt 'pipeline.dir', :long => 'pipeline-dir', :short => 'd', :description => "The pipeline directory we are using", :cast => :string
|
16
|
+
opt 'config.dir' , :long => 'config-dir', :short => 'c', :description => "The directory to load configuration from", :cast => :string
|
17
|
+
opt 'timelimit' , :long => 'time-limit', :short => 't', :description => "The amount of time to run for", :cast => :integer
|
18
|
+
opt 'system' , :long => 'system', :short => 's', :description => "The system setting", :cast => :string
|
19
|
+
opt 'debug' , :long => 'debug', :sortt => 'D', :description => "Turn on debugging", :cast => :boolean
|
20
|
+
end
|
21
|
+
|
22
|
+
# The Parser class. This is kept explicitly separate from the Options class
|
23
|
+
# so that, you may, if you like use whatever commadnline parser
|
24
|
+
# library/program you whish. By default this library will automatically use
|
25
|
+
# trollop and generate a commandline for you from it. If you whish to use
|
26
|
+
# another commandline library, you may define your own Parser class.
|
27
|
+
#
|
28
|
+
# Use Yacl::Define::Cli::Parser as a template for how you would like to do
|
29
|
+
# your work. YOu can probably get by with inheriting from
|
30
|
+
# Yacl::Define::Cli::Parser and overwriting the #delegate_parser and #parse
|
31
|
+
# methods.
|
32
|
+
class Parser < Yacl::Define::Cli::Parser
|
33
|
+
banner "myapp [options]+"
|
34
|
+
options MyApp::Cli::Options
|
35
|
+
end
|
36
|
+
|
37
|
+
# The Plan class, this defines the order of loading of your properties and the
|
38
|
+
# order of resolution of when looking up a property. The property Loaders
|
39
|
+
# are loaded in the defined order below, and that is their priority. For
|
40
|
+
# example the 'config.dir' property may be defiend in the Parser and the
|
41
|
+
# Environment, and in this case if it has a value in the Env but not the
|
42
|
+
# Parser the Env value will take precidence. If there is a value in the
|
43
|
+
# Parser though, that will be the value used.
|
44
|
+
#
|
45
|
+
# In this case, since we know that this plan has a commandline, we're
|
46
|
+
# catching any load errors and printing out to stderr on a failure. If this
|
47
|
+
# perhaps was used in a non-commandline situation the on_error block could
|
48
|
+
# do something completely different.
|
49
|
+
class Plan < Yacl::Define::Plan
|
50
|
+
|
51
|
+
# 1) parse the commandline and load properties from the mapping of the
|
52
|
+
# commandline to the property names.
|
53
|
+
try MyApp::Cli::Parser
|
54
|
+
|
55
|
+
# 2) using the environment and only those environment variables that
|
56
|
+
# start with MY_APP load additional properties.
|
57
|
+
try Yacl::Loader::Env, :prefix => 'MY_APP'
|
58
|
+
|
59
|
+
# 3) using the config.dir value, which is probably set via the
|
60
|
+
# --config-dir parser option, or via the MY_APP_CONFIG_DIR environment
|
61
|
+
# variable laod up some more properties.
|
62
|
+
try Yacl::Loader::YamlDir, :parameter => 'config.dir'
|
63
|
+
|
64
|
+
# 4) if a property is not found in any of the previous locations, then use
|
65
|
+
# the defaults. And if it is not in the defaults, then we will return nil
|
66
|
+
try MyApp::Defaults
|
67
|
+
|
68
|
+
# If an error happens while attempting to load the properties the print a
|
69
|
+
# message on stderr and exit the program.
|
70
|
+
on_error do |exception|
|
71
|
+
$stderr.puts "ERROR: #{exception}"
|
72
|
+
$stderr.puts "Try --help for help"
|
73
|
+
exit 1
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# The Runner class, this is what is instantiated in the bin script and
|
78
|
+
# invoked from the commandline. It uses the Plan and a #run method you
|
79
|
+
# define to take actione.
|
80
|
+
#
|
81
|
+
# In this particular case, it just prints out the properties.
|
82
|
+
class Runner < ::Yacl::Define::Cli::Runner
|
83
|
+
plan MyApp::Cli::Plan
|
84
|
+
|
85
|
+
def run
|
86
|
+
p = properties
|
87
|
+
puts p.map.inspect
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'yacl'
|
2
|
+
module MyApp
|
3
|
+
# The core defaults of your system. Not all of your default properties need to
|
4
|
+
# be defined. It is your choice what is defined and what isn't. Think of these
|
5
|
+
# as the hardcoded defaults that if the property is not overwritte by
|
6
|
+
# something else in the system, then it will fall back to this.
|
7
|
+
#
|
8
|
+
# Sensible Defaults in other words.
|
9
|
+
#
|
10
|
+
# Possible ways of using these:
|
11
|
+
#
|
12
|
+
# - Have different Defaults for development/test/production
|
13
|
+
# - Use this for things that are hardly ever overwritten
|
14
|
+
# - global defaults that are common across many sub-components.
|
15
|
+
#
|
16
|
+
# It would be perfectly reasonable to have different classes defined for
|
17
|
+
# different things. Different commandline applications, or entrypoints into
|
18
|
+
# the library etc.
|
19
|
+
class Defaults < Yacl::Define::Defaults
|
20
|
+
default 'archive.uri' , 'http://archive.example.com'
|
21
|
+
default 'messaging.uri' , 'kestrel://messaging1.example.com:2229/'
|
22
|
+
default 'messaging.queue', 'pending'
|
23
|
+
default 'system' , 'main'
|
24
|
+
default 'timelimit' , '10'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'myapp/defaults'
|
2
|
+
module MyApp
|
3
|
+
# In this case we are assuming that the application is not part of a
|
4
|
+
# commandline program and it may be used from some other library and it still
|
5
|
+
# needs to load its config from some location.
|
6
|
+
#
|
7
|
+
# This could be the case of :
|
8
|
+
# - Resque or some other background job system
|
9
|
+
# - Part of a torquebox configuration
|
10
|
+
# - embedded in some other library
|
11
|
+
module Job
|
12
|
+
|
13
|
+
# We have a plan just as we did with the commandline one, but without the
|
14
|
+
# commandline parser.
|
15
|
+
class Plan < Yacl::Define::Plan
|
16
|
+
# First try to load properties from the environment variables that start
|
17
|
+
# with MY_PREFIX
|
18
|
+
try Yacl::Loader::Env, :prefix => 'MY_APP'
|
19
|
+
|
20
|
+
# Next we will load from an explicit directory.
|
21
|
+
try Yacl::Loader::YamlDir, :path => File.expand_path( "../../../config", __FILE__ )
|
22
|
+
|
23
|
+
# And finally we will use the built in defaults
|
24
|
+
try MyApp::Defaults
|
25
|
+
|
26
|
+
# On an error we just print to stderr saying that we do not know what is
|
27
|
+
# going on. We could re-reise the exception, or just let it naturally
|
28
|
+
# percolate up if we wanted something else to handle it.
|
29
|
+
on_error do |exception|
|
30
|
+
$stderr.puts exception
|
31
|
+
$stderr.puts exception.backtrace.join("\n")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# In this situation we have a class that needs to use the plan and do
|
36
|
+
# something with it. Instead of having a commandline program, this is the
|
37
|
+
# clasee that serves as the interface between our code and someone elses
|
38
|
+
# code.
|
39
|
+
class ForSomething
|
40
|
+
|
41
|
+
# We will take a hash here so that the external program can explicitly
|
42
|
+
# pass in as set of initial properties and have them bee the most highly
|
43
|
+
# prioritiezed values in the plan stack.
|
44
|
+
#
|
45
|
+
# We also explictly use the Plan here, and do not assume that there is a
|
46
|
+
# runner.
|
47
|
+
def initialize( params )
|
48
|
+
p = Yacl::Properties.new( params )
|
49
|
+
plan = Job::Plan.new( :initial_properties => p )
|
50
|
+
puts plan.properties.map.inspect
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
data/lib/yacl.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# Yacl is Your Application Configuration Library.
|
2
|
+
#
|
3
|
+
# See the README
|
4
|
+
module Yacl
|
5
|
+
# The Current Version of the library
|
6
|
+
VERSION = "1.0.0"
|
7
|
+
class Error < ::StandardError; end
|
8
|
+
end
|
9
|
+
require 'yacl/properties'
|
10
|
+
require 'yacl/loader'
|
11
|
+
require 'yacl/define'
|
12
|
+
require 'yacl/simple'
|
data/lib/yacl/define.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
module Yacl::Define::Cli
|
2
|
+
|
3
|
+
# Internal: Encapsulation of all the elements pertaining to a single
|
4
|
+
# commandline option.
|
5
|
+
Option = Struct.new( :property_name, :long, :short, :description, :cast)
|
6
|
+
|
7
|
+
# Public: Inherit from Cli::Options to define your the mapping between your
|
8
|
+
# application properties and commandline switches.
|
9
|
+
#
|
10
|
+
# The class you create from here is to be used in conjuction with a class you
|
11
|
+
# create that is a child class of Cli::Parser.
|
12
|
+
#
|
13
|
+
# Example:
|
14
|
+
#
|
15
|
+
# class MyOptions < ::Yacl::Define::Cli::Options
|
16
|
+
# opt 'log.level', :long => 'log-level', :short => 'l', :description => "Logging Level", :cast => :string
|
17
|
+
# opt 'config.dir',:long => 'config-dir', :short => 'c', :description => "Configuration directory", :cast => :string
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# o = MyOptions.new( 'log-level' => 'debug', 'config-dir' => '/tmp/foo' )
|
21
|
+
# o.properties # => Properties instance with 'log.level' => debug and 'config.dir' => '/tmp/foo'
|
22
|
+
#
|
23
|
+
class Options < ::Yacl::Loader
|
24
|
+
|
25
|
+
# Internal: access to the defined list of options
|
26
|
+
#
|
27
|
+
# Returns the Array of options
|
28
|
+
def self.opt_list
|
29
|
+
@opt_list ||= []
|
30
|
+
end
|
31
|
+
|
32
|
+
# Public: Declare a property and its corresponding commandline options.
|
33
|
+
#
|
34
|
+
# name - The property name as a String
|
35
|
+
# params - The Hash options to accompany the property name (default: {})
|
36
|
+
# :long - The long commandline option. Without leading dashes
|
37
|
+
# :short - The short commandline option. Without leading dashes
|
38
|
+
# :description - The text description of this commandline option
|
39
|
+
# :cast - What to cast the value of the commandline option
|
40
|
+
# to. This can be one of: :integer, :float, :string,
|
41
|
+
# :boolean
|
42
|
+
#
|
43
|
+
# Examples:
|
44
|
+
#
|
45
|
+
# opt 'app.thing.one', :long => 'thing-one', :short => 't', :description => "Thing One", :cast => :string
|
46
|
+
#
|
47
|
+
# Returns nothing.
|
48
|
+
def self.opt(name, params = {} )
|
49
|
+
opt_list << Option.new( name, params[:long], params[:short], params[:description ], params[:cast] )
|
50
|
+
end
|
51
|
+
|
52
|
+
# Public: Load the Properties from the options that were passed to the
|
53
|
+
# initializer.
|
54
|
+
#
|
55
|
+
# Returns a Properties instance.
|
56
|
+
def properties
|
57
|
+
load_properties( @options )
|
58
|
+
end
|
59
|
+
|
60
|
+
# Public: yield each defined Option in this class to the caller
|
61
|
+
#
|
62
|
+
# Yields the Option instance of the iteration.
|
63
|
+
#
|
64
|
+
# Returns nothing.
|
65
|
+
def each
|
66
|
+
opt_list.each do |o|
|
67
|
+
yield o
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Internal: Return the list of defined options for this Class.
|
72
|
+
#
|
73
|
+
# Returns an Array of Option instances
|
74
|
+
def opt_list
|
75
|
+
self.class.opt_list
|
76
|
+
end
|
77
|
+
|
78
|
+
# Internal: convert the given hash of long options into a Properties
|
79
|
+
# instance using the defined options.
|
80
|
+
#
|
81
|
+
# It is assumed that the commandline has already been parsed and that the
|
82
|
+
# hash passed in is the long options that were parsed out of the
|
83
|
+
# commandline.
|
84
|
+
#
|
85
|
+
# hash - a Hash of long options and their values.
|
86
|
+
#
|
87
|
+
# Returns a Properties instance
|
88
|
+
def load_properties( hash )
|
89
|
+
prop_hash = {}
|
90
|
+
opt_list.each do |o|
|
91
|
+
next unless hash.has_key?( o.long )
|
92
|
+
prop_hash[o.property_name] = hash[o.long]
|
93
|
+
end
|
94
|
+
return Yacl::Properties.new( prop_hash )
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'trollop'
|
2
|
+
module Yacl::Define::Cli
|
3
|
+
# Public: Parser is a Loader that uses a Cli::Options class and the Trollop
|
4
|
+
# parser to convert commandline options into a Properties instance. It is to
|
5
|
+
# be inherited from so you can have your own parser per commandline program in
|
6
|
+
# your application suite.
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
#
|
10
|
+
# class MyOptions < ::Yacl::Define::Cli::Options
|
11
|
+
# opt 'log.level', :long => 'log-level', :short => 'l', :description => "Logging Level", :cast => :string
|
12
|
+
# opt 'config.dir',:long => 'config-dir', :short => 'c', :description => "Configuration directory", :cast => :string
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# class MyParser < ::Yacl::Define::Cli::Parser
|
16
|
+
# banner "Usage: myapp [options]+"
|
17
|
+
# options MyOptions
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# p = MyParser.new( :argv => ARGV )
|
21
|
+
# p.properties #=> a Properties instance
|
22
|
+
#
|
23
|
+
class Parser < ::Yacl::Loader
|
24
|
+
|
25
|
+
# Public: Define the options Class that is be used by this Parser, or return
|
26
|
+
# the existin Class if it is already defined.
|
27
|
+
#
|
28
|
+
# klass - A Class that is a child class of Cli::Options.
|
29
|
+
#
|
30
|
+
# Returns the current options Class.
|
31
|
+
def self.options( *args )
|
32
|
+
@options_klass ||= args.first unless args.empty?
|
33
|
+
return @options_klass
|
34
|
+
end
|
35
|
+
|
36
|
+
# Public: Set or retrieve the banner text.
|
37
|
+
#
|
38
|
+
# text - A String to be displayed as part of the help text.
|
39
|
+
#
|
40
|
+
# Returns the value set, or the default value if one is not set.
|
41
|
+
def self.banner( *args )
|
42
|
+
@banner = args.first unless args.empty?
|
43
|
+
@banner ||= "Usage : #{File.basename($0)} [options]+\nOptions:"
|
44
|
+
end
|
45
|
+
|
46
|
+
# Public: Define a commandline option for this Parser.
|
47
|
+
# Using 'opt' over options will dynamically create a child class of Options
|
48
|
+
# for use by this class
|
49
|
+
def self.opt( *args )
|
50
|
+
options( Class.new( Yacl::Define::Cli::Options ) )
|
51
|
+
options.opt( *args )
|
52
|
+
end
|
53
|
+
|
54
|
+
# Create a new Parser instance
|
55
|
+
#
|
56
|
+
# opts - The hash of options for this Loader
|
57
|
+
# :argv - The commandline options passed to the Parser.
|
58
|
+
# other options as per the Loader class.
|
59
|
+
#
|
60
|
+
def initialize( opts = {} )
|
61
|
+
super
|
62
|
+
@argv = opts[:argv] || []
|
63
|
+
end
|
64
|
+
|
65
|
+
# Public: Retrive the class level banner text.
|
66
|
+
#
|
67
|
+
# Returns the String banner text
|
68
|
+
def banner
|
69
|
+
self.class.banner
|
70
|
+
end
|
71
|
+
|
72
|
+
# Public: Return the Properties instance that is created by parsing the
|
73
|
+
# commandline options.
|
74
|
+
#
|
75
|
+
# Nil values from possible defaults from the commandline parser are
|
76
|
+
# filtered out before being merged onto the options.
|
77
|
+
#
|
78
|
+
# Returns a Properties instance.
|
79
|
+
def properties
|
80
|
+
h = {}
|
81
|
+
parse( @argv ).each do |k,v|
|
82
|
+
h[k] = v unless v.nil?
|
83
|
+
end
|
84
|
+
o = options_klass.new( h )
|
85
|
+
o.properties
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
# Internal: Return the class level value stored in Parser#options
|
91
|
+
#
|
92
|
+
# Returns a Class
|
93
|
+
def options_klass
|
94
|
+
self.class.options
|
95
|
+
end
|
96
|
+
|
97
|
+
def delegate_parser
|
98
|
+
Trollop::Parser.new( options_klass.new, self.banner ) do |trollop_options, banner_text|
|
99
|
+
text banner_text
|
100
|
+
trollop_options.each do |x|
|
101
|
+
opt x.long, x.description, :type => x.cast
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def parse( argv )
|
107
|
+
Trollop::with_standard_exception_handling( delegate_parser ) do
|
108
|
+
delegate_parser.parse( argv )
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|