Almost-minimal filesystem based blog.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

85 lines
1.6 KiB

package App::WRT::Sort;
use strict;
use warnings;
use 5.10.0;
use Carp;
use base qw(Exporter);
our @EXPORT_OK = qw(sort_entries);
=pod
=head1 NAME
App::WRT::Sort - functions for sorting wrt entry lists
=head1 SYNOPSIS
use App::WRT::Sort qw(sort_entries);
my (@sorted) = sort_entries(@unsorted);
=head1 DESCRIPTION
This makes an effort to sort a list of entries, which may include both simple
dates and names, or a combination thereof, reasonably.
The main goal is to have dates sorted in order, followed by alphanumeric names.
=head1 FUNCTIONS
=over
=item sort_entries(@entries)
Sort a list of entries by converting them to an array with an easily sortable
string format as the second value, sorting these arrayrefs by that value, and
then re-mapping them to the original values.
See here: L<https://en.wikipedia.org/wiki/Schwartzian_transform>
=cut
sub sort_entries {
my (@entries) = @_;
return map { $_->[0] }
sort { $a->[1] cmp $b->[1] }
map { [$_, sortable_from_entry($_)] }
@entries;
}
=item sortable_from_entry($entry)
Get a sortable string value that does (more or less) what we want.
In this case, it pads numeric components of the path out to 5 leading 0s and
leaves everything else alone.
=cut
sub sortable_from_entry {
my ($entry) = @_;
my @parts = map {
my $padded;
if (m/^\d+$/) {
# There's a year 100k bug here, but I guess I'll cross that bridge when I
# come to it:
$padded = sprintf("%05d", $_);
} else {
$padded = $_;
}
$padded;
} split '/', $entry;
return join '', @parts;
}
=back
=cut
1;