versionomy 0.4.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,15 +1,15 @@
1
1
  # -----------------------------------------------------------------------------
2
- #
2
+ #
3
3
  # Versionomy delimiter format
4
- #
4
+ #
5
5
  # -----------------------------------------------------------------------------
6
6
  # Copyright 2008-2009 Daniel Azuma
7
- #
7
+ #
8
8
  # All rights reserved.
9
- #
9
+ #
10
10
  # Redistribution and use in source and binary forms, with or without
11
11
  # modification, are permitted provided that the following conditions are met:
12
- #
12
+ #
13
13
  # * Redistributions of source code must retain the above copyright notice,
14
14
  # this list of conditions and the following disclaimer.
15
15
  # * Redistributions in binary form must reproduce the above copyright notice,
@@ -18,7 +18,7 @@
18
18
  # * Neither the name of the copyright holder, nor the names of any other
19
19
  # contributors to this software, may be used to endorse or promote products
20
20
  # derived from this software without specific prior written permission.
21
- #
21
+ #
22
22
  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
23
  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
24
  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -35,28 +35,28 @@
35
35
 
36
36
 
37
37
  module Versionomy
38
-
38
+
39
39
  module Format
40
-
41
-
40
+
41
+
42
42
  # The Delimiter format class provides a DSL for building formats that
43
43
  # can handle most cases where the fields of a version number appear
44
44
  # consecutively in order in the string formatting. We expect most
45
45
  # version number schemes should fall into this category.
46
- #
46
+ #
47
47
  # In general, the strategy is to provide, for each field, a set of
48
48
  # regular expressions that recognize different formats for that field.
49
49
  # Every field must be of the form "(pre)(value)(post)"
50
50
  # where (pre) and (post) are delimiters preceding and
51
51
  # following the value. Either or both delimiters may be the empty string.
52
- #
52
+ #
53
53
  # To parse a string, the string is scanned from left to right and
54
54
  # matched against the format for the fields in order. If the string
55
55
  # matches, that part of the string is consumed and the field value is
56
56
  # interpreted from it. If the string does not match, and the field is
57
57
  # not marked as "required", then the field is set to its default value
58
58
  # and the next field is tried.
59
- #
59
+ #
60
60
  # During parsing, the actual delimiters, along with other information
61
61
  # such as whether or not fields are required, are saved into a default
62
62
  # set of parameters for unparsing. These are saved in the unparse_params
@@ -64,26 +64,26 @@ module Versionomy
64
64
  # generally the same form. If the version number value is modified, this
65
65
  # allows the unparsing of the new value to generally follow the format
66
66
  # of the original string.
67
- #
67
+ #
68
68
  # Formats that use the Delimiter mechanism also provide support for
69
69
  # certain parsing and unparsing parameters. See the documentation for
70
70
  # the parse and unparse methods for details.
71
- #
71
+ #
72
72
  # For a usage example, see the definition of the standard format in
73
73
  # Versionomy::Format::Standard#create.
74
-
74
+
75
75
  class Delimiter < Base
76
-
77
-
76
+
77
+
78
78
  # Create a format using delimiter tools.
79
79
  # You should provide the version number schema, a set of default
80
- # options, and a block.
81
- #
80
+ # options, and a block.
81
+ #
82
82
  # Within the block, you can call methods of
83
83
  # Versionomy::Format::Delimiter::Builder
84
84
  # to provide parsers for the fields of the schema. Any fields you do
85
85
  # not explicitly configure will get parsed in a default manner.
86
-
86
+
87
87
  def initialize(schema_, default_opts_={}, &block_)
88
88
  # Special case used by modified_copy
89
89
  if schema_.kind_of?(Delimiter)
@@ -97,7 +97,7 @@ module Versionomy
97
97
  ::Blockenspiel.invoke(block_, builder_)
98
98
  return
99
99
  end
100
-
100
+
101
101
  @schema = schema_
102
102
  @field_handlers = {}
103
103
  @default_parse_params = {}
