rename use_pagespec to pagespec_match_list

To avoid breaking plugins, also support the old pagespec_match_list
calling convention, with a deprecation warning.
master
Joey Hess 2009-10-08 23:51:06 -04:00
parent 955bcea2a7
commit 5e7b2dea84
12 changed files with 141 additions and 164 deletions

View File

@ -17,7 +17,7 @@ use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase
%forcerebuild %loaded_plugins};
use Exporter q{import};
our @EXPORT = qw(hook debug error template htmlpage deptype use_pagespec
our @EXPORT = qw(hook debug error template htmlpage deptype
add_depends pagespec_match pagespec_match_list bestlink
htmllink readfile writefile pagetype srcfile pagename
displaytime will_render gettext urlto targetpage
@ -1798,91 +1798,6 @@ sub add_depends ($$;$) {
return 1;
}
sub use_pagespec ($$;@) {
my $page=shift;
my $pagespec=shift;
my %params=@_;
my $sub=pagespec_translate($pagespec);
error "syntax error in pagespec \"$pagespec\""
if $@ || ! defined $sub;
my @candidates;
if (exists $params{limit}) {
@candidates=grep { $params{limit}->($_) } keys %pagesources;
}
else {
@candidates=keys %pagesources;
}
if (defined $params{sort}) {
my $f;
if ($params{sort} eq 'title') {
$f=sub { pagetitle(basename($a)) cmp pagetitle(basename($b)) };
}
elsif ($params{sort} eq 'title_natural') {
eval q{use Sort::Naturally};
if ($@) {
error(gettext("Sort::Naturally needed for title_natural sort"));
}
$f=sub { Sort::Naturally::ncmp(pagetitle(basename($a)), pagetitle(basename($b))) };
}
elsif ($params{sort} eq 'mtime') {
$f=sub { $pagemtime{$b} <=> $pagemtime{$a} };
}
elsif ($params{sort} eq 'age') {
$f=sub { $pagectime{$b} <=> $pagectime{$a} };
}
else {
error sprintf(gettext("unknown sort type %s"), $params{sort});
}
@candidates = sort { &$f } @candidates;
}
@candidates=reverse(@candidates) if $params{reverse};
my @matches;
my $firstfail;
my $count=0;
foreach my $p (@candidates) {
my $r=$sub->($p, location => $page);
if ($r) {
push @matches, [$p, $r];
last if defined $params{num} && ++$count == $params{num};
}
elsif (! defined $firstfail) {
$firstfail=$r;
}
}
$depends{$page}{$pagespec} |= ($params{deptype} || $DEPEND_CONTENT);
my @ret;
if (@matches) {
# Add all influences from successful matches.
foreach my $m (@matches) {
push @ret, $m->[0];
my %i=$m->[1]->influences;
foreach my $i (keys %i) {
$depends_simple{$page}{lc $i} |= $i{$i};
}
}
}
elsif (defined $firstfail) {
# Add influences from one failure. (Which one should not
# matter; all should have the same influences.)
my %i=$firstfail->influences;
foreach my $i (keys %i) {
$depends_simple{$page}{lc $i} |= $i{$i};
}
error(sprintf(gettext("cannot match pages: %s"), $firstfail))
if $firstfail->isa("IkiWiki::ErrorReason");
}
return @ret;
}
sub deptype (@) {
my $deptype=0;
foreach my $type (@_) {
@ -2055,27 +1970,95 @@ sub pagespec_match ($$;@) {
}
sub pagespec_match_list ($$;@) {
my $pages=shift;
my $spec=shift;
my @params=@_;
my $page=shift;
my $pagespec=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;
# Backwards compatability with old calling convention.
if (ref $page) {
print STDERR "warning: a plugin (".caller().") is using pagespec_match_list in an obsolete way, and needs to be updated\n";
$params{list}=$page;
$page=$params{location}; # ugh!
}
if (! @ret && defined $r && $r->isa("IkiWiki::ErrorReason")) {
error(sprintf(gettext("cannot match pages: %s"), $r));
my $sub=pagespec_translate($pagespec);
error "syntax error in pagespec \"$pagespec\""
if $@ || ! defined $sub;
my @candidates;
if (exists $params{limit}) {
@candidates=grep { $params{limit}->($_) } keys %pagesources;
}
else {
return @ret;
@candidates=keys %pagesources;
}
if (defined $params{sort}) {
my $f;
if ($params{sort} eq 'title') {
$f=sub { pagetitle(basename($a)) cmp pagetitle(basename($b)) };
}
elsif ($params{sort} eq 'title_natural') {
eval q{use Sort::Naturally};
if ($@) {
error(gettext("Sort::Naturally needed for title_natural sort"));
}
$f=sub { Sort::Naturally::ncmp(pagetitle(basename($a)), pagetitle(basename($b))) };
}
elsif ($params{sort} eq 'mtime') {
$f=sub { $pagemtime{$b} <=> $pagemtime{$a} };
}
elsif ($params{sort} eq 'age') {
$f=sub { $pagectime{$b} <=> $pagectime{$a} };
}
else {
error sprintf(gettext("unknown sort type %s"), $params{sort});
}
@candidates = sort { &$f } @candidates;
}
@candidates=reverse(@candidates) if $params{reverse};
my @matches;
my $firstfail;
my $count=0;
foreach my $p (@candidates) {
my $r=$sub->($p, location => $page);
if ($r) {
push @matches, [$p, $r];
last if defined $params{num} && ++$count == $params{num};
}
elsif (! defined $firstfail) {
$firstfail=$r;
}
}
$depends{$page}{$pagespec} |= ($params{deptype} || $DEPEND_CONTENT);
my @ret;
if (@matches) {
# Add all influences from successful matches.
foreach my $m (@matches) {
push @ret, $m->[0];
my %i=$m->[1]->influences;
foreach my $i (keys %i) {
$depends_simple{$page}{lc $i} |= $i{$i};
}
}
}
elsif (defined $firstfail) {
# Add influences from one failure. (Which one should not
# matter; all should have the same influences.)
my %i=$firstfail->influences;
foreach my $i (keys %i) {
$depends_simple{$page}{lc $i} |= $i{$i};
}
error(sprintf(gettext("cannot match pages: %s"), $firstfail))
if $firstfail->isa("IkiWiki::ErrorReason");
}
return @ret;
}
sub pagespec_valid ($) {

View File

@ -74,7 +74,7 @@ sub format_month (@) {
my $nyear = $params{nyear};
my %linkcache;
foreach my $p (use_pagespec($params{page}, $params{pagespec},
foreach my $p (pagespec_match_list($params{page}, $params{pagespec},
# add presence dependencies to update
# month calendar when pages are added/removed
deptype => deptype("presence"))) {

View File

@ -216,7 +216,7 @@ sub preprocess_inline (@) {
$num+=$params{skip};
}
@list = use_pagespec($params{page}, $params{pages},
@list = pagespec_match_list($params{page}, $params{pages},
deptype => deptype($quick ? "presence" : "content"),
limit => sub { $_[0] ne $params{page} },
sort => exists $params{sort} ? $params{sort} : "age",
@ -245,9 +245,11 @@ sub preprocess_inline (@) {
}
if ($feeds && exists $params{feedpages}) {
@feedlist = use_pagespec($params{page}, "($params{pages}) and ($params{feedpages})",
@feedlist = pagespec_match_list(
$params{page}, "($params{pages}) and ($params{feedpages})",
deptype => deptype($quick ? "presence" : "content"),
list => \@feedlist);
list => \@feedlist,
);
}
my ($feedbase, $feednum);

View File

@ -36,7 +36,8 @@ sub preprocess (@) {
# Get all the items to map.
my %mapitems;
foreach my $page (use_pagespec($params{page}, $params{pages}, deptype => $deptype)) {
foreach my $page (pagespec_match_list($params{page}, $params{pages},
deptype => $deptype)) {
if (exists $params{show} &&
exists $pagestate{$page} &&
exists $pagestate{$page}{meta}{$params{show}}) {

View File

@ -28,7 +28,7 @@ sub preprocess (@) {
# considering as orphans.
add_depends($params{page}, "*", deptype("links"));
my @orphans=use_pagespec($params{page}, $params{pages},
my @orphans=pagespec_match_list($params{page}, $params{pages},
# update when orphans are added/removed
deptype => deptype("presence"),
limit => sub {

View File

@ -32,7 +32,7 @@ sub preprocess (@) {
return scalar keys %pagesources;
}
return scalar use_pagespec($params{page}, $pages,
return scalar pagespec_match_list($params{page}, $pages,
deptype => deptype("presence"));
}

View File

@ -37,16 +37,17 @@ sub preprocess (@) {
my %counts;
my $max = 0;
foreach my $page (use_pagespec($params{page}, $params{pages},
# update when a displayed page is added or removed
deptype => deptype("presence"))) {
foreach my $page (pagespec_match_list($params{page}, $params{pages},
# update when a displayed page is added/removed
deptype => deptype("presence"))) {
use IkiWiki::Render;
my @backlinks = IkiWiki::backlink_pages($page);
if (exists $params{among}) {
# only consider backlinks from the amoung pages
@backlinks = use_pagespec($params{page}, $params{among},
@backlinks = pagespec_match_list(
$params{page}, $params{among},
# update whenever links on those pages change
deptype => deptype("links"),
list => \@backlinks

View File

@ -54,7 +54,7 @@ sub preprocess (@) {
}
my @list=sort { $params{timehash}->{$b} <=> $params{timehash}->{$a} }
use_pagespec($params{page}, $params{pages},
pagespec_match_list($params{page}, $params{pages},
deptype => $deptype,
limit => sub { $_[0] ne $params{page} },
);

6
debian/changelog vendored
View File

@ -33,9 +33,9 @@ ikiwiki (3.14159266) UNRELEASED; urgency=low
info.
* Plugins providing PageSpec `match_*` functions should pass additional
influence information when creating result objects.
* Added `use_pagespec` function, that plugins can use to find a list
of matching pages and add dependencies and influences, all at once,
and efficiently.
* API change: `pagespec_match_list` has completly changed its interface.
The old interface will be removed soon, and a warning will be printed
if any plugins try to use it.
* Optimize away most expensive file prune calls, when refreshing,
by only checking new files.

View File

@ -625,16 +625,16 @@ dependency type from one or more of these keywords:
If multiple types are specified, they are combined.
#### `use_pagespec($$;@)`
#### `pagespec_match_list($$;@)`
Passed a page name, and [[ikiwiki/PageSpec]], returns a list of pages
in the wiki that match the [[ikiwiki/PageSpec]].
The page will automatically be made to depend on the specified
[[ikiwiki/PageSpec]], so `add_depends` does not need to be called. This
is significantly more efficient than calling `add_depends`
followed by `pagespec_match_list`. You should use this anytime a plugin
needs to match a set of pages and generate something based on that list.
is significantly more efficient than calling `add_depends` and
`pagespec_match` in a loop. You should use this anytime a plugin
needs to match a set of pages and do something based on that list.
Additional named parameters can be specified:
@ -650,6 +650,9 @@ Additional named parameters can be specified:
* `list` makes it only match amoung the specified list of pages.
Default is to match amoung all pages in the wiki.
Unlike pagespec_match, this may throw an error if there is an error in
the pagespec.
#### `add_depends($$;$)`
Makes the specified page depend on the specified [[ikiwiki/PageSpec]].
@ -672,19 +675,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_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

View File

@ -0,0 +1,31 @@
#!/usr/bin/perl
use warnings;
use strict;
use Test::More tests => 10;
BEGIN { use_ok("IkiWiki"); }
%pagesources=(
foo => "foo.mdwn",
bar => "bar.mdwn",
"post/1" => "post/1.mdwn",
"post/2" => "post/2.mdwn",
"post/3" => "post/3.mdwn",
);
is_deeply([pagespec_match_list("foo", "bar")], ["bar"]);
is_deeply([sort(pagespec_match_list("foo", "post/*"))], ["post/1", "post/2", "post/3"]);
is_deeply([pagespec_match_list("foo", "post/*", sort => "title", reverse => 1)],
["post/3", "post/2", "post/1"]);
is_deeply([pagespec_match_list("foo", "post/*", sort => "title", num => 2)],
["post/1", "post/2"]);
is_deeply([pagespec_match_list("foo", "post/*", sort => "title", num => 50)],
["post/1", "post/2", "post/3"]);
is_deeply([pagespec_match_list("foo", "post/*", sort => "title",
limit => sub { $_[0] !~ /3/}) ],
["post/1", "post/2"]);
my $r=eval { pagespec_match_list("foo", "beep") };
ok(eval { pagespec_match_list("foo", "beep") } == 0);
ok(! $@, "does not fail with error when unable to match anything");
eval { pagespec_match_list("foo", "this is not a legal pagespec!") };
ok($@, "fails with error when pagespec bad");

View File

@ -1,31 +0,0 @@
#!/usr/bin/perl
use warnings;
use strict;
use Test::More tests => 10;
BEGIN { use_ok("IkiWiki"); }
%pagesources=(
foo => "foo.mdwn",
bar => "bar.mdwn",
"post/1" => "post/1.mdwn",
"post/2" => "post/2.mdwn",
"post/3" => "post/3.mdwn",
);
is_deeply([use_pagespec("foo", "bar")], ["bar"]);
is_deeply([sort(use_pagespec("foo", "post/*"))], ["post/1", "post/2", "post/3"]);
is_deeply([use_pagespec("foo", "post/*", sort => "title", reverse => 1)],
["post/3", "post/2", "post/1"]);
is_deeply([use_pagespec("foo", "post/*", sort => "title", num => 2)],
["post/1", "post/2"]);
is_deeply([use_pagespec("foo", "post/*", sort => "title", num => 50)],
["post/1", "post/2", "post/3"]);
is_deeply([use_pagespec("foo", "post/*", sort => "title",
limit => sub { $_[0] !~ /3/}) ],
["post/1", "post/2"]);
my $r=eval { use_pagespec("foo", "beep") };
ok(eval { use_pagespec("foo", "beep") } == 0);
ok(! $@, "does not fail with error when unable to match anything");
eval { use_pagespec("foo", "this is not a legal pagespec!") };
ok($@, "fails with error when pagespec bad");