From aa306957bac11477b914ac19b93890184ffe4062 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 23 Apr 2009 15:45:30 -0400 Subject: [PATCH] pagespec_match_list added and used in most appropriate places * pagespec_match_list: New API function, matches pages in a list and throws an error if the pagespec is bad. * inline, brokenlinks, calendar, linkmap, map, orphans, pagecount, pagestate, postsparkline: Display a handy error message if the pagespec is erronious. --- IkiWiki.pm | 32 ++++++++++++++++++--- IkiWiki/Plugin/brokenlinks.pm | 23 ++++++++-------- IkiWiki/Plugin/calendar.pm | 3 +- IkiWiki/Plugin/external.pm | 9 +++++- IkiWiki/Plugin/inline.pm | 17 ++---------- IkiWiki/Plugin/linkmap.pm | 7 ++--- IkiWiki/Plugin/map.pm | 49 ++++++++++++++++----------------- IkiWiki/Plugin/orphans.pm | 7 +++-- IkiWiki/Plugin/pagecount.pm | 9 ++---- IkiWiki/Plugin/pagestats.pm | 11 ++++---- IkiWiki/Plugin/postsparkline.pm | 10 ++----- debian/changelog | 7 +++-- doc/plugins/write.mdwn | 13 +++++++++ 13 files changed, 111 insertions(+), 86 deletions(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index fca8da874..e260fffea 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -18,10 +18,10 @@ use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase use Exporter q{import}; our @EXPORT = qw(hook debug error template htmlpage add_depends pagespec_match - bestlink htmllink readfile writefile pagetype srcfile pagename - displaytime will_render gettext urlto targetpage - add_underlay pagetitle titlepage linkpage newpagefile - inject + pagespec_match_list bestlink htmllink readfile writefile + pagetype srcfile pagename displaytime will_render gettext urlto + targetpage add_underlay pagetitle titlepage linkpage + newpagefile inject %config %links %pagestate %wikistate %renderedfiles %pagesources %destsources); our $VERSION = 3.00; # plugin interface version, next is ikiwiki version @@ -1832,6 +1832,30 @@ sub pagespec_match ($$;@) { return $sub->($page, @params); } +sub pagespec_match_list ($$;@) { + my $pages=shift; + my $spec=shift; + my @params=@_; + + my $sub=pagespec_translate($spec); + error "syntax error in pagespec \"$spec\"" + if $@ || ! defined $sub; + + my @ret; + my $r; + foreach my $page (@$pages) { + $r=$sub->($page, @params); + push @ret, $page if $r; + } + + if (! @ret && defined $r && $r->isa("IkiWiki::ErrorReason")) { + error(sprintf(gettext("cannot match pages: %s"), $r)); + } + else { + return @ret; + } +} + sub pagespec_valid ($) { my $spec=shift; diff --git a/IkiWiki/Plugin/brokenlinks.pm b/IkiWiki/Plugin/brokenlinks.pm index bf0d7560d..da97dbc28 100644 --- a/IkiWiki/Plugin/brokenlinks.pm +++ b/IkiWiki/Plugin/brokenlinks.pm @@ -28,18 +28,17 @@ sub preprocess (@) { add_depends($params{page}, $params{pages}); my %broken; - foreach my $page (keys %links) { - if (pagespec_match($page, $params{pages}, location => $params{page})) { - my $discussion=gettext("discussion"); - my %seen; - foreach my $link (@{$links{$page}}) { - next if $seen{$link}; - $seen{$link}=1; - next if $link =~ /.*\/\Q$discussion\E/i && $config{discussion}; - my $bestlink=bestlink($page, $link); - next if length $bestlink; - push @{$broken{$link}}, $page; - } + foreach my $page (pagespec_match_list([keys %links], + $params{pages}, location => $params{page})) { + my $discussion=gettext("discussion"); + my %seen; + foreach my $link (@{$links{$page}}) { + next if $seen{$link}; + $seen{$link}=1; + next if $link =~ /.*\/\Q$discussion\E/i && $config{discussion}; + my $bestlink=bestlink($page, $link); + next if length $bestlink; + push @{$broken{$link}}, $page; } } diff --git a/IkiWiki/Plugin/calendar.pm b/IkiWiki/Plugin/calendar.pm index d473c8348..fe4b16072 100644 --- a/IkiWiki/Plugin/calendar.pm +++ b/IkiWiki/Plugin/calendar.pm @@ -369,8 +369,7 @@ sub preprocess (@) { my $page =$params{page}; if (! defined $cache{$pagespec}) { - foreach my $p (keys %pagesources) { - next unless pagespec_match($p, $pagespec); + foreach my $p (pagespec_match_list([keys %pagesources], $pagespec)) { my $mtime = $IkiWiki::pagectime{$p}; my $src = $pagesources{$p}; my @date = localtime($mtime); diff --git a/IkiWiki/Plugin/external.pm b/IkiWiki/Plugin/external.pm index 066f15cf1..aeee15dea 100644 --- a/IkiWiki/Plugin/external.pm +++ b/IkiWiki/Plugin/external.pm @@ -230,10 +230,17 @@ sub hook ($@) { } sub pagespec_match ($@) { - # convert pagespec_match's return object into a XML RPC boolean + # convert return object into a XML RPC boolean my $plugin=shift; return RPC::XML::boolean->new(0 + IkiWiki::pagespec_march(@_)); } +sub pagespec_match_list ($@) { + # convert return object into a XML RPC boolean + my $plugin=shift; + + return RPC::XML::boolean->new(0 + IkiWiki::pagespec_march_list(@_)); +} + 1 diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm index 551c38a65..366357095 100644 --- a/IkiWiki/Plugin/inline.pm +++ b/IkiWiki/Plugin/inline.pm @@ -183,20 +183,9 @@ sub preprocess_inline (@) { $params{template} = $archive ? "archivepage" : "inlinepage"; } - my @list; - my $lastmatch; - foreach my $page (keys %pagesources) { - next if $page eq $params{page}; - $lastmatch=pagespec_match($page, $params{pages}, location => $params{page}); - if ($lastmatch) { - push @list, $page; - } - } - - if (! @list && defined $lastmatch && - $lastmatch->isa("IkiWiki::ErrorReason")) { - error(sprintf(gettext("cannot match pages: %s"), $lastmatch)); - } + my @list=pagespec_match_list( + [ grep { $_ ne $params{page}} keys %pagesources ], + $params{pages}, location => $params{page}); if (exists $params{sort} && $params{sort} eq 'title') { @list=sort { pagetitle(basename($a)) cmp pagetitle(basename($b)) } @list; diff --git a/IkiWiki/Plugin/linkmap.pm b/IkiWiki/Plugin/linkmap.pm index 941ed5f36..0137476ac 100644 --- a/IkiWiki/Plugin/linkmap.pm +++ b/IkiWiki/Plugin/linkmap.pm @@ -56,10 +56,9 @@ sub genmap ($) { # Get all the items to map. my %mapitems = (); - foreach my $item (keys %links) { - if (pagespec_match($item, $params{pages}, location => $params{page})) { - $mapitems{$item}=urlto($item, $params{destpage}); - } + foreach my $item (pagespec_match_list([keys %links], + $params{pages}, location => $params{page})) { + $mapitems{$item}=urlto($item, $params{destpage}); } my $dest=$params{page}."/linkmap.png"; diff --git a/IkiWiki/Plugin/map.pm b/IkiWiki/Plugin/map.pm index 328493116..120451b5d 100644 --- a/IkiWiki/Plugin/map.pm +++ b/IkiWiki/Plugin/map.pm @@ -32,32 +32,31 @@ sub preprocess (@) { # Get all the items to map. my %mapitems; - foreach my $page (keys %pagesources) { - if (pagespec_match($page, $params{pages}, location => $params{page})) { - if (exists $params{show} && - exists $pagestate{$page} && - exists $pagestate{$page}{meta}{$params{show}}) { - $mapitems{$page}=$pagestate{$page}{meta}{$params{show}}; - } - else { - $mapitems{$page}=''; - } - # Check for a common prefix. - if (! defined $common_prefix) { - $common_prefix=$page; - } - elsif (length $common_prefix && - $page !~ /^\Q$common_prefix\E(\/|$)/) { - my @a=split(/\//, $page); - my @b=split(/\//, $common_prefix); - $common_prefix=""; - while (@a && @b && $a[0] eq $b[0]) { - if (length $common_prefix) { - $common_prefix.="/"; - } - $common_prefix.=shift(@a); - shift @b; + foreach my $page (pagespec_match_list([keys %pagesources], + $params{pages}, location => $params{page})) { + if (exists $params{show} && + exists $pagestate{$page} && + exists $pagestate{$page}{meta}{$params{show}}) { + $mapitems{$page}=$pagestate{$page}{meta}{$params{show}}; + } + else { + $mapitems{$page}=''; + } + # Check for a common prefix. + if (! defined $common_prefix) { + $common_prefix=$page; + } + elsif (length $common_prefix && + $page !~ /^\Q$common_prefix\E(\/|$)/) { + my @a=split(/\//, $page); + my @b=split(/\//, $common_prefix); + $common_prefix=""; + while (@a && @b && $a[0] eq $b[0]) { + if (length $common_prefix) { + $common_prefix.="/"; } + $common_prefix.=shift(@a); + shift @b; } } } diff --git a/IkiWiki/Plugin/orphans.pm b/IkiWiki/Plugin/orphans.pm index 605e6e43a..cf74c9b79 100644 --- a/IkiWiki/Plugin/orphans.pm +++ b/IkiWiki/Plugin/orphans.pm @@ -35,9 +35,10 @@ sub preprocess (@) { my @orphans; my $discussion=gettext("discussion"); - foreach my $page (keys %pagesources) { - next if $linkedto{$page} || $page eq 'index'; - next unless pagespec_match($page, $params{pages}, location => $params{page}); + foreach my $page (pagespec_match_list( + [ grep { ! $linkedto{$_} && $_ ne 'index' } + keys %pagesources ], + $params{pages}, location => $params{page})) { # If the page has a link to some other page, it's # indirectly linked to a page via that page's backlinks. next if grep { diff --git a/IkiWiki/Plugin/pagecount.pm b/IkiWiki/Plugin/pagecount.pm index a143f24d0..f8881a04b 100644 --- a/IkiWiki/Plugin/pagecount.pm +++ b/IkiWiki/Plugin/pagecount.pm @@ -27,12 +27,9 @@ sub preprocess (@) { add_depends($params{page}, $params{pages}); my @pages=keys %pagesources; - return $#pages+1 if $params{pages} eq "*"; # optimisation - my $count=0; - foreach my $page (@pages) { - $count++ if pagespec_match($page, $params{pages}, location => $params{page}); - } - return $count; + @pages=pagespec_match_list(\@pages, $params{pages}, location => $params{page}) + if $params{pages} ne "*"; # optimisation; + return $#pages+1; } 1 diff --git a/IkiWiki/Plugin/pagestats.pm b/IkiWiki/Plugin/pagestats.pm index dbe69539d..8ab5d3666 100644 --- a/IkiWiki/Plugin/pagestats.pm +++ b/IkiWiki/Plugin/pagestats.pm @@ -41,12 +41,11 @@ sub preprocess (@) { my %counts; my $max = 0; - foreach my $page (keys %links) { - if (pagespec_match($page, $params{pages}, location => $params{page})) { - use IkiWiki::Render; - $counts{$page} = scalar(IkiWiki::backlinks($page)); - $max = $counts{$page} if $counts{$page} > $max; - } + foreach my $page (pagespec_match_list([keys %links], + $params{pages}, location => $params{page})) { + use IkiWiki::Render; + $counts{$page} = scalar(IkiWiki::backlinks($page)); + $max = $counts{$page} if $counts{$page} > $max; } if ($style eq 'table') { diff --git a/IkiWiki/Plugin/postsparkline.pm b/IkiWiki/Plugin/postsparkline.pm index ba43561fb..c2ebbc5eb 100644 --- a/IkiWiki/Plugin/postsparkline.pm +++ b/IkiWiki/Plugin/postsparkline.pm @@ -50,13 +50,9 @@ sub preprocess (@) { add_depends($params{page}, $params{pages}); - my @list; - foreach my $page (keys %pagesources) { - next if $page eq $params{page}; - if (pagespec_match($page, $params{pages}, location => $params{page})) { - push @list, $page; - } - } + my @list=pagespec_match_list( + [ grep { $_ ne $params{page} } keys %pagesources], + $params{pages}, location => $params{page}); @list = sort { $params{timehash}->{$b} <=> $params{timehash}->{$a} } @list; diff --git a/debian/changelog b/debian/changelog index de4ac4a8c..37b69ada0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -11,8 +11,11 @@ ikiwiki (3.11) UNRELEASED; urgency=low * Add IkiWiki::ErrorReason objects, and modify pagespecs to return them in cases where they fail to match due to a configuration or syntax error. - * inline: Display a handy error message if the inline cannot display any - pages due to such an error. + * pagespec_match_list: New API function, matches pages in a list + and throws an error if the pagespec is bad. + * inline, brokenlinks, calendar, linkmap, map, orphans, pagecount, + pagestate, postsparkline: Display a handy error message if the pagespec + is erronious. * comments: Add link to comment post form to allow user to sign in if they wish to, if the configuration makes signin optional for commenting. diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 23df01ca7..0b358b215 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -572,6 +572,19 @@ 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_match_list($$;@)` + +Passed a reference to a list of page names, and [[ikiwiki/PageSpec]], +returns the set of pages that match the [[ikiwiki/PageSpec]]. + +Additional named parameters can be passed, to further limit the match. +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. + +Unlike pagespec_match, this may throw an error if there is an error in +the pagespec. + #### `bestlink($$)` Given a page and the text of a link on the page, determine which -- 2.26.2