@@ -110,22 +110,22 @@ module Versionomy
110
110
  @field_handlers[name_] ||= Delimiter::FieldHandler.new(@schema.field_named(name_), default_opts_)
111
111
  end
112
112
  end
113
-
114
-
113
+
114
+
115
115
  # Returns the schema understood by this format.
116
116
  # This method is required by the Format contract.
117
-
117
+
118
118
  def schema
119
119
  @schema
120
120
  end
121
-
122
-
121
+
122
+
123
123
  # Parse the given string and return a value.
124
124
  # This method is required by the Format contract.
125
- #
125
+ #
126
126
  # This method provides, out of the box, support for the following
127
127
  # parse parameters:
128
- #
128
+ #
129
129
  # <tt>:extra_characters</tt>::
130
130
  # Determines what to do if the entire string cannot be consumed by
131
131
  # the parsing process. If set to <tt>:ignore</tt>, any extra
@@ -135,7 +135,7 @@ module Versionomy
135
135
  # place. If set to <tt>:error</tt> (the default), causes a
136
136
  # Versionomy::Errors::ParseError to be raised if there are
137
137
  # uninterpreted characters.
138
-
138
+
139
139
  def parse(string_, params_=nil)
140
140
  parse_params_ = default_parse_params
141
141
  parse_params_.merge!(params_) if params_
@@ -201,14 +201,14 @@ module Versionomy
201
201
  end
202
202
  Value.new(parse_state_[:values], self, unparse_params_)
203
203
  end
204
-
205
-
204
+
205
+
206
206
  # Unparse the given value and return a string.
207
207
  # This method is required by the Format contract.
208
- #
208
+ #
209
209
  # This method provides, out of the box, support for the following
210
210
  # unparse parameters:
211
- #
211
+ #
212
212
  # <tt>:suffix</tt>::
213
213
  # A string to append to the unparsed string. Default is nothing.
214
214
  # <tt>:required_fields</tt>::
@@ -241,7 +241,7 @@ module Versionomy
241
241
  # This is used by letter-formatted integer fields only, and
242
242
  # sets the case to use while unparsing. Recognized values are
243
243
  # <tt>:lower</tt> (the default), and <tt>:upper</tt>.
244
-
244
+
245
245
  def unparse(value_, params_=nil)
246
246
  unparse_params_ = value_.unparse_params || default_unparse_params
247
247
  _interpret_field_lists(unparse_params_)
@@ -280,42 +280,42 @@ module Versionomy
280
280
  string_ << (unparse_params_[:suffix] || '')
281
281
  string_
282
282
  end
283
-
284
-
283
+
284
+
285
285
  # Return a copy of the default parsing parameters used by this format.
286
286
  # This hash cannot be edited in place. To modify the default parsing
287
287
  # parameters, use modified_copy and call
288
288
  # Versionomy::Format::Delimiter::Builder#default_parse_params in the block.
289
-
289
+
290
290
  def default_parse_params
291
291
  @default_parse_params.dup
292
292
  end
293
-
294
-
293
+
294
+
295
295
  # Return a copy of the default unparsing parameters used by this format.
296
296
  # This hash cannot be edited in place. To modify the default unparsing
297
297
  # parameters, use modified_copy and call
298
298
  # Versionomy::Format::Delimiter::Builder#default_unparse_params in the block.
299
-
299
+
300
300
  def default_unparse_params
301
301
  @default_unparse_params.dup
302
302
  end
303
-
304
-
303
+
304
+
305
305
  # Create a copy of this format, with the modifications given in the
306
306
  # provided block. You can call methods of Versionomy::Format::Delimiter::Builder
307
307
  # in the block. Field handlers that you specify in that block will
308
308
  # override and change the field handlers from the original. Any fields
309
309
  # not specified in this block will use the handlers from the original.
310
-
310
+
311
311
  def modified_copy(&block_)
312
312
  Delimiter.new(self, &block_)
313
313
  end
