bookeeping
[ikiwiki] / doc / todo / inline:_numerical_ordering_by_title.mdwn
1 Could you please add numerical ordering by title to [[inline|plugins/inline]]
2 plugin? Now I can do only alphabetical order by title, but sometime it's not enough.
3
4 > Implemented, see [[natural_sorting]] [[!tag done]] --[[Joey]] 
5
6 BTW, it seems that ordering by title is rather ordering by filename of page.
7 For me "title" means title of page I can set using `title` parameter
8 of [[meta|plugins/meta]] plugin :)
9
10 Why do I need that feature? I've just been migrating an info site of our university
11 [mail system](http://poczta.uw.edu.pl/) to Ikiwiki from very static, console handling
12 Makefile+[WML](http://thewml.org/)+XML+XSL=HTML solution. I have many news files
13 (`1.mdwn`, `2.mdwn`, etc.) and unfortunately I did very stupid thing. I've commited
14 all of them in the same revision of our Subversion repo...
15
16 Now I have a problem with sorting these files using inline plugin. I can't do
17 sorting by age, because both old and young news files have the same age. I can't
18 sort by title too. For example, when I sort them by title, then `9.mdwn` page is
19 between `90.mdwn` and `89.mdwn` pages... It sucks, of course. Sorting by mtime
20 also is not a solution for me, because it means that I can't touch/fix old news
21 anymore.
22
23 Do you have any idea how to workaround that issue? --[[Paweł|ptecza]]
24
25 > Delete all files. Add files back one at a time, committing after adding
26 > each file. Sort by date. --[[Joey]]
27
28 >> The simplest solutions are the best :D Thanks for the hint! I didn't
29 >> want to do it before, because I was affaid that my Subversion keeps
30 >> old date of creation of file. --[[Paweł|ptecza]]
31
32 > Maybe you can rename `9.mdwn` to `09.mdwn`? See `rename(1)`, it renames multiple files
33 > in one go. --[[buo]]
34
35 >> Thanks for your suggestion! But what about if number of my news files grows to 100+?
36
37 >>     $ ls
38 >>     09.mdwn  100.mdwn  101.mdwn  102.mdwn  89.mdwn  90.mdwn
39
40 >> I don't want to rename all previous files to add `0` prefix. --[[Paweł|ptecza]]
41
42 >>> Rather than adding 0's or or a 'sorttype' parameter, I'd just fix the sort order.
43 >>> Both MacOS and Windows use a smarter sort order than just lexical in their
44 >>> file browsers (e.g. <http://support.microsoft.com/default.aspx?kbid=319827>,
45 >>> <http://docs.info.apple.com/article.html?artnum=300989>).
46 >>>
47 >>> The [Unicode Collation algorithm](http://en.wikipedia.org/wiki/Unicode_collation_algorithm)
48 >>> would seem to be a reasonable sort order.  (See also <http://www.unicode.org/unicode/reports/tr10/>.)
49 >>> Unfortunately the standard perl implementation, [Unicode::Collate](http://perldoc.perl.org/Unicode/Collate.html)
50 >>> doesn't handle the optional [numbers](http://www.unicode.org/unicode/reports/tr10/#Customization)
51 >>> extension which is what you want.  --[[Will]]
52
53 ---
54
55 Below is my simple patch. Feel free to use it or comment!
56
57 I have also 2 considerations for inline sorting:
58
59 1. Maybe changing name of `sort` parameter to `sortby` or `sortkey` will
60    be good idea?
61
62    > No, that would break existing wikis. --[[Joey]]
63    >> It's no problem. You just have `ikiwiki-transition` utility :D --[[Paweł|ptecza]]
64
65 1. Maybe you should use `title` sort key for title from meta plugin and `name`, 
66    `filename`, `page` or `pagename` for page names? In the future you can also
67    sort by meta author, license or another key.
68
69    > There are many places in ikiwiki that do not use meta title info and
70    > could. I'd prefer to deal with that issue as a whole, not here,
71    > --[[Joey]]
72
73 --[[Paweł|ptecza]]
74
75     --- inline.pm-orig  2008-09-02 09:53:20.000000000 +0200
76     +++ inline.pm       2008-09-02 10:09:02.000000000 +0200
77     @@ -186,7 +186,15 @@
78         }
79
80         if (exists $params{sort} && $params{sort} eq 'title') {
81     -           @list=sort { pagetitle(basename($a)) cmp pagetitle(basename($b)) } @list;
82     +           if (! $params{sorttype} || $params{sorttype} eq 'lexical') {
83     +                   @list=sort { pagetitle(basename($a)) cmp pagetitle(basename($b)) } @list;
84     +           }
85     +           elsif ($params{sorttype} eq 'numeric') {
86     +                   @list=sort { pagetitle(basename($a)) <=> pagetitle(basename($b)) } @list;
87     +           }
88     +           else {
89     +                   return sprintf(gettext("unknown sort type %s"), $params{sorttype});
90     +           }
91         }
92         elsif (exists $params{sort} && $params{sort} eq 'mtime') {
93                 @list=sort { $pagemtime{$b} <=> $pagemtime{$a} } @list;
94     @@ -195,7 +203,7 @@
95                 @list=sort { $pagectime{$b} <=> $pagectime{$a} } @list;
96         }
97         else {
98     -           return sprintf(gettext("unknown sort type %s"), $params{sort});
99     +           return sprintf(gettext("unknown sort key %s"), $params{sort});
100         }
101
102         if (yesno($params{reverse})) {
103
104 > To users, "sort" already determines the type of sort. It can be by title,
105 > or by date, etc. Adding a separate "sorttype" value is thus fairly
106 > confusing. --[[Joey]]
107
108 >> OK. I will be more careful when I play with inline plugin :) --[[Paweł|ptecza]]
109
110 ---
111
112 Joey, have you forgotten about that request? ;) --[[Paweł|ptecza]]
113
114 > Okie.  Here is a different [[patch]] based on my comment above.  It doesn't introduce
115 > a new key, but rather changes the title sorting order. Two caveats:
116
117  * I've only tested this in `inline`, not the other places I changed the sort order.
118  * I'm unsure if the regexp used in the split should be `/(-?\d+)/` instead of `/(\d+)/`.
119     As written, '-' is interpreted as a hyphen rather than a minus sign.
120
121 > --[[Will]]
122
123 >> I"m not comfortable with tossing out perl's default collator and trying
124 >> to maintain some other one going forward. Especially not for such an
125 >> edge case. --[[Joey]]
126
127 >> Hi Will! Your idea looks interesting for me, but I'm affraid that it's too big
128 >> change in Ikiwiki... Maybe I'm wrong? ;) What do you think, Joey? --[[Paweł|ptecza]]
129
130 >>> It isn't that big a change.  It is just supplying a sort order to the sort.  The
131 >>> patch is a little larger because I then went through and made that sort
132 >>> order available in other places where it makes sense.  (Looking at the
133 >>> patch again briefly, I should have also used it in the `map` plugin.)
134 >>>
135 >>> If you wanted a simple patch, you could just move the `titlecmp` function
136 >>> into the inline plugin and only use it there.  The problem with that is that
137 >>> it only fixes the inline plugin. -- [[Will]]
138
139 >>>> Will, I agree with you that it's improved way of sort order. But on the other
140 >>>> hand I prefer to be careful when I change something in a several places,
141 >>>> because I don't want to break any working things when I fix one thing.
142 >>>> I hope that Joey agree with us too and all Ikiwiki users will be happy
143 >>>> after applying your patch ;) --[[Paweł|ptecza]]
144
145 ----
146
147     diff --git a/IkiWiki.pm b/IkiWiki.pm
148     index c0f5dea..d001f8d 100644
149     --- a/IkiWiki.pm
150     +++ b/IkiWiki.pm
151     @@ -20,7 +20,7 @@ use Exporter q{import};
152      our @EXPORT = qw(hook debug error template htmlpage add_depends pagespec_match
153                       bestlink htmllink readfile writefile pagetype srcfile pagename
154                       displaytime will_render gettext urlto targetpage
155     -            add_underlay
156     +            add_underlay titlecmp
157                       %config %links %pagestate %renderedfiles
158                       %pagesources %destsources);
159      our $VERSION = 2.00; # plugin interface version, next is ikiwiki version
160     @@ -835,6 +835,42 @@ sub titlepage ($) {
161         return $title;
162      }
163      
164     +sub titlecmp ($$) {
165     +   my $titleA=shift;
166     +   my $titleB=shift;
167     +   
168     +   my @listA=split(/(\d+)/,$titleA);
169     +   my @listB=split(/(\d+)/,$titleB);
170     +   
171     +   while (@listA && @listB) {
172     +           # compare bits of text
173     +           my $a = shift @listA;
174     +           my $b = shift @listB;
175     +           my $c = ($a cmp $b);
176     +           return $c if ($c);
177     +
178     +           if (@listA && @listB) {
179     +                   # compare numbers
180     +                   $a = shift @listA;
181     +                   $b = shift @listB;
182     +                   $c = $a <=> $b;
183     +                   return $c if ($c);
184     +                   
185     +                   # 01 is different to 1
186     +                   $c = (length($a) <=> length($b));
187     +                   return $c if ($c);
188     +
189     +                   $c = ($a cmp $b);
190     +                   return $c if ($c);
191     +           }
192     +   }
193     +   
194     +   return 1 if (@listA);
195     +   return -1 if (@listB);
196     +   
197     +   return 0;
198     +}
199     +
200      sub linkpage ($) {
201         my $link=shift;
202         my $chars = defined $config{wiki_file_chars} ? $config{wiki_file_chars} : "-[:alnum:]+/.:_";
203     diff --git a/IkiWiki/Plugin/brokenlinks.pm b/IkiWiki/Plugin/brokenlinks.pm
204     index 37752dd..ccaa399 100644
205     --- a/IkiWiki/Plugin/brokenlinks.pm
206     +++ b/IkiWiki/Plugin/brokenlinks.pm
207     @@ -59,7 +59,7 @@ sub preprocess (@) {
208                         map {
209                                 "<li>$_</li>"
210                         }
211     -                   sort @broken)
212     +                   sort titlecmp @broken)
213                 ."</ul>\n";
214      }
215      
216     diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm
217     index 8efef3f..263e7a6 100644
218     --- a/IkiWiki/Plugin/inline.pm
219     +++ b/IkiWiki/Plugin/inline.pm
220     @@ -192,7 +192,7 @@ sub preprocess_inline (@) {
221         }
222      
223         if (exists $params{sort} && $params{sort} eq 'title') {
224     -           @list=sort { pagetitle(basename($a)) cmp pagetitle(basename($b)) } @list;
225     +           @list=sort { titlecmp(pagetitle(basename($a)),pagetitle(basename($b))) } @list;
226         }
227         elsif (exists $params{sort} && $params{sort} eq 'mtime') {
228                 @list=sort { $pagemtime{$b} <=> $pagemtime{$a} } @list;
229     diff --git a/IkiWiki/Plugin/orphans.pm b/IkiWiki/Plugin/orphans.pm
230     index b910758..10a1d87 100644
231     --- a/IkiWiki/Plugin/orphans.pm
232     +++ b/IkiWiki/Plugin/orphans.pm
233     @@ -56,7 +56,7 @@ sub preprocess (@) {
234                                 htmllink($params{page}, $params{destpage}, $_,
235                                          noimageinline => 1).
236                                 "</li>"
237     -                   } sort @orphans).
238     +                   } sort titlecmp @orphans).
239                 "</ul>\n";
240      }
241      
242     diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm
243     index ceb7c84..00798e1 100644
244     --- a/IkiWiki/Render.pm
245     +++ b/IkiWiki/Render.pm
246     @@ -89,7 +89,7 @@ sub genpage ($$) {
247                 $template->param(have_actions => 1);
248         }
249      
250     -   my @backlinks=sort { $a->{page} cmp $b->{page} } backlinks($page);
251     +   my @backlinks=sort { titlecmp($a->{page}, $b->{page}) } backlinks($page);
252         my ($backlinks, $more_backlinks);
253         if (@backlinks <= $config{numbacklinks} || ! $config{numbacklinks}) {
254                 $backlinks=\@backlinks;