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
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;
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;
}
}
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);
}
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
$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;
# 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";
# 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;
}
}
}
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 {
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
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') {
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;
* 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.
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