an updated branch
[ikiwiki.git] / doc / todo / allow_plugins_to_add_sorting_methods.mdwn
1 [[!template id=gitbranch branch=smcv/sort-hooks author="[[Simon_McVittie|smcv]]"]]
2 [[!tag patch]]
3
4 The available [[ikiwiki/pagespec/sorting]] methods are currently hard-coded in
5 IkiWiki.pm, making it difficult to add any extra sorting mechanisms. I've
6 prepared a branch which adds 'sort' as a hook type and uses it to implement a
7 new `meta_title` sort type.
8
9 Someone could use this hook to make `\[[!inline sort=title]]` prefer the meta
10 title over the page name, but for compatibility, I'm not going to (I do wonder
11 whether it would be worth making sort=name an alias for the current sort=title,
12 and changing the meaning of sort=title in 4.0, though).
13
14 Gitweb:
15 <http://git.pseudorandom.co.uk/smcv/ikiwiki.git?a=shortlog;h=refs/heads/sort-hooks>
16
17 I briefly tried to turn *all* the current sort types into hook functions, and
18 have some of them pre-registered, but decided that probably wasn't a good idea.
19 That earlier version of the branch is also available for comparison:
20
21 <http://git.pseudorandom.co.uk/smcv/ikiwiki.git?a=shortlog;h=refs/heads/sort-hooks-excessive>
22
23 (The older version is untested, and probably doesn't really work as-is - I
24 misunderstood the details of how the built-in function `sort` works when using
25 `$a` and `$b`. The newer version has been tested, and has a regression test for
26 its core functionality.)
27
28 This hook *isn't* (yet) sufficient to implement [[plugins/contrib/report]]'s
29 NIH'd sorting mechanisms:
30
31 * `report` can sort by any [[plugins/contrib/field]], whereas this one has a
32   finite number of hooks: if the `field` plugin's functionality is desirable,
33   perhaps parameterized sort mechanisms similar to pagespec match functions
34   would be useful? Then the `field` plugin could register
35   `hook(type => "sort", id => "field")` and you could have
36   `\[[!inline ... sort="field(Mood)"]]` or something?
37
38 * `report` can sort by multiple criteria, with independent direction-changing:
39   if this is desirable, perhaps `pagespec_match_list` could be enhanced to
40   interpret `sort="x -y z(w)"` as sorting by (pseudocode)
41   `{ $cmp_x->($a, $b) || (-$cmp_y->($a, $b)) || $cmp_z->($a, $b, "w") }`?
42
43 > I've now added both of these features to the sort-hooks branch. --[[smcv]]
44
45 >> I wonder if IkiWiki would benefit from the concept of a "sortspec", like a [[ikiwiki/PageSpec]] but dedicated to sorting lists of pages rather than defining lists of pages?  Rather than defining a sort-hook, define a SortSpec class, and enable people to add their own sort methods as functions defined inside that class, similarly to the way they can add their own pagespec definitions. --[[KathrynAndersen]]
46
47 >>> I'd be inclined to think that's overkill, but it probably wouldn't be
48 >>> all that hard to implement... Joey? Any thoughts? --s
49
50 ## Documentation extracted from the branch
51
52 ### sort hook (added to [[plugins/write]])
53
54        hook(type => "sort", id => "foo", call => \&sort_by_foo);
55
56 This hook adds an additional [[ikiwiki/pagespec/sorting]] order or overrides
57 an existing one.
58
59 The callback is given two page names followed by the parameter as arguments, and
60 returns negative, zero or positive if the first page should come before,
61 close to (i.e. undefined order), or after the second page.
62
63 For instance, the built-in `title` sort order could be reimplemented as
64
65        sub sort_by_title {
66                pagetitle(basename($_[0])) cmp pagetitle(basename($_[1]));
67        }
68
69 and to sort by an arbitrary `meta` value, you could use:
70
71        # usage: sort="meta(description)"
72        sub sort_by_meta {
73                my $param = $_[2];
74                error "sort=meta requires a parameter" unless defined $param;
75                my $left = $pagestate{$_[0]}{meta}{$param};
76                $left = "" unless defined $left;
77                my $right = $pagestate{$_[1]}{meta}{$param};
78                $right = "" unless defined $right;
79                return $left cmp $right;
80        }
81
82
83 ### meta_title sort order (conditionally added to [[ikiwiki/pagespec/sorting]])
84
85 * `meta_title` - Order according to the `\[[!meta title="foo" sort="bar"]]`
86   or `\[[!meta title="foo"]]` [[ikiwiki/directive]], or the page name if no
87   full title was set.
88
89 ### Multiple sort orders (added to [[ikiwiki/pagespec/sorting]])
90
91 In addition, you can combine several sort orders and/or reverse the order of
92 sorting, with a string like `age -title` (which would sort by age, then by
93 title in reverse order if two pages have the same age).
94
95 ### meta title sort parameter (added to [[ikiwiki/directive/meta]])
96
97 An optional `sort` parameter will be used preferentially when
98 [[ikiwiki/pagespec/sorting]] by `meta_title`:
99
100        \[[!meta title="The Beatles" sort="Beatles, The"]]
101
102        \[[!meta title="David Bowie" sort="Bowie, David"]]