aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/regexp_with_named_groups.rb
blob: c11292b2a26288888839dbaed06f9d9b92c6dea1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
module Rack::Mount
  if Regin.regexp_supports_named_captures?
    RegexpWithNamedGroups = Regexp
  else
    require 'strscan'

    # A wrapper that adds shim named capture support to older
    # versions of Ruby.
    #
    # Because the named capture syntax causes a parse error, an
    # alternate syntax is used to indicate named captures.
    #
    # Ruby 1.9+ named capture syntax:
    #
    #   /(?<foo>[a-z]+)/
    #
    # Ruby 1.8 shim syntax:
    #
    #   /(?:<foo>[a-z]+)/
    class RegexpWithNamedGroups < Regexp
      def self.new(regexp) #:nodoc:
        if regexp.is_a?(RegexpWithNamedGroups)
          regexp
        else
          super
        end
      end

      # Wraps Regexp with named capture support.
      def initialize(regexp)
        regexp = Regexp.compile(regexp) unless regexp.is_a?(Regexp)
        source, options = regexp.source, regexp.options
        @names, scanner = [], StringScanner.new(source)

        while scanner.skip_until(/\(/)
          if scanner.scan(/\?:<([^>]+)>/)
            @names << scanner[1]
          elsif scanner.scan(/\?(i?m?x?\-?i?m?x?)?:/)
            # ignore noncapture
          else
            @names << nil
          end
        end
        source.gsub!(/\?:<([^>]+)>/, '')

        @names = [] unless @names.any?
        @names.freeze

        super(source, options)
      end

      def names
        @names.dup
      end

      def named_captures
        named_captures = {}
        names.each_with_index { |n, i|
          named_captures[n] = [i+1] if n
        }
        named_captures
      end

      def eql?(other)
        super && @names.eql?(other.names)
      end
    end
  end
end