[Bps-public-commit] Path-Dispatcher branch, master, updated. 7fd79d2487d93bc880f76789abd06a6e935f0d74

sartak at bestpractical.com sartak at bestpractical.com
Wed Jan 6 19:55:55 EST 2010


The branch, master has been updated
       via  7fd79d2487d93bc880f76789abd06a6e935f0d74 (commit)
      from  c91a2f93d6e247575483b0a2b9e15a447c9c5ab7 (commit)

Summary of changes:
 lib/Path/Dispatcher/Rule.pm          |    1 +
 lib/Path/Dispatcher/Rule/Sequence.pm |   44 +++++++++++
 t/024-sequence.t                     |  136 ++++++++++++++++++++++++++++++++++
 3 files changed, 181 insertions(+), 0 deletions(-)
 create mode 100644 lib/Path/Dispatcher/Rule/Sequence.pm
 create mode 100644 t/024-sequence.t

- Log -----------------------------------------------------------------
commit 7fd79d2487d93bc880f76789abd06a6e935f0d74
Author: Shawn M Moore <sartak at bestpractical.com>
Date:   Wed Jan 6 19:55:43 2010 -0500

    First cut of a generic Sequence rule (like Tokens but better)

diff --git a/lib/Path/Dispatcher/Rule.pm b/lib/Path/Dispatcher/Rule.pm
index b32dfaf..90ad4be 100644
--- a/lib/Path/Dispatcher/Rule.pm
+++ b/lib/Path/Dispatcher/Rule.pm
@@ -149,6 +149,7 @@ require Path::Dispatcher::Rule::Eq;
 require Path::Dispatcher::Rule::Intersection;
 require Path::Dispatcher::Rule::Metadata;
 require Path::Dispatcher::Rule::Regex;
+require Path::Dispatcher::Rule::Sequence;
 require Path::Dispatcher::Rule::Tokens;
 require Path::Dispatcher::Rule::Under;
 
