Class: Flags

Inherits:
Object
  • Object
show all
Defined in:
lib/flags.rb

Overview

Note that the Flags class is a singleton, and all of its methods and data storage are class-level rather than instance-level. It is currently not possible to have multiple Flags instances within a single process.

Defined Under Namespace

Classes: AllowedValuesValidator, BoolFlag, ClassValidator, DisallowedValuesValidator, Flag, FlagValidator, FloatFlag, IntFlag, InvalidFlagValueError, RangeValidator, StringFlag, SymbolFlag

Class Method Summary collapse

Class Method Details

.args_from_yaml(yaml) ⇒ Object

Serializes the arguments from yaml and returns an array of arguments that can be passed to init.



219
220
221
# File 'lib/flags.rb', line 219

def self.args_from_yaml(yaml)
  YAML.load(yaml)
end

.comment_for_flag(name) ⇒ Object

Returns the description of a flag, or nil if the given flag is not defined. TODO: Deprecate and remove?



137
138
139
140
# File 'lib/flags.rb', line 137

def self.comment_for_flag(name)
  return nil unless @@flags.key? name.to_sym
  return @@flags[name.to_sym].description
end

.define_bool(name, default_value, description) ⇒ Object Also known as: define_bool_flag

Defines a new flag of boolean type, such as: Flags.define_bool(:my_flag_name, true, “An example of a boolean flag”)



81
82
83
# File 'lib/flags.rb', line 81

def self.define_bool(name, default_value, description)
  self.define_flag(name, default_value, description, BoolFlag)
end

.define_float(name, default_value, description) ⇒ Object Also known as: define_float_flag

Defines a new flag of float type, such as: Flags.define_float(:my_flag_name, 3.14, “An example of a float flag”)



87
88
89
# File 'lib/flags.rb', line 87

def self.define_float(name, default_value, description)
  self.define_flag(name, default_value, description, FloatFlag)
end

.define_int(name, default_value, description) ⇒ Object Also known as: define_int_flag

Defines a new flag of integer type, such as: Flags.define_int(:my_flag_name, 42, “An example of an integer flag”)



75
76
77
# File 'lib/flags.rb', line 75

def self.define_int(name, default_value, description)
  self.define_flag(name, default_value, description, IntFlag)
end

.define_string(name, default_value, description) ⇒ Object Also known as: define_string_flag

Defines a new flag of string type, such as: Flags.define_string(:my_flag_name, “hello world”, “An example of a string flag”)



63
64
65
# File 'lib/flags.rb', line 63

def self.define_string(name, default_value, description)
  self.define_flag(name, default_value, description, StringFlag)
end

.define_symbol(name, default_value, description) ⇒ Object Also known as: define_symbol_flag

Defines a new flag of symbol type, such as: Flags.define_symbol(:my_flag_name, :a_symbol, “An example of a symbol flag”)



69
70
71
# File 'lib/flags.rb', line 69

def self.define_symbol(name, default_value, description)
  self.define_flag(name, default_value, description, SymbolFlag)
end

.flags_get_comment(name) ⇒ Object

TODO: how to do aliases for class methods?



143
144
145
# File 'lib/flags.rb', line 143

def self.flags_get_comment(name)
  self.comment_for_flag(name)
end

.flags_get_default_value(name) ⇒ Object



147
148
149
150
# File 'lib/flags.rb', line 147

def self.flags_get_default_value(name)
  raise_unless_flag_defined!(name)
  return @@flags[name.to_sym].default_value
end

.flags_is_default(name) ⇒ Object



152
153
154
155
# File 'lib/flags.rb', line 152

def self.flags_is_default(name)
  raise_unless_flag_defined!(name)
  return @@flags[name.to_sym].default?
end

.init(args = $*) ⇒ Object

Parses the command line args and extracts flag value pairs. Should be called at least once before getting or setting any flag value. In the future, Flags will start throwing errors if any flag is accessed prior to Flags.init being called.

NOTE: this method HAS SIDE EFFECTS - it removes the flag name/value pairs from the supplied array of argument strings! For example, if -meaning_of_life is a flag then after this call to Flags.init:

args = [ "-meaning_of_life", "42", "path/to/output/file" ]
Flags.init(args)

the args array will be [ “path/to/output/file” ].



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/flags.rb', line 42

def self.init(args=$*)
  @@init_called = true

  if args.index("--help") || args.index("-help")
    puts self.help_message
    exit(0)
  end
  @@flags.each do |flag_name, flag|
    flag_name = "-#{flag.name}"
    setter = "#{flag.name}="
    # Use a loop in order to consume all settings for a flag and to keep the last one.
    while true
      value = self.extract_value_for_flag(args, flag_name)
      break if value.nil?  # Check for nil because false values are ok for boolean flags.
      self.send(setter, value)
    end
  end
end

.inspectObject

This override makes it so that the mocha rubygem prints nicer debug messages. The downside is that now you need to call Flags.to_s to print human-readable strings.



246
247
248
# File 'lib/flags.rb', line 246

def self.inspect
  "Flags"
end

.register_allowed_values_validator(name, *allowed_values) ⇒ Object

