fiksu-af 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/.gitignore +24 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +14 -0
  4. data/Gemfile +22 -0
  5. data/LICENSE +30 -0
  6. data/README.md +175 -0
  7. data/Rakefile +42 -0
  8. data/examples/af_script_with_options.rb +73 -0
  9. data/examples/af_side_component.rb +16 -0
  10. data/examples/my_application.rb +8 -0
  11. data/fiksu-af.gemspec +27 -0
  12. data/lib/fiksu-af/application/component.rb +95 -0
  13. data/lib/fiksu-af/application.rb +361 -0
  14. data/lib/fiksu-af/deprecated.rb +15 -0
  15. data/lib/fiksu-af/get_options.rb +68 -0
  16. data/lib/fiksu-af/logging/configurator.rb +152 -0
  17. data/lib/fiksu-af/logging.rb +13 -0
  18. data/lib/fiksu-af/option_parser/columnizer.rb +36 -0
  19. data/lib/fiksu-af/option_parser/dsl.rb +290 -0
  20. data/lib/fiksu-af/option_parser/get_options.rb +65 -0
  21. data/lib/fiksu-af/option_parser/helper.rb +80 -0
  22. data/lib/fiksu-af/option_parser/instance_variable_setter.rb +117 -0
  23. data/lib/fiksu-af/option_parser/interface.rb +63 -0
  24. data/lib/fiksu-af/option_parser/option.rb +40 -0
  25. data/lib/fiksu-af/option_parser/option_check.rb +66 -0
  26. data/lib/fiksu-af/option_parser/option_finder.rb +82 -0
  27. data/lib/fiksu-af/option_parser/option_group.rb +37 -0
  28. data/lib/fiksu-af/option_parser/option_select.rb +68 -0
  29. data/lib/fiksu-af/option_parser/option_store.rb +89 -0
  30. data/lib/fiksu-af/option_parser/option_type.rb +59 -0
  31. data/lib/fiksu-af/option_parser.rb +145 -0
  32. data/lib/fiksu-af/q_thread/base.rb +20 -0
  33. data/lib/fiksu-af/q_thread/interface.rb +23 -0
  34. data/lib/fiksu-af/q_thread/message.rb +14 -0
  35. data/lib/fiksu-af/q_thread/message_handler.rb +30 -0
  36. data/lib/fiksu-af/tcp_command/client.rb +49 -0
  37. data/lib/fiksu-af/tcp_command/server.rb +119 -0
  38. data/lib/fiksu-af/thread_pool.rb +102 -0
  39. data/lib/fiksu-af/version.rb +4 -0
  40. data/lib/fiksu-af.rb +12 -0
  41. data/logging/af.yml +32 -0
  42. data/spec/dummy/.rspec +1 -0
  43. data/spec/dummy/README.rdoc +261 -0
  44. data/spec/dummy/Rakefile +7 -0
  45. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  46. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  47. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  48. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  49. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  50. data/spec/dummy/config/application.rb +59 -0
  51. data/spec/dummy/config/boot.rb +10 -0
  52. data/spec/dummy/config/database-sample.yml +32 -0
  53. data/spec/dummy/config/environment.rb +5 -0
  54. data/spec/dummy/config/environments/development.rb +31 -0
  55. data/spec/dummy/config/environments/production.rb +67 -0
  56. data/spec/dummy/config/environments/test.rb +35 -0
  57. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  58. data/spec/dummy/config/initializers/inflections.rb +15 -0
  59. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  60. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  61. data/spec/dummy/config/initializers/session_store.rb +8 -0
  62. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  63. data/spec/dummy/config/locales/en.yml +5 -0
  64. data/spec/dummy/config/routes.rb +58 -0
  65. data/spec/dummy/config.ru +4 -0
  66. data/spec/dummy/public/404.html +26 -0
  67. data/spec/dummy/public/422.html +26 -0
  68. data/spec/dummy/public/500.html +25 -0
  69. data/spec/dummy/public/favicon.ico +0 -0
  70. data/spec/dummy/script/rails +6 -0
  71. data/spec/dummy/spec/spec_helper.rb +32 -0
  72. data/spec/lib/af/application_spec.rb +60 -0
  73. data/spec/lib/af/get_options_spec.rb +24 -0
  74. data/spec/lib/af/option_parser/option_check_spec.rb +50 -0
  75. data/spec/lib/af/option_parser/option_select_spec.rb +51 -0
  76. data/spec/spec_helper.rb +33 -0
  77. 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