1 my %is_boolean_opt = map { $_ => 1 } qw(
9 my %is_value_opt = map { $_ => 1 } qw(
13 my %is_key = map { $_ => 1 } qw(
22 plain => \&make_plain_sort,
24 GRT => \&make_GRT_sort,
35 $sources{ +shift } || $error_source ;
43 my( $options, $keys ) = process_options( @ARGV ) ;
45 print Dumper $options, $keys ;
47 die "no keys specified" unless @{$keys} ;
49 my $sort_maker = $sort_makers{ $options->{style} } ;
51 die "no sort style selected" unless $sort_maker ;
53 my $source = $sort_maker( $keys ) ;
55 my $sorter = eval $source ;
57 die "bad source $@" if $@ ;
59 $sources{ $sorter } = $source ;
61 if ( my $name = $options->{name} ) {
65 my $package = (caller())[0] ;
67 *${"${package}::$name"} = $sorter ;
75 my( %options, @keys ) ;
81 if ( $sort_makers{ $opt } ) {
84 die "no options after keys"
87 if ( $options{ style } ) {
90 "style was already set to $options{ style }" ;
93 $options{ style } = $opt ;
97 if ( $is_boolean_opt{ $opt } ) {
100 die "no options after keys"
103 $options{ $opt } = 1 ;
107 if ( $is_value_opt{ $opt } ) {
110 die "no value options after keys"
115 die "no value for option $opt"
118 $options{ $opt } = shift ;
122 if ( my( $order, $key, $case ) =
123 $opt =~ /^([+-])?([a-z]+)(_\w+)?$/ ) {
125 unless( $is_key{ $key } ) {
127 die "unknown option '$opt'" ;
130 my $descend = ( $order || '' eq '+' ) ? 0 :
131 $options{ 'descending' } ;
133 my $nocase = $opt =~ s/_nocase$// ||
136 $opt = 'numeric' if $opt eq 'integer' &&
141 unless ( defined( $code ) ||
142 ( $code =~ /^([+-])?(\w+)$/ && $is_key{ $2 } ) ) {
161 die "unknown option or key '$opt'" ;
164 return( \%options, \@keys ) ;
172 my( @st_compares, @st_extracts ) ;
175 foreach my $key ( @keys ) {
177 my $st_compare = <<'CMP' ;
181 $st_compare =~ tr/ab/ba/ if $key->{descending} ;
182 $st_compare =~ s/cmp/<=>/ if $key->{numeric} ;
183 $st_compare =~ s/1/$st_ind/g ;
187 push( @st_compares, $st_compare ) ;
189 my $st_extract = <<EXT
190 uc do{ $key->{code} }
193 $st_extract =~ s/uc// if $key->{no_case} ;
195 push( @st_extracts, $st_extract ) ;
198 my $compare_source = join "||\n", @st_compares ;
200 my $extract_source = join ",\n", @st_extracts ;
218 my( @plain_compares )
220 foreach my $key ( @keys ) {
222 my $plain_compare = <<'CMP' ;
223 do{ my( \$left, \$right ) = map { $key->{code} } \$a, \$b;
227 $plain_compare =~ s/\$a, \$b/\$b, \$a/ if $key->{descending} ;
228 $plain_compare =~ s/cmp/<=>/ if $key->{numeric} ;
229 $plain_compare =~ s/=/= map uc,/ if $key->{no_case} ;
231 push( @st_compares, $st_compare ) ;
233 push( @st_extracts, $st_extract ) ;
236 my $compare_source = join "||\n", @st_compares ;
240 sort { sort { $compare_source } @_ ;
248 my( @st_compares, @st_extracts ) ;
251 foreach my $key ( @keys ) {
253 push( @st_compares, $st_compare ) ;
255 my $st_extract = <<EXT
256 uc do{ $key->{code} }
259 $st_extract =~ s/uc// if $key->{no_case} ;
261 push( @st_extracts, $st_extract ) ;
264 my $extract_source = join ",\n", @st_extracts ;