[pmwiki-users] Custom order= options for pagelists

Patrick R. Michaud pmichaud at pobox.com
Tue Oct 17 00:52:34 CDT 2006


On Mon, Oct 16, 2006 at 10:04:53PM -0400, Crisses wrote:
> 
> On Oct 16, 2006, at 7:26 PM, Patrick R. Michaud wrote:
> 
> >    order=yearauthorwork
> >
> >and have a custom function do whatever sort you wish, including
> >grabbing page text variables from other related pages (where the
> >function defines the relation).

First, we have to tell PmWiki which function to call in response
to the custom order= parameter.  Since the original query in this
thread was for $:Year, $:Work, and $:WAuthor to come from
corresponding Data- pages, I'll use 'yearworkwauthor' as the 
order parameter for my example.

The array that maps order= parameters to custom comparison code
to be called to perform comparisons is $PageListSortCmp:

    $PageListSortCmp['yearworkwauthor'] = 'YearWorkWAuthor($x, $y)';

This says that to perform a comparison between two pages in the
pagelist (given by $x and $y), call the function YearWorkAuthor()
and pass those pagenames as arguments.  The YearWorkAuthor()
function should return a value that is less than zero if $x 
should be before $y in the list, greater than zero if $x should
come after $y, and zero if they're "equivalent" for the purposes 
of this comparison.

Of course, in this scenario, the pages given by $x and $y
don't contain the values we want to sort by -- those values
are in the corresponding Data-* pages for $x and $y.  Thus,
we figure out the names of the "Data-" pages, and then
test the page text variables from those pages:

    function YearWorkWAuthor($x, $y) {
      ## first, get the Data- versions of the pagenames
      $datax = 'Data-' . PageVar($x, '$BaseName');
      $datay = 'Data-' . PageVar($y, '$BaseName');

      ## compare the $:Year values 
      $c = strcmp(PageVar($datax, '$:Year'), PageVar($datay, '$:Year'));
      if ($c != 0) return $c;

      ## compare the $:Work values 
      $c = strcmp(PageVar($datax, '$:Work'), PageVar($datay, '$:Work'));
      if ($c != 0) return $c;

      ## compare the $:WAuthor values
      $c = strcmp(PageVar($datax, '$:WAuthor'), PageVar($datay, '$:WAuthor'));
      return $c;
    }

So, the first two lines figure out the names of the Data-* pages
corresponding to $x and $y, and store them in $datax and $datay.
The next two lines grab the $:Year page text variables for
$datax and $datay, and return a negative or positive value
if they're different.  If they're the same (i.e., $c == 0), we 
fall through to test the $:Work page text variables, by
similar logic, and if those are also the same we test the $:WAuthor
page text variables and return that.

As written there's a slight bit of overhead in the repeated calls
to PageVar() that we can avoid if speed becomes an issue, but the
above code illustrates the basic concept behind the custom sort.

Another approach would be to create a generic DataCompare() function
for comparing page text variables in Data-* pages, and then define 
separate "year", "work", and "wauthor" options for the order= 
parameter that pass an appropriate argument to DataCompare():

    function DataCompare($x, $y, $var) {
      ## get the Data- versions of the pagenames
      $datax = 'Data-' . PageVar($x, '$BaseName');
      $datay = 'Data-' . PageVar($y, '$BaseName');

      ## perform the requested comparison
      $c = strcmp(PageVar($datax, $var), PageVar($datay, $var));
      return $c;
    }

    $PageListSortCmp['year'] = 'DataCompare($x, $y, "$:Year")';
    $PageListSortCmp['work'] = 'DataCompare($x, $y, "$:Work")';
    $PageListSortCmp['wauthor'] = 'DataCompare($x, $y, "$:WAuthor")';

Then one can do any of

    order=year           # sort by $:Year from the Data- pages
    order=year,work      # sort by $:Year, then $:Work
    order=year,-wauthor  # sort by $:Year, reverse by $:WAuthor
    order=wauthor        # sort by $:WAuthor only

Does that work?

Pm




More information about the pmwiki-users mailing list