mustermann 0.3.1 → 0.4.0
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.
- checksums.yaml +4 -4
- data/README.md +429 -672
- data/lib/mustermann.rb +95 -20
- data/lib/mustermann/ast/boundaries.rb +44 -0
- data/lib/mustermann/ast/compiler.rb +13 -7
- data/lib/mustermann/ast/expander.rb +22 -12
- data/lib/mustermann/ast/node.rb +69 -5
- data/lib/mustermann/ast/param_scanner.rb +20 -0
- data/lib/mustermann/ast/parser.rb +138 -19
- data/lib/mustermann/ast/pattern.rb +59 -7
- data/lib/mustermann/ast/template_generator.rb +28 -0
- data/lib/mustermann/ast/transformer.rb +2 -2
- data/lib/mustermann/ast/translator.rb +20 -0
- data/lib/mustermann/ast/validation.rb +4 -3
- data/lib/mustermann/composite.rb +101 -0
- data/lib/mustermann/expander.rb +2 -2
- data/lib/mustermann/identity.rb +56 -0
- data/lib/mustermann/pattern.rb +185 -10
- data/lib/mustermann/pattern_cache.rb +49 -0
- data/lib/mustermann/regexp.rb +1 -0
- data/lib/mustermann/regexp_based.rb +18 -1
- data/lib/mustermann/regular.rb +4 -1
- data/lib/mustermann/simple_match.rb +5 -0
- data/lib/mustermann/sinatra.rb +22 -5
- data/lib/mustermann/to_pattern.rb +11 -6
- data/lib/mustermann/version.rb +1 -1
- data/mustermann.gemspec +1 -14
- data/spec/ast_spec.rb +14 -0
- data/spec/composite_spec.rb +147 -0
- data/spec/expander_spec.rb +15 -0
- data/spec/identity_spec.rb +44 -0
- data/spec/mustermann_spec.rb +17 -2
- data/spec/pattern_spec.rb +7 -3
- data/spec/regular_spec.rb +25 -0
- data/spec/sinatra_spec.rb +184 -9
- data/spec/to_pattern_spec.rb +49 -0
- metadata +15 -180
- data/.gitignore +0 -18
- data/.rspec +0 -2
- data/.travis.yml +0 -4
- data/.yardopts +0 -1
- data/Gemfile +0 -2
- data/LICENSE +0 -22
- data/Rakefile +0 -6
- data/internals.md +0 -64
- data/lib/mustermann/ast/tree_renderer.rb +0 -29
- data/lib/mustermann/rails.rb +0 -17
- data/lib/mustermann/shell.rb +0 -29
- data/lib/mustermann/simple.rb +0 -35
- data/lib/mustermann/template.rb +0 -47
- data/spec/rails_spec.rb +0 -521
- data/spec/shell_spec.rb +0 -108
- data/spec/simple_spec.rb +0 -236
- data/spec/support.rb +0 -5
- data/spec/support/coverage.rb +0 -16
- data/spec/support/env.rb +0 -16
- data/spec/support/expand_matcher.rb +0 -27
- data/spec/support/match_matcher.rb +0 -39
- data/spec/support/pattern.rb +0 -39
- data/spec/template_spec.rb +0 -814
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d7452f3272ea2fe09869f438b2cef90dcba6bf4b
         | 
| 4 | 
            +
              data.tar.gz: 5d79d32db97549662b82ef1b589d6d35f1f9df80
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 22ad9c7d0bfb6ae62a339cbfbe2581a91a9f860e4ba2f035ea26157ec0e31e16125d9f159561f43f821e2a07f239eda9e3df318ef3c29d63296a9107bcf65265
         | 
| 7 | 
            +
              data.tar.gz: 5394bb963e310669de6e569b06bc690f90060dded1ecbb991d9307c904f5dcb4d6a1c39da7683be8e79eec4782ec28502c716ae9bc528c4221ea7ae0e708434a
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,15 +1,8 @@ | |
| 1 1 | 
             
            # The Amazing Mustermann
         | 
