fiksu-af 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +24 -0
- data/.rspec +2 -0
- data/.travis.yml +14 -0
- data/Gemfile +22 -0
- data/LICENSE +30 -0
- data/README.md +175 -0
- data/Rakefile +42 -0
- data/examples/af_script_with_options.rb +73 -0
- data/examples/af_side_component.rb +16 -0
- data/examples/my_application.rb +8 -0
- data/fiksu-af.gemspec +27 -0
- data/lib/fiksu-af/application/component.rb +95 -0
- data/lib/fiksu-af/application.rb +361 -0
- data/lib/fiksu-af/deprecated.rb +15 -0
- data/lib/fiksu-af/get_options.rb +68 -0
- data/lib/fiksu-af/logging/configurator.rb +152 -0
- data/lib/fiksu-af/logging.rb +13 -0
- data/lib/fiksu-af/option_parser/columnizer.rb +36 -0
- data/lib/fiksu-af/option_parser/dsl.rb +290 -0
- data/lib/fiksu-af/option_parser/get_options.rb +65 -0
- data/lib/fiksu-af/option_parser/helper.rb +80 -0
- data/lib/fiksu-af/option_parser/instance_variable_setter.rb +117 -0
- data/lib/fiksu-af/option_parser/interface.rb +63 -0
- data/lib/fiksu-af/option_parser/option.rb +40 -0
- data/lib/fiksu-af/option_parser/option_check.rb +66 -0
- data/lib/fiksu-af/option_parser/option_finder.rb +82 -0
- data/lib/fiksu-af/option_parser/option_group.rb +37 -0
- data/lib/fiksu-af/option_parser/option_select.rb +68 -0
- data/lib/fiksu-af/option_parser/option_store.rb +89 -0
- data/lib/fiksu-af/option_parser/option_type.rb +59 -0
- data/lib/fiksu-af/option_parser.rb +145 -0
- data/lib/fiksu-af/q_thread/base.rb +20 -0
- data/lib/fiksu-af/q_thread/interface.rb +23 -0
- data/lib/fiksu-af/q_thread/message.rb +14 -0
- data/lib/fiksu-af/q_thread/message_handler.rb +30 -0
- data/lib/fiksu-af/tcp_command/client.rb +49 -0
- data/lib/fiksu-af/tcp_command/server.rb +119 -0
- data/lib/fiksu-af/thread_pool.rb +102 -0
- data/lib/fiksu-af/version.rb +4 -0
- data/lib/fiksu-af.rb +12 -0
- data/logging/af.yml +32 -0
- data/spec/dummy/.rspec +1 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +59 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database-sample.yml +32 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +31 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +35 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/spec/spec_helper.rb +32 -0
- data/spec/lib/af/application_spec.rb +60 -0
- data/spec/lib/af/get_options_spec.rb +24 -0
- data/spec/lib/af/option_parser/option_check_spec.rb +50 -0
- data/spec/lib/af/option_parser/option_select_spec.rb +51 -0
- data/spec/spec_helper.rb +33 -0
- metadata +288 -0
@@ -0,0 +1,290 @@
|
|
1
|
+
module Af::OptionParser
|
2
|
+
# Utility base class for executing Ruby scripts on the command line. Provides
|
3
|
+
# methods to define, gather, parse and cast command line options. Options are
|
4
|
+
# stored as class instance variables.
|
5
|
+
module Dsl
|
6
|
+
### Class methods ###
|
7
|
+
|
8
|
+
@@opt_group_stack = []
|
9
|
+
def opt_get_top_of_stack
|
10
|
+
return (@@opt_group_stack[-1] || {}).clone
|
11
|
+
end
|
12
|
+
|
13
|
+
# Declare a command line options group.
|
14
|
+
#
|
15
|
+
# *Arguments*
|
16
|
+
# * group_name - name of the group
|
17
|
+
# * extra_stuff (Hash)
|
18
|
+
# * :title - display title of the group (optional)
|
19
|
+
# * :description - details about group
|
20
|
+
# * :priority - order to show groups in help --?
|
21
|
+
# * :hidden - true if this group's options should only be seen with --?
|
22
|
+
# * :disabled - (default: false)
|
23
|
+
# * anything else in this hash can be passed to yield block as defaults for other opt/opt_group invocations
|
24
|
+
# * yeilds to block if given with extra_stuff in a global space that opt/opt_group calls use as defaults
|
25
|
+
|
26
|
+
def opt_group(group_name, *extra_stuff)
|
27
|
+
# grab information from our yield scope
|
28
|
+
factory_hash = opt_get_top_of_stack
|
29
|
+
|
30
|
+
# update factory_hash with information in array area first (left parameters of the dsl)
|
31
|
+
maybe_title = extra_stuff.shift
|
32
|
+
if maybe_title.is_a? String
|
33
|
+
factory_hash[:title] = maybe_title
|
34
|
+
else
|
35
|
+
extra_stuff.unshift(maybe_title)
|
36
|
+
end
|
37
|
+
|
38
|
+
# then fold in the hash
|
39
|
+
maybe_hash = extra_stuff[-1] || {}
|
40
|
+
if maybe_hash.is_a? Hash
|
41
|
+
factory_hash.merge! maybe_hash
|
42
|
+
end
|
43
|
+
|
44
|
+
# Add group_name to OptionStore if it's not present. Otherwise, retrieve the value
|
45
|
+
# associated with that key and merge the value into factory_hash
|
46
|
+
OptionStore.factory(self).get_option_group(group_name).merge!(factory_hash)
|
47
|
+
|
48
|
+
# if a block is given, then let the yielded block
|
49
|
+
# have access to our scoped hash.
|
50
|
+
if block_given?
|
51
|
+
begin
|
52
|
+
@@opt_group_stack.push factory_hash.merge({ group: group_name })
|
53
|
+
yield
|
54
|
+
ensure
|
55
|
+
@@opt_group_stack.pop
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Declare a command line option switch.
|
61
|
+
#
|
62
|
+
# *Arguments*
|
63
|
+
# * long_name - long version of the switch
|
64
|
+
# * extra_stuff - hash with the following possible keys:
|
65
|
+
# :type - (:option_type) the OptionType
|
66
|
+
# :argument - (:requirements) is a parameter value requied (valid values: :required, :optional, :none)
|
67
|
+
# :short - (:short_name) the single letter used for this option (i.e., :e = '-e')
|
68
|
+
# :argument_note - used in --? as the typename of the parameter (e.g. ENGLISH_WORD)
|
69
|
+
# :note - used in --? as the help text
|
70
|
+
# :environment_variable - the name of the environment variable associated with this switch
|
71
|
+
# :default - (:default_value) the default value of the parameter
|
72
|
+
# :method - (:evaluation_method) called to evaluate argument: lambda{|argument,option| ... }
|
73
|
+
# :group - (:option_group_name) name of group
|
74
|
+
# :hidden - should option only be shown in --?
|
75
|
+
# :disabled - (default: false)
|
76
|
+
# :choices - array of valid choices, e.g: [:blue, :green, :red]
|
77
|
+
# :set - (:value_to_set_target_variable) value to set if option specified (use for switches where --blue means set @color = 'blue')
|
78
|
+
# :no_accessor - (:do_not_create_accessor) don't class_eval 'attr_accessor :#{target_variable}'
|
79
|
+
# :var - (:target_variable) name of instance variable to set
|
80
|
+
# :target_container - name of object to set instance value
|
81
|
+
#
|
82
|
+
# if block is passed it is used as :method
|
83
|
+
#
|
84
|
+
def opt(long_name, *extra_stuff, &b)
|
85
|
+
factory_hash = opt_get_top_of_stack
|
86
|
+
|
87
|
+
# Ensure long name is in the proper string format.
|
88
|
+
long_name = long_name.to_s
|
89
|
+
unless long_name.starts_with? "--"
|
90
|
+
long_name = "--#{long_name.gsub(/_/,'-')}"
|
91
|
+
end
|
92
|
+
factory_hash[:var] = long_name[2..-1].gsub(/-/, '_').gsub(/[^0-9a-zA-Z]/, '_')
|
93
|
+
|
94
|
+
# Create hash for processed options.
|
95
|
+
maybe_hash = extra_stuff[-1]
|
96
|
+
if maybe_hash.is_a? Hash
|
97
|
+
# if maybe_hash is a Hash, then the rest of extra_stuff is an array, which
|
98
|
+
# is expected to be:
|
99
|
+
# NOTE (String)
|
100
|
+
# or:
|
101
|
+
# TYPE (Symbol)
|
102
|
+
# or:
|
103
|
+
# REQUIREMENT (Symbol)
|
104
|
+
extra_stuff.pop
|
105
|
+
factory_hash.merge! maybe_hash
|
106
|
+
end
|
107
|
+
|
108
|
+
# Iterate through and process all of the other arguments.
|
109
|
+
while extra_stuff.length > 0
|
110
|
+
extra = extra_stuff.shift
|
111
|
+
if extra.is_a? Symbol
|
112
|
+
if [:required, :optional, :none].include? extra
|
113
|
+
factory_hash[:argument] = extra
|
114
|
+
elsif OptionType.valid_option_type_names.include? extra
|
115
|
+
factory_hash[:type] = extra
|
116
|
+
else
|
117
|
+
raise MisconfiguredOptionError.new("#{long_name}: extra options: #{extra.inspect} are not understood")
|
118
|
+
end
|
119
|
+
elsif extra.is_a? String
|
120
|
+
factory_hash[:note] = extra
|
121
|
+
else
|
122
|
+
raise MisconfiguredOptionError.new("#{long_name}: extra options: #{extra.inspect} are not understood")
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
unless factory_hash[:type]
|
127
|
+
# If we are not just setting a switch, then we can use the default value
|
128
|
+
# and assume this switch has a required argument.
|
129
|
+
if factory_hash[:default].present? && factory_hash[:set].nil?
|
130
|
+
type = OptionType.find_by_value(factory_hash[:default]).try(:short_name)
|
131
|
+
factory_hash[:type] = type unless type.nil?
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Determine argument requirement type.
|
136
|
+
factory_hash[:argument] = if factory_hash[:argument] == :required
|
137
|
+
::Af::OptionParser::GetOptions::REQUIRED_ARGUMENT
|
138
|
+
elsif factory_hash[:argument] == :none
|
139
|
+
::Af::OptionParser::GetOptions::NO_ARGUMENT
|
140
|
+
elsif factory_hash[:argument] == :optional
|
141
|
+
::Af::OptionParser::GetOptions::OPTIONAL_ARGUMENT
|
142
|
+
elsif factory_hash[:argument] == nil
|
143
|
+
if factory_hash[:type]
|
144
|
+
if factory_hash[:type] == :switch
|
145
|
+
::Af::OptionParser::GetOptions::OPTIONAL_ARGUMENT
|
146
|
+
else
|
147
|
+
::Af::OptionParser::GetOptions::REQUIRED_ARGUMENT
|
148
|
+
end
|
149
|
+
else
|
150
|
+
factory_hash[:type] = :switch
|
151
|
+
::Af::OptionParser::GetOptions::OPTIONAL_ARGUMENT
|
152
|
+
end
|
153
|
+
else
|
154
|
+
factory_hash[:argument]
|
155
|
+
end
|
156
|
+
|
157
|
+
# Determine argument type if it is not explictly given
|
158
|
+
unless factory_hash[:type]
|
159
|
+
if factory_hash[:set]
|
160
|
+
type = OptionType.find_by_value(factory_hash[:set]).try(:short_name)
|
161
|
+
factory_hash[:type] = type unless type.nil?
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Add the switch to the store, along with all of it's options.
|
166
|
+
if factory_hash[:short]
|
167
|
+
short = factory_hash[:short].to_s
|
168
|
+
unless short[0] == '-'
|
169
|
+
short = "-#{short}"
|
170
|
+
end
|
171
|
+
factory_hash[:short] = short
|
172
|
+
end
|
173
|
+
|
174
|
+
if factory_hash[:type]
|
175
|
+
type = OptionType.find_by_short_name(factory_hash[:type])
|
176
|
+
raise MisconfiguredOptionError.new("#{long_name}: option type #{factory_hash[:type].inspect} is not recognized. " +
|
177
|
+
"(valid option types: #{OptionType.valid_option_type_names.join(', ')})") unless type
|
178
|
+
factory_hash[:type] = type
|
179
|
+
end
|
180
|
+
|
181
|
+
factory_hash[:method] = b if b
|
182
|
+
|
183
|
+
unless factory_hash[:argument_note]
|
184
|
+
unless type.argument_note.blank?
|
185
|
+
factory_hash[:argument_note] = type.argument_note
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# rename keys in factory hash from the UI names to the API names
|
190
|
+
|
191
|
+
{
|
192
|
+
env: :environment_variable,
|
193
|
+
default: :default_value,
|
194
|
+
type: :option_type,
|
195
|
+
var: :target_variable,
|
196
|
+
set: :value_to_set_target_variable,
|
197
|
+
no_accessor: :do_not_create_accessor,
|
198
|
+
group: :option_group_name,
|
199
|
+
short: :short_name,
|
200
|
+
method: :evaluation_method,
|
201
|
+
argument: :requirements
|
202
|
+
}.each do |current_key_name, new_key_name|
|
203
|
+
if factory_hash.has_key? current_key_name
|
204
|
+
factory_hash[new_key_name] = factory_hash.delete(current_key_name)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# Add long_name to OptionStore if it's not present. Otherwise, retrieve the value
|
209
|
+
# associated with that key and merge the value into factory_hash
|
210
|
+
OptionStore.factory(self).get_option(long_name).merge!(factory_hash)
|
211
|
+
end
|
212
|
+
|
213
|
+
def opt_check(var_name, *extra_stuff, &b)
|
214
|
+
factory_hash = {}
|
215
|
+
factory_hash[:target_variable] = var_name[0..-1]
|
216
|
+
# Set the target_container when using an application component
|
217
|
+
if extra_stuff[0][:target_container].present?
|
218
|
+
factory_hash[:target_container] = extra_stuff[0][:target_container]
|
219
|
+
end
|
220
|
+
|
221
|
+
if extra_stuff[-1].is_a? Hash
|
222
|
+
action, targets = extra_stuff[-1].flatten
|
223
|
+
|
224
|
+
if [:requires, :excludes].include?(action)
|
225
|
+
factory_hash[:action] = action
|
226
|
+
if targets.is_a? Array
|
227
|
+
factory_hash[:targets] = targets
|
228
|
+
else
|
229
|
+
raise MisconfiguredOptionError.new("#{var_name}: check targets '#{targets.inspect}' must be Array")
|
230
|
+
end
|
231
|
+
raise MisconfiguredOptionError.new("#{var_name}: check action '#{action}' given block") unless b.nil?
|
232
|
+
elsif action == :check
|
233
|
+
raise MisconfiguredOptionError.new("#{var_name}: check action '#{action}' requires block") if b.nil?
|
234
|
+
factory_hash[:block] = b
|
235
|
+
else
|
236
|
+
raise MisconfiguredOptionError.new("unknown check action '#{action}' for #{var_name}")
|
237
|
+
end
|
238
|
+
else
|
239
|
+
raise MisconfiguredOptionError.new("check: #{var_name} must be given a hash")
|
240
|
+
end
|
241
|
+
|
242
|
+
# Add var_name to OptionStore if it's not present. Otherwise, retrieve the value
|
243
|
+
# associated with that key and merge the value into factory_hash
|
244
|
+
OptionStore.factory(self).get_option_check(var_name).merge!(factory_hash)
|
245
|
+
end
|
246
|
+
|
247
|
+
def opt_select(var_name, *extra_stuff, &b)
|
248
|
+
factory_hash = {}
|
249
|
+
factory_hash[:target_variable] = var_name[0..-1]
|
250
|
+
# Set the target_container when using an application component
|
251
|
+
if extra_stuff[0][:target_container].present?
|
252
|
+
factory_hash[:target_container] = extra_stuff[0][:target_container]
|
253
|
+
end
|
254
|
+
|
255
|
+
if extra_stuff[-1].is_a? Hash
|
256
|
+
action, targets = extra_stuff[-1].flatten
|
257
|
+
|
258
|
+
if [:one_of, :one_or_more_of, :none_or_one_of].include?(action)
|
259
|
+
factory_hash[:action] = action
|
260
|
+
if targets.is_a? Symbol
|
261
|
+
factory_hash[:targets] = [targets]
|
262
|
+
elsif targets.is_a? Array
|
263
|
+
factory_hash[:targets] = targets
|
264
|
+
else
|
265
|
+
raise MisconfiguredOptionError.new("#{var_name}: select targets '#{targets.inspect}' must be Symbol or Array")
|
266
|
+
end
|
267
|
+
raise MisconfiguredOptionError.new("#{var_name}: select action '#{action}' given block") unless b.nil?
|
268
|
+
else
|
269
|
+
raise MisconfiguredOptionError.new("unknown select action '#{action}' for #{var_name}")
|
270
|
+
end
|
271
|
+
else
|
272
|
+
raise MisconfiguredOptionError.new("select: #{var_name} must be given a hash")
|
273
|
+
end
|
274
|
+
|
275
|
+
# Add var_name to OptionStore if it's not present. Otherwise, retrieve the value
|
276
|
+
# associated with that key and merge the value into factory_hash
|
277
|
+
OptionStore.factory(self).get_option_select(var_name).merge!(factory_hash)
|
278
|
+
end
|
279
|
+
|
280
|
+
def opt_error(text)
|
281
|
+
puts "ERROR: #{text} (--? for help)"
|
282
|
+
exit 1
|
283
|
+
end
|
284
|
+
|
285
|
+
def usage
|
286
|
+
return "USAGE: rails runner #{self.name}.run [OPTIONS]"
|
287
|
+
end
|
288
|
+
|
289
|
+
end
|
290
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'getoptlong'
|
2
|
+
|
3
|
+
module Af::OptionParser
|
4
|
+
# Subclasses Getoptlong from the Ruby standard library.
|
5
|
+
# Docs: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/getoptlong/rdoc/GetoptLong.html.
|
6
|
+
# Source: https://github.com/ruby/ruby/blob/trunk/lib/getoptlong.rb.
|
7
|
+
class GetOptions < GetoptLong
|
8
|
+
|
9
|
+
# Local constants which map to superclass argument types.
|
10
|
+
ARGUMENT_FLAGS = [
|
11
|
+
NO_ARGUMENT = GetoptLong::NO_ARGUMENT,
|
12
|
+
REQUIRED_ARGUMENT = GetoptLong::REQUIRED_ARGUMENT,
|
13
|
+
OPTIONAL_ARGUMENT = GetoptLong::OPTIONAL_ARGUMENT
|
14
|
+
]
|
15
|
+
|
16
|
+
# Instantiate a new long command line option parser with a hash of switches.
|
17
|
+
#
|
18
|
+
# *Arguments*
|
19
|
+
# * switches - optional hash of command line switches, with long switch as
|
20
|
+
# key to a set of options:
|
21
|
+
# :short => <optional short switch>
|
22
|
+
# :argument => <constant arg type>
|
23
|
+
# :environment_variable => <how do these work???>
|
24
|
+
# :note => <arg description>
|
25
|
+
def initialize(declared_options = [])
|
26
|
+
getopt_options = []
|
27
|
+
argv_additions = []
|
28
|
+
|
29
|
+
# Iterate through all of the options.
|
30
|
+
declared_options.each do |option|
|
31
|
+
# Set aside
|
32
|
+
if option.environment_variable.present?
|
33
|
+
# Add enviroment variables to the front of ARGV.
|
34
|
+
if ENV[option.environment_variable]
|
35
|
+
argv_additions << option.long_name
|
36
|
+
unless ENV[option.environment_variable].empty?
|
37
|
+
# if the envvar is empty we assume this is a switch (no parameter)
|
38
|
+
argv_additions << ENV[option.environment_variable]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Convert hash into array, in format expected by Getoptlong#new.
|
44
|
+
# Example: ['--foo', '-f', GetoptLong::NO_ARGUMENT]
|
45
|
+
options = []
|
46
|
+
options << option.long_name
|
47
|
+
if (option.short_name)
|
48
|
+
options << option.short_name
|
49
|
+
end
|
50
|
+
options << option.requirements
|
51
|
+
getopt_options << options
|
52
|
+
end
|
53
|
+
|
54
|
+
# add any ARGVs to our list
|
55
|
+
for arg in ARGV do
|
56
|
+
argv_additions << arg
|
57
|
+
end
|
58
|
+
|
59
|
+
# Rewrite ARGV with environment variable with the new list.
|
60
|
+
argv_additions.each_with_index { |v,i| ARGV[i] = v }
|
61
|
+
|
62
|
+
super(*getopt_options)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module ::Af::OptionParser
|
2
|
+
class Helper
|
3
|
+
def initialize(af_opt_class_path)
|
4
|
+
option_finder = OptionFinder.new(af_opt_class_path)
|
5
|
+
@options = option_finder.all_options
|
6
|
+
@grouped_options = @options.group_by{|option| option.option_group_name || :basic}
|
7
|
+
@groups = option_finder.all_option_groups.sort{|a,b| (a.priority || 50) <=> (b.priority || 50)}
|
8
|
+
end
|
9
|
+
|
10
|
+
# Prints to stdout application usage and all command line options.
|
11
|
+
def help(command_line_usage, show_hidden = false)
|
12
|
+
# Print usage.
|
13
|
+
puts(command_line_usage)
|
14
|
+
|
15
|
+
# Array of strings to be printed to stdout.
|
16
|
+
output = []
|
17
|
+
|
18
|
+
# Iterate through all command groups sorted by priority.
|
19
|
+
@groups.each do |group|
|
20
|
+
options_in_group = @grouped_options[group.group_name]
|
21
|
+
unless options_in_group.blank?
|
22
|
+
if group.hidden == true && show_hidden == false
|
23
|
+
# skipping hidden groups
|
24
|
+
else
|
25
|
+
output << "#{group.group_name}: #{group.title}"
|
26
|
+
unless group.description.blank?
|
27
|
+
output << " " + group.description.split("\n").map(&:strip).join("\n ")
|
28
|
+
end
|
29
|
+
|
30
|
+
rows = []
|
31
|
+
|
32
|
+
# Iterate trhough all commands in this group.
|
33
|
+
options_in_group.sort{|a,b| a.long_name <=> b.long_name}.each do |option|
|
34
|
+
if option.hidden == true && show_hidden == false
|
35
|
+
# skipping hidden commands
|
36
|
+
else
|
37
|
+
columns = []
|
38
|
+
switches = "#{option.long_name}"
|
39
|
+
if (option.short_name)
|
40
|
+
switches << " | #{option.short_name}"
|
41
|
+
end
|
42
|
+
unless (option.requirements == ::Af::OptionParser::GetOptions::NO_ARGUMENT)
|
43
|
+
if (option.argument_note)
|
44
|
+
switches << " #{option.argument_note}"
|
45
|
+
elsif (option.option_type)
|
46
|
+
note = OptionType.find_by_short_name(option.option_type).try(:argument_note)
|
47
|
+
switches << " #{note}" if note
|
48
|
+
end
|
49
|
+
end
|
50
|
+
columns << switches
|
51
|
+
notes = []
|
52
|
+
unless (option.requirements == ::Af::OptionParser::GetOptions::NO_ARGUMENT)
|
53
|
+
if option.default_value.present?
|
54
|
+
if option.default_value.is_a? Array
|
55
|
+
notes << "(default: #{option.default_value.join(',')})"
|
56
|
+
elsif option.default_value.is_a? Hash
|
57
|
+
notes << "(default: #{option.default_value.map{|k,v| k.to_s + '=>' + v.to_s}.join(',')}"
|
58
|
+
else
|
59
|
+
notes << "(default: #{option.default_value})"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
notes << (option.note || "")
|
64
|
+
notes << "(choices: #{option.choices.map(&:to_s).join(', ')})" unless option.choices.blank?
|
65
|
+
if option.environment_variable
|
66
|
+
notes << " [env: #{option.environment_variable}]"
|
67
|
+
end
|
68
|
+
columns << notes.join(' ')
|
69
|
+
rows << columns
|
70
|
+
end
|
71
|
+
end
|
72
|
+
output += Columnizer.new.columnized(rows)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
puts output.join("\n")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module ::Af::OptionParser
|
2
|
+
class InstanceVariableSetter
|
3
|
+
FACTORY_SETTABLES = [
|
4
|
+
:evaluation_method,
|
5
|
+
:hidden,
|
6
|
+
:value_to_set_target_variable,
|
7
|
+
:do_not_create_accessor,
|
8
|
+
:target_variable,
|
9
|
+
:target_container,
|
10
|
+
:disabled
|
11
|
+
]
|
12
|
+
attr_accessor *FACTORY_SETTABLES
|
13
|
+
|
14
|
+
def initialize(parameters = {})
|
15
|
+
set_instance_variables(parameters)
|
16
|
+
@target_container ||= :af_application
|
17
|
+
end
|
18
|
+
|
19
|
+
#-------------------------
|
20
|
+
# *** Instance Methods ***
|
21
|
+
#+++++++++++++++++++++++++
|
22
|
+
|
23
|
+
def target_container
|
24
|
+
if @target_container == :af_application
|
25
|
+
@target_container = ::Af::Application.singleton
|
26
|
+
end
|
27
|
+
return @target_container
|
28
|
+
end
|
29
|
+
|
30
|
+
def target_class_variable
|
31
|
+
return "@@#{target_variable}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def target_instance_variable
|
35
|
+
return "@#{target_variable}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def has_value_to_set_target_variable?
|
39
|
+
return @has_value_to_set_target_variable || false
|
40
|
+
end
|
41
|
+
|
42
|
+
def evaluate_and_set_target(argument)
|
43
|
+
value = evaluate(argument)
|
44
|
+
set_target_variable(value)
|
45
|
+
end
|
46
|
+
|
47
|
+
def evaluate(argument)
|
48
|
+
if has_value_to_set_target_variable?
|
49
|
+
argument = @value_to_set_target_variable
|
50
|
+
else
|
51
|
+
if @requirements == ::Af::OptionParser::GetOptions::NO_ARGUMENT
|
52
|
+
argument = true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
evaluator = @evaluation_method ||
|
57
|
+
@option_type ||
|
58
|
+
OptionType.find_by_value(argument) ||
|
59
|
+
OptionType.find_by_short_name(:switch)
|
60
|
+
|
61
|
+
if evaluator.nil?
|
62
|
+
raise UndeterminedArgumentTypeError.new(@long_name)
|
63
|
+
elsif evaluator.is_a? Proc
|
64
|
+
return evaluator.call(argument, self)
|
65
|
+
else
|
66
|
+
return evaluator.evaluate_argument(argument, self)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def instantiate_target_variable
|
71
|
+
if target_container.present? && target_variable.present?
|
72
|
+
set_target_variable(@default_value)
|
73
|
+
unless @do_not_create_accessor
|
74
|
+
if target_container.is_a? Class
|
75
|
+
target_container.class_eval "def self.#{target_variable}; return #{target_class_variable}; end"
|
76
|
+
target_container.class_eval "def self.#{target_variable}=(value); return #{target_class_variable} = value; end"
|
77
|
+
else
|
78
|
+
target_container.class.class_eval "attr_accessor :#{target_variable}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def set_target_variable(value)
|
85
|
+
if target_container.present? && target_variable.present?
|
86
|
+
if target_container.is_a? Class
|
87
|
+
# this is a Class -- set @@foo
|
88
|
+
target_container.class_variable_set(target_class_variable, value)
|
89
|
+
else
|
90
|
+
# this is an instance -- set @foo
|
91
|
+
target_container.instance_variable_set(target_instance_variable, value)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def set_instance_variables(parameters = {}, other_settables = [])
|
97
|
+
parameters.select do |name, value|
|
98
|
+
(FACTORY_SETTABLES + other_settables).include? name
|
99
|
+
end.each do |name, value|
|
100
|
+
instance_variable_set("@#{name}", value)
|
101
|
+
end
|
102
|
+
|
103
|
+
if parameters[:value_to_set_target_variable]
|
104
|
+
@has_value_to_set_target_variable = true
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def merge(that_option, other_settables = [])
|
109
|
+
(FACTORY_SETTABLES + other_settables).each do |name|
|
110
|
+
if that_option.instance_variable_defined?("@#{name}")
|
111
|
+
self.send("#{name}=", that_option.send(name))
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Af::OptionParser
|
2
|
+
module Interface
|
3
|
+
# used by application code to note an error and exit
|
4
|
+
def opt_error(text)
|
5
|
+
self.class.opt_error(text)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Returns a string detailing application usage.
|
9
|
+
def usage
|
10
|
+
return self.class.usage
|
11
|
+
end
|
12
|
+
|
13
|
+
# Update Options for the provided long switch option name.
|
14
|
+
# Just a helper to UI method "opt"
|
15
|
+
def opt(long_name, *extra_stuff, &b)
|
16
|
+
self.class.opt(long_name, *extra_stuff, &b)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Update OptionGroups for the provided group option name.
|
20
|
+
# Just a helper to UI method "opt_group"
|
21
|
+
def opt_group(group_name, *extra_stuff, &b)
|
22
|
+
self.class.opt_group(group_name, *extra_stuff, &b)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Update OptionChecks for the provided group option name.
|
26
|
+
# Just a helper to UI method "opt_check"
|
27
|
+
def opt_check(var_name, *extra_stuff, &b)
|
28
|
+
self.class.opt_check(var_name, *extra_stuff, &b)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Update OptionSelects for the provided group option name.
|
32
|
+
# Just a helper to UI method "opt_select"
|
33
|
+
def opt_select(var_name, *extra_stuff, &b)
|
34
|
+
self.class.opt_select(var_name, *extra_stuff, &b)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Collect and process all of the switches (values) on the command
|
38
|
+
# line, as previously configured.
|
39
|
+
def process_command_line_options(af_option_interests)
|
40
|
+
# Iterate through all options in the class heirachy.
|
41
|
+
# Create instance variables and accessor methods for each.
|
42
|
+
|
43
|
+
option_finder = OptionFinder.new(af_option_interests)
|
44
|
+
|
45
|
+
options = option_finder.all_options
|
46
|
+
options.each(&:instantiate_target_variable)
|
47
|
+
|
48
|
+
# Fetch the actual switches (and values) from the command line.
|
49
|
+
get_options = GetOptions.new(options)
|
50
|
+
|
51
|
+
# Iterate through the command line options. Print and exit if the switch
|
52
|
+
# is invalid, help or app version. Otherwise, process and handle.
|
53
|
+
begin
|
54
|
+
get_options.each do |long_name, argument|
|
55
|
+
option_finder.find_option(long_name).evaluate_and_set_target(argument)
|
56
|
+
end
|
57
|
+
rescue GetoptLong::Error, Error => e
|
58
|
+
opt_error e.message
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ::Af::OptionParser
|
2
|
+
class Option < InstanceVariableSetter
|
3
|
+
FACTORY_SETTABLES = [
|
4
|
+
:option_type,
|
5
|
+
:requirements,
|
6
|
+
:short_name,
|
7
|
+
:argument_note,
|
8
|
+
:note,
|
9
|
+
:environment_variable,
|
10
|
+
:default_value,
|
11
|
+
:option_group_name,
|
12
|
+
:choices
|
13
|
+
]
|
14
|
+
attr_accessor *FACTORY_SETTABLES
|
15
|
+
attr_accessor :long_name
|
16
|
+
|
17
|
+
def initialize(long_name, parameters = {})
|
18
|
+
super(parameters)
|
19
|
+
@long_name = long_name
|
20
|
+
end
|
21
|
+
|
22
|
+
#-------------------------
|
23
|
+
# *** Instance Methods ***
|
24
|
+
#+++++++++++++++++++++++++
|
25
|
+
|
26
|
+
def set_instance_variables(parameters = {})
|
27
|
+
super(parameters, FACTORY_SETTABLES)
|
28
|
+
end
|
29
|
+
|
30
|
+
def merge(that_option)
|
31
|
+
super(that_option, FACTORY_SETTABLES)
|
32
|
+
end
|
33
|
+
|
34
|
+
def error(text)
|
35
|
+
puts "ERROR: #{self.long_name}: #{text} (--? for help)"
|
36
|
+
exit 1
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|