314
-
315
-
314
+
315
+
316
316
  # A utility method that interprets required_fields and
317
317
  # optional_fields parameters.
318
-
318
+
319
319
  def _interpret_field_lists(unparse_params_) # :nodoc:
320
320
  fields_ = unparse_params_.delete(:required_fields)
321
321
  if fields_
@@ -333,34 +333,34 @@ module Versionomy
333
333
  end
334
334
  end
335
335
  private :_interpret_field_lists
336
-
337
-
336
+
337
+
338
338
  # This class defines methods that you can call within the DSL block
339
339
  # passed to Versionomy::Format::Delimiter#new.
340
- #
340
+ #
341
341
  # Generally, you call the field method of this class a number of times
342
342
  # to define the formatting for each field.
343
-
343
+
344
344
  class Builder
345
-
345
+
346
346
  include ::Blockenspiel::DSL
347
-
347
+
348
348
  def initialize(schema_, field_handlers_, default_parse_params_, default_unparse_params_) # :nodoc:
349
349
  @schema = schema_
350
350
  @field_handlers = field_handlers_
351
351
  @default_parse_params = default_parse_params_
352
352
  @default_unparse_params = default_unparse_params_
353
353
  end
354
-
355
-
354
+
355
+
356
356
  # Specify how to handle a given field.
357
357
  # You must pass the name of the field, a hash of options, and a
358
358
  # block defining the handling of the field.
359
- #
359
+ #
360
360
  # Within the block, you set up "recognizers" for various regular
361
361
  # expression patterns. These recognizers are tested in order when
362
362
  # parsing a version number.
363
- #
363
+ #
364
364
  # The methods that can be called from the block are determined by
365
365
  # the type of field. If the field is an integer field, the methods
366
366
  # of Versionomy::Format::Delimiter::IntegerFieldBuilder can be
@@ -368,20 +368,20 @@ module Versionomy
368
368
  # of Versionomy::Format::Delimiter::StringFieldBuilder can be
369
369
  # called. If the field is a symbolic field, the methods of
370
370
  # Versionomy::Format::Delimiter::SymbolFieldBuilder can be called.
371
- #
371
+ #
372
372
  # === Options
373
- #
373
+ #
374
374
  # The opts hash includes a number of options that control how the
375
375
  # field is parsed.
376
- #
376
+ #
377
377
  # Some of these are regular expressions that indicate what patterns
378
378
  # are recognized by the parser. Regular expressions should be passed
379
379
  # in as the string representation of the regular expression, not a
380
380
  # Regexp object itself. For example, use the string '-' rather than
381
381
  # the Regexp /-/ to recognize a hyphen delimiter.
382
- #
382
+ #
383
383
  # The following options are recognized:
384
- #
384
+ #
385
385
  # <tt>:default_value_optional</tt>::
386
386
  # If set to true, this the field may be omitted in the unparsed
387
387
  # (formatted) version number, if the value is the default value
@@ -447,15 +447,15 @@ module Versionomy
447
447
  # The default style for this field. This is the style used for
448
448
  # unparsing if the value was not constructed by a parser or is
449
449
  # otherwise missing the style for this field.
450
- #
450
+ #
451
451
  # === Styles
452
- #
452
+ #
453
453
  # A field may have different representation "styles". For example,
454
454
  # you could represent a patchlevel of 1 as "1.0-1" or "1.0a".
455
455
  # When a version number string is parsed, the parser and unparser
456
456
  # work together to remember which style was parsed, and that style
457
457
  # is used when the version number is unparsed.
458
- #
458
+ #
459
459
  # Specify styles as options to the calls made within the block that
460
460
  # is passed to this method. In the above case, you could define the
461
461
  # patchlevel field with a block that has two calls, one that uses
@@ -463,11 +463,11 @@ module Versionomy
463
463
  # option <tt>:style => :number</tt>, and another that uses
464
464
  # Delimiter::IntegerFieldBuilder#recognize_letter and passes the