| 2 2 |  | 
| 3 | 
            -
            [](https://travis-ci.org/rkh/mustermann) [](https://coveralls.io/r/rkh/mustermann) [](https://codeclimate.com/github/rkh/mustermann) [](https://gemnasium.com/rkh/mustermann) [](https://rubygems.org/gems/mustermann)
         | 
| 4 | 
            -
            [](http://inch-ci.org/github/rkh/mustermann)
         | 
| 5 | 
            -
            [](http://rubydoc.info/gems/mustermann/frames)
         | 
| 6 | 
            -
            [](http://rkh.mit-license.org)
         | 
| 7 | 
            -
            [](http://img.shields.io) 
         | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 3 | 
             
            *Make sure you view the correct docs: [latest release](http://rubydoc.info/gems/mustermann/frames), [master](http://rubydoc.info/github/rkh/mustermann/master/frames).*
         | 
| 11 4 |  | 
| 12 | 
            -
            Welcome to [Mustermann](http://en.wikipedia.org/wiki/List_of_placeholder_names_by_language#German). Mustermann is your personal string matching expert. As an expert in the field of strings and patterns, Mustermann  | 
| 5 | 
            +
            Welcome to [Mustermann](http://en.wikipedia.org/wiki/List_of_placeholder_names_by_language#German). Mustermann is your personal string matching expert. As an expert in the field of strings and patterns, Mustermann keeps its runtime dependencies to a minimum and is fully covered with specs and documentation.
         | 
| 13 6 |  | 
| 14 7 | 
             
            Given a string pattern, Mustermann will turn it into an object that behaves like a regular expression and has comparable performance characteristics.
         | 
| 15 8 |  | 
| @@ -23,139 +16,358 @@ when Mustermann.new('foo/*') then puts "prefixed with foo" | |
| 23 16 | 
             
            when Mustermann.new('*.pdf') then puts "it's a PDF"
         | 
| 24 17 | 
             
            when Mustermann.new('*.png') then puts "it's an image"
         | 
| 25 18 | 
             
            end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            pattern = Mustermann.new('/:prefix/*.*')
         | 
| 21 | 
            +
            pattern.params('/a/b.c') # => { "prefix" => "a", splat => ["b", "c"] }
         | 
| 22 | 
            +
            ```
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            ## Overview
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            ### Features
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            * **[Pattern Types](#-pattern-types):** Mustermann supports a wide variety of different pattern types, making it compatible with a large variety of existing software.
         | 
| 29 | 
            +
            * **[Fine Grained Control](#-available-options):** You can easily adjust matching behavior and add constraints to the placeholders and capture groups.
         | 
| 30 | 
            +
            * **[Binary Operators](#-binary-operators):** Patterns can be combined into composite patterns using binary operators.
         | 
| 31 | 
            +
            * **[Regexp Look Alike](#-regexp-look-alike):** Mustermann patterns can be used as a replacement for regular expressions.
         | 
| 32 | 
            +
            * **[Parameter Parsing](#-parameter-parsing):** Mustermann can parse matched parameters into a Sinatra-style "params" hash, including type casting.
         | 
| 33 | 
            +
            * **[Peeking](#-peeking):** Lets you check if the beginning of a string matches a pattern.
         | 
| 34 | 
            +
            * **[Expanding](#-expanding):** Besides parsing a parameters from an input string, a pattern object can also be used to generate a string from a set of parameters.
         | 
| 35 | 
            +
            * **[Generating Templates](#-generating-templates):** This comes in handy when wanting to hand on patterns rather than fully expanded strings as part of an external API.
         | 
| 36 | 
            +
            * **[Proc Look Alike](#-proc-look-alike):** Pass on a pattern instead of a block.
         | 
| 37 | 
            +
            * **[Duck Typing](#-duck-typing):** You can create your own pattern-like objects by implementing `to_pattern`.
         | 
| 38 | 
            +
            * **[Performance](#-performance):** Patterns are implemented with both performance and a low memory footprint in mind.
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            ### Additional Tooling
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            These features are included in the library, but not loaded by default
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            * **[Mapper](#-mapper):** A simple tool for mapping one string to another based on patterns.
         | 
| 45 | 
            +
            * **[Routers](#-routers):** Model execution flow based on pattern matching. Comes with a simple Rack router.
         | 
| 46 | 
            +
            * **[Sinatra Integration](#-sinatra-integration):** Mustermann can be used as a [Sinatra](http://www.sinatrarb.com/) extension. Sinatra 2.0 and beyond will use Mustermann by default.
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            <a name="-pattern-types"></a>
         | 
| 49 | 
            +
            ## Pattern Types
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            Mustermann support multiple pattern types. A pattern type defines the syntax, matching semantics and whether certain features, like [expanding](#-expanding) and [generating templates](#-generating-templates), are available.
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            You can create a pattern of a certain type by passing `type` option to `Mustermann.new`:
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            ``` ruby
         | 
| 56 | 
            +
            require 'mustermann'
         | 
| 57 | 
            +
            pattern = Mustermann.new('/*/**', type: :shell)
         | 
| 58 | 
            +
            ```
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            Note that this will use the type as suggestion: When passing in a string argument, it will create a pattern of the given type, but it might choose a different type for other objects (a regular expression argument will always result in a [regexp](#-pattern-details-regexp) pattern, a symbol always in a [sinatra](#-pattern-details-sinatra) pattern, etc).
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            Alternatively, you can also load and instantiate the pattern type directly:
         | 
| 63 | 
            +
             | 
| 64 | 
            +
            ``` ruby
         | 
| 65 | 
            +
            require 'mustermann/shell'
         | 
| 66 | 
            +
            pattern = Mustermann::Shell.new('/*/**')
         | 
| 67 | 
            +
            ```
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            Mustermann itself includes the [sinatra](#-sinatra-pattern), [identity](#-identity-pattern) and [regexp](#-regexp-pattern) pattern types. Other pattern types are available as separate gems.
         | 
| 70 | 
            +
             | 
| 71 | 
            +
            <a name="-binary-operators"></a>
         | 
| 72 | 
            +
            ## Binary Operators
         | 
| 73 | 
            +
             | 
| 74 | 
            +
            Patterns can be combined via binary operators. These are:
         | 
| 75 | 
            +
             | 
| 76 | 
            +
            * `|` (or):  Resulting pattern matches if at least one of the input pattern matches.
         | 
| 77 | 
            +
            * `&` (and): Resulting pattern matches if all input patterns match.
         | 
| 78 | 
            +
            * `^` (xor): Resulting pattern matches if exactly one of the input pattern matches.
         | 
| 79 | 
            +
             | 
| 80 | 
            +
            ``` ruby
         | 
| 81 | 
            +
            require 'mustermann'
         | 
| 82 | 
            +
             | 
| 83 | 
            +
            first  = Mustermann.new('/foo/:input')
         | 
| 84 | 
            +
            second = Mustermann.new('/:input/bar')
         | 
| 85 | 
            +
             | 
| 86 | 
            +
            first | second === "/foo/foo" # => true
         | 
| 87 | 
            +
            first | second === "/foo/bar" # => true
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            first & second === "/foo/foo" # => false
         | 
| 90 | 
            +
            first & second === "/foo/bar" # => true
         | 
| 91 | 
            +
             | 
| 92 | 
            +
            first ^ second === "/foo/foo" # => true
         | 
| 93 | 
            +
            first ^ second === "/foo/bar" # => false
         | 
| 94 | 
            +
            ```
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            These resulting objects are fully functional pattern objects, allowing you to call methods like `params` or `to_proc` on them. Moreover, *or* patterns created solely from expandable patterns will also be expandable. The same logic also applies to generating templates from *or* patterns.
         | 
| 97 | 
            +
             | 
| 98 | 
            +
            <a name="-regexp-look-alike"></a>
         | 
| 99 | 
            +
            ## Regexp Look Alike
         | 
| 100 | 
            +
             | 
| 101 | 
            +
            Pattern objects mimic Ruby's `Regexp` class by implementing `match`, `=~`, `===`, `names` and `named_captures`.
         | 
| 102 | 
            +
             | 
| 103 | 
            +
            ``` ruby
         | 
| 104 | 
            +
            require 'mustermann'
         | 
| 105 | 
            +
             | 
| 106 | 
            +
            pattern = Mustermann.new('/:page')
         | 
| 107 | 
            +
            pattern.match('/')     # => nil
         | 
| 108 | 
            +
            pattern.match('/home') # => #<MatchData "/home" page:"home">
         | 
| 109 | 
            +
            pattern =~ '/home'     # => 0
         | 
| 110 | 
            +
            pattern === '/home'    # => true (this allows using it in case statements)
         | 
| 111 | 
            +
            pattern.names          # => ['page']
         | 
| 112 | 
            +
            pattern.names          # => {"page"=>[1]}
         | 
| 113 | 
            +
             | 
| 114 | 
            +
            pattern = Mustermann.new('/home', type: :identity)
         | 
| 115 | 
            +
            pattern.match('/')     # => nil
         | 
| 116 | 
            +
            pattern.match('/home') # => #<Mustermann::SimpleMatch "/home">
         | 
| 117 | 
            +
            pattern =~ '/home'     # => 0
         | 
| 118 | 
            +
            pattern === '/home'    # => true (this allows using it in case statements)
         | 
| 119 | 
            +
            pattern.names          # => []
         | 
| 120 | 
            +
            pattern.names          # => {}
         | 
| 26 121 | 
             
            ```
         | 
| 27 122 |  | 
| 123 | 
            +
            Moreover, patterns based on regular expressions (all but `identity` and `shell`) automatically convert to regular expressions when needed:
         | 
| 124 | 
            +
             | 
| 125 | 
            +
            ``` ruby
         | 
| 126 | 
            +
            require 'mustermann'
         | 
| 127 | 
            +
             | 
| 128 | 
            +
            pattern = Mustermann.new('/:page')
         | 
| 129 | 
            +
            union   = Regexp.union(pattern, /^$/)
         | 
| 130 | 
            +
             | 
| 131 | 
            +
            union =~ "/foo" # => 0
         | 
| 132 | 
            +
            union =~ ""     # => 0
         | 
| 133 | 
            +
             | 
| 134 | 
            +
            Regexp.try_convert(pattern) # => /.../
         | 
| 135 | 
            +
            ```
         | 
| 136 | 
            +
             | 
| 137 | 
            +
            This way, unless some code explicitly checks the class for a regular expression, you should be able to pass in a pattern object instead even if the code in question was not written with Mustermann in mind.
         | 
| 138 | 
            +
             | 
| 139 | 
            +
            <a name="-parameter-parsing"></a>
         | 
| 140 | 
            +
            ## Parameter Parsing
         | 
| 141 | 
            +
             | 
| 28 142 | 
             
            Besides being a `Regexp` look-alike, Mustermann also adds a `params` method, that will give you a Sinatra-style hash:
         | 
| 29 143 |  | 
| 30 144 | 
             
            ``` ruby
         | 
| 145 | 
            +
            require 'mustermann'
         | 
| 146 | 
            +
             | 
| 31 147 | 
             
            pattern = Mustermann.new('/:prefix/*.*')
         | 
| 32 148 | 
             
            pattern.params('/a/b.c') # => { "prefix" => "a", splat => ["b", "c"] }
         | 
| 33 149 | 
             
            ```
         | 
| 34 150 |  | 
| 35 | 
            -
             | 
| 151 | 
            +
            For patterns with typed captures, it will also automatically convert them:
         | 
| 36 152 |  | 
| 37 | 
            -
             | 
| 153 | 
            +
            ``` ruby
         | 
| 154 | 
            +
            require 'mustermann'
         | 
| 38 155 |  | 
| 39 | 
            -
             | 
| 156 | 
            +
            pattern = Mustermann.new('/<prefix>/<int:id>', type: :flask)
         | 
| 157 | 
            +
            pattern.params('/page/10') # => { "prefix" => "page", "id" => 10 }
         | 
| 158 | 
            +
            ```
         | 
| 159 | 
            +
             | 
| 160 | 
            +
            <a name="-peeking"></a>
         | 
| 161 | 
            +
            ## Peeking
         | 
| 162 | 
            +
             | 
| 163 | 
            +
            Peeking gives the option to match a pattern against the beginning of a string rather the full string. Patterns come with four methods for peeking:
         | 
| 164 | 
            +
             | 
| 165 | 
            +
            * `peek` returns the matching substring.
         | 
| 166 | 
            +
            * `peek_size` returns the number of characters matching.
         | 
| 167 | 
            +
            * `peek_match` will return a `MatchData` or `Mustermann::SimpleMatch` (just like `match` does for the full string)
         | 
| 168 | 
            +
            * `peek_params` will return the `params` hash parsed from the substring and the number of characters.
         | 
| 169 | 
            +
             | 
| 170 | 
            +
            All of the above will turn `nil` if there was no match.
         | 
| 40 171 |  | 
| 41 172 | 
             
            ``` ruby
         | 
| 42 | 
            -
             | 
| 173 | 
            +
            require 'mustermann'
         | 
| 174 | 
            +
             | 
| 175 | 
            +
            pattern = Mustermann.new('/:prefix')
         | 
| 176 | 
            +
            pattern.peek('/foo/bar')      # => '/foo'
         | 
| 177 | 
            +
            pattern.peek_size('/foo/bar') # => 4
         | 
| 178 | 
            +
             | 
| 179 | 
            +
            path_info    = '/foo/bar'
         | 
| 180 | 
            +
            params, size = patter.peek_params(path_info)  # params == { "prefix" => "foo" }
         | 
| 181 | 
            +
            rest         = path_info[size..-1]            # => "/bar"
         | 
| 43 182 | 
             
            ```
         | 
| 44 183 |  | 
| 45 | 
            -
             | 
| 184 | 
            +
            <a name="-expanding"></a>
         | 
| 185 | 
            +
            ## Expanding
         | 
| 186 | 
            +
             | 
| 187 | 
            +
            Similarly to parsing, it is also possible to generate a string from a pattern by expanding it with a hash.
         | 
| 188 | 
            +
            For simple expansions, you can use `Pattern#expand`.
         | 
| 46 189 |  | 
| 47 190 | 
             
            ``` ruby
         | 
| 48 | 
            -
            Mustermann.new(' | 
| 191 | 
            +
            pattern = Mustermann.new('/:file(.:ext)?')
         | 
| 192 | 
            +
            pattern.expand(file: 'pony')             # => "/pony"
         | 
| 193 | 
            +
            pattern.expand(file: 'pony', ext: 'jpg') # => "/pony.jpg"
         | 
| 194 | 
            +
            pattern.expand(ext: 'jpg')               # raises Mustermann::ExpandError
         | 
| 49 195 | 
             
            ```
         | 
| 50 196 |  | 
| 51 | 
            -
             | 
| 197 | 
            +
            Expanding can be useful for instance when implementing link helpers.
         | 
| 52 198 |  | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
                  <td>Unix style patterns</td>
         | 
| 103 | 
            -
                  <td><tt>/*.{png,jpg}</tt></td>
         | 
| 104 | 
            -
                  <td>
         | 
| 105 | 
            -
                    <a href="#ignore_unknown_options"><tt>ignore_unknown_options</tt></a>,
         | 
| 106 | 
            -
                    <a href="#uri_decode"><tt>uri_decode</tt></a>
         | 
| 107 | 
            -
                  </td>
         | 
| 108 | 
            -
                  <td></td>
         | 
| 109 | 
            -
                </tr>
         | 
| 110 | 
            -
                <tr>
         | 
| 111 | 
            -
                  <th><a href="#simple"><tt>simple</tt></a></th>
         | 
| 112 | 
            -
                  <td>Sinatra 1.3 style patterns</td>
         | 
| 113 | 
            -
                  <td><tt>/:slug.:ext</tt></td>
         | 
| 114 | 
            -
                  <td>
         | 
| 115 | 
            -
                    <a href="#greedy"><tt>greedy</tt></a>,
         | 
| 116 | 
            -
                    <a href="#ignore_unknown_options"><tt>ignore_unknown_options</tt></a>,
         | 
| 117 | 
            -
                    <a href="#space_matches_plus"><tt>space_matches_plus</tt></a>,
         | 
| 118 | 
            -
                    <a href="#uri_decode"><tt>uri_decode</tt></a>
         | 
| 119 | 
            -
                  </td>
         | 
| 120 | 
            -
                  <td></td>
         | 
| 121 | 
            -
                </tr>
         | 
| 122 | 
            -
                <tr>
         | 
| 123 | 
            -
                  <th><a href="#sinatra"><tt>sinatra</tt></a></th>
         | 
| 124 | 
            -
                  <td>Sinatra 2.0 style patterns (default)</td>
         | 
| 125 | 
            -
                  <td><tt>/:slug(.:ext)?</tt></td>
         | 
| 126 | 
            -
                  <td>
         | 
| 127 | 
            -
                    <a href="#capture"><tt>capture</tt></a>,
         | 
| 128 | 
            -
                    <a href="#except"><tt>except</tt></a>,
         | 
| 129 | 
            -
                    <a href="#greedy"><tt>greedy</tt></a>,
         | 
| 130 | 
            -
                    <a href="#ignore_unknown_options"><tt>ignore_unknown_options</tt></a>,
         | 
| 131 | 
            -
                    <a href="#space_matches_plus"><tt>space_matches_plus</tt></a>,
         | 
| 132 | 
            -
                    <a href="#uri_decode"><tt>uri_decode</tt></a>
         | 
| 133 | 
            -
                  </td>
         | 
| 134 | 
            -
                  <td>
         | 
| 135 | 
            -
                    <a href="#pattern_expanding">Expanding</a>
         | 
| 136 | 
            -
                  </td>
         | 
| 137 | 
            -
                </tr>
         | 
| 138 | 
            -
                <tr>
         | 
| 139 | 
            -
                  <th><a href="#template"><tt>template</tt></a></th>
         | 
| 140 | 
            -
                  <td><a href="http://tools.ietf.org/html/rfc6570">URI templates</a></td>
         | 
| 141 | 
            -
                  <td><tt>/dictionary/{term}</tt></td>
         | 
| 142 | 
            -
                  <td>
         | 
| 143 | 
            -
                    <a href="#capture"><tt>capture</tt></a>,
         | 
| 144 | 
            -
                    <a href="#except"><tt>except</tt></a>,
         | 
| 145 | 
            -
                    <a href="#greedy"><tt>greedy</tt></a>,
         | 
| 146 | 
            -
                    <a href="#ignore_unknown_options"><tt>ignore_unknown_options</tt></a>,
         | 
| 147 | 
            -
                    <a href="#space_matches_plus"><tt>space_matches_plus</tt></a>,
         | 
| 148 | 
            -
                    <a href="#uri_decode"><tt>uri_decode</tt></a>
         | 
| 149 | 
            -
                  </td>
         | 
| 150 | 
            -
                  <td>
         | 
| 151 | 
            -
                    <a href="#pattern_expanding">Expanding</a>
         | 
| 152 | 
            -
                  </td>
         | 
| 153 | 
            -
                </tr>
         | 
| 154 | 
            -
              </tbody>
         | 
| 155 | 
            -
            </table>
         | 
| 199 | 
            +
            ### Expander Objects
         | 
| 200 | 
            +
             | 
| 201 | 
            +
            To get fine-grained control over expansion, you can use `Mustermann::Expander` directly.
         | 
| 202 | 
            +
             | 
| 203 | 
            +
            You can create an expander object directly from a string:
         | 
| 204 | 
            +
             | 
| 205 | 
            +
            ``` ruby
         | 
| 206 | 
            +
            require 'mustermann/expander'
         | 
| 207 | 
            +
            expander = Mustermann::Expander("/:file.jpg")
         | 
| 208 | 
            +
            expander.expand(file: 'pony') # => "/pony.jpg"
         | 
| 209 | 
            +
             | 
| 210 | 
            +
            expander = Mustermann::Expander(":file(.:ext)", type: :rails)
         | 
| 211 | 
            +
            expander.expand(file: 'pony', ext: 'jpg') # => "/pony.jpg"
         | 
| 212 | 
            +
            ```
         | 
| 213 | 
            +
             | 
| 214 | 
            +
            Or you can pass it a pattern instance:
         | 
| 215 | 
            +
             | 
| 216 | 
            +
            ``` ruby
         | 
| 217 | 
            +
            require 'mustermann'
         | 
| 218 | 
            +
            pattern = Mustermann.new("/:file")
         | 
| 219 | 
            +
             | 
| 220 | 
            +
            require 'mustermann/expander'
         | 
| 221 | 
            +
            expander = Mustermann::Expander.new(pattern)
         | 
| 222 | 
            +
            ```
         | 
| 223 | 
            +
             | 
| 224 | 
            +
            ### Expanding Multiple Patterns
         | 
| 225 | 
            +
             | 
| 226 | 
            +
            You can add patterns to an expander object via `<<`:
         | 
| 227 | 
            +
             | 
| 228 | 
            +
            ``` ruby
         | 
| 229 | 
            +
            require 'mustermann'
         | 
| 230 | 
            +
             | 
| 231 | 
            +
            expander = Mustermann::Expander.new
         | 
| 232 | 
            +
            expander << "/users/:user_id"
         | 
| 233 | 
            +
            expander << "/pages/:page_id"
         | 
| 234 | 
            +
             | 
| 235 | 
            +
            expander.expand(user_id: 15) # => "/users/15"
         | 
| 236 | 
            +
            expander.expand(page_id: 58) # => "/pages/58"
         | 
| 237 | 
            +
            ```
         | 
| 238 | 
            +
             | 
| 239 | 
            +
            You can set pattern options when creating the expander:
         | 
| 240 | 
            +
             | 
| 241 | 
            +
            ``` ruby
         | 
| 242 | 
            +
            require 'mustermann'
         | 
| 243 | 
            +
             | 
| 244 | 
            +
            expander = Mustermann::Expander.new(type: :template)
         | 
| 245 | 
            +
            expander << "/users/{user_id}"
         | 
| 246 | 
            +
            expander << "/pages/{page_id}"
         | 
| 247 | 
            +
            ```
         | 
| 156 248 |  | 
| 157 | 
            -
             | 
| 249 | 
            +
            Additionally, it is possible to combine patterns of different types:
         | 
| 158 250 |  | 
| 251 | 
            +
            ``` ruby
         | 
| 252 | 
            +
            require 'mustermann'
         | 
| 253 | 
            +
             | 
| 254 | 
            +
            expander = Mustermann::Expander.new
         | 
| 255 | 
            +
            expander << Mustermann.new("/users/{user_id}", type: :template)
         | 
| 256 | 
            +
            expander << Mustermann.new("/pages/:page_id",  type: :rails)
         | 
| 257 | 
            +
            ```
         | 
| 258 | 
            +
             | 
| 259 | 
            +
            ### Handling Additional Values
         | 
| 260 | 
            +
             | 
| 261 | 
            +
            The handling of additional values passed in to `expand` can be changed by setting the `additional_values` option:
         | 
| 262 | 
            +
             | 
| 263 | 
            +
            ``` ruby
         | 
| 264 | 
            +
            require 'mustermann'
         | 
| 265 | 
            +
             | 
| 266 | 
            +
            expander = Mustermann::Expander.new("/:slug", additional_values: :raise)
         | 
| 267 | 
            +
            expander.expand(slug: "foo", value: "bar") # raises Mustermann::ExpandError
         | 
| 268 | 
            +
             | 
| 269 | 
            +
            expander = Mustermann::Expander.new("/:slug", additional_values: :ignore)
         | 
| 270 | 
            +
            expander.expand(slug: "foo", value: "bar") # => "/foo"
         | 
| 271 | 
            +
             | 
| 272 | 
            +
            expander = Mustermann::Expander.new("/:slug", additional_values: :append)
         | 
| 273 | 
            +
            expander.expand(slug: "foo", value: "bar") # => "/foo?value=bar"
         | 
| 274 | 
            +
            ```
         | 
| 275 | 
            +
             | 
| 276 | 
            +
            It is also possible to pass this directly to the `expand` call:
         | 
| 277 | 
            +
             | 
| 278 | 
            +
            ``` ruby
         | 
| 279 | 
            +
            require 'mustermann'
         | 
| 280 | 
            +
             | 
| 281 | 
            +
            pattern = Mustermann.new('/:slug')
         | 
| 282 | 
            +
            pattern.expand(:append, slug: "foo", value: "bar") # => "/foo?value=bar"
         | 
| 283 | 
            +
            ```
         | 
| 284 | 
            +
             | 
| 285 | 
            +
            <a name="-generating-templates"></a>
         | 
| 286 | 
            +
            ## Generating Templates
         | 
| 287 | 
            +
             | 
| 288 | 
            +
            ... TODO ...
         | 
| 289 | 
            +
             | 
| 290 | 
            +
            <a name="-proc-look-alike"></a>
         | 
| 291 | 
            +
            ## Proc Look Alike
         | 
| 292 | 
            +
             | 
| 293 | 
            +
            Patterns implement `to_proc`:
         | 
| 294 | 
            +
             | 
| 295 | 
            +
            ``` ruby
         | 
| 296 | 
            +
            require 'mustermann'
         | 
| 297 | 
            +
            pattern  = Mustermann.new('/foo')
         | 
| 298 | 
            +
            callback = pattern.to_proc # => #<Proc>
         | 
| 299 | 
            +
             | 
| 300 | 
            +
            callback.call('/foo') # => true
         | 
| 301 | 
            +
            callback.call('/bar') # => false
         | 
| 302 | 
            +
            ```
         | 
| 303 | 
            +
             | 
| 304 | 
            +
            They can therefore be easily passed to methods expecting a block:
         | 
| 305 | 
            +
             | 
| 306 | 
            +
            ``` ruby
         | 
| 307 | 
            +
            require 'mustermann'
         | 
| 308 | 
            +
             | 
| 309 | 
            +
            list    = ["foo", "example@email.com", "bar"]
         | 
| 310 | 
            +
            pattern = Mustermann.new(":name@:domain.:tld")
         | 
| 311 | 
            +
            email   = list.detect(&pattern) # => "example@email.com"
         | 
| 312 | 
            +
            ```
         | 
| 313 | 
            +
             | 
| 314 | 
            +
            <a name="-mapper"></a>
         | 
| 315 | 
            +
            ## Mapper
         | 
| 316 | 
            +
             | 
| 317 | 
            +
             | 
| 318 | 
            +
            You can use a mapper to transform strings according to two or more mappings:
         | 
| 319 | 
            +
             | 
| 320 | 
            +
            ``` ruby
         | 
| 321 | 
            +
            require 'mustermann/mapper'
         | 
| 322 | 
            +
             | 
| 323 | 
            +
            mapper = Mustermann::Mapper.new("/:page(.:format)?" => ["/:page/view.:format", "/:page/view.html"])
         | 
| 324 | 
            +
            mapper['/foo']     # => "/foo/view.html"
         | 
| 325 | 
            +
            mapper['/foo.xml'] # => "/foo/view.xml"
         | 
| 326 | 
            +
            mapper['/foo/bar'] # => "/foo/bar"
         | 
| 327 | 
            +
            ```
         | 
| 328 | 
            +
             | 
| 329 | 
            +
            <a name="-routers"></a>
         | 
| 330 | 
            +
            ## Routers
         | 
| 331 | 
            +
             | 
| 332 | 
            +
            Mustermann comes with basic router implementations that will call certain callbacks depending on the input.
         | 
| 333 | 
            +
             | 
| 334 | 
            +
            ### Simple Router
         | 
| 335 | 
            +
             | 
| 336 | 
            +
            The simple router chooses callbacks based on an input string.
         | 
| 337 | 
            +
             | 
| 338 | 
            +
            ``` ruby
         | 
| 339 | 
            +
            require 'mustermann/router/simple'
         | 
| 340 | 
            +
             | 
| 341 | 
            +
            router = Mustermann::Router::Simple.new(default: 42)
         | 
| 342 | 
            +
            router.on(':name', capture: :digit) { |string| string.to_i }
         | 
| 343 | 
            +
            router.call("23")      # => 23
         | 
| 344 | 
            +
            router.call("example") # => 42
         | 
| 345 | 
            +
            ```
         | 
| 346 | 
            +
             | 
| 347 | 
            +
            ### Rack Router
         | 
| 348 | 
            +
             | 
| 349 | 
            +
            This is not a full replacement for Rails, Sinatra, Cuba, etc, as it only cares about path based routing.
         | 
| 350 | 
            +
             | 
| 351 | 
            +
            ``` ruby
         | 
| 352 | 
            +
            require 'mustermann/router/rack'
         | 
| 353 | 
            +
             | 
| 354 | 
            +
            router = Mustermann::Router::Rack.new do
         | 
| 355 | 
            +
              on '/' do |env|
         | 
| 356 | 
            +
                [200, {'Content-Type' => 'text/plain'}, ['Hello World!']]
         | 
| 357 | 
            +
              end
         | 
| 358 | 
            +
             | 
| 359 | 
            +
              on '/:name' do |env|
         | 
| 360 | 
            +
                name = env['mustermann.params']['name']
         | 
| 361 | 
            +
                [200, {'Content-Type' => 'text/plain'}, ["Hello #{name}!"]]
         | 
| 362 | 
            +
              end
         | 
| 363 | 
            +
             | 
| 364 | 
            +
              on '/something/*', call: SomeApp
         | 
| 365 | 
            +
            end
         | 
| 366 | 
            +
             | 
| 367 | 
            +
            # in a config.ru
         | 
| 368 | 
            +
            run router
         | 
| 369 | 
            +
            ```
         | 
| 370 | 
            +
            <a name="-sinatra-integration"></a>
         | 
| 159 371 | 
             
            ## Sinatra Integration
         | 
| 160 372 |  | 
| 161 373 | 
             
            All patterns implement `match`, which means they can be dropped into Sinatra and other Rack routers:
         | 
| @@ -272,97 +484,17 @@ end | |
| 272 484 | 
             
            * Sinatra 2.0 will use Mustermann internally
         | 
| 273 485 | 
             
            * Better exceptions for broken route syntax
         | 
| 274 486 |  | 
| 275 | 
            -
            ### Why not include this in Sinatra 1.x?
         | 
| 276 | 
            -
             | 
| 277 | 
            -
            * It would introduce breaking changes, even though these would be minor
         | 
| 278 | 
            -
            * Like Sinatra 2.0, Mustermann requires Ruby 2.0 or newer
         | 
| 279 | 
            -
             | 
| 280 | 
            -
            <a name="pattern_expanding"></a>
         | 
| 281 | 
            -
            ## Expanding
         | 
| 282 | 
            -
             | 
| 283 | 
            -
            Similarly to parsing, it is also possible to generate a string from a pattern by expanding it with a hash.
         | 
| 284 | 
            -
            For simple expansions, you can use `Pattern#expand`.
         | 
| 285 | 
            -
             | 
| 286 | 
            -
            ``` ruby
         | 
| 287 | 
            -
            pattern = Mustermann.new('/:file(.:ext)?')
         | 
| 288 | 
            -
            pattern.expand(file: 'pony')             # => "/pony"
         | 
| 289 | 
            -
            pattern.expand(file: 'pony', ext: 'jpg') # => "/pony.jpg"
         | 
| 290 | 
            -
            pattern.expand(ext: 'jpg')               # raises Mustermann::ExpandError
         | 
| 291 | 
            -
            ```
         | 
| 292 | 
            -
             | 
| 293 | 
            -
            Expanding can be useful for instance when implementing link helpers.
         | 
| 294 | 
            -
             | 
| 295 | 
            -
            ### Expander Objects
         | 
| 296 | 
            -
             | 
| 297 | 
            -
            To get fine-grained control over expansion, you can use `Mustermann::Expander` directly.
         | 
| 298 | 
            -
             | 
| 299 | 
            -
            You can create an expander object directly from a string:
         | 
| 300 | 
            -
             | 
| 301 | 
            -
            ``` ruby
         | 
| 302 | 
            -
            require 'mustermann/expander'
         | 
| 303 | 
            -
            expander = Mustermann::Expander("/:file.jpg")
         | 
| 304 | 
            -
            expander.expand(file: 'pony') # => "/pony.jpg"
         | 
| 305 | 
            -
             | 
| 306 | 
            -
            expander = Mustermann::Expander(":file(.:ext)", type: :rails)
         | 
| 307 | 
            -
            expander.expand(file: 'pony', ext: 'jpg') # => "/pony.jpg"
         | 
| 308 | 
            -
            ```
         | 
| 309 | 
            -
             | 
| 310 | 
            -
            Or you can pass it a pattern instance:
         | 
| 311 | 
            -
             | 
| 312 | 
            -
            ``` ruby
         | 
| 313 | 
            -
            require 'mustermann'
         | 
| 314 | 
            -
            pattern = Mustermann.new("/:file")
         | 
| 315 | 
            -
             | 
| 316 | 
            -
            require 'mustermann/expander'
         | 
| 317 | 
            -
            expander = Mustermann::Expander.new(pattern)
         | 
| 318 | 
            -
            ```
         | 
| 319 | 
            -
             | 
| 320 | 
            -
            ### Expanding Multiple Patterns
         | 
| 321 | 
            -
             | 
| 322 | 
            -
            You can add patterns to an expander object via `<<`:
         | 
| 323 | 
            -
             | 
| 324 | 
            -
            ``` ruby
         | 
| 325 | 
            -
            expander = Mustermann::Expander.new
         | 
| 326 | 
            -
            expander << "/users/:user_id"
         | 
| 327 | 
            -
            expander << "/pages/:page_id"
         | 
| 328 | 
            -
             | 
| 329 | 
            -
            expander.expand(user_id: 15) # => "/users/15"
         | 
| 330 | 
            -
            expander.expand(page_id: 58) # => "/pages/58"
         | 
| 331 | 
            -
            ```
         | 
| 332 | 
            -
             | 
| 333 | 
            -
            You can set pattern options when creating the expander:
         | 
| 334 | 
            -
             | 
| 335 | 
            -
            ``` ruby
         | 
| 336 | 
            -
            expander = Mustermann::Expander.new(type: :template)
         | 
| 337 | 
            -
            expander << "/users/{user_id}"
         | 
| 338 | 
            -
            expander << "/pages/{page_id}"
         | 
| 339 | 
            -
            ```
         | 
| 340 | 
            -
             | 
| 341 | 
            -
            Additionally, it is possible to combine patterns of different types:
         | 
| 342 | 
            -
             | 
| 343 | 
            -
            ``` ruby
         | 
| 344 | 
            -
            expander = Mustermann::Expander.new
         | 
| 345 | 
            -
            expander << Mustermann.new("/users/{user_id}", type: :template)
         | 
| 346 | 
            -
            expander << Mustermann.new("/pages/:page_id",  type: :rails)
         | 
| 347 | 
            -
            ```
         | 
| 348 | 
            -
             | 
| 349 | 
            -
            ### Handling Additional Values
         | 
| 350 | 
            -
             | 
| 351 | 
            -
            The handling of additional values passed in to `expand` can be changed by setting the `additional_values` option:
         | 
| 352 | 
            -
             | 
| 353 | 
            -
            ``` ruby
         | 
| 354 | 
            -
            expander = Mustermann::Expander.new("/:slug", additional_values: :raise)
         | 
| 355 | 
            -
            expander.expand(slug: "foo", value: "bar") # raises Mustermann::ExpandError
         | 
| 356 | 
            -
             | 
| 357 | 
            -
            expander = Mustermann::Expander.new("/:slug", additional_values: :ignore)
         | 
| 358 | 
            -
            expander.expand(slug: "foo", value: "bar") # => "/foo"
         | 
| 487 | 
            +
            ### Why not include this in Sinatra 1.x?
         | 
| 359 488 |  | 
| 360 | 
            -
             | 
| 361 | 
            -
             | 
| 362 | 
            -
            ```
         | 
| 489 | 
            +
            * It would introduce breaking changes, even though these would be minor
         | 
| 490 | 
            +
            * Like Sinatra 2.0, Mustermann requires Ruby 2.0 or newer
         | 
| 363 491 |  | 
| 492 | 
            +
            <a name="-duck-typing"></a>
         | 
| 364 493 | 
             
            ## Duck Typing
         | 
| 365 494 |  | 
| 495 | 
            +
            <a name="-duck-typing-to-pattern"></a>
         | 
| 496 | 
            +
            ### `to_pattern`
         | 
| 497 | 
            +
             | 
| 366 498 | 
             
            All methods converting string input to pattern objects will also accept any arbitrary object that implements `to_pattern`:
         | 
| 367 499 |  | 
| 368 500 | 
             
            ``` ruby
         | 
| @@ -405,28 +537,43 @@ end | |
| 405 537 | 
             
            MyObject.new.to_pattern # => #<Mustermann::Sinatra:"/foo">
         | 
| 406 538 | 
             
            ```
         | 
| 407 539 |  | 
| 408 | 
            -
             | 
| 540 | 
            +
            <a name="-duck-typing-respond-to"></a>
         | 
| 541 | 
            +
            ### `respond_to?`
         | 
| 409 542 |  | 
| 410 | 
            -
             | 
| 543 | 
            +
            You can and should use `respond_to?` to check if a pattern supports certain features.
         | 
| 411 544 |  | 
| 412 | 
            -
             | 
| 545 | 
            +
            ``` ruby
         | 
| 546 | 
            +
            require 'mustermann'
         | 
| 547 | 
            +
            pattern = Mustermann.new("/")
         | 
| 413 548 |  | 
| 414 | 
            -
             | 
| 549 | 
            +
            puts "supports expanding"             if pattern.respond_to? :expand
         | 
| 550 | 
            +
            puts "supports generating templates"  if pattern.respond_to? :to_templates
         | 
| 551 | 
            +
            ```
         | 
| 415 552 |  | 
| 416 | 
            -
             | 
| 553 | 
            +
            Alternatively, you can handle a `NotImplementedError` raised from such a method.
         | 
| 417 554 |  | 
| 418 555 | 
             
            ``` ruby
         | 
| 419 | 
            -
            require 'mustermann | 
| 420 | 
            -
            Mustermann | 
| 556 | 
            +
            require 'mustermann'
         | 
| 557 | 
            +
            pattern = Mustermann.new("/")
         | 
| 558 | 
            +
             | 
| 559 | 
            +
            begin
         | 
| 560 | 
            +
              p pattern.to_templates
         | 
| 561 | 
            +
            rescue NotImplementedError
         | 
| 562 | 
            +
              puts "does not support generating templates"
         | 
| 563 | 
            +
            end
         | 
| 421 564 | 
             
            ```
         | 
| 422 565 |  | 
| 423 | 
            -
             | 
| 566 | 
            +
            This behavior corresponds to what Ruby does, for instance for [`fork`](http://ruby-doc.org/core-2.1.1/NotImplementedError.html).
         | 
| 567 | 
            +
             | 
| 568 | 
            +
            <a name="-available-options"></a>
         | 
| 569 | 
            +
            ## Available Options
         | 
| 424 570 |  | 
| 571 | 
            +
            <a name="-available-options--capture"></a>
         | 
| 425 572 | 
             
            ### `capture`
         | 
| 426 573 |  | 
| 427 | 
            -
            Supported by: ` | 
| 574 | 
            +
            Supported by: All types except `identity`, `shell` and `simple` patterns.
         | 
| 428 575 |  | 
| 429 | 
            -
             | 
| 576 | 
            +
            Most pattern types support changing the strings named captures will match via the `capture` options.
         | 
| 430 577 |  | 
| 431 578 | 
             
            Possible values for a capture:
         | 
| 432 579 |  | 
| @@ -449,9 +596,10 @@ Mustermann.new('/:id.:ext', capture: { id: /\d+/, ext: ['png', 'jpg'] }) | |
| 449 596 |  | 
| 450 597 | 
             
            Available POSIX character classes are: `:alnum`, `:alpha`, `:blank`, `:cntrl`, `:digit`, `:graph`, `:lower`, `:print`, `:punct`, `:space`, `:upper`, `:xdigit`, `:word` and `:ascii`.
         | 
| 451 598 |  | 
| 599 | 
            +
            <a name="-available-options--except"></a>
         | 
| 452 600 | 
             
            ### `except`
         | 
| 453 601 |  | 
| 454 | 
            -
            Supported by: ` | 
| 602 | 
            +
            Supported by: All types except `identity`, `shell` and `simple` patterns.
         | 
| 455 603 |  | 
| 456 604 | 
             
            Given you supply a second pattern via the except option. Any string that would match the primary pattern but also matches the except pattern will not result in a successful match. Feel free to read that again. Or just take a look at this example:
         | 
| 457 605 |  | 
| @@ -469,13 +617,15 @@ pattern === '/foo.jpg' # => true | |
| 469 617 | 
             
            pattern === '/foo.png' # => false
         | 
| 470 618 | 
             
            ```
         | 
| 471 619 |  | 
| 620 | 
            +
            <a name="-available-options--greedy"></a>
         | 
| 472 621 | 
             
            ### `greedy`
         | 
| 473 622 |  | 
| 474 | 
            -
            Supported by:  | 
| 623 | 
            +
            Supported by: All types except `identity` and `shell` patterns.
         | 
| 624 | 
            +
            Default value: `true`
         | 
| 475 625 |  | 
| 476 626 | 
             
            **Simple** patterns are greedy, meaning that for the pattern `:foo:bar?`, everything will be captured as `foo`, `bar` will always be `nil`. By setting `greedy` to `false`, `foo` will capture as little as possible (which in this case would only be the first letter), leaving the rest to `bar`.
         | 
| 477 627 |  | 
| 478 | 
            -
            ** | 
| 628 | 
            +
            **All other** supported patterns are semi-greedy. This means `:foo(.:bar)?` (`:foo(.:bar)` for Rails patterns) will capture everything before the *last* dot as `foo`. For these two pattern types, you can switch into non-greedy mode by setting the `greedy` option to false. In that case `foo` will only capture the part before the *first* dot.
         | 
| 479 629 |  | 
| 480 630 | 
             
            Semi-greedy behavior is not specific to dots, it works with all characters or strings. For instance, `:a(foo:b)` will capture everything before the *last* `foo` as `a`, and `:foo(bar)?` will not capture a `bar` at the end.
         | 
| 481 631 |  | 
| @@ -487,11 +637,13 @@ pattern = Mustermann.new(':a.:b', greedy: false) | |
| 487 637 | 
             
            pattern.match('a.b.c.d') # => #<MatchData a:"a" b:"b.c.d">
         | 
| 488 638 | 
             
            ```
         | 
| 489 639 |  | 
| 640 | 
            +
            <a name="-available-options--space_matches_plus"></a>
         | 
| 490 641 | 
             
            ### `space_matches_plus`
         | 
| 491 642 |  | 
| 492 | 
            -
            Supported by:  | 
| 643 | 
            +
            Supported by: All types except `identity`, `regexp` and `shell` patterns.
         | 
| 644 | 
            +
            Default value: `true`
         | 
| 493 645 |  | 
| 494 | 
            -
             | 
| 646 | 
            +
            Most pattern types will by default also match a plus sign for a space in the pattern:
         | 
| 495 647 |  | 
| 496 648 | 
             
            ``` ruby
         | 
| 497 649 | 
             
            Mustermann.new('a b') === 'a+b' # => true
         | 
| @@ -511,9 +663,11 @@ pattern.match('a b')[:x] # => 'a b' | |
| 511 663 | 
             
            pattern.match('a+b')[:x] # => 'a+b'
         | 
| 512 664 | 
             
            ````
         | 
| 513 665 |  | 
| 666 | 
            +
            <a name="-available-options--uri_decode"></a>
         | 
| 514 667 | 
             
            ### `uri_decode`
         | 
| 515 668 |  | 
| 516 | 
            -
            Supported by all  | 
| 669 | 
            +
            Supported by all pattern types.
         | 
| 670 | 
            +
            Default value: `true`
         | 
| 517 671 |  | 
| 518 672 | 
             
            Usually, characters in the pattern will also match the URI encoded version of these characters:
         | 
| 519 673 |  | 
| @@ -529,165 +683,49 @@ Mustermann.new('a b', uri_decode: false) === 'a b'   # => true | |
| 529 683 | 
             
            Mustermann.new('a b', uri_decode: false) === 'a%20b' # => false
         | 
| 530 684 | 
             
            ```
         | 
| 531 685 |  | 
| 686 | 
            +
            <a name="-available-options--ignore_unknown_options"></a>
         | 
| 532 687 | 
             
            ### `ignore_unknown_options`
         | 
| 533 688 |  | 
| 534 | 
            -
            Supported by all patterns. | 
| 689 | 
            +
            Supported by all patterns.
         | 
| 690 | 
            +
            Default value: `false`
         | 
| 535 691 |  | 
| 536 692 | 
             
            If you pass an option in that is not supported by the specific pattern type, Mustermann will raise an `ArgumentError`.
         | 
| 537 693 | 
             
            By setting `ignore_unknown_options` to `true`, it will happily ignore the option.
         | 
| 538 694 |  | 
| 539 | 
            -
             | 
| 540 | 
            -
             | 
| 541 | 
            -
            ### `identity`
         | 
| 542 | 
            -
             | 
| 543 | 
            -
            Identity patterns are strings that have to match the input exactly.
         | 
| 544 | 
            -
             | 
| 545 | 
            -
            ``` ruby
         | 
| 546 | 
            -
            require 'mustermann'
         | 
| 547 | 
            -
             | 
| 548 | 
            -
            pattern = Mustermann.new('/:example', type: :identity)
         | 
| 549 | 
            -
            pattern === "/foo.bar"      # => false
         | 
| 550 | 
            -
            pattern === "/:example"     # => true
         | 
| 551 | 
            -
            pattern.params("/foo.bar")  # => nil
         | 
| 552 | 
            -
            pattern.params("/:example") # => {}
         | 
| 553 | 
            -
            ```
         | 
| 554 | 
            -
             | 
| 555 | 
            -
            <table>
         | 
| 556 | 
            -
              <thead>
         | 
| 557 | 
            -
                <tr>
         | 
| 558 | 
            -
                  <th>Syntax Element</th>
         | 
| 559 | 
            -
                  <th>Description</th>
         | 
| 560 | 
            -
                </tr>
         | 
| 561 | 
            -
              </thead>
         | 
| 562 | 
            -
              <tbody>
         | 
| 563 | 
            -
                <tr>
         | 
| 564 | 
            -
                  <td><i>any character</i></td>
         | 
| 565 | 
            -
                  <td>Matches exactly that character or a URI escaped version of it.</td>
         | 
| 566 | 
            -
                </tr>
         | 
| 567 | 
            -
              </tbody>
         | 
| 568 | 
            -
            </table>
         | 
| 569 | 
            -
             | 
| 570 | 
            -
            ### `rails`
         | 
| 571 | 
            -
             | 
| 572 | 
            -
            Patterns with the syntax used in Rails route definitions.
         | 
| 573 | 
            -
             | 
| 574 | 
            -
            ``` ruby
         | 
| 575 | 
            -
            require 'mustermann'
         | 
| 576 | 
            -
             | 
| 577 | 
            -
            pattern = Mustermann.new('/:example', type: :rails)
         | 
| 578 | 
            -
            pattern === "/foo.bar"     # => true
         | 
| 579 | 
            -
            pattern === "/foo/bar"     # => false
         | 
| 580 | 
            -
            pattern.params("/foo.bar") # => { "example" => "foo.bar" }
         | 
| 581 | 
            -
            pattern.params("/foo/bar") # => nil
         | 
| 582 | 
            -
             | 
| 583 | 
            -
            pattern = Mustermann.new('/:example(/:optional)', type: :rails)
         | 
| 584 | 
            -
            pattern === "/foo.bar"     # => true
         | 
| 585 | 
            -
            pattern === "/foo/bar"     # => true
         | 
| 586 | 
            -
            pattern.params("/foo.bar") # => { "example" => "foo.bar", "optional" => nil   }
         | 
| 587 | 
            -
            pattern.params("/foo/bar") # => { "example" => "foo",     "optional" => "bar" }
         | 
| 588 | 
            -
             | 
| 589 | 
            -
            pattern = Mustermann.new('/*example', type: :rails)
         | 
| 590 | 
            -
            pattern === "/foo.bar"     # => true
         | 
| 591 | 
            -
            pattern === "/foo/bar"     # => true
         | 
| 592 | 
            -
            pattern.params("/foo.bar") # => { "example" => "foo.bar" }
         | 
| 593 | 
            -
            pattern.params("/foo/bar") # => { "example" => "foo/bar" }
         | 
| 594 | 
            -
            ```
         | 
| 595 | 
            -
             | 
| 596 | 
            -
            <table>
         | 
| 597 | 
            -
              <thead>
         | 
| 598 | 
            -
                <tr>
         | 
| 599 | 
            -
                  <th>Syntax Element</th>
         | 
| 600 | 
            -
                  <th>Description</th>
         | 
| 601 | 
            -
                </tr>
         | 
| 602 | 
            -
              </thead>
         | 
| 603 | 
            -
              <tbody>
         | 
| 604 | 
            -
                <tr>
         | 
| 605 | 
            -
                  <td><b>:</b><i>name</i></td>
         | 
| 606 | 
            -
                  <td>
         | 
| 607 | 
            -
                    Captures anything but a forward slash in a semi-greedy fashion. Capture is named <i>name</i>.
         | 
| 608 | 
            -
                    Capture behavior can be modified with <a href="#capture"><tt>capture</tt></a> and <a href="#greedy"><tt>greedy</tt></a> option.
         | 
| 609 | 
            -
                  </td>
         | 
| 610 | 
            -
                </tr>
         | 
| 611 | 
            -
                <tr>
         | 
| 612 | 
            -
                  <td><b>*</b><i>name</i></td>
         | 
| 613 | 
            -
                  <td>
         | 
| 614 | 
            -
                    Captures anything in a non-greedy fashion. Capture is named <i>name</i>.
         | 
| 615 | 
            -
                  </td>
         | 
| 616 | 
            -
                </tr>
         | 
| 617 | 
            -
                <tr>
         | 
| 618 | 
            -
                  <td><b>(</b><i>expression</i><b>)</b></td>
         | 
| 619 | 
            -
                  <td>Enclosed <i>expression</i> is optional.</td>
         | 
| 620 | 
            -
                </tr>
         | 
| 621 | 
            -
                <tr>
         | 
| 622 | 
            -
                  <td><b>/</b></td>
         | 
| 623 | 
            -
                  <td>
         | 
| 624 | 
            -
                    Matches forward slash. Does not match URI encoded version of forward slash.
         | 
| 625 | 
            -
                  </td>
         | 
| 626 | 
            -
                </tr>
         | 
| 627 | 
            -
                <tr>
         | 
| 628 | 
            -
                  <td><i>any other character</i></td>
         | 
| 629 | 
            -
                  <td>Matches exactly that character or a URI encoded version of it.</td>
         | 
| 630 | 
            -
                </tr>
         | 
| 631 | 
            -
              </tbody>
         | 
| 632 | 
            -
            </table>
         | 
| 695 | 
            +
            <a name="-performance"></a>
         | 
| 696 | 
            +
            ## Performance
         | 
| 633 697 |  | 
| 634 | 
            -
             | 
| 698 | 
            +
            It's generally a good idea to reuse pattern objects, since as much computation as possible is happening during object creation, so that the actual matching or expanding is quite fast.
         | 
| 635 699 |  | 
| 636 | 
            -
             | 
| 637 | 
            -
            This pattern type is also known as `regular` and the pattern class is `Mustermann::Regular` (located in `mustermann/regular`).
         | 
| 700 | 
            +
            Pattern objects should be treated as immutable. Their internals have been designed for both performance and low memory usage. To reduce pattern compilation, `Mustermann.new` and `Mustermann::Pattern.new` might return the same instance when given the same arguments, if that instance has not yet been garbage collected. However, this is not guaranteed, so do not rely on object identity.
         | 
| 638 701 |  | 
| 639 | 
            -
             | 
| 640 | 
            -
            require 'mustermann'
         | 
| 702 | 
            +
            ### String Matching
         | 
| 641 703 |  | 
| 642 | 
            -
            pattern  | 
| 643 | 
            -
            pattern === "/foo.bar"     # => true
         | 
| 644 | 
            -
            pattern === "/foo/bar"     # => true
         | 
| 645 | 
            -
            pattern.params("/foo.bar") # => { "example" => "foo.bar" }
         | 
| 646 | 
            -
            pattern.params("/foo/bar") # => { "example" => "foo/bar" }
         | 
| 647 | 
            -
            ```
         | 
| 704 | 
            +
            When using a pattern instead of a regular expression for string matching, performance will usually be comparable.
         | 
| 648 705 |  | 
| 649 | 
            -
             | 
| 650 | 
            -
              <thead>
         | 
| 651 | 
            -
                <tr>
         | 
| 652 | 
            -
                  <th>Syntax Element</th>
         | 
| 653 | 
            -
                  <th>Description</th>
         | 
| 654 | 
            -
                </tr>
         | 
| 655 | 
            -
              </thead>
         | 
| 656 | 
            -
              <tbody>
         | 
| 657 | 
            -
                <tr>
         | 
| 658 | 
            -
                  <td><i>any string</i></td>
         | 
| 659 | 
            -
                  <td>Interpreted as regular expression.</td>
         | 
| 660 | 
            -
                </tr>
         | 
| 661 | 
            -
              </tbody>
         | 
| 662 | 
            -
            </table>
         | 
| 706 | 
            +
            In certain cases, Mustermann might outperform naive, equivalent regular expressions. It achieves this by using look-ahead and atomic groups in ways that work well with a backtracking, NFA-based regular expression engine (such as the Oniguruma/Onigmo engine used by Ruby). It can be difficult and error prone to construct complex regular expressions using these techniques by hand. This only applies to patterns generating an AST internally (all but [identity](#-pattern-details-identity), [shell](#-pattern-details-shell), [simple](#-pattern-details-simple) and [regexp](#-pattern-details-regexp) patterns).
         | 
| 663 707 |  | 
| 664 | 
            -
             | 
| 708 | 
            +
            When using a Mustermann pattern as a direct Regexp replacement (ie, via methods like `=~`, `match` or `===`), the overhead will be a single method dispatch, which some Ruby implementations might even eliminate with method inlining. This only applies to patterns using a regular expression internally (all but [identity](#-pattern-details-identity) and [shell](#-pattern-details-shell) patterns).
         | 
| 665 709 |  | 
| 666 | 
            -
             | 
| 667 | 
            -
            require 'mustermann'
         | 
| 668 | 
            -
            Mustermann.new(/(?<example>.*)/).params("input") # => { "example" => "input" }
         | 
| 669 | 
            -
            ```
         | 
| 710 | 
            +
            ### Expanding
         | 
| 670 711 |  | 
| 671 | 
            -
             | 
| 712 | 
            +
            Pattern expansion significantly outperforms other, widely used Ruby tools for generating URLs from URL patterns in most use cases.
         | 
| 672 713 |  | 
| 673 | 
            -
             | 
| 714 | 
            +
            This comes with a few trade-offs:
         | 
| 674 715 |  | 
| 675 | 
            -
             | 
| 676 | 
            -
             | 
| 716 | 
            +
            * As with pattern compilation, as much computation as possible has been shifted to compiling expansion rules. This will add compilation overhead, which is why patterns only generate these rules on the first invocation to `Mustermann::Pattern#expand`. Create a `Mustermann::Expander` instance yourself to get better control over the point in time this computation should happen.
         | 
| 717 | 
            +
            * Memory is sacrificed in favor of performance: The size of the expander object will grow linear with the number of possible combination for expansion keys ("/:foo/:bar" has one such combination, but "/(:foo/)?:bar?" has four)
         | 
| 718 | 
            +
            * Parsing a params hash from a string generated from another params hash might not result in two identical hashes, and vice versa. Specifically, expanding ignores capture constraints, type casting and greediness.
         | 
| 719 | 
            +
            * Partial expansion is (currently) not supported.
         | 
| 677 720 |  | 
| 678 | 
            -
             | 
| 679 | 
            -
            pattern === "/foo.bar" # => true
         | 
| 680 | 
            -
            pattern === "/foo/bar" # => false
         | 
| 721 | 
            +
            ## Details on Pattern Types
         | 
| 681 722 |  | 
| 682 | 
            -
             | 
| 683 | 
            -
             | 
| 684 | 
            -
            pattern === "/foo/bar" # => true
         | 
| 723 | 
            +
            <a name="-identity-pattern"></a>
         | 
| 724 | 
            +
            ### `identity`
         | 
| 685 725 |  | 
| 686 | 
            -
             | 
| 687 | 
            -
             | 
| 688 | 
            -
             | 
| 689 | 
            -
            pattern === "/baz"     # => false
         | 
| 690 | 
            -
            ```
         | 
| 726 | 
            +
            **Supported options:**
         | 
| 727 | 
            +
            [`uri_decode`](#-available-options--uri_decode),
         | 
| 728 | 
            +
            [`ignore_unknown_options`](#-available-options--ignore_unknown_options).
         | 
| 691 729 |  | 
| 692 730 | 
             
            <table>
         | 
| 693 731 | 
             
              <thead>
         | 
| @@ -698,57 +736,18 @@ pattern === "/baz"     # => false | |
| 698 736 | 
             
              </thead>
         | 
| 699 737 | 
             
              <tbody>
         | 
| 700 738 | 
             
                <tr>
         | 
| 701 | 
            -
                  <td>< | 
| 702 | 
            -
                  <td>Matches  | 
| 703 | 
            -
                </tr>
         | 
| 704 | 
            -
                <tr>
         | 
| 705 | 
            -
                  <td><b>**</b></td>
         | 
| 706 | 
            -
                  <td>Matches anything.</td>
         | 
| 707 | 
            -
                </tr>
         | 
| 708 | 
            -
                <tr>
         | 
| 709 | 
            -
                  <td><b>[</b><i>set</i><b>]</b></td>
         | 
| 710 | 
            -
                  <td>Matches one character in <i>set</i>.</td>
         | 
| 711 | 
            -
                </tr>
         | 
| 712 | 
            -
                <tr>
         | 
| 713 | 
            -
                  <td><b>{</b><i>a</i>,<i>b</i><b>}</b></td>
         | 
| 714 | 
            -
                  <td>Matches <i>a</i> or <i>b</i>.</td>
         | 
| 715 | 
            -
                </tr>
         | 
| 716 | 
            -
                <tr>
         | 
| 717 | 
            -
                  <td><b>\</b><i>x</i></td>
         | 
| 718 | 
            -
                  <td>Matches <i>x</i> or URI encoded version of <i>x</i>. For instance <tt>\*</tt> matches <tt>*</tt>.</td>
         | 
| 719 | 
            -
                </tr>
         | 
| 720 | 
            -
                <tr>
         | 
| 721 | 
            -
                  <td><i>any other character</i></td>
         | 
| 722 | 
            -
                  <td>Matches exactly that character or a URI encoded version of it.</td>
         | 
| 739 | 
            +
                  <td><i>any character</i></td>
         | 
| 740 | 
            +
                  <td>Matches exactly that character or a URI escaped version of it.</td>
         | 
| 723 741 | 
             
                </tr>
         | 
| 724 742 | 
             
              </tbody>
         | 
| 725 743 | 
             
            </table>
         | 
| 726 744 |  | 
| 727 | 
            -
             | 
| 728 | 
            -
             | 
| 729 | 
            -
            Patterns as used by Sinatra 1.3. Useful for porting an application that relies on this behavior to a later Sinatra version and to make sure [Sinatra 2.0](#sinatra) patterns do not decrease performance. Simple patterns internally use the same code older Sinatra versions used for compiling the pattern. Error messages for broken patterns will therefore not be as informative as for other pattern implementations.
         | 
| 730 | 
            -
             | 
| 731 | 
            -
            ``` ruby
         | 
| 732 | 
            -
            require 'mustermann'
         | 
| 745 | 
            +
            <a name="-regexp-pattern"></a>
         | 
| 746 | 
            +
            ### `regexp`
         | 
| 733 747 |  | 
| 734 | 
            -
             | 
| 735 | 
            -
             | 
| 736 | 
            -
             | 
| 737 | 
            -
            pattern.params("/foo.bar") # => { "example" => "foo.bar" }
         | 
| 738 | 
            -
            pattern.params("/foo/bar") # => nil
         | 
| 739 | 
            -
             | 
| 740 | 
            -
            pattern = Mustermann.new('/:example/?:optional?', type: :simple)
         | 
| 741 | 
            -
            pattern === "/foo.bar"     # => true
         | 
| 742 | 
            -
            pattern === "/foo/bar"     # => true
         | 
| 743 | 
            -
            pattern.params("/foo.bar") # => { "example" => "foo.bar", "optional" => nil   }
         | 
| 744 | 
            -
            pattern.params("/foo/bar") # => { "example" => "foo",     "optional" => "bar" }
         | 
| 745 | 
            -
             | 
| 746 | 
            -
            pattern = Mustermann.new('/*', type: :simple)
         | 
| 747 | 
            -
            pattern === "/foo.bar"     # => true
         | 
| 748 | 
            -
            pattern === "/foo/bar"     # => true
         | 
| 749 | 
            -
            pattern.params("/foo.bar") # => { "splat" => ["foo.bar"] }
         | 
| 750 | 
            -
            pattern.params("/foo/bar") # => { "splat" => ["foo/bar"] }
         | 
| 751 | 
            -
            ```
         | 
| 748 | 
            +
            **Supported options:**
         | 
| 749 | 
            +
            [`uri_decode`](#-available-options--uri_decode),
         | 
| 750 | 
            +
            [`ignore_unknown_options`](#-available-options--ignore_unknown_options).
         | 
| 752 751 |  | 
| 753 752 | 
             
            <table>
         | 
| 754 753 | 
             
              <thead>
         | 
| @@ -759,76 +758,22 @@ pattern.params("/foo/bar") # => { "splat" => ["foo/bar"] } | |
| 759 758 | 
             
              </thead>
         | 
| 760 759 | 
             
              <tbody>
         | 
| 761 760 | 
             
                <tr>
         | 
| 762 | 
            -
                  <td>< | 
| 763 | 
            -
                  <td>
         | 
| 764 | 
            -
                    Captures anything but a forward slash in a greedy fashion. Capture is named <i>name</i>.
         | 
| 765 | 
            -
                  </td>
         | 
| 766 | 
            -
                </tr>
         | 
| 767 | 
            -
                <tr>
         | 
| 768 | 
            -
                  <td><b>*</b></td>
         | 
| 769 | 
            -
                  <td>
         | 
| 770 | 
            -
                    Captures anything in a non-greedy fashion. Capture is named splat.
         | 
| 771 | 
            -
                    It is always an array of captures, as you can use <tt>*</tt> more than once in a pattern.
         | 
| 772 | 
            -
                  </td>
         | 
| 773 | 
            -
                </tr>
         | 
| 774 | 
            -
                <tr>
         | 
| 775 | 
            -
                  <td><i>x</i><b>?</b></td>
         | 
| 776 | 
            -
                  <td>Makes <i>x</i> optional. For instance <tt>foo?</tt> matches <tt>foo</tt> or <tt>fo</tt>.</td>
         | 
| 777 | 
            -
                </tr>
         | 
| 778 | 
            -
                <tr>
         | 
| 779 | 
            -
                  <td><b>/</b></td>
         | 
| 780 | 
            -
                  <td>
         | 
| 781 | 
            -
                    Matches forward slash. Does not match URI encoded version of forward slash.
         | 
| 782 | 
            -
                  </td>
         | 
| 783 | 
            -
                </tr>
         | 
| 784 | 
            -
                <tr>
         | 
| 785 | 
            -
                  <td><i>any special character</i></td>
         | 
| 786 | 
            -
                  <td>Matches exactly that character or a URI encoded version of it.</td>
         | 
| 787 | 
            -
                </tr>
         | 
| 788 | 
            -
                <tr>
         | 
| 789 | 
            -
                  <td><i>any other character</i></td>
         | 
| 790 | 
            -
                  <td>Matches exactly that character.</td>
         | 
| 761 | 
            +
                  <td><i>any string</i></td>
         | 
| 762 | 
            +
                  <td>Interpreted as regular expression.</td>
         | 
| 791 763 | 
             
                </tr>
         | 
| 792 764 | 
             
              </tbody>
         | 
| 793 765 | 
             
            </table>
         | 
| 794 766 |  | 
| 767 | 
            +
            <a name="-sinatra-pattern"></a>
         | 
| 795 768 | 
             
            ### `sinatra`
         | 
| 796 769 |  | 
| 797 | 
            -
             | 
| 798 | 
            -
             | 
| 799 | 
            -
             | 
| 800 | 
            -
             | 
| 801 | 
            -
             | 
| 802 | 
            -
             | 
| 803 | 
            -
             | 
| 804 | 
            -
            pattern === "/foo/bar"     # => false
         | 
| 805 | 
            -
            pattern.params("/foo.bar") # => { "example" => "foo.bar" }
         | 
| 806 | 
            -
            pattern.params("/foo/bar") # => nil
         | 
| 807 | 
            -
             | 
| 808 | 
            -
            pattern = Mustermann.new('/\:example')
         | 
| 809 | 
            -
            pattern === "/foo.bar"      # => false
         | 
| 810 | 
            -
            pattern === "/:example"     # => true
         | 
| 811 | 
            -
            pattern.params("/foo.bar")  # => nil
         | 
| 812 | 
            -
            pattern.params("/:example") # => {}
         | 
| 813 | 
            -
             | 
| 814 | 
            -
            pattern = Mustermann.new('/:example(/:optional)?')
         | 
| 815 | 
            -
            pattern === "/foo.bar"     # => true
         | 
| 816 | 
            -
            pattern === "/foo/bar"     # => true
         | 
| 817 | 
            -
            pattern.params("/foo.bar") # => { "example" => "foo.bar", "optional" => nil   }
         | 
| 818 | 
            -
            pattern.params("/foo/bar") # => { "example" => "foo",     "optional" => "bar" }
         | 
| 819 | 
            -
             | 
| 820 | 
            -
            pattern = Mustermann.new('/*')
         | 
| 821 | 
            -
            pattern === "/foo.bar"     # => true
         | 
| 822 | 
            -
            pattern === "/foo/bar"     # => true
         | 
| 823 | 
            -
            pattern.params("/foo.bar") # => { "splat" => ["foo.bar"] }
         | 
| 824 | 
            -
            pattern.params("/foo/bar") # => { "splat" => ["foo/bar"] }
         | 
| 825 | 
            -
             | 
| 826 | 
            -
            pattern = Mustermann.new('/*example')
         | 
| 827 | 
            -
            pattern === "/foo.bar"     # => true
         | 
| 828 | 
            -
            pattern === "/foo/bar"     # => true
         | 
| 829 | 
            -
            pattern.params("/foo.bar") # => { "example" => "foo.bar" }
         | 
| 830 | 
            -
            pattern.params("/foo/bar") # => { "example" => "foo/bar" }
         | 
| 831 | 
            -
            ```
         | 
| 770 | 
            +
            **Supported options:**
         | 
| 771 | 
            +
            [`capture`](#-available-options--capture),
         | 
| 772 | 
            +
            [`except`](#-available-options--except),
         | 
| 773 | 
            +
            [`greedy`](#-available-options--greedy),
         | 
| 774 | 
            +
            [`space_matches_plus`](#-available-options--space_matches_plus),
         | 
| 775 | 
            +
            [`uri_decode`](#-available-options--uri_decode),
         | 
| 776 | 
            +
            [`ignore_unknown_options`](#-available-options--ignore_unknown_options).
         | 
| 832 777 |  | 
| 833 778 | 
             
            <table>
         | 
| 834 779 | 
             
              <thead>
         | 
| @@ -839,23 +784,23 @@ pattern.params("/foo/bar") # => { "example" => "foo/bar" } | |
| 839 784 | 
             
              </thead>
         | 
| 840 785 | 
             
              <tbody>
         | 
| 841 786 | 
             
                <tr>
         | 
| 842 | 
            -
                  <td><b>:</b><i>name</i></td>
         | 
| 787 | 
            +
                  <td><b>:</b><i>name</i> <i><b>or</b></i> <b>{</b><i>name</i><b>}</b></td>
         | 
| 843 788 | 
             
                  <td>
         | 
| 844 789 | 
             
                    Captures anything but a forward slash in a semi-greedy fashion. Capture is named <i>name</i>.
         | 
| 845 | 
            -
                    Capture behavior can be modified with < | 
| 790 | 
            +
                    Capture behavior can be modified with <tt>capture</tt> and <tt>greedy</tt> option.
         | 
| 846 791 | 
             
                  </td>
         | 
| 847 792 | 
             
                </tr>
         | 
| 848 793 | 
             
                <tr>
         | 
| 849 | 
            -
                  <td><b>*</b><i>name</i></td>
         | 
| 794 | 
            +
                  <td><b>*</b><i>name</i> <i><b>or</b></i> <b>{+</b><i>name</i><b>}</b></td>
         | 
| 850 795 | 
             
                  <td>
         | 
| 851 796 | 
             
                    Captures anything in a non-greedy fashion. Capture is named <i>name</i>.
         | 
| 852 797 | 
             
                  </td>
         | 
| 853 798 | 
             
                </tr>
         | 
| 854 799 | 
             
                <tr>
         | 
| 855 | 
            -
                  <td><b>*</b></td>
         | 
| 800 | 
            +
                  <td><b>*</b> <i><b>or</b></i> <b>{+splat}</b></td>
         | 
| 856 801 | 
             
                  <td>
         | 
| 857 802 | 
             
                    Captures anything in a non-greedy fashion. Capture is named splat.
         | 
| 858 | 
            -
                    It is always an array of captures, as you can use  | 
| 803 | 
            +
                    It is always an array of captures, as you can use it more than once in a pattern.
         | 
| 859 804 | 
             
                  </td>
         | 
| 860 805 | 
             
                </tr>
         | 
| 861 806 | 
             
                <tr>
         | 
| @@ -865,9 +810,15 @@ pattern.params("/foo/bar") # => { "example" => "foo/bar" } | |
| 865 810 | 
             
                    or to separate two elements that would otherwise be parsed as one.
         | 
| 866 811 | 
             
                  </td>
         | 
| 867 812 | 
             
                </tr>
         | 
| 813 | 
            +
                <tr>
         | 
| 814 | 
            +
                  <td><b>(</b><i>expression</i><b>|</b><i>expression</i><b>|</b><i>...</i><b>)</b></td>
         | 
| 815 | 
            +
                  <td>
         | 
| 816 | 
            +
                    Will match anything matching the nested expressions. May contain any other syntax element, including captures.
         | 
| 817 | 
            +
                  </td>
         | 
| 818 | 
            +
                </tr>
         | 
| 868 819 | 
             
                <tr>
         | 
| 869 820 | 
             
                  <td><i>x</i><b>?</b></td>
         | 
| 870 | 
            -
                  <td>Makes <i>x</i> optional. For instance <tt>(foo)?</tt> matches <tt>foo</tt> or an empty string.</td>
         | 
| 821 | 
            +
                  <td>Makes <i>x</i> optional. For instance, <tt>(foo)?</tt> matches <tt>foo</tt> or an empty string.</td>
         | 
| 871 822 | 
             
                </tr>
         | 
| 872 823 | 
             
                <tr>
         | 
| 873 824 | 
             
                  <td><b>/</b></td>
         | 
| @@ -885,197 +836,3 @@ pattern.params("/foo/bar") # => { "example" => "foo/bar" } | |
| 885 836 | 
             
                </tr>
         | 
| 886 837 | 
             
              </tbody>
         | 
| 887 838 | 
             
            </table>
         | 
| 888 | 
            -
             | 
| 889 | 
            -
            ### `template`
         | 
| 890 | 
            -
             | 
| 891 | 
            -
            Parses fully expanded URI templates as specified by [RFC 6570](http://tools.ietf.org/html/rfc6570).
         | 
| 892 | 
            -
             | 
| 893 | 
            -
            Note that it differs from URI templates in that it takes the unescaped version of special character instead of the escaped version.
         | 
| 894 | 
            -
             | 
| 895 | 
            -
            ``` ruby
         | 
| 896 | 
            -
            require 'mustermann'
         | 
| 897 | 
            -
             | 
| 898 | 
            -
            pattern = Mustermann.new('/{example}', type: :template)
         | 
| 899 | 
            -
            pattern === "/foo.bar"     # => true
         | 
| 900 | 
            -
            pattern === "/foo/bar"     # => false
         | 
| 901 | 
            -
            pattern.params("/foo.bar") # => { "example" => "foo.bar" }
         | 
| 902 | 
            -
            pattern.params("/foo/bar") # => nil
         | 
| 903 | 
            -
             | 
| 904 | 
            -
            pattern = Mustermann.new("{/segments*}/{page}{.ext,cmpr:2}", type: :template)
         | 
| 905 | 
            -
            pattern.params("/a/b/c.tar.gz") # => {"segments"=>["a","b"], "page"=>"c", "ext"=>"tar", "cmpr"=>"gz"}
         | 
| 906 | 
            -
            ```
         | 
| 907 | 
            -
             | 
| 908 | 
            -
            <table>
         | 
| 909 | 
            -
              <thead>
         | 
| 910 | 
            -
                <tr>
         | 
| 911 | 
            -
                  <th>Syntax Element</th>
         | 
| 912 | 
            -
                  <th>Description</th>
         | 
| 913 | 
            -
                </tr>
         | 
| 914 | 
            -
              </thead>
         | 
| 915 | 
            -
              <tbody>
         | 
| 916 | 
            -
                <tr>
         | 
| 917 | 
            -
                  <td><b>{</b><i>o</i> <i>var</i> <i>m</i><b>,</b> <i>var</i> <i>m</i><b>,</b> ...<b>}</b></td>
         | 
| 918 | 
            -
                  <td>
         | 
| 919 | 
            -
                    Captures expansion.
         | 
| 920 | 
            -
                    Operator <i>o</i>: <code>+ # . / ; ? &</tt> or none.
         | 
| 921 | 
            -
                    Modifier <i>m</i>: <code>:num *</tt> or none.
         | 
| 922 | 
            -
                  </td>
         | 
| 923 | 
            -
                </tr>
         | 
| 924 | 
            -
                <tr>
         | 
| 925 | 
            -
                  <td><b>/</b></td>
         | 
| 926 | 
            -
                  <td>
         | 
| 927 | 
            -
                    Matches forward slash. Does not match URI encoded version of forward slash.
         | 
| 928 | 
            -
                  </td>
         | 
| 929 | 
            -
                </tr>
         | 
| 930 | 
            -
                <tr>
         | 
| 931 | 
            -
                  <td><i>any other character</i></td>
         | 
| 932 | 
            -
                  <td>Matches exactly that character or a URI encoded version of it.</td>
         | 
| 933 | 
            -
                </tr>
         | 
| 934 | 
            -
              </tbody>
         | 
| 935 | 
            -
            </table>
         | 
| 936 | 
            -
             | 
| 937 | 
            -
            The operators `+` and `#` will always match non-greedy, whereas all other operators match semi-greedy by default.
         | 
| 938 | 
            -
            All modifiers and operators are supported. However, it does not parse lists as single values without the *explode* modifier (aka *star*).
         | 
| 939 | 
            -
            Parametric operators (`;`, `?` and `&`) currently only match parameters in given order.
         | 
| 940 | 
            -
             | 
| 941 | 
            -
            Please keep the following in mind:
         | 
| 942 | 
            -
             | 
| 943 | 
            -
            > "Some URI Templates can be used in reverse for the purpose of variable matching: comparing the template to a fully formed URI in order to extract the variable parts from that URI and assign them to the named variables.  Variable matching only works well if the template expressions are delimited by the beginning or end of the URI or by characters that cannot be part of the expansion, such as reserved characters surrounding a simple string expression.  In general, regular expression languages are better suited for variable matching."
         | 
| 944 | 
            -
            > — *RFC 6570, Sec 1.5: "Limitations"*
         | 
| 945 | 
            -
             | 
| 946 | 
            -
            If you reuse the exact same templates and expose them via an external API meant for expansion,
         | 
| 947 | 
            -
            you should set `uri_decode` to `false` in order to conform with the specification.
         | 
| 948 | 
            -
             | 
| 949 | 
            -
            If you are looking for an alternative implementation that also supports expanding, check out [addressable](http://addressable.rubyforge.org/).
         | 
| 950 | 
            -
             | 
| 951 | 
            -
            ## Mapper
         | 
| 952 | 
            -
             | 
| 953 | 
            -
            You can use a mapper to transform strings according to two or more mappings:
         | 
| 954 | 
            -
             | 
| 955 | 
            -
            ``` ruby
         | 
| 956 | 
            -
            require 'mustermann/mapper'
         | 
| 957 | 
            -
             | 
| 958 | 
            -
            mapper = Mustermann::Mapper.new("/:page(.:format)?" => ["/:page/view.:format", "/:page/view.html"])
         | 
| 959 | 
            -
            mapper['/foo']     # => "/foo/view.html"
         | 
| 960 | 
            -
            mapper['/foo.xml'] # => "/foo/view.xml"
         | 
| 961 | 
            -
            mapper['/foo/bar'] # => "/foo/bar"
         | 
| 962 | 
            -
            ```
         | 
| 963 | 
            -
             | 
| 964 | 
            -
            ## Routers
         | 
| 965 | 
            -
             | 
| 966 | 
            -
            Mustermann comes with basic router implementations that will call certain callbacks depending on the input.
         | 
| 967 | 
            -
             | 
| 968 | 
            -
            ### Simple Router
         | 
| 969 | 
            -
             | 
| 970 | 
            -
            The simple router chooses callbacks based on an input string.
         | 
| 971 | 
            -
             | 
| 972 | 
            -
            ``` ruby
         | 
| 973 | 
            -
            require 'mustermann/router/simple'
         | 
| 974 | 
            -
             | 
| 975 | 
            -
            router = Mustermann::Router::Simple.new(default: 42)
         | 
| 976 | 
            -
            router.on(':name', capture: :digit) { |string| string.to_i }
         | 
| 977 | 
            -
            router.call("23")      # => 23
         | 
| 978 | 
            -
            router.call("example") # => 42
         | 
| 979 | 
            -
            ```
         | 
| 980 | 
            -
             | 
| 981 | 
            -
            ### Rack Router
         | 
| 982 | 
            -
             | 
| 983 | 
            -
            This is not a full replacement for Rails, Sinatra, Cuba, etc, as it only cares about path based routing.
         | 
| 984 | 
            -
             | 
| 985 | 
            -
            ``` ruby
         | 
| 986 | 
            -
            require 'mustermann/router/rack'
         | 
| 987 | 
            -
             | 
| 988 | 
            -
            router = Mustermann::Router::Rack.new do
         | 
| 989 | 
            -
              on '/' do |env|
         | 
| 990 | 
            -
                [200, {'Content-Type' => 'text/plain'}, ['Hello World!']]
         | 
| 991 | 
            -
              end
         | 
| 992 | 
            -
             | 
| 993 | 
            -
              on '/:name' do |env|
         | 
| 994 | 
            -
                name = env['mustermann.params']['name']
         | 
| 995 | 
            -
                [200, {'Content-Type' => 'text/plain'}, ["Hello #{name}!"]]
         | 
| 996 | 
            -
              end
         | 
| 997 | 
            -
             | 
| 998 | 
            -
              on '/something/*', call: SomeApp
         | 
| 999 | 
            -
            end
         | 
| 1000 | 
            -
             | 
| 1001 | 
            -
            # in a config.ru
         | 
| 1002 | 
            -
            run router
         | 
| 1003 | 
            -
            ```
         | 
| 1004 | 
            -
             | 
| 1005 | 
            -
            ## Requirements
         | 
| 1006 | 
            -
             | 
| 1007 | 
            -
            Mustermann has no dependencies besides a Ruby 2.0 compatible Ruby implementation.
         | 
| 1008 | 
            -
             | 
| 1009 | 
            -
            It is known to work on **MRI 2.0** and **MRI trunk**.
         | 
| 1010 | 
            -
             | 
| 1011 | 
            -
            **JRuby** is not yet fully supported. It is possible to run large parts of Mustermann by passing in `--2.0 -X-C` starting from JRuby 1.7.4. See [issue #2](https://github.com/rkh/mustermann/issues/2) for up to date information.
         | 
| 1012 | 
            -
             | 
| 1013 | 
            -
            **Rubinius** is not yet able to parse the Mustermann source code. See [issue #14](https://github.com/rkh/mustermann/issues/14) for up to date information.
         | 
| 1014 | 
            -
             | 
| 1015 | 
            -
            ## Release History
         | 
| 1016 | 
            -
             | 
| 1017 | 
            -
            Mustermann follows [Semantic Versioning 2.0](http://semver.org/). Anything documented in the README or via YARD and not declared private is part of the public API.
         | 
| 1018 | 
            -
             | 
| 1019 | 
            -
            ### Stable Releases
         | 
| 1020 | 
            -
             | 
| 1021 | 
            -
            There have been no stable releases yet. The code base is considered solid but I don't know of anyone using it in production yet.
         | 
| 1022 | 
            -
            As there has been no stable release yet, the API might still change, though I consider this unlikely.
         | 
| 1023 | 
            -
             | 
| 1024 | 
            -
            ### Development Releases
         | 
| 1025 | 
            -
             | 
| 1026 | 
            -
            * **Mustermann 0.3.1** (2014-09-12)
         | 
| 1027 | 
            -
                * More Infos:
         | 
| 1028 | 
            -
                  [RubyGems.org](http://rubygems.org/gems/mustermann/versions/0.3.1),
         | 
| 1029 | 
            -
                  [RubyDoc.info](http://rubydoc.info/gems/mustermann/0.3.1/frames),
         | 
| 1030 | 
            -
                  [GitHub.com](https://github.com/rkh/mustermann/tree/v0.3.1)
         | 
| 1031 | 
            -
                * Speed up pattern generation and matchin (thanks [Daniel Mendler](https://github.com/minad))
         | 
| 1032 | 
            -
                * Small change so `Mustermann === Mustermann.new('...')` returns `true`.
         | 
| 1033 | 
            -
            * **Mustermann 0.3.0** (2014-08-18)
         | 
| 1034 | 
            -
                * More Infos:
         | 
| 1035 | 
            -
                  [RubyGems.org](http://rubygems.org/gems/mustermann/versions/0.3.0),
         | 
| 1036 | 
            -
                  [RubyDoc.info](http://rubydoc.info/gems/mustermann/0.3.0/frames),
         | 
| 1037 | 
            -
                  [GitHub.com](https://github.com/rkh/mustermann/tree/v0.3.0)
         | 
| 1038 | 
            -
                * Add `regexp` pattern.
         | 
| 1039 | 
            -
                * Add named splats to Sinatra patterns.
         | 
| 1040 | 
            -
                * Add `Mustermann::Mapper`.
         | 
| 1041 | 
            -
                * Improve duck typing support.
         | 
| 1042 | 
            -
                * Improve documentation.
         | 
| 1043 | 
            -
            * **Mustermann 0.2.0** (2013-08-24)
         | 
| 1044 | 
            -
                * More Infos:
         | 
| 1045 | 
            -
                  [RubyGems.org](http://rubygems.org/gems/mustermann/versions/0.2.0),
         | 
| 1046 | 
            -
                  [RubyDoc.info](http://rubydoc.info/gems/mustermann/0.2.0/frames),
         | 
| 1047 | 
            -
                  [GitHub.com](https://github.com/rkh/mustermann/tree/v0.2.0)
         | 
| 1048 | 
            -
                * Add first class expander objects.
         | 
| 1049 | 
            -
                * Add params casting for expander.
         | 
| 1050 | 
            -
                * Add simple router and rack router.
         | 
| 1051 | 
            -
                * Add weak equality map to significantly improve performance.
         | 
| 1052 | 
            -
                * Fix Ruby warnings.
         | 
| 1053 | 
            -
                * Improve documentation.
         | 
| 1054 | 
            -
                * Refactor pattern validation, AST transformations.
         | 
| 1055 | 
            -
                * Increase test coverage (from 100%+ to 100%++).
         | 
| 1056 | 
            -
                * Improve JRuby compatibility.
         | 
| 1057 | 
            -
                * Work around bug in 2.0.0-p0.
         | 
| 1058 | 
            -
            * **Mustermann 0.1.0** (2013-05-12)
         | 
| 1059 | 
            -
                * More Infos:
         | 
| 1060 | 
            -
                  [RubyGems.org](http://rubygems.org/gems/mustermann/versions/0.1.0),
         | 
| 1061 | 
            -
                  [RubyDoc.info](http://rubydoc.info/gems/mustermann/0.1.0/frames),
         | 
| 1062 | 
            -
                  [GitHub.com](https://github.com/rkh/mustermann/tree/v0.1.0)
         | 
| 1063 | 
            -
                * Add `Pattern#expand` for generating strings from patterns.
         | 
| 1064 | 
            -
                * Add better internal API for working with the AST.
         | 
| 1065 | 
            -
                * Improved documentation.
         | 
| 1066 | 
            -
                * Avoids parsing the path twice when used as Sinatra extension.
         | 
| 1067 | 
            -
                * Better exceptions for unknown pattern types.
         | 
| 1068 | 
            -
                * Better handling of edge cases around extend.
         | 
| 1069 | 
            -
                * More specs to ensure API stability.
         | 
| 1070 | 
            -
                * Largely rework internals of Sinatra, Rails and Template patterns.
         | 
| 1071 | 
            -
            * **Mustermann 0.0.1** (2013-04-27)
         | 
| 1072 | 
            -
                * More Infos:
         | 
| 1073 | 
            -
                  [RubyGems.org](http://rubygems.org/gems/mustermann/versions/0.0.1),
         | 
| 1074 | 
            -
                  [RubyDoc.info](http://rubydoc.info/gems/mustermann/0.0.1/frames),
         | 
| 1075 | 
            -
                  [GitHub.com](https://github.com/rkh/mustermann/tree/v0.0.1)
         | 
| 1076 | 
            -
                * Initial Release.
         | 
| 1077 | 
            -
             | 
| 1078 | 
            -
            ### Upcoming Releases
         | 
| 1079 | 
            -
             | 
| 1080 | 
            -
            * **Mustermann 1.0.0** (before Sinatra 2.0)
         | 
| 1081 | 
            -
                * First stable release.
         |