diff --git a/lib/Path/Dispatcher/Rule/Sequence.pm b/lib/Path/Dispatcher/Rule/Sequence.pm
new file mode 100644
index 0000000..1c800de
--- /dev/null
+++ b/lib/Path/Dispatcher/Rule/Sequence.pm
@@ -0,0 +1,44 @@
+package Path::Dispatcher::Rule::Sequence;
+use Any::Moose;
+use Any::Moose '::Util::TypeConstraints';
+
+extends 'Path::Dispatcher::Rule';
+with 'Path::Dispatcher::Role::Rules';
+
+has delimiter => (
+    is      => 'rw',
+    isa     => 'Str',
+    default => ' ',
+);
+
+sub _match {
+    my $self = shift;
+    my $path = shift;
+
+    my @rules = $self->rules;
+    my $delimiter = $self->delimiter;
+    my @matches;
+    my $leftover = $path->path; # start with everything leftover
+
+    for my $rule (@rules) {
+        my $match = $rule->match($path);
+        return if !$match;
+
+        $leftover = $match->leftover;
+
+        push @matches, substr($path, 0, length($path) - length($leftover));
+
+        $leftover =~ s/^\Q$delimiter\E+//;
+        return \@matches if length($leftover) == 0;
+
+        $path = $path->clone_path($leftover);
+    }
+
+    # leftover text
+    return \@matches, $leftover if $self->prefix;
+
+    return;
+}
+
+1;
+
diff --git a/t/024-sequence.t b/t/024-sequence.t
new file mode 100644
index 0000000..777bc02
--- /dev/null
+++ b/t/024-sequence.t
@@ -0,0 +1,136 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More tests => 10;
+use Path::Dispatcher;
+
+my @calls;
+
+my $dispatcher = Path::Dispatcher->new;
+$dispatcher->add_rule(
+    Path::Dispatcher::Rule::Sequence->new(
+        rules => [
+            Path::Dispatcher::Rule::Eq->new(
+                string => 'foo',
+                prefix => 1,
+            ),
+            Path::Dispatcher::Rule::Eq->new(
+                string => 'bar',
+                prefix => 1,
+            ),
+        ],
+        block  => sub { push @calls, [$1, $2, $3] },
+    ),
+);
+
+$dispatcher->run('foo bar');
+is_deeply([splice @calls], [ ['foo', 'bar', undef] ], "correctly populated number vars from [str, str] token rule");
+
+$dispatcher->add_rule(
+    Path::Dispatcher::Rule::Sequence->new(
+        rules => [
+            Path::Dispatcher::Rule::Eq->new(
+                string => 'foo',
+                prefix => 1,
+            ),
+            Path::Dispatcher::Rule::Regex->new(
+                regex => qr/bar/,
+            ),
+        ],
+        block  => sub { push @calls, [$1, $2, $3] },
+    ),
+);
+
+$dispatcher->run('foo bar');
+is_deeply([splice @calls], [ ['foo', 'bar', undef] ], "ran the first [str, str] rule");
+
+$dispatcher->run('foo barbaz');
+is_deeply([splice @calls], [ ['foo', 'barbaz', undef] ], "ran the second [str, regex] rule");
+
+$dispatcher->run('foo bar baz');
+is_deeply([splice @calls], [], "no matches");
+
+$dispatcher->add_rule(
+    Path::Dispatcher::Rule::Sequence->new(
+        rules => [
+            Path::Dispatcher::Rule::Alternation->new(
+                rules => [
+                    Path::Dispatcher::Rule::Eq->new(
+                        string => 'Bat',
+                        prefix => 1,
+                    ),
+                    Path::Dispatcher::Rule::Eq->new(
+                        string => 'Super',
+                        prefix => 1,
+                    ),
+                ],
+            ),
+            Path::Dispatcher::Rule::Eq->new(
+                string => 'Man',
+            ),
+        ],
+        block  => sub { push @calls, [$1, $2, $3] },
+    ),
+);
+
+$dispatcher->run('Super Man');
+is_deeply([splice @calls], [ ['Super', 'Man', undef] ], "ran the [ [Str,Str], Str ] rule");
+
+$dispatcher->run('Bat Man');
+is_deeply([splice @calls], [ ['Bat', 'Man', undef] ], "ran the [ [Str,Str], Str ] rule");
+
+$dispatcher->run('Aqua Man');
+is_deeply([splice @calls], [ ], "no match");
+
+$dispatcher->add_rule(
+    Path::Dispatcher::Rule::Sequence->new(
+        rules => [
+            Path::Dispatcher::Rule::Alternation->new(
+                rules => [
+                    Path::Dispatcher::Rule::Alternation->new(
+                        rules => [
+                            Path::Dispatcher::Rule::Alternation->new(
+                                rules => [
+                                    Path::Dispatcher::Rule::Regex->new(
+                                        regex => qr/Deep/,
+                                    ),
+                                ],
+                            ),
+                        ],
+                    ),
+                ],
+            ),
+            Path::Dispatcher::Rule::Eq->new(
+                string => "Man",
+            ),
+        ],
+        block => sub { push @calls, [$1, $2, $3] },
+    ),
+);
+
+$dispatcher->run('Deep Man');
+is_deeply([splice @calls], [ ['Deep', 'Man', undef] ], "alternations can be arbitrarily deep");
+
+$dispatcher->run('Not Appearing in this Dispatcher Man');
+is_deeply([splice @calls], [ ], "no match");
+
+my $rule = Path::Dispatcher::Rule::Sequence->new(
+    rules => [
+        Path::Dispatcher::Rule::Eq->new(
+            string         => 'path',
+            case_sensitive => 0,
+            prefix         => 1,
+        ),
+        Path::Dispatcher::Rule::Eq->new(
+            string         => 'dispatcher',
+            case_sensitive => 0,
+            prefix         => 1,
+        ),
+    ],
+    prefix    => 1,
+    delimiter => '::',
+);
+
+my $match = $rule->match(Path::Dispatcher::Path->new('Path::Dispatcher::Rule::Tokens'));
+is($match->leftover, 'Rule::Tokens');
+

-----------------------------------------------------------------------



More information about the Bps-public-commit mailing list