465
465
  # option <tt>:style => :letter</tt>.
466
- #
466
+ #
467
467
  # The standard format uses styles to preserve the different
468
468
  # syntaxes for the release_type field. See the source code in
469
469
  # Versionomy::Format::Standard#create for this example.
470
-
470
+
471
471
  def field(name_, opts_={}, &block_)
472
472
  name_ = name_.to_sym
473
473
  field_ = @schema.field_named(name_)
@@ -476,193 +476,193 @@ module Versionomy
476
476
  end
477
477
  @field_handlers[name_] = Delimiter::FieldHandler.new(field_, opts_, &block_)
478
478
  end
479
-
480
-
479
+
480
+
481
481
  # Set or modify the default parameters used when parsing a value.
482
-
482
+
483
483
  def default_parse_params(params_)
484
484
  @default_parse_params.merge!(params_)
485
485
  end
486
-
487
-
486
+
487
+
488
488
  # Set or modify the default parameters used when unparsing a value.
489
-
489
+
490
490
  def default_unparse_params(params_)
491
491
  @default_unparse_params.merge!(params_)
492
492
  end
493
-
493
+
494
494
  end
495
-
496
-
495
+
496
+
497
497
  # This class defines methods that can be called from the block passed
498
498
  # to Versionomy::Format::Delimiter::Builder#field if the field is
499
499
  # of integer type.
500
-
500
+
501
501
  class IntegerFieldBuilder
502
-
502
+
503
503
  include ::Blockenspiel::DSL
504
-
504
+
505
505
  def initialize(recognizers_, field_, default_opts_) # :nodoc:
506
506
  @recognizers = recognizers_
507
507
  @field = field_
508
508
  @default_opts = default_opts_
509
509
  end
510
-
511
-
510
+
511
+
512
512
  # Recognize a numeric-formatted integer field.
513
513
  # Using the opts parameter, you can override any of the field's
514
514
  # overall parsing options. You may also set the following additional
515
515
  # options:
516
- #
516
+ #
517
517
  # <tt>:strip_leading_zeros</tt>::
518
518
  # If false (the default), and a value has leading zeros, it is
519
519
  # assumed that the field has a minimum width, and unparsing will
520
520
  # always pad left with zeros to reach that minimum width. If set
521
521
  # to true, leading zeros are stripped from a value, and this
522
522
  # padding is never done.
523
-
523
+
524
524
  def recognize_number(opts_={})
525
525
  @recognizers << Delimiter::BasicIntegerRecognizer.new(@field, @default_opts.merge(opts_))
526
526
  end
527
-
528
-
527
+
528
+
529
529
  # Recognize a letter-formatted integer field. That is, the value is
530
530
  # formatted as an alphabetic letter where "a" represents 1, up to
531
531
  # "z" representing 26.
532
- #
532
+ #
533
533
  # Using the opts parameter, you can override any of the field's
534
534
  # overall parsing options. You may also set the following additional
535
535
  # options:
536
- #
536
+ #
537
537
  # <tt>:case</tt>::
538
538
  # Case-sensitivity of the letter. Possible values are
539
539
  # <tt>:upper</tt>, <tt>:lower</tt>, and <tt>:either</tt>.
540
540
  # Default is <tt>:either</tt>.
541
-
541
+
542
542
  def recognize_letter(opts_={})
543
543
  @recognizers << Delimiter::AlphabeticIntegerRecognizer.new(@field, @default_opts.merge(opts_))
544
544
  end
545
-
545
+
546
546
  end
547
-
548
-
547
+
548
+
549
549
  # This class defines methods that can be called from the block passed
550
550
  # to Versionomy::Format::Delimiter::Builder#field if the field is
551
551
  # of string type.
552
-
552
+
553
553
  class StringFieldBuilder
554
-
554
+
555
555
  include ::Blockenspiel::DSL
556
-
556
+
557
557
  def initialize(recognizers_, field_, default_opts_) # :nodoc:
558
558
  @recognizers = recognizers_
