(no commit message)
[ikiwiki] / doc / todo / pagespec_relative_to_a_target.mdwn
1 Sometimes you want to match a page only if it has certain properties. The use
2 case I have in mind is this: show me all the pages that have children. You
3 can't do that with a pagespec, so I created a plugin that adds some pagespec
4 functions.
5
6 `match_relative(blah)` will match a page x if a pagespec from x would match 
7 `blah`. This is only actually useful with relative pagespecs.
8
9 `match_has_child(blah)` will match a child if it has a descendant named 
10 `blah`. If blah is empty, any child will match.
11
12 So if I have:
13
14 * foo
15 * foo/blah
16 * foo/bar
17 * foo/bar/blah
18 * foo/bar/bahoo
19 * foo/baz
20 * foo/baz/goo
21 * foo/baz/goo/blah
22
23 A pagespec `match_relative(./blah)` will match `foo/bar/bahoo`, because
24 a pagespec of `./blah` from `bahoo` would match `foo/bar/blah`. A
25 pagespec of `match_has_child(blah)` would match `foo`, `foo/bar`,
26 `foo/baz`, and `foo/baz/goo`.
27
28 Note that if you try to inline `*/blah` you will match `foo/blah`,
29 `foo/bar/blah`, and `foo/baz/goo/blah` -- that is, the blah pages 
30 themselves rather than any relatives of theirs.
31
32 This patch is useful for (among other things) constructing blogging 
33 systems where leaf nodes are organized hierarchically; using `has_child`,
34 you can inline only leaf nodes and ignore "intermediate" nodes.
35 `match_relative` can be used recursively to match properties of arbitrary
36 complexity: "show me all the pages who have children called foo that 
37 have children called blah". I'm not sure what use it is, though.
38
39 You can see the patch in action at 
40 <http://ikidev.betacantrips.com/conditionaltest/>,
41 so named because I had hoped that something in conditional.pm could 
42 help me. I know the name "relative" sucks, feel free to come up with a 
43 better one. --Ethan
44
45 <pre>
46 diff -urNX ignorepats ikiwiki/IkiWiki/Plugin/relative.pm ikidev/IkiWiki/Plugin/relative.pm
47 --- ikiwiki/IkiWiki/Plugin/relative.pm  1969-12-31 16:00:00.000000000 -0800
48 +++ ikidev/IkiWiki/Plugin/relative.pm   2007-07-26 21:48:10.642686000 -0700
49 @@ -0,0 +1,39 @@
50 +#!/usr/bin/perl
51 +# relative.pm: support for pagespecs on possible matches
52 +package IkiWiki::Plugin::relative;
53 +
54 +use warnings;
55 +use strict;
56 +use IkiWiki 2.00;
57 +
58 +package IkiWiki::PageSpec;
59 +
60 +sub match_relative($$;@) {
61 +       my $parent = shift;
62 +       my $spec = shift;
63 +       my %params = @_;
64 +
65 +       foreach my $page (keys %IkiWiki::pagesources) {
66 +               next if $page eq $parent;
67 +               if (IkiWiki::pagespec_match($page, $spec, location => $parent)) {
68 +                       return IkiWiki::SuccessReason->new("$parent can match $spec against $page");
69 +               }
70 +       }
71 +       return IkiWiki::FailReason->new("$parent can't match $spec against anything");
72 +}
73 +
74 +sub match_has_child($$;@) {
75 +       my $page = shift;
76 +       my $childname = shift;
77 +       my $spec;
78 +       if ($childname) {
79 +               $spec = "$page/$childname or $page/*/$childname";
80 +       }
81 +       else {
82 +               $spec = "$page/*";
83 +       }
84 +
85 +       return match_relative($page, $spec, @_);
86 +}
87 +
88 +1
89 </pre>
90
91 [[!tag patch]]
92
93 > This looks really interesting.  It reminds me of [[!wikipedia XPath]] and its conditionals.
94 > Those might actually work well adapted to pagespecs.  For instance, to write
95 > "match any page with a child blah", you could just write *[blah] , or if you
96 > don't want to use relative-by-default in the conditionals, *[./blah].
97 > -- [[JoshTriplett]]
98
99 > And it [[!taglink also_reminds_me|pagespec_in_DL_style]] of [[!wikipedia description logics]]: of course, given the relation `subpage` one could write a description-logic-style formula which would define the class of pages that are ("existentially") in a given relation (`subpage` or `inverse(subpage)*subpage`) to a certain other class of pages (e.g., named "blah") ("existentially" means there must exist a page, e.g., named "blah", which is in the given relation to the candidate).
100
101 > Probably the model behind XPath is similar (although I don't know enough to say this definitely).--Ivan Z.