From 8fa8bd0adb034f05131648dcb7b14011672649e8 Mon Sep 17 00:00:00 2001 From: joey Date: Fri, 27 Apr 2007 08:34:09 +0000 Subject: [PATCH] the kind of perl code that can only be written at 4:30 am (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 | 73 ++++++++++++++++++++++++++-------- IkiWiki/Plugin/conditional.pm | 32 +++++++++++---- IkiWiki/Plugin/testpagespec.pm | 8 +++- debian/changelog | 6 +-- doc/plugins/testpagespec.mdwn | 16 ++++++-- doc/plugins/write.mdwn | 8 +--- po/ikiwiki.pot | 2 +- t/pagespec_match.t | 3 +- 8 files changed, 108 insertions(+), 40 deletions(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index 88d6d442b..73280abf1 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1006,8 +1006,22 @@ sub pagespec_match ($$;@) { #{{{ 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, ); @@ -1037,7 +1051,7 @@ sub match_glob ($$;@) { #{{{ $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"); @@ -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) { - 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"); } #}}} @@ -1077,10 +1092,15 @@ sub match_created_before ($$;@) { #{{{ 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 { - 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}) { - 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 { - return IkiWiki::FailReason->new("$page not created after $testpage"); + return IkiWiki::FailReason->new("$testpage has no ctime"); } } #}}} 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 ($$;@) { #{{{ - 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 ($$;@) { #{{{ - 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 ($$;@) { #{{{ @@ -1117,8 +1154,12 @@ sub match_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 diff --git a/IkiWiki/Plugin/conditional.pm b/IkiWiki/Plugin/conditional.pm index 58e2b04b9..a7ed6590e 100644 --- a/IkiWiki/Plugin/conditional.pm +++ b/IkiWiki/Plugin/conditional.pm @@ -62,8 +62,12 @@ sub match_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 ($$;@) { #{{{ @@ -72,8 +76,12 @@ sub match_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 ($$;@) { #{{{ @@ -82,8 +90,12 @@ sub match_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 ($$;$) { #{{{ @@ -92,8 +104,12 @@ sub match_included ($$;$) { #{{{ 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 diff --git a/IkiWiki/Plugin/testpagespec.pm b/IkiWiki/Plugin/testpagespec.pm index 56dc03cef..4966f4e10 100644 --- a/IkiWiki/Plugin/testpagespec.pm +++ b/IkiWiki/Plugin/testpagespec.pm @@ -16,8 +16,12 @@ sub preprocess (@) { #{{{ 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 diff --git a/debian/changelog b/debian/changelog index ee3792892..867934f24 100644 --- a/debian/changelog +++ b/debian/changelog @@ -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 - * 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 - matching something. + working as desired. -- Joey Hess Fri, 27 Apr 2007 03:41:52 -0400 diff --git a/doc/plugins/testpagespec.mdwn b/doc/plugins/testpagespec.mdwn index 28e5ba7a7..c5155129d 100644 --- a/doc/plugins/testpagespec.mdwn +++ b/doc/plugins/testpagespec.mdwn @@ -2,11 +2,21 @@ [[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"]] -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. + + \[[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. diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index ef9d412e5..0eef3d2ba 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -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. -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 @@ -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 -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. diff --git a/po/ikiwiki.pot b/po/ikiwiki.pot index aaac2ef04..fd4d4d8ea 100644 --- a/po/ikiwiki.pot +++ b/po/ikiwiki.pot @@ -8,7 +8,7 @@ msgid "" 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 \n" "Language-Team: LANGUAGE \n" diff --git a/t/pagespec_match.t b/t/pagespec_match.t index f0cadcdc7..635381e2b 100755 --- a/t/pagespec_match.t +++ b/t/pagespec_match.t @@ -1,7 +1,7 @@ #!/usr/bin/perl use warnings; use strict; -use Test::More tests => 51; +use Test::More tests => 52; 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("foo", "foo and bar"), "foo and bar"); # The link and backlink stuff needs this. $config{userdir}="";