559
559
  @field = field_
560
560
  @default_opts = default_opts_
561
561
  end
562
-
563
-
562
+
563
+
564
564
  # Recognize a string field whose value matches a regular expression.
565
565
  # The regular expression must be passed as a string. E.g. use
566
566
  # "[a-z]+" instead of /[a-z]+/.
567
567
  # Using the opts parameter, you can override any of the field's
568
568
  # overall parsing options.
569
-
569
+
570
570
  def recognize_regexp(regexp_, opts_={})
571
571
  @recognizers << Delimiter::RegexpStringRecognizer.new(@field, regexp_, @default_opts.merge(opts_))
572
572
  end
573
-
573
+
574
574
  end
575
-
576
-
575
+
576
+
577
577
  # This class defines methods that can be called from the block passed
578
578
  # to Versionomy::Format::Delimiter::Builder#field if the field is
579
579
  # of symbolic type.
580
-
580
+
581
581
  class SymbolFieldBuilder
582
-
582
+
583
583
  include ::Blockenspiel::DSL
584
-
584
+
585
585
  def initialize(recognizers_, field_, default_opts_) # :nodoc:
586
586
  @recognizers = recognizers_
587
587
  @field = field_
588
588
  @default_opts = default_opts_
589
589
  end
590
-
591
-
590
+
591
+
592
592
  # Recognize a symbolic value represented by a particular regular
593
593
  # expression. The regular expression must be passed as a string.
594
594
  # E.g. use "[a-z]+" instead of /[a-z]+/.
595
595
  # The "canonical" parameter indicates the canonical syntax for the
596
596
  # value, for use in unparsing.
597
- #
597
+ #
598
598
  # Using the opts parameter, you can override any of the field's
599
599
  # overall parsing options.
600
-
600
+
601
601
  def recognize_regexp(value_, regexp_, canonical_, opts_={}, &block_)
602
602
  @recognizers << Delimiter::RegexpSymbolRecognizer.new(@field, value_, regexp_, canonical_, @default_opts.merge(opts_))
603
603
  end
604
-
605
-
604
+
605
+
606
606
  # Recognize a set of symbolic values, each represented by a
607
607
  # particular regular expression, but all sharing the same delimiters
608
608
  # and options. Use this instead of repeated calls to recognize_regexp
609
609
  # for better performance.
610
- #
610
+ #
611
611
  # Using the opts parameter, you can override any of the field's
612
612
  # overall parsing options.
613
- #
613
+ #
614
614
  # In the block, you should call methods of
615
615
  # Versionomy::Format::Delimiter::MappingSymbolBuilder to map values
616
616
  # to regular expression representations.
617
-
617
+
618
618
  def recognize_regexp_map(opts_={}, &block_)
619
619
  @recognizers << Delimiter::MappingSymbolRecognizer.new(@field, @default_opts.merge(opts_), &block_)
620
620
  end
621
-
621
+
622
622
  end
623
-
624
-
623
+
624
+
625
625
  # Methods in this class can be called from the block passed to
626
626
  # Versionomy::Format::Delimiter::SymbolFieldBuilder#recognize_regexp_map
627
627
  # to define the mapping between the values of a symbolic field and
628
628
  # the string representations of those values.
629
-
629
+
630
630
  class MappingSymbolBuilder
631
-
631
+
632
632
  include ::Blockenspiel::DSL
633
-
633
+
634
634
  def initialize(mappings_in_order_, mappings_by_value_) # :nodoc:
635
635
  @mappings_in_order = mappings_in_order_
636
636
  @mappings_by_value = mappings_by_value_
637
637
  end
638
-
639
-
638
+
639
+
640
640
  # Map a value to a string representation.
641
641
  # The optional regexp field, if specified, provides a regular
642
642
  # expression pattern for matching the value representation. If it
643
643
  # is omitted, the representation is used as the regexp.
644
-
644
+
645
645
  def map(value_, representation_, regexp_=nil)
