versionomy 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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