Registers a flag validator that ensures that the flag value is one of the allowed values.



110
111
112
113
114
115
# File 'lib/flags.rb', line 110

def self.register_allowed_values_validator(name, *allowed_values)
  raise_unless_symbol!(name)
  raise_unless_flag_defined!(name)
  flag = @@flags[name]
  flag.add_validator(AllowedValuesValidator.new(allowed_values))
end

.register_custom_validator(name, proc, error_message) ⇒ Object

Registers a custom flag validator that will raise an error with the specified message if proc.call(value) returns false whenever a value is assigned to the flag.



127
128
129
130
131
132
133
# File 'lib/flags.rb', line 127

def self.register_custom_validator(name, proc, error_message)
  raise_unless_symbol!(name)
  raise_unless_flag_defined!(name)
  flag = @@flags[name]
  validator = FlagValidator.new(proc, error_message)
  flag.add_validator(validator)
end

.register_disallowed_values_validator(name, *disallowed_values) ⇒ Object

Registers a flag validator that ensures that the flag value is not one of the disallowed values.



118
119
120
121
122
123
# File 'lib/flags.rb', line 118

def self.register_disallowed_values_validator(name, *disallowed_values)
  raise_unless_symbol!(name)
  raise_unless_flag_defined!(name)
  flag = @@flags[name]
  flag.add_validator(DisallowedValuesValidator.new(disallowed_values))
end

.register_range_validator(name, range) ⇒ Object

Registers a flag validator that checks the range of a flag.



102
103
104
105
106
107
# File 'lib/flags.rb', line 102

def self.register_range_validator(name, range)
  raise_unless_symbol!(name)
  raise_unless_flag_defined!(name)
  flag = @@flags[name]
  flag.add_validator(RangeValidator.new(range))
end

.restore_all_defaultsObject

Restores the values of all flags to their default settings, and returns nil.



200
201
202
203
204
205
# File 'lib/flags.rb', line 200

def self.restore_all_defaults()
  @@flags.each_pair do |name, flag|
    flag.restore_default
  end
  nil
end

.restore_default(name) ⇒ Object

Restores the value of the named flag to its default setting, and returns nil. Raises an error if the named flag does not exist.



184
185
186
187
188
189
190
# File 'lib/flags.rb', line 184

def self.restore_default(name)
  raise_unless_symbol!(name)
  raise_unless_flag_defined!(name)

  @@flags[name].restore_default
  nil
end

.restore_multiple_defaults(names) ⇒ Object

Takes an Array or Set of flag names, and calls self.restore_default() on each element.



193
194
195
196
197
# File 'lib/flags.rb', line 193

def self.restore_multiple_defaults(names)
  names.each do |flag_name|
    self.restore_default(flag_name)
  end
end

.set_if_default(name, value) ⇒ Object

Sets the value of the named flag if the default value has not been overridden. A default value can be overridden in one of these ways: 1) By specifying a value for the flag on the command line (i.e. “-x y”) 2) By explicitly changing the value of the flag in the code (i.e. Flags.x = y) 3) By loading a value for the flag from a hash or yaml file.

Returns true if the flag value was changed and false if it was not. Raises an error if the named flag does not exist.



165
166
167
168
169
170
171
172
173
# File 'lib/flags.rb', line 165

def self.set_if_default(name, value)
  raise_unless_symbol!(name)
  raise_unless_flag_defined!(name)

  flag = @@flags[name]
  return false unless flag.default?
  flag.value = value  # NOTE: calling the setter method changes the internal is_default field to false
  return true
end

.set_multiple_if_default(hash) ⇒ Object

Takes a hash of { flag name => flag value } pairs and calls self.set_if_default() on each pair.



176
177
178
179
180
# File 'lib/flags.rb', line 176

def self.set_multiple_if_default(hash)
  hash.each_pair do |flag_name, flag_value|
    self.set_if_default(flag_name, flag_value)
  end
end

.to_hashObject

This function takes the @@flags object, and returns a hash of just the key, value pairs



224
225
226
# File 'lib/flags.rb', line 224

def self.to_hash
  return Hash[@@flags.map { |name, flag| [name, flag.value] }]
end

.to_sObject

Converts the flags to a printable string.



229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/flags.rb', line 229

def self.to_s
  flags = []
  @@flags.keys.sort { |a, b| a.to_s <=> b.to_s }.each do |name|
    flag = @@flags[name]
    flag_name = "-#{name}"
    value = flag.value
    if value.is_a?(String)  # we call inspect() on String flags to take care of embedded quotes, spaces, etc.
      flags << "-#{name} #{value.inspect}"
    else
      flags << "-#{name} #{value.to_s}"
    end
  end
  flags.join(" ")
end

.to_yaml(io = nil) ⇒ Object

Dumps the flags, serialized to yaml to the specified io object. Returns a string if io is nil.



208
209
210
211
212
213
214
215
# File 'lib/flags.rb', line 208

def self.to_yaml(io=nil)
  flags = []
  @@flags.keys.sort { |a, b| a.to_s <=> b.to_s }.each do |name|
    flag = @@flags[name]
    flags += [ "-#{name}", flag.value ]
  end
  YAML.dump(flags, io)
end