646
646
  regexp_ ||= representation_
647
647
  array_ = [regexp_, representation_, value_]
648
648
  @mappings_by_value[value_] ||= array_
649
649
  @mappings_in_order << array_
650
650
  end
651
-
651
+
652
652
  end
653
-
654
-
653
+
654
+
655
655
  # This class handles the parsing and unparsing of a single field.
656
656
  # It manages an ordered list of recognizers, each understanding a
657
657
  # particular syntax. These recognizers are checked in order when
658
658
  # parsing and unparsing.
659
-
659
+
660
660
  class FieldHandler # :nodoc:
661
-
662
-
661
+
662
+
663
663
  # Creates a FieldHandler, using a DSL block appropriate to the
664
664
  # field type to configure the recognizers.
665
-
665
+
666
666
  def initialize(field_, default_opts_={}, &block_)
667
667
  @field = field_
668
668
  @recognizers = []
@@ -682,45 +682,45 @@ module Versionomy
682
682
  ::Blockenspiel.invoke(block_, builder_)
683
683
  end
684
684
  end
685
-
686
-
685
+
686
+
687
687
  # Returns true if this field can appear in an unparsed string only
688
688
  # if the previous field also appears.
689
-
689
+
690
690
  def requires_previous_field
691
691
  @requires_previous_field
692
692
  end
693
-
694
-
693
+
694
+
695
695
  # Returns the default value set when this field is missing from a
696
696
  # version string.
697
-
697
+
698
698
  def default_value
699
699
  @default_value
700
700
  end
701
-
702
-
701
+
702
+
703
703
  # Gets the given indexed recognizer. Returns nil if the index is out
704
704
  # of range.
705
-
705
+
706
706
  def get_recognizer(index_)
707
707
  @recognizers[index_]
708
708
  end
709
-
710
-
709
+
710
+
711
711
  # Finishes up parsing by setting the appropriate style field in the
712
712
  # unparse_params, if needed.
713
-
713
+
714
714
  def set_style_unparse_param(style_, unparse_params_)
715
715
  if style_ && style_ != @default_style
716
716
  unparse_params_[@style_unparse_param_key] = style_
717
717
  end
718
718
  end
719
-
720
-
719
+
720
+
721
721
  # Unparse a string from this field value.
722
722
  # This may return nil if this field is not required.
723
-
723
+
724
724
  def unparse(value_, unparse_params_, required_for_later_)
725
725
  style_ = unparse_params_[@style_unparse_param_key] || @default_style
726
726
  @recognizers.each do |recog_|
@@ -731,10 +731,10 @@ module Versionomy
731
731
  end
732
732
  required_for_later_ ? ['', false] : nil
733
733
  end
734
-
734
+
735
735
  end
736
-
737
-
736
+
737
+
738
738
  # A recognizer handles both parsing and unparsing of a particular kind
739
739
  # of syntax. During parsing, it recognizes the syntax based on regular
740
740
  # expressions for the delimiters and the value. If the string matches
@@ -745,16 +745,16 @@ module Versionomy
745
745
  # true, the unparse method should be called to actually generate a
746
746
  # a string fragment, or return nil if the field is determined to be
747
747
  # optional in the unparsed string.
748
- #
748
+ #
749
749
  # This is a base class. The actual classes should implement
750
750
  # initialize, parsed_value, and unparsed_value, and may optionally
751
751
  # override the should_unparse? method.
752
-
752
+
753
753
  class RecognizerBase # :nodoc:
754
-
754
+
755
755
  # Derived classes should call this from their initialize method
756
756
  # to set up the recognizer's basic parameters.
757
-
757
+
758
758
  def setup(field_, value_regexp_, opts_)
759
759
  @style = opts_[:style]
760
760
  @default_value_optional = opts_[:default_value_optional]
@@ -778,13 +778,13 @@ module Versionomy
778
778
  @post_delim_unparse_param_key = "#{name_}_postdelim".to_sym
779
779
  @required_unparse_param_key = "#{name_}_required".to_sym
