Class: CTioga2::MetaBuilder::Type

Inherits:
Object
  • Object
show all
Defined in:
lib/ctioga2/metabuilder/type.rb

Overview

A class that handles a parameter type. It has to be subclassed to actually provide a parameter. The subclasses must provide the following:

  • a #string_to_type function to convert from string to the type;

  • a #type_to_string to convert back from type to string

  • an instance #type_name that returns a really small description of the type, to be used for instance to name command-line parameters.

  • a #type_name statement that registers the current class to the Type system.

Moerover, it is a good idea to reimplement the #qt4_create_input_widget method; the default implementation works, but you probably wish it would look better.

Types are implemented using hashes: this way, additionnal parameters can easily be added. The hash must have a :type key that will be interpreted by the children of Type. Examples:

{ :type => :integer}
{ :type => :file, :filter => "Text Files (*.txt)}

And so on. You definitely should document your type and it’s attributes properly, if you ever want that someone uses it.

The list of currently recognised types is here:

:integer

Types::IntegerParameter

:float

Types::FloatParameter

:string

Types::StringParameter

:file

Types::FileParameter

:boolean

Types::BooleanParameter

:list

Types::ListParameter

Additionally to the parameters the given type is requiring, you can pass some other kind of information using this hash, such as option parser short argument, aliases, and so on. This has nothing to do with type conversion, but it is the best place where to put this kind of things, in my humble opinion. The currently recognized such additional parameters are:

  • :option_parser_short: a short option name for option_parser.

  • :namespace: a ruby module that will be searched by #string_to_type for a constant. If one of the given name is found, its value is returned.

  • :shortctus: a hash specifiying strings shortcuts for given values. Elements of this hash that are regular expressions are taken

Constant Summary collapse

@@types =

A hash that makes the :type value of the type argument correspond to a Type child

{ }
@@type_names =
{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type) ⇒ Type

A default constructor. It should be safe to use it directly for children, unless something more specific is needed. Any descendent should always register type as @type - or, even better, call super.



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/ctioga2/metabuilder/type.rb', line 118

def initialize(type)
  if type.is_a?(Symbol)
    type = {:type => type}
  end
  @type = type
  if @type[:shortcuts]
    @shortcuts = @type[:shortcuts]
    @re_shortcuts = {}
    for k,v in @shortcuts
      if k.is_a? Regexp
        @re_shortcuts[k] = v
      end
    end
  end
  if @type[:passthrough]
    @passthrough = @type[:passthrough]
  end

end

Instance Attribute Details

#namespaceObject

An array of module whose constants can be used “as such”



108
109
110
# File 'lib/ctioga2/metabuilder/type.rb', line 108

def namespace
  @namespace
end

#namespace_lookupObject

When a :namespace option is provided, this hash provides a lookup ‘lowercase name’ => constant value.



112
113
114
# File 'lib/ctioga2/metabuilder/type.rb', line 112

def namespace_lookup
  @namespace_lookup
end

#passthroughObject

If the given string matches this regular expression, it is passed through without further modification.



105
106
107
# File 'lib/ctioga2/metabuilder/type.rb', line 105

def passthrough
  @passthrough
end

#re_shortcutsObject

A hash Regexp -> value. All elements will be looked for matches for every single string conversion, so don’t dump too many of them here.



101
102
103
# File 'lib/ctioga2/metabuilder/type.rb', line 101

def re_shortcuts
  @re_shortcuts
end

#shortcutsObject

A hash shortcut -> value. Can be nil



96
97
98
# File 'lib/ctioga2/metabuilder/type.rb', line 96

def shortcuts
  @shortcuts
end

#typeObject

The initial type specification that was given to the Type



93
94
95
# File 'lib/ctioga2/metabuilder/type.rb', line 93

def type
  @type
end

Class Method Details

.from_string(type, string) ⇒ Object

Shortcut to convert directly a string to the given type specification. Handy shortcut.



176
177
178
# File 'lib/ctioga2/metabuilder/type.rb', line 176

def self.from_string(type, string)
  return get_type(type).string_to_type(string)
end

.get_param_type(type) ⇒ Object

This function converts a ‘description’ (see the Type) of the type wanted into a Type child. As a special treat, a lone symbol is converted into => :symbol

Raises:



161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/ctioga2/metabuilder/type.rb', line 161

def self.get_param_type(type)
  if type.is_a?(Symbol)
    type = {:type => type}
  end
  raise InvalidType,"The type argument must be a Hash" unless 
    type.is_a?(Hash)
  begin
    return @@types.fetch(type[:type])
  rescue
    raise InvalidType, "Type #{type[:type]} unknown to the type system"
  end
end

.get_type(type) ⇒ Object

Returns a Type child instance suitable for conversion of the given type specification



182
183
184
185
186
187
# File 'lib/ctioga2/metabuilder/type.rb', line 182

def self.get_type(type)
  if type.is_a? Type
    return type
  end
  return get_param_type(type).new(type)
end

.type_name(name, public_name = nil, default_value = nil) ⇒ Object

This class function actually registers the current type to the Type ancestor. name should be a symbol. Moreover, if the second argument is provided, it automatically creates a #type_name instance method returning this value.



143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/ctioga2/metabuilder/type.rb', line 143

def self.type_name(name, public_name = nil, default_value = nil)
  if @@types.has_key?(name)
    warn { "Redefining type #{name} " +
      "from #{@@types[name]} to #{self}" }
  end
  @@types[name] = self
  @@type_names[self] = name
  self.send(:define_method,:type_name) do
    public_name
  end
  self.send(:define_method,:default_value) do
    default_value
  end
end

Instance Method Details

#boolean?Boolean

Whether the type is a boolean. Booleans are special cased for their use in the command-line.

Returns:

  • (Boolean)


288
289
290
# File 'lib/ctioga2/metabuilder/type.rb', line 288

def boolean?
  return false
end

#default_valueObject

Returns a default value for the given type. This is reimplemented systematically from children, with the Type::type_name statement.



246
247
# File 'lib/ctioga2/metabuilder/type.rb', line 246

def default_value
end

#option_parser_long_option(name, param = nil) ⇒ Object

Returns a value to be fed to OptionParser#on as a ‘long’ option. It is separated from the rest to allow easy redefinition (in special cases). name is the name of the option.



280
281
282
283
284
# File 'lib/ctioga2/metabuilder/type.rb', line 280

def option_parser_long_option(name, param = nil)
  param ||= type_name
  param = param.gsub(/\s+/, '_')
  return "--#{name} #{param.upcase}"
end

#option_parser_option(parser, name, desc, &block) ⇒ Object

Creates an option for the OptionParser parser. The block is fed with the converted value. The default implementation should be fine for most classes, but this still leaves the room for reimplementation if necessary. The parameters are:

  • parser: the OptionParser;

  • name: the name of the option;

  • desc: it description,

  • block: the block used to set the data.



268
269
270
271
272
273
274
# File 'lib/ctioga2/metabuilder/type.rb', line 268

def option_parser_option(parser, name, desc, &block)
  args = [option_parser_long_option(name), desc]
  if @type.has_key?(:option_parser_short)
    args.unshift(@type[:option_parser_short])
  end
  option_parser_raw(parser, *args, &block)
end

#string_to_type(string, tn = nil) ⇒ Object

This function converts the given string to the appropriate type. It is a wrapper around the #string_to_type_internal function that can take advantage of a few general features. It is recommanded to define a #string_to_type_internal function rather to redefine #string_to_type



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/ctioga2/metabuilder/type.rb', line 196

def string_to_type(string, tn = nil)
  begin
    # First, passthrough
    if @passthrough && @passthrough === string
      return stt_run_hook(string)
    end
    # First, shortcuts:
    if @shortcuts and @shortcuts.key? string
      return stt_run_hook(@shortcuts[string])
    end
    if @re_shortcuts
      for k, v in @re_shortcuts
        if string =~ k
          return stt_run_hook(v)
        end
      end
    end

    # Then, constants lookup.
    if @type.key?(:namespace)
      begin
        return stt_run_hook(lookup_const(string))
      rescue IncorrectInput
      end
    end
    return stt_run_hook(string_to_type_internal(string))
  rescue Exception => e
    txt = if tn
            "to type '#{tn}' failed:\n\t -> "
          else
            "failed: "
          end
    raise "Conversion of '#{string}' #{txt}#{e.message}"
  end
end

#type_nameObject

Returns a type name suitable for displaying, for instance, in an option parser, or inside a dialog box, and so on. Has to be one word (not to confuse the option parser, for instance); it is better if it is lowercase.



254
255
256
# File 'lib/ctioga2/metabuilder/type.rb', line 254

def type_name
  return 'notype'
end

#type_to_string(type) ⇒ Object

This function does the exact opposite of the #string_to_type one. It defaults to using the to_s methods of the parameter. Be careful: it is absolutely important that for any valid type,

string_to_type(type_to_string(type)) == type


238
239
240
# File 'lib/ctioga2/metabuilder/type.rb', line 238

def type_to_string(type)
  return type_to_string_internal(type)
end