From a63929f6cc7778ffc4ba57d784cdf2206ec650c7 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 11 Feb 2010 22:24:15 -0500 Subject: Group related plugins into sections in the setup file, and drop unused rcs plugins from the setup file. --- IkiWiki/Plugin/meta.pm | 1 + 1 file changed, 1 insertion(+) (limited to 'IkiWiki/Plugin/meta.pm') diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index 55c9ddbd1..5f046cb2a 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -20,6 +20,7 @@ sub getsetup () { plugin => { safe => 1, rebuild => undef, + section => "core", }, } -- cgit v1.2.3 From 0618f099dab8bd4f7f47e2695db01eabe49e3316 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 24 Mar 2010 00:59:01 +0000 Subject: Have the meta plugin add a meta_title sort order --- IkiWiki/Plugin/meta.pm | 15 +++++++++++++++ doc/ikiwiki/pagespec/sorting.mdwn | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'IkiWiki/Plugin/meta.pm') diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index 5f046cb2a..bf8159814 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -13,6 +13,7 @@ sub import { hook(type => "needsbuild", id => "meta", call => \&needsbuild); hook(type => "preprocess", id => "meta", call => \&preprocess, scan => 1); hook(type => "pagetemplate", id => "meta", call => \&pagetemplate); + hook(type => "sort", id => "meta_title", call => \&sort_meta_title); } sub getsetup () { @@ -282,6 +283,20 @@ sub pagetemplate (@) { } } +sub title { + my $title = $pagestate{$_[0]}{meta}{title}; + + if (defined $title) { + return $title; + } + + return pagetitle(IkiWiki::basename($_[0])); +} + +sub sort_meta_title { + return title($_[0]) cmp title($_[1]); +} + sub match { my $field=shift; my $page=shift; diff --git a/doc/ikiwiki/pagespec/sorting.mdwn b/doc/ikiwiki/pagespec/sorting.mdwn index 9007c23bf..3a9fef9b6 100644 --- a/doc/ikiwiki/pagespec/sorting.mdwn +++ b/doc/ikiwiki/pagespec/sorting.mdwn @@ -9,7 +9,12 @@ orders can be specified. * `title_natural` - Only available if [[!cpan Sort::Naturally]] is installed. Orders by title, but numbers in the title are treated as such, ("1 2 9 10 20" instead of "1 10 2 20 9") +[[!if test="enabled(meta)" then=""" +* `meta_title` - Order by the full title set by the `\[[!meta title="foo"]]` + [[ikiwiki/directive]]. +"""]] -Plugins can add additional sort orders. +Plugins can add additional sort orders, so more might be available on this +wiki. [[!meta robots="noindex, follow"]] -- cgit v1.2.3 From b0ae19872d443860aeaab7069255e3a68a520887 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 24 Mar 2010 03:18:24 +0000 Subject: Add an optional "sort" argument to meta titles, defaulting to the title This allows correct sorting of titles, names, etc., with: [[!meta title="David Bowie" sort="Bowie, David"]] [[!meta title="The Beatles" sort="Beatles, The"]] --- IkiWiki/Plugin/meta.pm | 16 +++++++++++----- doc/ikiwiki/directive/meta.mdwn | 7 +++++++ doc/ikiwiki/pagespec/sorting.mdwn | 7 ++++--- 3 files changed, 22 insertions(+), 8 deletions(-) (limited to 'IkiWiki/Plugin/meta.pm') diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index bf8159814..a470041c9 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -90,6 +90,12 @@ sub preprocess (@) { # Metadata collection that needs to happen during the scan pass. if ($key eq 'title') { $pagestate{$page}{meta}{title}=HTML::Entities::encode_numeric($value); + if (exists $params{sort}) { + $pagestate{$page}{meta}{titlesort}=$params{sort}; + } + else { + $pagestate{$page}{meta}{titlesort}=$value; + } return ""; } elsif ($key eq 'description') { @@ -283,18 +289,18 @@ sub pagetemplate (@) { } } -sub title { - my $title = $pagestate{$_[0]}{meta}{title}; +sub titlesort { + my $key = $pagestate{$_[0]}{meta}{titlesort}; - if (defined $title) { - return $title; + if (defined $key) { + return $key; } return pagetitle(IkiWiki::basename($_[0])); } sub sort_meta_title { - return title($_[0]) cmp title($_[1]); + return titlesort($_[0]) cmp titlesort($_[1]); } sub match { diff --git a/doc/ikiwiki/directive/meta.mdwn b/doc/ikiwiki/directive/meta.mdwn index 557441c0b..8d2a5b1ad 100644 --- a/doc/ikiwiki/directive/meta.mdwn +++ b/doc/ikiwiki/directive/meta.mdwn @@ -23,6 +23,13 @@ Supported fields: be set to a true value in the template; this can be used to format things differently in this case. + An optional `sort` parameter will be used preferentially when + [[ikiwiki/pagespec/sorting]] by `meta_title`: + + \[[!meta title="The Beatles" sort="Beatles, The"]] + + \[[!meta title="David Bowie" sort="Bowie, David"]] + * license Specifies a license for the page, for example, "GPL". Can contain diff --git a/doc/ikiwiki/pagespec/sorting.mdwn b/doc/ikiwiki/pagespec/sorting.mdwn index 3a9fef9b6..61516bec5 100644 --- a/doc/ikiwiki/pagespec/sorting.mdwn +++ b/doc/ikiwiki/pagespec/sorting.mdwn @@ -5,13 +5,14 @@ orders can be specified. * `age` - List pages from the most recently created to the oldest. * `mtime` - List pages with the most recently modified first. -* `title` - Order by title. +* `title` - Order by title (page name). * `title_natural` - Only available if [[!cpan Sort::Naturally]] is installed. Orders by title, but numbers in the title are treated as such, ("1 2 9 10 20" instead of "1 10 2 20 9") [[!if test="enabled(meta)" then=""" -* `meta_title` - Order by the full title set by the `\[[!meta title="foo"]]` - [[ikiwiki/directive]]. +* `meta_title` - Order according to the `\[[!meta title="foo" sort="bar"]]` + or `\[[!meta title="foo"]]` [[ikiwiki/directive]], or the page name if no + full title was set. """]] Plugins can add additional sort orders, so more might be available on this -- cgit v1.2.3 From b86276ffed7ee001b35cd610e5d56e5afb4088cf Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Thu, 25 Mar 2010 23:31:53 +0000 Subject: Reimplement extensible sorting mechanisms, in the same way as pagespecs --- IkiWiki.pm | 145 ++++++++++++++++++++++++++++-------------------- IkiWiki/Plugin/meta.pm | 11 ++-- doc/plugins/write.mdwn | 53 ++++++++---------- t/pagespec_match_list.t | 6 +- 4 files changed, 120 insertions(+), 95 deletions(-) (limited to 'IkiWiki/Plugin/meta.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index ce8fdd454..a89c14058 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -37,6 +37,7 @@ our $DEPEND_LINKS=4; # Optimisation. use Memoize; memoize("abs2rel"); +memoize("cmpspec_translate"); memoize("pagespec_translate"); memoize("template_file"); @@ -1934,6 +1935,70 @@ sub add_link ($$) { unless grep { $_ eq $link } @{$links{$page}}; } +sub cmpspec_translate ($) { + my $spec = shift; + + my $code = ""; + my @data; + while ($spec =~ m{ + \s* + (-?) # group 1: perhaps negated + \s* + ( # group 2: a word + \w+\([^\)]*\) # command(params) + | + [^\s]+ # or anything else + ) + \s* + }gx) { + my $negated = $1; + my $word = $2; + my $params = undef; + + if ($word =~ m/^(\w+)\((.*)\)$/) { + # command with parameters + $params = $2; + $word = $1; + } + elsif ($word !~ m/^\w+$/) { + error(sprintf(gettext("invalid sort type %s"), $word)); + } + + if (length $code) { + $code .= " || "; + } + + if ($negated) { + $code .= "-"; + } + + if (exists $IkiWiki::PageSpec::{"cmp_$word"}) { + if (exists $IkiWiki::PageSpec::{"check_cmp_$word"}) { + $IkiWiki::PageSpec::{"check_cmp_$word"}->($params); + } + + if (defined $params) { + push @data, $params; + $code .= "IkiWiki::PageSpec::cmp_$word(\@_, \$data[$#data])"; + } + else { + $code .= "IkiWiki::PageSpec::cmp_$word(\@_, undef)"; + } + } + else { + error(sprintf(gettext("unknown sort type %s"), $word)); + } + } + + if (! length $code) { + # undefined sorting method... sort arbitrarily + return sub { 0 }; + } + + no warnings; + return eval 'sub { '.$code.' }'; +} + sub pagespec_translate ($) { my $spec=shift; @@ -2005,64 +2070,6 @@ sub pagespec_match ($$;@) { return $sub->($page, @params); } -sub get_sort_function { - my $method = $_[0]; - - if ($method =~ m/\s/) { - my @methods = map { get_sort_function($_) } split(' ', $method); - - return sub { - foreach my $method (@methods) { - my $answer = $method->($_[0], $_[1]); - return $answer if $answer; - } - - return 0; - }; - } - - my $sense = 1; - - if ($method =~ s/^-//) { - $sense = -1; - } - - my $token = $method; - my $parameter = undef; - - if ($method =~ m/^(\w+)\((.*)\)$/) { - $token = $1; - $parameter = $2; - } - - if (exists $hooks{sort}{$token}{call}) { - my $callback = $hooks{sort}{$token}{call}; - return sub { $sense * $callback->($_[0], $_[1], $parameter) }; - } - - if ($method eq 'title') { - return sub { $sense * (pagetitle(basename($_[0])) cmp pagetitle(basename($_[1]))) }; - } - - if ($method eq 'title_natural') { - eval q{use Sort::Naturally}; - if ($@) { - error(gettext("Sort::Naturally needed for title_natural sort")); - } - return sub { $sense * Sort::Naturally::ncmp(pagetitle(basename($_[0])), pagetitle(basename($_[1]))) }; - } - - if ($method eq 'mtime') { - return sub { $sense * ($pagemtime{$_[1]} <=> $pagemtime{$_[0]}) }; - } - - if ($method eq 'age') { - return sub { $sense * ($pagectime{$_[1]} <=> $pagectime{$_[0]}) }; - } - - error sprintf(gettext("unknown sort type %s"), $method); -} - sub pagespec_match_list ($$;@) { my $page=shift; my $pagespec=shift; @@ -2092,7 +2099,7 @@ sub pagespec_match_list ($$;@) { } if (defined $params{sort}) { - my $f = get_sort_function($params{sort}); + my $f = cmpspec_translate($params{sort}); @candidates = sort { $f->($a, $b) } @candidates; } @@ -2407,4 +2414,24 @@ sub match_ip ($$;@) { } } +sub cmp_title { + IkiWiki::pagetitle(IkiWiki::basename($_[0])) + cmp + IkiWiki::pagetitle(IkiWiki::basename($_[1])) +} + +sub cmp_mtime { $IkiWiki::pagemtime{$_[1]} <=> $IkiWiki::pagemtime{$_[0]} } +sub cmp_age { $IkiWiki::pagectime{$_[1]} <=> $IkiWiki::pagectime{$_[0]} } + +sub check_cmp_title_natural { + eval q{use Sort::Naturally}; + if ($@) { + error(gettext("Sort::Naturally needed for title_natural sort")); + } +} +sub cmp_title_natural { + Sort::Naturally::ncmp(IkiWiki::pagetitle(IkiWiki::basename($_[0])), + IkiWiki::pagetitle(IkiWiki::basename($_[1]))) +} + 1 diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index a470041c9..e8cc1e392 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -13,7 +13,6 @@ sub import { hook(type => "needsbuild", id => "meta", call => \&needsbuild); hook(type => "preprocess", id => "meta", call => \&preprocess, scan => 1); hook(type => "pagetemplate", id => "meta", call => \&pagetemplate); - hook(type => "sort", id => "meta_title", call => \&sort_meta_title); } sub getsetup () { @@ -299,10 +298,6 @@ sub titlesort { return pagetitle(IkiWiki::basename($_[0])); } -sub sort_meta_title { - return titlesort($_[0]) cmp titlesort($_[1]); -} - sub match { my $field=shift; my $page=shift; @@ -353,4 +348,10 @@ sub match_copyright ($$;@) { IkiWiki::Plugin::meta::match("copyright", @_); } +sub cmp_meta_title { + IkiWiki::Plugin::meta::titlesort($_[0]) + cmp + IkiWiki::Plugin::meta::titlesort($_[1]) +} + 1 diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 1010e76e4..de2b47015 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -588,36 +588,6 @@ describes the plugin as a whole. For example: This hook is used to inject C code (which it returns) into the `main` function of the ikiwiki wrapper when it is being generated. -### sort - - hook(type => "sort", id => "foo", call => \&sort_by_foo); - -This hook adds an additional [[ikiwiki/pagespec/sorting]] order or overrides -an existing one. - -The callback is given two page names followed by the parameter as arguments, and -returns negative, zero or positive if the first page should come before, -close to (i.e. undefined order), or after the second page. - -For instance, the built-in `title` sort order could be reimplemented as - - sub sort_by_title { - pagetitle(basename($_[0])) cmp pagetitle(basename($_[1])); - } - -and to sort by an arbitrary `meta` value, you could use: - - # usage: sort="meta(description)" - sub sort_by_meta { - my $param = $_[2]; - error "sort=meta requires a parameter" unless defined $param; - my $left = $pagestate{$_[0]}{meta}{$param}; - $left = "" unless defined $left; - my $right = $pagestate{$_[1]}{meta}{$param}; - $right = "" unless defined $right; - return $left cmp $right; - } - ## Exported variables Several variables are exported to your plugin when you `use IkiWiki;` @@ -1140,6 +1110,29 @@ For example, "backlink(foo)" is influenced by the contents of page foo; they match; "created_before(foo)" is influenced by the metadata of foo; while "glob(*)" is not influenced by the contents of any page. +### Sorting plugins + +Similarly, it's possible to write plugins that add new functions as +[[ikiwiki/pagespec/sorting]] methods. To achieve this, add a function to +the IkiWiki::PageSpec package named `cmp_foo`, which will be used when sorting +by `foo` or `foo(...)` is requested. + +The function will be passed three or more parameters. The first two are +page names, and the third is `undef` if invoked as `foo`, or the parameter +`"bar"` if invoked as `foo(bar)`. It may also be passed additional, named +parameters. + +It should return the same thing as Perl's `cmp` and `<=>` operators: negative +if the first argument is less than the second, positive if the first argument +is greater, or zero if they are considered equal. It may also raise an +error using `error`, for instance if it needs a parameter but one isn't +provided. + +You can also define a function called `check_cmp_foo` in the same package. +If you do, it will be called while preparing to sort by `foo` or `foo(bar)`, +with argument `undef` or `"bar"` respectively; it may raise an error using +`error`, if sorting like that isn't going to work. + ### Setup plugins The ikiwiki setup file is loaded using a pluggable mechanism. If you look diff --git a/t/pagespec_match_list.t b/t/pagespec_match_list.t index 309961f1c..743ae4637 100755 --- a/t/pagespec_match_list.t +++ b/t/pagespec_match_list.t @@ -9,7 +9,11 @@ BEGIN { use_ok("IkiWiki"); } $config{srcdir}=$config{destdir}="/dev/null"; IkiWiki::checkconfig(); -hook(type => "sort", id => "path", call => sub { $_[0] cmp $_[1] }); +{ + package IkiWiki::PageSpec; + + sub cmp_path { $_[0] cmp $_[1] } +} %pagesources=( foo => "foo.mdwn", -- cgit v1.2.3 From 04a59b3c65e8e60805b6ed6d11d448b1d5babe64 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Sat, 3 Apr 2010 13:57:38 +0100 Subject: Move sort hooks to the IkiWiki::SortSpec namespace Also rename cmpspec_translate (internal function) to sortspec_translate for consistency. --- IkiWiki.pm | 14 ++++++++------ IkiWiki/Plugin/meta.pm | 2 ++ IkiWiki/Plugin/sortnaturally.pm | 2 +- doc/plugins/write.mdwn | 2 +- t/pagespec_match_list.t | 2 +- 5 files changed, 13 insertions(+), 9 deletions(-) (limited to 'IkiWiki/Plugin/meta.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 7547f1751..d716e8b39 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -37,7 +37,7 @@ our $DEPEND_LINKS=4; # Optimisation. use Memoize; memoize("abs2rel"); -memoize("cmpspec_translate"); +memoize("sortspec_translate"); memoize("pagespec_translate"); memoize("template_file"); @@ -1935,7 +1935,7 @@ sub add_link ($$) { unless grep { $_ eq $link } @{$links{$page}}; } -sub cmpspec_translate ($) { +sub sortspec_translate ($) { my $spec = shift; my $code = ""; @@ -1972,13 +1972,13 @@ sub cmpspec_translate ($) { $code .= "-"; } - if (exists $IkiWiki::PageSpec::{"cmp_$word"}) { + if (exists $IkiWiki::SortSpec::{"cmp_$word"}) { if (defined $params) { push @data, $params; - $code .= "IkiWiki::PageSpec::cmp_$word(\@_, \$data[$#data])"; + $code .= "IkiWiki::SortSpec::cmp_$word(\@_, \$data[$#data])"; } else { - $code .= "IkiWiki::PageSpec::cmp_$word(\@_, undef)"; + $code .= "IkiWiki::SortSpec::cmp_$word(\@_, undef)"; } } else { @@ -2095,7 +2095,7 @@ sub pagespec_match_list ($$;@) { } if (defined $params{sort}) { - my $f = cmpspec_translate($params{sort}); + my $f = sortspec_translate($params{sort}); @candidates = sort { $f->($a, $b) } @candidates; } @@ -2410,6 +2410,8 @@ sub match_ip ($$;@) { } } +package IkiWiki::SortSpec; + sub cmp_title { IkiWiki::pagetitle(IkiWiki::basename($_[0])) cmp diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index e8cc1e392..cd7d0d127 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -348,6 +348,8 @@ sub match_copyright ($$;@) { IkiWiki::Plugin::meta::match("copyright", @_); } +package IkiWiki::SortSpec; + sub cmp_meta_title { IkiWiki::Plugin::meta::titlesort($_[0]) cmp diff --git a/IkiWiki/Plugin/sortnaturally.pm b/IkiWiki/Plugin/sortnaturally.pm index 0023f31f9..f498820a5 100644 --- a/IkiWiki/Plugin/sortnaturally.pm +++ b/IkiWiki/Plugin/sortnaturally.pm @@ -22,7 +22,7 @@ sub checkconfig () { error $@ if $@; } -package IkiWiki::PageSpec; +package IkiWiki::SortSpec; sub cmp_title_natural { Sort::Naturally::ncmp(IkiWiki::pagetitle(IkiWiki::basename($_[0])), diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 06c8f8e44..b67142230 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -1114,7 +1114,7 @@ while "glob(*)" is not influenced by the contents of any page. Similarly, it's possible to write plugins that add new functions as [[ikiwiki/pagespec/sorting]] methods. To achieve this, add a function to -the IkiWiki::PageSpec package named `cmp_foo`, which will be used when sorting +the IkiWiki::SortSpec package named `cmp_foo`, which will be used when sorting by `foo` or `foo(...)` is requested. The function will be passed three or more parameters. The first two are diff --git a/t/pagespec_match_list.t b/t/pagespec_match_list.t index 743ae4637..68112f5c0 100755 --- a/t/pagespec_match_list.t +++ b/t/pagespec_match_list.t @@ -10,7 +10,7 @@ $config{srcdir}=$config{destdir}="/dev/null"; IkiWiki::checkconfig(); { - package IkiWiki::PageSpec; + package IkiWiki::SortSpec; sub cmp_path { $_[0] cmp $_[1] } } -- cgit v1.2.3 From 618bbaee3815daffe329fc1e2d77f04fcd8392b8 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Sat, 3 Apr 2010 14:17:48 +0100 Subject: meta: generalize meta_title into meta(title); support author, updated, date I've left meta_title in, undocumented, as a possible replacement for sort=title in IkiWiki 4.0 or something. --- IkiWiki/Plugin/meta.pm | 58 +++++++++++++++++++++++++++++++++------ doc/ikiwiki/directive/meta.mdwn | 7 ++++- doc/ikiwiki/pagespec/sorting.mdwn | 5 ++-- 3 files changed, 58 insertions(+), 12 deletions(-) (limited to 'IkiWiki/Plugin/meta.pm') diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index cd7d0d127..c9fdbc934 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -122,6 +122,12 @@ sub preprocess (@) { } elsif ($key eq 'author') { $pagestate{$page}{meta}{author}=$value; + if (exists $params{sort}) { + $pagestate{$page}{meta}{authorsort}=$params{sort}; + } + else { + $pagestate{$page}{meta}{authorsort}=$value; + } # fallthorough } elsif ($key eq 'authorurl') { @@ -288,14 +294,31 @@ sub pagetemplate (@) { } } -sub titlesort { - my $key = $pagestate{$_[0]}{meta}{titlesort}; +sub get_sort_key { + my $page = $_[0]; + my $meta = $_[1]; - if (defined $key) { - return $key; - } + # e.g. titlesort (also makes sense for author) + my $key = $pagestate{$page}{meta}{$meta . "sort"}; + return $key if defined $key; + + # e.g. title + $key = $pagestate{$page}{meta}{$meta}; + return $key if defined $key; - return pagetitle(IkiWiki::basename($_[0])); + # fall back to closer-to-core things + if ($meta eq 'title') { + return pagetitle(IkiWiki::basename($page)); + } + elsif ($meta eq 'date') { + return $IkiWiki::pagectime{$page}; + } + elsif ($meta eq 'updated') { + return $IkiWiki::pagemtime{$page}; + } + else { + return ''; + } } sub match { @@ -350,10 +373,27 @@ sub match_copyright ($$;@) { package IkiWiki::SortSpec; +sub cmp_meta { + my $left = $_[0]; + my $right = $_[1]; + my $meta = $_[2]; + error(gettext("sort=meta requires a parameter")) unless defined $meta; + + if ($meta eq 'updated' || $meta eq 'date') { + return IkiWiki::Plugin::meta::get_sort_key($left, $meta) + <=> + IkiWiki::Plugin::meta::get_sort_key($right, $meta); + } + + return IkiWiki::Plugin::meta::get_sort_key($left, $meta) + cmp + IkiWiki::Plugin::meta::get_sort_key($right, $meta); +} + +# A prototype of how sort=title could behave in 4.0 or something sub cmp_meta_title { - IkiWiki::Plugin::meta::titlesort($_[0]) - cmp - IkiWiki::Plugin::meta::titlesort($_[1]) + $_[2] = 'title'; + return cmp_meta(@_); } 1 diff --git a/doc/ikiwiki/directive/meta.mdwn b/doc/ikiwiki/directive/meta.mdwn index 8d2a5b1ad..c5f74fac5 100644 --- a/doc/ikiwiki/directive/meta.mdwn +++ b/doc/ikiwiki/directive/meta.mdwn @@ -24,7 +24,7 @@ Supported fields: differently in this case. An optional `sort` parameter will be used preferentially when - [[ikiwiki/pagespec/sorting]] by `meta_title`: + [[ikiwiki/pagespec/sorting]] by `meta(title)`: \[[!meta title="The Beatles" sort="Beatles, The"]] @@ -44,6 +44,11 @@ Supported fields: Specifies the author of a page. + An optional `sort` parameter will be used preferentially when + [[ikiwiki/pagespec/sorting]] by `meta(author)`: + + \[[!meta author="Joey Hess" sort="Hess, Joey"]] + * authorurl Specifies an url for the author of a page. diff --git a/doc/ikiwiki/pagespec/sorting.mdwn b/doc/ikiwiki/pagespec/sorting.mdwn index ba995a521..fbf598340 100644 --- a/doc/ikiwiki/pagespec/sorting.mdwn +++ b/doc/ikiwiki/pagespec/sorting.mdwn @@ -11,9 +11,10 @@ orders can be specified. as such, ("1 2 9 10 20" instead of "1 10 2 20 9") """]] [[!if test="enabled(meta)" then=""" -* `meta_title` - Order according to the `\[[!meta title="foo" sort="bar"]]` +* `meta(title)` - Order according to the `\[[!meta title="foo" sort="bar"]]` or `\[[!meta title="foo"]]` [[ikiwiki/directive]], or the page name if no - full title was set. + full title was set. `meta(author)`, `meta(date)`, `meta(updated)`, etc. + also work. """]] In addition, you can combine several sort orders and/or reverse the order of -- cgit v1.2.3 From 490f95616a8a49f2120655d07c282eefd067e640 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Sat, 3 Apr 2010 14:19:18 +0100 Subject: Rename sort parameter to meta title/author to sortas=bar Joey pointed out that sort=x usually takes a sort order. --- IkiWiki/Plugin/meta.pm | 8 ++++---- doc/ikiwiki/directive/meta.mdwn | 10 +++++----- doc/ikiwiki/pagespec/sorting.mdwn | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'IkiWiki/Plugin/meta.pm') diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index c9fdbc934..4992617d0 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -89,8 +89,8 @@ sub preprocess (@) { # Metadata collection that needs to happen during the scan pass. if ($key eq 'title') { $pagestate{$page}{meta}{title}=HTML::Entities::encode_numeric($value); - if (exists $params{sort}) { - $pagestate{$page}{meta}{titlesort}=$params{sort}; + if (exists $params{sortas}) { + $pagestate{$page}{meta}{titlesort}=$params{sortas}; } else { $pagestate{$page}{meta}{titlesort}=$value; @@ -122,8 +122,8 @@ sub preprocess (@) { } elsif ($key eq 'author') { $pagestate{$page}{meta}{author}=$value; - if (exists $params{sort}) { - $pagestate{$page}{meta}{authorsort}=$params{sort}; + if (exists $params{sortas}) { + $pagestate{$page}{meta}{authorsort}=$params{sortas}; } else { $pagestate{$page}{meta}{authorsort}=$value; diff --git a/doc/ikiwiki/directive/meta.mdwn b/doc/ikiwiki/directive/meta.mdwn index c5f74fac5..5a3919dea 100644 --- a/doc/ikiwiki/directive/meta.mdwn +++ b/doc/ikiwiki/directive/meta.mdwn @@ -23,12 +23,12 @@ Supported fields: be set to a true value in the template; this can be used to format things differently in this case. - An optional `sort` parameter will be used preferentially when + An optional `sortas` parameter will be used preferentially when [[ikiwiki/pagespec/sorting]] by `meta(title)`: - \[[!meta title="The Beatles" sort="Beatles, The"]] + \[[!meta title="The Beatles" sortas="Beatles, The"]] - \[[!meta title="David Bowie" sort="Bowie, David"]] + \[[!meta title="David Bowie" sortas="Bowie, David"]] * license @@ -44,10 +44,10 @@ Supported fields: Specifies the author of a page. - An optional `sort` parameter will be used preferentially when + An optional `sortas` parameter will be used preferentially when [[ikiwiki/pagespec/sorting]] by `meta(author)`: - \[[!meta author="Joey Hess" sort="Hess, Joey"]] + \[[!meta author="Joey Hess" sortas="Hess, Joey"]] * authorurl diff --git a/doc/ikiwiki/pagespec/sorting.mdwn b/doc/ikiwiki/pagespec/sorting.mdwn index fbf598340..5c6cfcc2b 100644 --- a/doc/ikiwiki/pagespec/sorting.mdwn +++ b/doc/ikiwiki/pagespec/sorting.mdwn @@ -11,7 +11,7 @@ orders can be specified. as such, ("1 2 9 10 20" instead of "1 10 2 20 9") """]] [[!if test="enabled(meta)" then=""" -* `meta(title)` - Order according to the `\[[!meta title="foo" sort="bar"]]` +* `meta(title)` - Order according to the `\[[!meta title="foo" sortas="bar"]]` or `\[[!meta title="foo"]]` [[ikiwiki/directive]], or the page name if no full title was set. `meta(author)`, `meta(date)`, `meta(updated)`, etc. also work. -- cgit v1.2.3 From cb8b2f80b2f8c91eba3f3a6a5b9913ab80326df8 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 5 Apr 2010 22:50:51 +0100 Subject: Use $a and $b for SortSpec cmp callbacks --- IkiWiki.pm | 27 ++++++++++++++++++--------- IkiWiki/Plugin/meta.pm | 14 ++++++-------- IkiWiki/Plugin/sortnaturally.pm | 4 ++-- doc/plugins/write.mdwn | 20 ++++++++++---------- t/pagespec_match_list.t | 2 +- 5 files changed, 37 insertions(+), 30 deletions(-) (limited to 'IkiWiki/Plugin/meta.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index d716e8b39..da36494fb 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1975,10 +1975,10 @@ sub sortspec_translate ($) { if (exists $IkiWiki::SortSpec::{"cmp_$word"}) { if (defined $params) { push @data, $params; - $code .= "IkiWiki::SortSpec::cmp_$word(\@_, \$data[$#data])"; + $code .= "IkiWiki::SortSpec::cmp_$word(\$data[$#data])"; } else { - $code .= "IkiWiki::SortSpec::cmp_$word(\@_, undef)"; + $code .= "IkiWiki::SortSpec::cmp_$word(undef)"; } } else { @@ -2095,9 +2095,8 @@ sub pagespec_match_list ($$;@) { } if (defined $params{sort}) { - my $f = sortspec_translate($params{sort}); - - @candidates = sort { $f->($a, $b) } @candidates; + @candidates = IkiWiki::SortSpec::sort_pages($params{sort}, + @candidates); } @candidates=reverse(@candidates) if $params{reverse}; @@ -2412,13 +2411,23 @@ sub match_ip ($$;@) { package IkiWiki::SortSpec; +# This is in the SortSpec namespace so that the $a and $b that sort() uses +# $IkiWiki::SortSpec::a and $IkiWiki::SortSpec::b, so that plugins' cmp +# functions can access them easily. +sub sort_pages +{ + my $f = IkiWiki::sortspec_translate(shift); + + return sort $f @_; +} + sub cmp_title { - IkiWiki::pagetitle(IkiWiki::basename($_[0])) + IkiWiki::pagetitle(IkiWiki::basename($a)) cmp - IkiWiki::pagetitle(IkiWiki::basename($_[1])) + IkiWiki::pagetitle(IkiWiki::basename($b)) } -sub cmp_mtime { $IkiWiki::pagemtime{$_[1]} <=> $IkiWiki::pagemtime{$_[0]} } -sub cmp_age { $IkiWiki::pagectime{$_[1]} <=> $IkiWiki::pagectime{$_[0]} } +sub cmp_mtime { $IkiWiki::pagemtime{$b} <=> $IkiWiki::pagemtime{$a} } +sub cmp_age { $IkiWiki::pagectime{$b} <=> $IkiWiki::pagectime{$a} } 1 diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index 4992617d0..553f93455 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -374,25 +374,23 @@ sub match_copyright ($$;@) { package IkiWiki::SortSpec; sub cmp_meta { - my $left = $_[0]; - my $right = $_[1]; - my $meta = $_[2]; + my $meta = $_[0]; error(gettext("sort=meta requires a parameter")) unless defined $meta; if ($meta eq 'updated' || $meta eq 'date') { - return IkiWiki::Plugin::meta::get_sort_key($left, $meta) + return IkiWiki::Plugin::meta::get_sort_key($a, $meta) <=> - IkiWiki::Plugin::meta::get_sort_key($right, $meta); + IkiWiki::Plugin::meta::get_sort_key($b, $meta); } - return IkiWiki::Plugin::meta::get_sort_key($left, $meta) + return IkiWiki::Plugin::meta::get_sort_key($a, $meta) cmp - IkiWiki::Plugin::meta::get_sort_key($right, $meta); + IkiWiki::Plugin::meta::get_sort_key($b, $meta); } # A prototype of how sort=title could behave in 4.0 or something sub cmp_meta_title { - $_[2] = 'title'; + $_[0] = 'title'; return cmp_meta(@_); } diff --git a/IkiWiki/Plugin/sortnaturally.pm b/IkiWiki/Plugin/sortnaturally.pm index f498820a5..92453749d 100644 --- a/IkiWiki/Plugin/sortnaturally.pm +++ b/IkiWiki/Plugin/sortnaturally.pm @@ -25,8 +25,8 @@ sub checkconfig () { package IkiWiki::SortSpec; sub cmp_title_natural { - Sort::Naturally::ncmp(IkiWiki::pagetitle(IkiWiki::basename($_[0])), - IkiWiki::pagetitle(IkiWiki::basename($_[1]))) + Sort::Naturally::ncmp(IkiWiki::pagetitle(IkiWiki::basename($a)), + IkiWiki::pagetitle(IkiWiki::basename($b))) } 1; diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index b67142230..f42cc86ae 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -1117,16 +1117,16 @@ Similarly, it's possible to write plugins that add new functions as the IkiWiki::SortSpec package named `cmp_foo`, which will be used when sorting by `foo` or `foo(...)` is requested. -The function will be passed three or more parameters. The first two are -page names, and the third is `undef` if invoked as `foo`, or the parameter -`"bar"` if invoked as `foo(bar)`. It may also be passed additional, named -parameters. - -It should return the same thing as Perl's `cmp` and `<=>` operators: negative -if the first argument is less than the second, positive if the first argument -is greater, or zero if they are considered equal. It may also raise an -error using `error`, for instance if it needs a parameter but one isn't -provided. +The names of pages to be compared are in the global variables `$a` and `$b` +in the IkiWiki::SortSpec package. The function should return the same thing +as Perl's `cmp` and `<=>` operators: negative if `$a` is less than `$b`, +positive if `$a` is greater, or zero if they are considered equal. It may +also raise an error using `error`, for instance if it needs a parameter but +one isn't provided. + +The function will also be passed one or more parameters. The first is +`undef` if invoked as `foo`, or the parameter `"bar"` if invoked as `foo(bar)`; +it may also be passed additional, named parameters. ### Setup plugins diff --git a/t/pagespec_match_list.t b/t/pagespec_match_list.t index 68112f5c0..2ad7a9105 100755 --- a/t/pagespec_match_list.t +++ b/t/pagespec_match_list.t @@ -12,7 +12,7 @@ IkiWiki::checkconfig(); { package IkiWiki::SortSpec; - sub cmp_path { $_[0] cmp $_[1] } + sub cmp_path { $a cmp $b } } %pagesources=( -- cgit v1.2.3 From be1d97c0bd495fe876853d7d7f6eb42041867649 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 6 Apr 2010 00:58:55 +0100 Subject: Only store titlesort in meta pagestate if it differs from title --- IkiWiki/Plugin/meta.pm | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'IkiWiki/Plugin/meta.pm') diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index 553f93455..7f19b46a3 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -88,13 +88,18 @@ sub preprocess (@) { # Metadata collection that needs to happen during the scan pass. if ($key eq 'title') { - $pagestate{$page}{meta}{title}=HTML::Entities::encode_numeric($value); + my $encoded = HTML::Entities::encode_numeric($value); + $pagestate{$page}{meta}{title} = $encoded; + if (exists $params{sortas}) { $pagestate{$page}{meta}{titlesort}=$params{sortas}; } - else { + elsif ($encoded ne $value) { $pagestate{$page}{meta}{titlesort}=$value; } + else { + delete $pagestate{$page}{meta}{titlesort}; + } return ""; } elsif ($key eq 'description') { -- cgit v1.2.3 From a2dc8c9373b36f7cc8da239b823b5839788a743d Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 6 Apr 2010 00:59:16 +0100 Subject: Only store authorsort in meta pagestate if it differs from author --- IkiWiki/Plugin/meta.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'IkiWiki/Plugin/meta.pm') diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index 7f19b46a3..34e902bec 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -131,7 +131,7 @@ sub preprocess (@) { $pagestate{$page}{meta}{authorsort}=$params{sortas}; } else { - $pagestate{$page}{meta}{authorsort}=$value; + delete $pagestate{$page}{meta}{authorsort}; } # fallthorough } -- cgit v1.2.3 From 5408279b5ffd7038bb0c279d1379c7e0d21d0a96 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 6 Apr 2010 01:31:38 +0100 Subject: HTML-encode meta title, description, guid on output, but not in the pagestate This makes them consistent with the rest of the meta keys. A wiki rebuild will be needed on upgrade to this version; until the wiki is rebuilt, double-escaping will occur in the titles of pages that have not changed. --- IkiWiki/Plugin/comments.pm | 4 ++-- IkiWiki/Plugin/inline.pm | 3 ++- IkiWiki/Plugin/meta.pm | 15 ++++++++++----- 3 files changed, 14 insertions(+), 8 deletions(-) (limited to 'IkiWiki/Plugin/meta.pm') diff --git a/IkiWiki/Plugin/comments.pm b/IkiWiki/Plugin/comments.pm index 460341710..0aa043215 100644 --- a/IkiWiki/Plugin/comments.pm +++ b/IkiWiki/Plugin/comments.pm @@ -221,9 +221,9 @@ sub preprocess { } if (defined $params{subject}) { - # encode title the same way meta does + # decode title the same way meta does eval q{use HTML::Entities}; - $pagestate{$page}{meta}{title} = HTML::Entities::encode_numeric(decode_entities($params{subject})); + $pagestate{$page}{meta}{title} = decode_entities($params{subject}); } if ($params{page} =~ m/\/\Q$config{comments_pagename}\E\d+_/) { diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm index 44919e58c..644cb588d 100644 --- a/IkiWiki/Plugin/inline.pm +++ b/IkiWiki/Plugin/inline.pm @@ -553,7 +553,8 @@ sub genfeed ($$$$$@) { if (exists $pagestate{$p}) { if (exists $pagestate{$p}{meta}{guid}) { - $itemtemplate->param(guid => $pagestate{$p}{meta}{guid}); + eval q{use HTML::Entities}; + $itemtemplate->param(guid => HTML::Entities::encode_numeric($pagestate{$p}{meta}{guid})); } if (exists $pagestate{$p}{meta}{updated}) { diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index 5f046cb2a..9906c3f57 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -88,15 +88,15 @@ sub preprocess (@) { # Metadata collection that needs to happen during the scan pass. if ($key eq 'title') { - $pagestate{$page}{meta}{title}=HTML::Entities::encode_numeric($value); + $pagestate{$page}{meta}{title}=$value; return ""; } elsif ($key eq 'description') { - $pagestate{$page}{meta}{description}=HTML::Entities::encode_numeric($value); + $pagestate{$page}{meta}{description}=$value; # fallthrough } elsif ($key eq 'guid') { - $pagestate{$page}{meta}{guid}=HTML::Entities::encode_numeric($value); + $pagestate{$page}{meta}{guid}=$value; # fallthrough } elsif ($key eq 'license') { @@ -264,15 +264,20 @@ sub pagetemplate (@) { $template->param(meta => join("\n", grep { (! $seen{$_}) && ($seen{$_}=1) } @{$metaheaders{$page}})); } if (exists $pagestate{$page}{meta}{title} && $template->query(name => "title")) { - $template->param(title => $pagestate{$page}{meta}{title}); + $template->param(title => HTML::Entities::encode_numeric($pagestate{$page}{meta}{title})); $template->param(title_overridden => 1); } - foreach my $field (qw{author authorurl description permalink}) { + foreach my $field (qw{author authorurl permalink}) { $template->param($field => $pagestate{$page}{meta}{$field}) if exists $pagestate{$page}{meta}{$field} && $template->query(name => $field); } + foreach my $field (qw{description}) { + $template->param($field => HTML::Entities::encode_numeric($pagestate{$page}{meta}{$field})) + if exists $pagestate{$page}{meta}{$field} && $template->query(name => $field); + } + foreach my $field (qw{license copyright}) { if (exists $pagestate{$page}{meta}{$field} && $template->query(name => $field) && ($page eq $destpage || ! exists $pagestate{$destpage}{meta}{$field} || -- cgit v1.2.3 From 153c0ff13ba01fa42b3e34b410311c490ee084e9 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 6 Apr 2010 23:29:18 -0400 Subject: minor style etc changes --- IkiWiki.pm | 6 ++---- IkiWiki/Plugin/meta.pm | 6 +++--- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'IkiWiki/Plugin/meta.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 6d2f4dac3..2cad6a3ef 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -2435,10 +2435,8 @@ sub match_ip ($$;@) { package IkiWiki::SortSpec; # This is in the SortSpec namespace so that the $a and $b that sort() uses -# $IkiWiki::SortSpec::a and $IkiWiki::SortSpec::b, so that plugins' cmp -# functions can access them easily. -sub sort_pages -{ +# are easily available in this namespace, for cmp functions to use them. +sub sort_pages { my $f = IkiWiki::sortspec_translate(shift); return sort $f @_; diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index 34e902bec..892f6b2c9 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -300,8 +300,8 @@ sub pagetemplate (@) { } sub get_sort_key { - my $page = $_[0]; - my $meta = $_[1]; + my $page = shift; + my $meta = shift; # e.g. titlesort (also makes sense for author) my $key = $pagestate{$page}{meta}{$meta . "sort"}; @@ -379,7 +379,7 @@ sub match_copyright ($$;@) { package IkiWiki::SortSpec; sub cmp_meta { - my $meta = $_[0]; + my $meta = shift; error(gettext("sort=meta requires a parameter")) unless defined $meta; if ($meta eq 'updated' || $meta eq 'date') { -- cgit v1.2.3 From bc6d6026093ae6f2bfd72a2c06887358a0e59b6b Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 22 Apr 2010 00:10:13 -0400 Subject: add influence info for failed metadata matches This is needed so that when a negated pagespec like "!author(foo)" stops matching, due to the page being changed, ikiwiki knows that the match was influenced by the page content. --- IkiWiki/Plugin/meta.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'IkiWiki/Plugin/meta.pm') diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index 128a6342c..159008614 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -346,11 +346,11 @@ sub match { return IkiWiki::SuccessReason->new("$re matches $field of $page", $page => $IkiWiki::DEPEND_CONTENT, "" => 1); } else { - return IkiWiki::FailReason->new("$re does not match $field of $page", "" => 1); + return IkiWiki::FailReason->new("$re does not match $field of $page", $page => $IkiWiki::DEPEND_CONTENT, "" => 1); } } else { - return IkiWiki::FailReason->new("$page does not have a $field", "" => 1); + return IkiWiki::FailReason->new("$page does not have a $field", $page => $IkiWiki::DEPEND_CONTENT); } } -- cgit v1.2.3 From 7f3047f67c1bb45e25b91362f9ae4bb18734e140 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 26 Apr 2010 13:47:01 -0400 Subject: added match_guid function to meta plugin (cherry picked from commit 8b6fde73669ddf9204acb3d334c3984566f3c59d) Conflicts: IkiWiki/Plugin/meta.pm --- IkiWiki/Plugin/meta.pm | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'IkiWiki/Plugin/meta.pm') diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index 159008614..7d68a9b2d 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -376,6 +376,10 @@ sub match_copyright ($$;@) { IkiWiki::Plugin::meta::match("copyright", @_); } +sub match_guid ($$;@) { + IkiWiki::Plugin::meta::match("guid", @_); +} + package IkiWiki::SortSpec; sub cmp_meta { -- cgit v1.2.3