780
780
  end
781
-
782
-
781
+
782
+
783
783
  # Attempt to parse the field from the string if the syntax matches
784
784
  # this recognizer's configuration.
785
785
  # Returns either nil, indicating that this recognizer doesn't match
786
786
  # the given syntax, or a two element array of the value and style.
787
-
787
+
788
788
  def parse(parse_state_, parse_params_)
789
789
  return nil if @requires_previous_field && parse_state_[:previous_field_missing]
790
790
  string_ = parse_state_[:string]
@@ -824,32 +824,32 @@ module Versionomy
824
824
  unparse_params_[@required_unparse_param_key] = true if @default_value_optional
825
825
  [parse_result_[0], @style, string_, unparse_params_]
826
826
  end
827
-
828
-
827
+
828
+
829
829
  # Returns true if this field can appear in an unparsed string only
830
830
  # if the next field also appears.
831
-
831
+
832
832
  def requires_next_field
833
833
  @requires_next_field
834
834
  end
835
-
836
-
835
+
836
+
837
837
  # Returns true if this recognizer should be used to unparse the
838
838
  # given value and style.
839
-
839
+
840
840
  def should_unparse?(value_, style_)
841
841
  style_ == @style
842
842
  end
843
-
844
-
843
+
844
+
845
845
  # Unparse the given value in the given style, and return a string
846
846
  # fragment, or nil if the field is determined to be "optional" to
847
847
  # unparse and isn't otherwise required (because a later field needs
848
848
  # it to be present, for example).
849
- #
849
+ #
850
850
  # It is guaranteed that this will be called only if should_unparse?
851
851
  # returns true.
852
-
852
+
853
853
  def unparse(value_, style_, unparse_params_, required_for_later_)
854
854
  str_ = nil
855
855
  if !@default_value_optional || value_ != @default_value ||
@@ -880,20 +880,20 @@ module Versionomy
880
880
  nil
881
881
  end
882
882
  end
883
-
883
+
884
884
  end
885
-
886
-
885
+
886
+
887
887
  # A recognizer for a numeric integer field
888
-
888
+
889
889
  class BasicIntegerRecognizer < RecognizerBase #:nodoc:
890
-
890
+
891
891
  def initialize(field_, opts_={})
892
892
  @strip_leading_zeros = opts_[:strip_leading_zeros]
893
893
  @width_unparse_param_key = "#{field_.name}_width".to_sym
894
894
  setup(field_, '\d+', opts_)
895
895
  end
896
-
896
+
897
897
  def parsed_value(value_, parse_params_)
898
898
  if !@strip_leading_zeros && value_ =~ /^0\d/
899
899
  [value_.to_i, {@width_unparse_param_key => value_.length}]
@@ -901,7 +901,7 @@ module Versionomy
901
901
  [value_.to_i, nil]
902
902
  end
903
903
  end
904
-
904
+
905
905
  def unparsed_value(value_, style_, unparse_params_)
906
906
  if !@strip_leading_zeros && (width_ = unparse_params_[@width_unparse_param_key])
907
907
  "%0#{width_.to_i}d" % value_
@@ -909,15 +909,15 @@ module Versionomy
909
909
  value_.to_s
910
910
  end
911
911
  end
912
-
912
+
913
913
  end
914
-
915
-
914
+
915
+
916
916
  # A recognizer for an alphabetic integer field. Such a field
917
917
  # represents values 1-26 as letters of the English alphabet.
918
-
918
+
919
919
  class AlphabeticIntegerRecognizer < RecognizerBase # :nodoc:
920
-
920
+
921
921
  def initialize(field_, opts_={})
922
922
  @case_unparse_param_key = "#{field_.name}_case".to_sym
923
923
  @case = opts_[:case]
@@ -931,7 +931,7 @@ module Versionomy
931
931
  end
932
932
  setup(field_, value_regexp_, opts_)
933
933
  end
934
-
934
+
935
935
  def parsed_value(value_, parse_params_)
