Permalink
Browse files

Various fixes and rdoc cleanup

  • Loading branch information...
1 parent 98c3376 commit 5b52502f2b1d0b8de571fcef4398704997a7e199 @dazuma dazuma committed Oct 13, 2009
View
@@ -6,6 +6,8 @@ numbers in the wide variety of versioning schemes in use.
=== Some examples
+ require 'versionomy'
+
v1 = Versionomy.parse('1.3.2')
v1.major # => 1
v1.minor # => 3
@@ -53,9 +55,11 @@ numbers in the wide variety of versioning schemes in use.
v10.to_s # => '2.0.0-1'
microsoft_format = Versionomy.default_format.modified_copy do
- basic_integer_field(:minor,
- :delimiter_regexp => '\s?sp',
- :default_delimiter => ' SP')
+ field(:minor) do
+ recognize_number(:default_value_optional => true,
+ :delimiter_regexp => '\s?sp',
+ :default_delimiter => ' SP')
+ end
end
v11 = microsoft_format.parse('2008 SP2')
v11.major # => 2008
@@ -99,7 +103,7 @@ semantics for comparing, parsing, and modifying version numbers.
Documentation is available at http://virtuoso.rubyforge.org/versionomy
-Source code is hosted by Github at http://github.com/dazuma/versionomy/tree
+Source code is hosted by Github at http://github.com/dazuma/versionomy
Report bugs on RubyForge at http://rubyforge.org/projects/virtuoso
@@ -42,17 +42,19 @@ module Format
# The base format.
#
- # This format doesn't actually do anything useful. It parses all strings to the
- # schema's default initial value, and unparses all values to the empty string.
+ # This format doesn't actually do anything useful. It causes all strings
+ # to parse to the schema's default value, and unparses all values to the
+ # empty string.
#
- # Instead, the purpose here is to define the API for a format.
- # All formats must define the methods +schema+, +parse+, and +unparse+.
- # Formats need not extend this base class, as long as they duck-type these methods.
+ # Instead, the purpose here is to define the API for a format. All
+ # formats must define the methods +schema+, +parse+, and +unparse+.
+ # Formats need not extend this base class, as long as they duck-type
+ # these methods.
class Base
- # Create an instance of this base format, connected to the given schema.
+ # Create an instance of this base format, with the given schema.
def initialize(schema_)
@schema = schema_
@@ -67,15 +69,21 @@ def schema
# Parse the given string and return a value.
+ # The optional parameter hash can be used to pass parameters to the
+ # parser to affect its behavior. The exact parameters supported are
+ # defined by the format.
- def parse(string_, params_=nil)
+ def parse(string_, parse_params_=nil)
Value.new([], self)
end
# Unparse the given value and return a string.
+ # The optional parameter hash can be used to pass parameters to the
+ # unparser to affect its behavior. The exact parameters supported
+ # are defined by the format.
- def unparse(value_, params_=nil)
+ def unparse(value_, unparse_params_=nil)
''
end
@@ -265,12 +265,15 @@ def initialize(schema_, field_handlers_, default_parse_params_, default_unparse_
#
# The following options are recognized:
#
- # <tt>:required_unparse</tt>::
- # If set to true, this field must be present in the formatted
- # version number value. If false, the field may be omitted if it
- # is set to its default value.
+ # <tt>:default_value_optional</tt>::
+ # If set to true, this the field may be omitted in the unparsed
+ # (formatted) version number, if the value is the default value
+ # for this field. However, if the following field is present and
+ # set as <tt>:requires_previous_field</tt>, then this field is
+ # still unparsed even if it is its default value.
# For example, for a version number like "2.0.0", often the third
- # field is optional, but the first and second are required.
+ # field is optional, but the first and second are required, so it
+ # will often be unparsed as "2.0".
# Default is false.
# <tt>:case_sensitive</tt>::
# If set to true, the regexps are case-sensitive. Default is false.
@@ -504,7 +507,7 @@ def initialize(mappings_in_order_, mappings_by_value_) # :nodoc:
def map(value_, representation_, regexp_=nil)
regexp_ ||= representation_
array_ = [regexp_, representation_, value_]
- @mappings_by_value[value_] = array_
+ @mappings_by_value[value_] ||= array_
@mappings_in_order << array_
end
@@ -546,7 +549,7 @@ def parse(parse_params_, unparse_params_)
pair_ = recog_.parse(parse_params_, unparse_params_)
break if pair_
end
- pair_ ||= [@field.initial_value, @default_style]
+ pair_ ||= [@field.default_value, @default_style]
if pair_[1] && pair_[1] != @default_style
unparse_params_[@style_unparse_param_key] = pair_[1]
end
@@ -561,7 +564,7 @@ def unparse(value_, unparse_params_)
return recog_.unparse(value_, style_, unparse_params_)
end
end
- ''
+ unparse_params_[:required_for_later] ? '' : nil
end
end
@@ -571,7 +574,7 @@ class RecognizerBase # :nodoc:
def setup(field_, value_regexp_, opts_)
@style = opts_[:style]
- @required_unparse = opts_[:required_unparse]
+ @default_value_optional = opts_[:default_value_optional]
@regexp_options = opts_[:case_sensitive] ? nil : ::Regexp::IGNORECASE
@value_regexp = ::Regexp.new("^(#{value_regexp_})", @regexp_options)
regexp_ = opts_.fetch(:delimiter_regexp, '\.')
@@ -584,6 +587,7 @@ def setup(field_, value_regexp_, opts_)
@default_post_delimiter = opts_.fetch(:default_post_delimiter, '')
@requires_previous_field = opts_.fetch(:requires_previous_field, true)
name_ = field_.name
+ @default_field_value = field_.default_value
@delim_unparse_param_key = "#{name_}_delim".to_sym
@post_delim_unparse_param_key = "#{name_}_postdelim".to_sym
@required_unparse_param_key = "#{name_}_required".to_sym
@@ -628,14 +632,15 @@ def parse(parse_params_, unparse_params_)
if post_delim_ && post_delim_ != @default_post_delimiter
unparse_params_[@post_delim_unparse_param_key] = post_delim_
end
- unparse_params_[@required_unparse_param_key] = true unless @required_unparse
+ unparse_params_[@required_unparse_param_key] = true if @default_value_optional
[value_, @style]
end
def unparse(value_, style_, unparse_params_)
str_ = nil
- if @required_unparse || value_ != 0 || unparse_params_[:required_for_later] ||
+ if !@default_value_optional || value_ != @default_field_value ||
+ unparse_params_[:required_for_later] ||
unparse_params_[@required_unparse_param_key]
then
str_ = unparsed_value(value_, style_, unparse_params_)
@@ -104,7 +104,7 @@ def self._create_standard
# have a default value of 0. Thus, the default version number
# overall is "1.0".
# We first create the core version fields "major.minor.tiny.tiny2".
- field(:major, :initial => 1) do
+ field(:major, :default_value => 1) do
field(:minor) do
field(:tiny) do
field(:tiny2) do
@@ -142,44 +142,46 @@ def self._create_standard
symbol(:preview, :bump => :final)
# This type represents a final release. This is the
- # default initial value for the release_type field if no
- # value is explicitly provided.
+ # default value for the release_type field if no value is
+ # explicitly provided.
# Bumping the release type has no effect.
symbol(:final, :bump => :final)
- initial_value(:final)
+ default_value(:final)
# If the release type is development, these fields are
# made available to indicate which development release
# is being represented.
- field(:development_version, :only => :development, :initial => 1) do
+ field(:development_version, :only => :development,
+ :default_value => 1) do
field(:development_minor)
end
# If the release type is alpha, these fields are made
# available to indicate which alpha release is being
# represented.
- field(:alpha_version, :only => :alpha, :initial => 1) do
+ field(:alpha_version, :only => :alpha, :default_value => 1) do
field(:alpha_minor)
end
# If the release type is beta, these fields are made
# available to indicate which beta release is being
# represented.
- field(:beta_version, :only => :beta, :initial => 1) do
+ field(:beta_version, :only => :beta, :default_value => 1) do
field(:beta_minor)
end
# If the release type is release candidate, these fields
# are made available to indicate which release candidate
# is being represented.
- field(:release_candidate_version, :only => :release_candidate, :initial => 1) do
+ field(:release_candidate_version, :only => :release_candidate,
+ :default_value => 1) do
field(:release_candidate_minor)
end
# If the release type is preview, these fields are made
# available to indicate which preview release is being
# represented.
- field(:preview_version, :only => :preview, :initial => 1) do
+ field(:preview_version, :only => :preview, :default_value => 1) do
field(:preview_minor)
end
@@ -202,8 +204,7 @@ def self._create_standard
# All version number strings must start with the major version.
# Unlike other fields, it is not preceded by any delimiter.
field(:major) do
- recognize_number(:required_unparse => true,
- :delimiter_regexp => '', :default_delimiter => '')
+ recognize_number(:delimiter_regexp => '', :default_delimiter => '')
end
# The remainder of the core version number are represented as
@@ -213,11 +214,13 @@ def self._create_standard
field(:minor) do
recognize_number
end
+ # The tiny and tiny2 fields are optional in an unparsed string if
+ # they are set to the default value of 0.
field(:tiny) do
- recognize_number
+ recognize_number(:default_value_optional => true)
end
field(:tiny2) do
- recognize_number
+ recognize_number(:default_value_optional => true)
end
# The release type field is the most complex field because of the
@@ -235,13 +238,14 @@ def self._create_standard
# version number fields to be present. "1.0a5" and "1.0.0.0a5" are
# both valid version numbers.
field(:release_type, :requires_previous_field => false,
- :required_unparse => true, :default_style => :short) do
+ :default_style => :short) do
# First check for "short form" syntax. Not that we support post-
# delimiters; that is, we recognize "1.0 pre-2" where the hyphen
# is a post-delimiter. Also notice that we expect prerelease types
# to be followed by a numeric prerelease version number.
- recognize_regexp_map(:style => :short, :delimiter_regexp => '-|\.|\s?',
- :post_delimiter_regexp => '\s?|-', :default_delimiter => '',
+ recognize_regexp_map(:style => :short, :default_delimiter => '',
+ :delimiter_regexp => '-|\.|\s?',
+ :post_delimiter_regexp => '\s?|-',
:expected_follower_regexp => '\d') do
map(:development, 'd')
map(:alpha, 'a')
@@ -254,8 +258,9 @@ def self._create_standard
# just allow it to fall through to the default.
end
# Check for "long form" syntax. Note again that we omit :final.
- recognize_regexp_map(:style => :long, :delimiter_regexp => '-|\.|\s?',
- :post_delimiter_regexp => '\s?|-', :default_delimiter => '',
+ recognize_regexp_map(:style => :long, :default_delimiter => '',
+ :delimiter_regexp => '-|\.|\s?',
+ :post_delimiter_regexp => '\s?|-',
:expected_follower_regexp => '\d') do
map(:development, 'dev')
map(:alpha, 'alpha')
@@ -268,55 +273,51 @@ def self._create_standard
# The development version must appear in the string if it is present
# in the value, even if the value is 0. Similar for all the other
# prerelease version numbers: alpha, beta, release candidate, and
- # preview.
+ # preview. However, the minor fields are optional.
field(:development_version) do
- recognize_number(:required_unparse => true,
- :delimiter_regexp => '', :default_delimiter => '')
+ recognize_number(:delimiter_regexp => '', :default_delimiter => '')
end
field(:development_minor) do
- recognize_number
+ recognize_number(:default_value_optional => true)
end
field(:alpha_version) do
- recognize_number(:required_unparse => true,
- :delimiter_regexp => '', :default_delimiter => '')
+ recognize_number(:delimiter_regexp => '', :default_delimiter => '')
end
field(:alpha_minor) do
- recognize_number
+ recognize_number(:default_value_optional => true)
end
field(:beta_version) do
- recognize_number(:required_unparse => true,
- :delimiter_regexp => '', :default_delimiter => '')
+ recognize_number(:delimiter_regexp => '', :default_delimiter => '')
end
field(:beta_minor) do
- recognize_number
+ recognize_number(:default_value_optional => true)
end
field(:release_candidate_version) do
- recognize_number(:required_unparse => true,
- :delimiter_regexp => '', :default_delimiter => '')
+ recognize_number(:delimiter_regexp => '', :default_delimiter => '')
end
field(:release_candidate_minor) do
- recognize_number
+ recognize_number(:default_value_optional => true)
end
field(:preview_version) do
- recognize_number(:required_unparse => true,
- :delimiter_regexp => '', :default_delimiter => '')
+ recognize_number(:delimiter_regexp => '', :default_delimiter => '')
end
field(:preview_minor) do
- recognize_number
+ recognize_number(:default_value_optional => true)
end
# The patchlevel field does not require the previous field (which is
# release_type). Here we also set up two styles: a numeric style and
# a letter style. So "1.0a" and "1.0-1" are equivalent.
field(:patchlevel, :requires_previous_field => false,
- :default_style => :number) do
- recognize_number(:style => :number, :delimiter_regexp => '-|(-|\.|\s?)p',
- :default_delimiter => '-')
- recognize_letter(:style => :letter, :delimiter_regexp => '-|\.|\s?',
- :default_delimiter => '', :expected_follower_regexp => '$')
+ :default_value_optional => true, :default_style => :number) do
+ recognize_number(:style => :number, :default_delimiter => '-',
+ :delimiter_regexp => '-|(-|\.|\s?)p',)
+ recognize_letter(:style => :letter, :default_delimiter => '',
+ :delimiter_regexp => '-|\.|\s?',
+ :expected_follower_regexp => '$')
end
field(:patchlevel_minor) do
- recognize_number
+ recognize_number(:default_value_optional => true)
end
# By default, we require that at least the major and minor fields
Oops, something went wrong.

0 comments on commit 5b52502

Please sign in to comment.