experimental plugin called subset
[ikiwiki.git] / doc / todo / pagespec_aliases.mdwn
1 [[!tag patch wishlist]]I quite often find myself repeating a boiler-plate
2 [[ikiwiki/pagespec]] chunk, e.g.
3
4     and !*.png and !*.jpg...
5
6 it would be quite nice if I could conveniently bundle them together into a
7 pagespec "alias", and instead write
8
9     and !image()...
10
11 I wrote the following plugin to achieve this:
12
13     commit f3a9dd113338fe5d2b717de1dc69679ff74e2f8d
14     Author: Jon Dowland <jmtd@debian.org>
15     Date:   Tue May 3 17:40:16 2011 +0100
16     
17         new plugin: alias.pm - pagespec aliases
18     
19     diff --git a/IkiWiki/Plugin/alias.pm b/IkiWiki/Plugin/alias.pm
20     new file mode 100644
21     index 0000000..b8d4574
22     --- /dev/null
23     +++ b/IkiWiki/Plugin/alias.pm
24     @@ -0,0 +1,47 @@
25     +package IkiWiki::Plugin::alias;
26     +
27     +use warnings;
28     +use strict;
29     +use IkiWiki '3.00';
30     +
31     +sub import {
32     +  hook(type => "getsetup", id=> "alias", call => \&getsetup);
33     +  hook(type => "checkconfig", id=> "alias", call => \&checkconfig);
34     +}
35     +
36     +sub getsetup () {
37     +    return
38     +        plugin => {
39     +            description => "allows the definition of pagespec aliases",
40     +            safe => 1,
41     +            rebuild => 1,
42     +            section => "misc",
43     +        },
44     +        pagespec_aliases => {
45     +            type => "string",
46     +            example => {"image" => "*jpg or *jpeg or *png or *gif or *ico" },
47     +            description => "a set of mappings from alias name to pagespec",
48     +            safe => 1,
49     +            rebuild => 0,
50     +        },
51     +}
52     +
53     +sub checkconfig () {
54     +    no strict 'refs';
55     +    no warnings 'redefine';
56     +
57     +    if ($config{pagespec_aliases}) {
58     +        foreach my $key (keys %{$config{pagespec_aliases}}) {
59     +            my $value = ${$config{pagespec_aliases}}{$key};
60     +            # XXX: validate key?
61     +            my $subname = "IkiWiki::PageSpec::match_$key";
62     +            *{ $subname } = sub {
63     +              my $path = shift;
64     +              return IkiWiki::pagespec_match($path, $value);
65     +            }
66     +        }
67     +    }
68     +}
69     +
70     +1;
71
72 I need to reflect on this a bit more before I send a pull request.  In
73 particular I imagine the strict/warnings stuff will make you puke.  Also, I'm
74 not sure whether I should name-grab 'alias' since [[todo/alias_directive]] is
75 an existing wishlist item.
76
77 > I think it would make sense to have "pagespec" in the name somehow.
78 >
79 > No, the strict/warnings does not make me puke. Have you read my perl
80 > code? :-P
81
82 > Note that your XXX is right. It would be a security hole to not validate
83 > `$key`, as anyone with websetup access could cause it to run arbitrary
84 > perl code.
85
86 > Well, except that websetup doesn't currently support configuring hashes
87 > like used here. Which is a pity, but has led me to try to avoid using
88 > such hashes in the setup file.
89
90 > Have you considered not defining the pagespec aliases in the setup file, but
91 > instead as directives on pages in the wiki? Using pagestate could store
92 > up the aliases that have been defined. It could however, be hard to get
93 > the dependencies right; any page that uses a pagespec containing 
94 > an alias `foo` would need to somehow depend on the page where the alias
95 > was defined. --[[Joey]] 
96
97 Here's an example setup chunk:
98
99      pagespec_aliases:
100        image: "*.png or *.jpg or *.jpeg or *.gif or *.ico"
101        helper: "*.css or *.js"
102        boring: "image() or helper()"
103
104 The above demonstrates self-referential dynamic pagespec aliases.  It doesn't work,
105 however, to add ' or internal()' to `boring`, for some reason.
106
107 -- [[Jon]]
108
109 > Probably needs to be `or internal(*)` --[[Joey]] 
110
111 > another useful pagespec alias for large maps:
112
113        basewiki: "sandbox or templates or templates/* or ikiwiki or ikiwiki/* or shortcuts or recentchanges or wikiicons/*"
114
115 > -- [[Jon]]
116
117 >> Useful indeed! --[[Joey]] 
118
119 ---------------------------
120
121 Based on the above, I have written an experimental plugin called "subset".
122 It's in my "ikiplugins" repo on github, in the "experimental" branch.
123 <https://github.com/rubykat/ikiplugins/blob/experimental/IkiWiki/Plugin/subset.pm>
124
125 It takes Joey's suggestion of defining the subsets (aliases) as directives;
126 I took the example of the [[plugins/shortcut]] plugin and designated a single special page as the one where the directives are defined,
127 though unlike "shortcut" I haven't hardcoded the name of the page; it defaults to "subsets" but it can be re-defined in the config.
128
129 I've also added a feature which one might call subset-caching; I had to override `pagespec_match_list` to do it, however.
130 An extra parameter added to `pagespec_match_list` called `subset` which
131
132 * limits the result to look *only* within the set of pages defined by the subset (uses the "list" option to pagespec_match_list to do this)
133 * caches the result of the subset search so that the second time subset "foo" is used, it uses the stored result of the first search for "foo".
134
135 This speeds things up if one is using a particular subset more than once, which one probably is if one bothered to define the subset in the first place.
136 The speed increase is most dramatic when the site has a large number of pages and the number of pages in the subset is small.
137 (this is similar to the "trail" concept I used in my [[plugins/contrib/report]] plugin, but not quite the same)
138
139 Note that things like [[plugins/map]] can't make use of "subset" (yet) because they don't pass along all the parameters they're given.
140 But [[plugins/contrib/report]] actually works without alteration because it does pass along all the parameters.
141
142 Unfortunately I haven't figured out how to do the dependencies - I'd really appreciate help on that.
143
144 --[[KathrynAndersen]]