936
936
  value_ = value_.unpack('c')[0] # Compatible with both 1.8 and 1.9
937
937
  if value_ >= 97 && value_ <= 122
@@ -942,7 +942,7 @@ module Versionomy
942
942
  [0, nil]
943
943
  end
944
944
  end
945
-
945
+
946
946
  def unparsed_value(value_, style_, unparse_params_)
947
947
  if value_ >= 1 && value_ <= 26
948
948
  if unparse_params_[@case_unparse_param_key] == :upper
@@ -954,61 +954,61 @@ module Versionomy
954
954
  value_.to_s
955
955
  end
956
956
  end
957
-
957
+
958
958
  end
959
-
960
-
959
+
960
+
961
961
  # A recognizer for strings that match a particular given regular
962
962
  # expression, for use in string-valued fields.
963
-
963
+
964
964
  class RegexpStringRecognizer < RecognizerBase # :nodoc:
965
-
965
+
966
966
  def initialize(field_, regexp_='[a-zA-Z0-9]+', opts_={})
967
967
  setup(field_, regexp_, opts_)
968
968
  end
969
-
969
+
970
970
  def parsed_value(value_, parse_params_)
971
971
  [value_, nil]
972
972
  end
973
-
973
+
974
974
  def unparsed_value(value_, style_, unparse_params_)
975
975
  value_.to_s
976
976
  end
977
-
977
+
978
978
  end
979
-
980
-
979
+
980
+
981
981
  # A recognizer for symbolic fields that recognizes a single regular
982
982
  # expression and maps it to a single particular value.
983
-
983
+
984
984
  class RegexpSymbolRecognizer < RecognizerBase # :nodoc:
985
-
985
+
986
986
  def initialize(field_, value_, regexp_, canonical_, opts_={})
987
987
  setup(field_, regexp_, opts_)
988
988
  @value = value_
989
989
  @canonical = canonical_
990
990
  end
991
-
991
+
992
992
  def parsed_value(value_, parse_params_)
993
993
  [@value, nil]
994
994
  end
995
-
995
+
996
996
  def unparsed_value(value_, style_, unparse_params_)
997
997
  @canonical
998
998
  end
999
-
999
+
1000
1000
  def should_unparse?(value_, style_)
1001
1001
  style_ == @style && value_ == @value
1002
1002
  end
1003
-
1003
+
1004
1004
  end
1005
-
1006
-
1005
+
1006
+
1007
1007
  # A recognizer for symbolic fields that recognizes a mapping of values
1008
1008
  # to regular expressions.
1009
-
1009
+
1010
1010
  class MappingSymbolRecognizer < RecognizerBase # :nodoc:
1011
-
1011
+
1012
1012
  def initialize(field_, opts_={}, &block_)
1013
1013
  @mappings_in_order = []
1014
1014
  @mappings_by_value = {}
@@ -1020,28 +1020,28 @@ module Versionomy
1020
1020
  map_[0] = ::Regexp.new("\\A(#{map_[0]})", @regexp_options)
1021
1021
  end
1022
1022
  end
1023
-
1023
+
1024
1024
  def parsed_value(value_, parse_params_)
1025
1025
  @mappings_in_order.each do |map_|
1026
1026
  return [map_[2], nil] if map_[0].match(value_)
1027
1027
  end
1028
1028
  nil
1029
1029
  end
1030
-
1030
+
1031
1031
  def unparsed_value(value_, style_, unparse_params_)
1032
1032
  @mappings_by_value[value_][1]
1033
1033
  end
1034
-
1034
+
1035
1035
  def should_unparse?(value_, style_)
1036
1036
  style_ == @style && @mappings_by_value.include?(value_)
1037
1037
  end
1038
-
1038
+
1039
1039
  end
1040
-
1041
-
1040
+
1041
+
1042
1042
  end
1043
-
1044
-
1043
+
1044
+
1045
1045
  end
1046
-
1046
+
1047
1047
  end