the kind of perl code that can only be written at 4:30 am
authorjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Fri, 27 Apr 2007 08:34:09 +0000 (08:34 +0000)
committerjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Fri, 27 Apr 2007 08:34:09 +0000 (08:34 +0000)
(Get a good message when a PageSpec fails due to a negated success by
creating success objects with a reason string, which morph into failure
objects when negated.)

IkiWiki.pm
IkiWiki/Plugin/conditional.pm
IkiWiki/Plugin/testpagespec.pm
debian/changelog
doc/plugins/testpagespec.mdwn
doc/plugins/write.mdwn
po/ikiwiki.pot
t/pagespec_match.t

index 88d6d442b9c28b5cf2ab420b2b663158b5c5258e..73280abf1b13b0f3d56e3c71657ac401da061cc6 100644 (file)
@@ -1006,8 +1006,22 @@ sub pagespec_match ($$;@) { #{{{
 package IkiWiki::FailReason;
 
 use overload (
 package IkiWiki::FailReason;
 
 use overload (
-       '""' => sub { return ${$_[0]} },
-       '0+' => sub { return 0 },
+       '""'    => sub { return ${$_[0]} },
+       '0+'    => sub { return 0 },
+       '!'     => sub { bless $_[0], 'IkiWiki::SuccessReason'},
+       fallback => 1,
+);
+
+sub new {
+       bless \$_[1], $_[0];
+}
+
+package IkiWiki::SuccessReason;
+
+use overload (
+       '""'    => sub { return ${$_[0]} },
+       '0+'    => sub { return 1 },
+       '!'     => sub { bless $_[0], 'IkiWiki::FailReason'},
        fallback => 1,
 );
 
        fallback => 1,
 );
 
@@ -1037,7 +1051,7 @@ sub match_glob ($$;@) { #{{{
        $glob=~s/\\\?/./g;
 
        if ($page=~/^$glob$/i) {
        $glob=~s/\\\?/./g;
 
        if ($page=~/^$glob$/i) {
-               return 1
+               return IkiWiki::SuccessReason->new("$glob matches $page");
        }
        else {
                return IkiWiki::FailReason->new("$glob does not match $page");
        }
        else {
                return IkiWiki::FailReason->new("$glob does not match $page");
@@ -1063,7 +1077,8 @@ sub match_link ($$;@) { #{{{
        my $bestlink = IkiWiki::bestlink($from, $link);
        return IkiWiki::FailReason->new("no such link") unless length $bestlink;
        foreach my $p (@$links) {
        my $bestlink = IkiWiki::bestlink($from, $link);
        return IkiWiki::FailReason->new("no such link") unless length $bestlink;
        foreach my $p (@$links) {
-               return 1 if $bestlink eq IkiWiki::bestlink($page, $p);
+               return IkiWiki::SuccessReason->new("$page links to $link")
+                       if $bestlink eq IkiWiki::bestlink($page, $p);
        }
        return IkiWiki::FailReason->new("$page does not link to $link");
 } #}}}
        }
        return IkiWiki::FailReason->new("$page does not link to $link");
 } #}}}
@@ -1077,10 +1092,15 @@ sub match_created_before ($$;@) { #{{{
        my $testpage=shift;
 
        if (exists $IkiWiki::pagectime{$testpage}) {
        my $testpage=shift;
 
        if (exists $IkiWiki::pagectime{$testpage}) {
-               return $IkiWiki::pagectime{$page} < $IkiWiki::pagectime{$testpage};
+               if ($IkiWiki::pagectime{$page} < $IkiWiki::pagectime{$testpage}) {
+                       IkiWiki::SuccessReason->new("$page created before $testpage");
+               }
+               else {
+                       IkiWiki::FailReason->new("$page not created before $testpage");
+               }
        }
        else {
        }
        else {
-               return IkiWiki::FailReason->new("$page not created before $testpage");
+               return IkiWiki::FailReason->new("$testpage has no ctime");
        }
 } #}}}
 
        }
 } #}}}
 
@@ -1089,26 +1109,43 @@ sub match_created_after ($$;@) { #{{{
        my $testpage=shift;
 
        if (exists $IkiWiki::pagectime{$testpage}) {
        my $testpage=shift;
 
        if (exists $IkiWiki::pagectime{$testpage}) {
-               return $IkiWiki::pagectime{$page} > $IkiWiki::pagectime{$testpage};
+               if ($IkiWiki::pagectime{$page} > $IkiWiki::pagectime{$testpage}) {
+                       IkiWiki::SuccessReason->new("$page created after $testpage");
+               }
+               else {
+                       IkiWiki::FailReason->new("$page not created after $testpage");
+               }
        }
        else {
        }
        else {
-               return IkiWiki::FailReason->new("$page not created after $testpage");
+               return IkiWiki::FailReason->new("$testpage has no ctime");
        }
 } #}}}
 
 sub match_creation_day ($$;@) { #{{{
        }
 } #}}}
 
 sub match_creation_day ($$;@) { #{{{
-       return 1 if ((gmtime($IkiWiki::pagectime{shift()}))[3] == shift);
-       return IkiWiki::FailReason->new("creation_day did not match");
+       if ((gmtime($IkiWiki::pagectime{shift()}))[3] == shift) {
+               return IkiWiki::SuccessReason->new("creation_day matched");
+       }
+       else {
+               return IkiWiki::FailReason->new("creation_day did not match");
+       }
 } #}}}
 
 sub match_creation_month ($$;@) { #{{{
 } #}}}
 
 sub match_creation_month ($$;@) { #{{{
-       return 1 if ((gmtime($IkiWiki::pagectime{shift()}))[4] + 1 == shift);
-       return IkiWiki::FailReason->new("creation_month did not match");
+       if ((gmtime($IkiWiki::pagectime{shift()}))[4] + 1 == shift) {
+               return IkiWiki::SuccessReason->new("creation_month matched");
+       }
+       else {
+               return IkiWiki::FailReason->new("creation_month did not match");
+       }
 } #}}}
 
 sub match_creation_year ($$;@) { #{{{
 } #}}}
 
 sub match_creation_year ($$;@) { #{{{
-       return 1 if ((gmtime($IkiWiki::pagectime{shift()}))[5] + 1900 == shift);
-       return IkiWiki::FailReason->new("creation_year did not match");
+       if ((gmtime($IkiWiki::pagectime{shift()}))[5] + 1900 == shift) {
+               return IkiWiki::SuccessReason->new("creation_year matched");
+       }
+       else {
+               return IkiWiki::FailReason->new("creation_year did not match");
+       }
 } #}}}
 
 sub match_user ($$;@) { #{{{
 } #}}}
 
 sub match_user ($$;@) { #{{{
@@ -1117,8 +1154,12 @@ sub match_user ($$;@) { #{{{
        my %params=@_;
 
        return IkiWiki::FailReason->new("cannot match user") unless exists $params{user};
        my %params=@_;
 
        return IkiWiki::FailReason->new("cannot match user") unless exists $params{user};
-       return 1 if $user eq $params{user};
-       return IkiWiki::FailReason->new("user is not $user");
+       if ($user eq $params{user}) {
+               return IkiWiki::SuccessReason->new("user is $user")
+       }
+       else {
+               return IkiWiki::FailReason->new("user is not $user");
+       }
 } #}}}
 
 1
 } #}}}
 
 1
index 58e2b04b954b80eca221f7d62e05027a8ffa0d01..a7ed6590e52c26a6ab28b037c30e441dd73597f5 100644 (file)
@@ -62,8 +62,12 @@ sub match_enabled ($$;@) { #{{{
        my $plugin=shift;
        
        # test if the plugin is enabled
        my $plugin=shift;
        
        # test if the plugin is enabled
-       return 1 if UNIVERSAL::can("IkiWiki::Plugin::".$plugin, "import");
-       return IkiWiki::FailReason->new("$plugin is not enabled");
+       if (UNIVERSAL::can("IkiWiki::Plugin::".$plugin, "import")) {
+               return IkiWiki::SuccessReason->new("$plugin is enabled");
+       }
+       else {
+               return IkiWiki::FailReason->new("$plugin is not enabled");
+       }
 } #}}}
 
 sub match_sourcepage ($$;@) { #{{{
 } #}}}
 
 sub match_sourcepage ($$;@) { #{{{
@@ -72,8 +76,12 @@ sub match_sourcepage ($$;@) { #{{{
        my %params=@_;
 
        return IkiWiki::FailReason->new("cannot match sourcepage") unless exists $params{sourcepage};
        my %params=@_;
 
        return IkiWiki::FailReason->new("cannot match sourcepage") unless exists $params{sourcepage};
-       return 1 if match_glob($params{sourcepage}, $glob, @_);
-       return IkiWiki::FailReason->new("sourcepage does not match $glob");
+       if (match_glob($params{sourcepage}, $glob, @_)) {
+               return IkiWiki::SuccessReason->new("sourcepage matches $glob");
+       }
+       else {
+               return IkiWiki::FailReason->new("sourcepage does not match $glob");
+       }
 } #}}}
 
 sub match_destpage ($$;@) { #{{{
 } #}}}
 
 sub match_destpage ($$;@) { #{{{
@@ -82,8 +90,12 @@ sub match_destpage ($$;@) { #{{{
        my %params=@_;
        
        return IkiWiki::FailReason->new("cannot match destpage") unless exists $params{destpage};
        my %params=@_;
        
        return IkiWiki::FailReason->new("cannot match destpage") unless exists $params{destpage};
-       return 1 if match_glob($params{destpage}, $glob, @_);
-       return IkiWiki::FailReason->new("destpage does not match $glob");
+       if (match_glob($params{destpage}, $glob, @_)) {
+               return IkiWiki::SuccessReason->new("destpage matches $glob");
+       }
+       else {
+               return IkiWiki::FailReason->new("destpage does not match $glob");
+       }
 } #}}}
 
 sub match_included ($$;$) { #{{{
 } #}}}
 
 sub match_included ($$;$) { #{{{
@@ -92,8 +104,12 @@ sub match_included ($$;$) { #{{{
        my %params=@_;
 
        return IkiWiki::FailReason->new("cannot match included") unless exists $params{sourcepage} && exists $params{destpage};
        my %params=@_;
 
        return IkiWiki::FailReason->new("cannot match included") unless exists $params{sourcepage} && exists $params{destpage};
-       return 1 if $params{sourcepage} ne $params{destpage};
-       return IkiWiki::FailReason->new("page $params{sourcepage} is not included");
+       if ($params{sourcepage} ne $params{destpage}) {
+               return IkiWiki::SuccessReason->new("page $params{sourcepage} is included");
+       }
+       else {
+               return IkiWiki::FailReason->new("page $params{sourcepage} is not included");
+       }
 } #}}}
 
 1
 } #}}}
 
 1
index 56dc03cef98ad67c0e979397189185c1c2c8708c..4966f4e10b1a01d441cb45a4fb75205edaf4fe74 100644 (file)
@@ -16,8 +16,12 @@ sub preprocess (@) { #{{{
        
        my $ret=pagespec_match($params{match}, $params{pagespec}, 
                        location => $params{page});
        
        my $ret=pagespec_match($params{match}, $params{pagespec}, 
                        location => $params{page});
-       return $ret if ! $ret;
-       return "the pagespec matches";
+       if ($ret) {
+               return "match: $ret";
+       }
+       else {
+               return "no match: $ret";
+       }
 } # }}}
 
 1
 } # }}}
 
 1
index ee3792892c70f272a9724db740c6f0e09ba20af5..867934f24643a2a58b550a6f9d80da9e0c4a9514 100644 (file)
@@ -30,10 +30,10 @@ ikiwiki (1.51) UNRELEASED; urgency=low
   * Plugin interface version increased to 2.00 since I don't anticipate any
     more interface changes before 2.0.
   * Updated Gujarati translation from Kartik Mistry. Closes: #421198
   * Plugin interface version increased to 2.00 since I don't anticipate any
     more interface changes before 2.0.
   * Updated Gujarati translation from Kartik Mistry. Closes: #421198
-  * Make pagespec_match on failure return a value that is false, but in a
-    scalar context, evaluates to a reason why the match failed.
+  * Make pagespec_match return an object that can be stringified to tell 
+    the reason why the match failed or succeeded.
   * Add testpagespec plugin, which might be useful to see why a pagespec isn't
   * Add testpagespec plugin, which might be useful to see why a pagespec isn't
-    matching something.
+    working as desired.
 
  -- Joey Hess <joeyh@debian.org>  Fri, 27 Apr 2007 03:41:52 -0400
 
 
  -- Joey Hess <joeyh@debian.org>  Fri, 27 Apr 2007 03:41:52 -0400
 
index 28e5ba7a73321172eaec91d643ff691a47c80c01..c5155129dcdb53bddd90a7e5a442556101f911d5 100644 (file)
@@ -2,11 +2,21 @@
 [[tag type/useful]]
 
 This plugin allows testing a [[PageSpec]] to see if it matches a page, and
 [[tag type/useful]]
 
 This plugin allows testing a [[PageSpec]] to see if it matches a page, and
-if not, why it fails to match.
+to see the part that matches, or causes the match to fail.
 
 
-Example use:
+Example uses:
 
        \[[testpagespec pagespec="foopage and barpage" match="foopage"]]
 
 
        \[[testpagespec pagespec="foopage and barpage" match="foopage"]]
 
-This will print out something like "barpage does not match foopage",
+This will print out something like "no match: barpage does not match foopage",
 highlighting which part of the [[PageSpec]] is causing the match to fail.
 highlighting which part of the [[PageSpec]] is causing the match to fail.
+       
+       \[[testpagespec pagespec="foopage or !bar*" match="barpage"]]
+
+This will print out something like "no match: bar* matches barpage", since the part
+of the [[PageSpec]] that fails is this negated match.
+       
+       \[[testpagespec pagespec="foopage or barpage" match="barpage"]]
+
+This will print out something like "match: barpage matches barpage",
+indicating the part of the [[PageSpec]] that did match.
index ef9d412e5081070eb65aba70f316ce95414068e1..0eef3d2baa996d9fc566b6bc2d9a4c99664a8eeb 100644 (file)
@@ -328,10 +328,6 @@ The most often used is "location", which specifies the location the
 PageSpec should match against. If not passed, relative PageSpecs will match
 relative to the top of the wiki.
 
 PageSpec should match against. If not passed, relative PageSpecs will match
 relative to the top of the wiki.
 
-If the PageSpec fails to match, it may return a IkiWiki::FailReason object,
-which evaluates to false in a boolean context, but in a string context,
-evaulates to the reason the PageSpec failed to match.
-
 #### `bestlink($$)`
 
 Given a page and the text of a link on the page, determine which
 #### `bestlink($$)`
 
 Given a page and the text of a link on the page, determine which
@@ -452,5 +448,5 @@ IkiWiki::PageSpec package, that is named `match_foo`, where "foo()" is
 how it will be accessed in a [[PageSpec]]. The function will be passed
 two parameters: The name of the page being matched, and the thing to match
 against. It may also be passed additional, named parameters. It should return
 how it will be accessed in a [[PageSpec]]. The function will be passed
 two parameters: The name of the page being matched, and the thing to match
 against. It may also be passed additional, named parameters. It should return
-true if the match succeeds, and either false or a IkiWiki::FailReason object
-if the match fails.
+a IkiWiki::SuccessReason object if the match succeeds, or an
+IkiWiki::FailReason object if the match fails.
index aaac2ef04c961e452479039559db926dfc52f893..fd4d4d8ea8c62da947b8f8890e18568bbe8daaf3 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2007-04-27 03:55-0400\n"
+"POT-Creation-Date: 2007-04-27 04:24-0400\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
index f0cadcdc76843a63e3de5f615c70e3521b086978..635381e2bccc9ce0573ee14eb59c2662914e2330 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/perl
 use warnings;
 use strict;
 #!/usr/bin/perl
 use warnings;
 use strict;
-use Test::More tests => 51;
+use Test::More tests => 52;
 
 BEGIN { use_ok("IkiWiki"); }
 
 
 BEGIN { use_ok("IkiWiki"); }
 
@@ -25,6 +25,7 @@ ok(pagespec_match("a/b/foo", "./*", location => "a/b"), "relative 2");
 ok(pagespec_match("a/foo", "./*", "a/b"), "relative oldstyle call");
 ok(pagespec_match("foo", "./*", location => "a"), "relative toplevel");
 ok(pagespec_match("foo/bar", "*", location => "baz"), "absolute");
 ok(pagespec_match("a/foo", "./*", "a/b"), "relative oldstyle call");
 ok(pagespec_match("foo", "./*", location => "a"), "relative toplevel");
 ok(pagespec_match("foo/bar", "*", location => "baz"), "absolute");
+ok(! pagespec_match("foo", "foo and bar"), "foo and bar");
 
 # The link and backlink stuff needs this.
 $config{userdir}="";
 
 # The link and backlink stuff needs this.
 $config{userdir}="";