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.)
master
joey 2007-04-27 08:34:09 +00:00
parent f8a7fb227b
commit 8fa8bd0adb
8 changed files with 108 additions and 40 deletions

View File

@ -1006,8 +1006,22 @@ sub pagespec_match ($$;@) { #{{{
package IkiWiki::FailReason; package IkiWiki::FailReason;
use overload ( use overload (
'""' => sub { return ${$_[0]} }, '""' => sub { return ${$_[0]} },
'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; $glob=~s/\\\?/./g;
if ($page=~/^$glob$/i) { if ($page=~/^$glob$/i) {
return 1 return IkiWiki::SuccessReason->new("$glob matches $page");
} }
else { else {
return IkiWiki::FailReason->new("$glob does not match $page"); return IkiWiki::FailReason->new("$glob does not match $page");
@ -1063,7 +1077,8 @@ sub match_link ($$;@) { #{{{
my $bestlink = IkiWiki::bestlink($from, $link); my $bestlink = IkiWiki::bestlink($from, $link);
return IkiWiki::FailReason->new("no such link") unless length $bestlink; return IkiWiki::FailReason->new("no such link") unless length $bestlink;
foreach my $p (@$links) { 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; my $testpage=shift;
if (exists $IkiWiki::pagectime{$testpage}) { 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; my $testpage=shift;
if (exists $IkiWiki::pagectime{$testpage}) { 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); if ((gmtime($IkiWiki::pagectime{shift()}))[3] == shift) {
return IkiWiki::FailReason->new("creation_day did not match"); 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); if ((gmtime($IkiWiki::pagectime{shift()}))[4] + 1 == shift) {
return IkiWiki::FailReason->new("creation_month did not match"); 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); if ((gmtime($IkiWiki::pagectime{shift()}))[5] + 1900 == shift) {
return IkiWiki::FailReason->new("creation_year did not match"); 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=@_; my %params=@_;
return IkiWiki::FailReason->new("cannot match user") unless exists $params{user}; return IkiWiki::FailReason->new("cannot match user") unless exists $params{user};
return 1 if $user eq $params{user}; if ($user eq $params{user}) {
return IkiWiki::FailReason->new("user is not $user"); return IkiWiki::SuccessReason->new("user is $user")
}
else {
return IkiWiki::FailReason->new("user is not $user");
}
} #}}} } #}}}
1 1

View File

@ -62,8 +62,12 @@ sub match_enabled ($$;@) { #{{{
my $plugin=shift; my $plugin=shift;
# test if the plugin is enabled # test if the plugin is enabled
return 1 if UNIVERSAL::can("IkiWiki::Plugin::".$plugin, "import"); if (UNIVERSAL::can("IkiWiki::Plugin::".$plugin, "import")) {
return IkiWiki::FailReason->new("$plugin is not enabled"); 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=@_; my %params=@_;
return IkiWiki::FailReason->new("cannot match sourcepage") unless exists $params{sourcepage}; return IkiWiki::FailReason->new("cannot match sourcepage") unless exists $params{sourcepage};
return 1 if match_glob($params{sourcepage}, $glob, @_); if (match_glob($params{sourcepage}, $glob, @_)) {
return IkiWiki::FailReason->new("sourcepage does not match $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=@_; my %params=@_;
return IkiWiki::FailReason->new("cannot match destpage") unless exists $params{destpage}; return IkiWiki::FailReason->new("cannot match destpage") unless exists $params{destpage};
return 1 if match_glob($params{destpage}, $glob, @_); if (match_glob($params{destpage}, $glob, @_)) {
return IkiWiki::FailReason->new("destpage does not match $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=@_; my %params=@_;
return IkiWiki::FailReason->new("cannot match included") unless exists $params{sourcepage} && exists $params{destpage}; return IkiWiki::FailReason->new("cannot match included") unless exists $params{sourcepage} && exists $params{destpage};
return 1 if $params{sourcepage} ne $params{destpage}; if ($params{sourcepage} ne $params{destpage}) {
return IkiWiki::FailReason->new("page $params{sourcepage} is not included"); return IkiWiki::SuccessReason->new("page $params{sourcepage} is included");
}
else {
return IkiWiki::FailReason->new("page $params{sourcepage} is not included");
}
} #}}} } #}}}
1 1

View File

@ -16,8 +16,12 @@ sub preprocess (@) { #{{{
my $ret=pagespec_match($params{match}, $params{pagespec}, my $ret=pagespec_match($params{match}, $params{pagespec},
location => $params{page}); location => $params{page});
return $ret if ! $ret; if ($ret) {
return "the pagespec matches"; return "match: $ret";
}
else {
return "no match: $ret";
}
} # }}} } # }}}
1 1

6
debian/changelog vendored
View File

@ -30,10 +30,10 @@ ikiwiki (1.51) UNRELEASED; urgency=low
* Plugin interface version increased to 2.00 since I don't anticipate any * Plugin interface version increased to 2.00 since I don't anticipate any
more interface changes before 2.0. more interface changes before 2.0.
* Updated Gujarati translation from Kartik Mistry. Closes: #421198 * Updated Gujarati translation from Kartik Mistry. Closes: #421198
* Make pagespec_match on failure return a value that is false, but in a * Make pagespec_match return an object that can be stringified to tell
scalar context, evaluates to a reason why the match failed. 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

View File

@ -2,11 +2,21 @@
[[tag type/useful]] [[tag type/useful]]
This plugin allows testing a [[PageSpec]] to see if it matches a page, and 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.

View 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 PageSpec should match against. If not passed, relative PageSpecs will match
relative to the top of the wiki. 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($$)` #### `bestlink($$)`
Given a page and the text of a link on the page, determine which 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 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 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 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 a IkiWiki::SuccessReason object if the match succeeds, or an
if the match fails. IkiWiki::FailReason object if the match fails.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"

View File

@ -1,7 +1,7 @@
#!/usr/bin/perl #!/usr/bin/perl
use warnings; use warnings;
use strict; 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("a/foo", "./*", "a/b"), "relative oldstyle call");
ok(pagespec_match("foo", "./*", location => "a"), "relative toplevel"); ok(pagespec_match("foo", "./*", location => "a"), "relative toplevel");
ok(pagespec_match("foo/bar", "*", location => "baz"), "absolute"); 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. # The link and backlink stuff needs this.
$config{userdir}=""; $config{userdir}="";