#!/usr/bin/env perl # $Id$ # Public domain. Originally written by Andreas Scherer, 2023. use strict; use warnings; use File::Basename; use Getopt::Long qw(:config no_ignore_case bundling); use Pod::Usage; my $progname = basename $0; BEGIN { # Unicode::Collate has been around a long time, # but it's not part of core Perl. my $rc = eval { require Unicode::Collate; }; die "$progname: the Unicode::Collate module is required\n" unless $rc; } # We expect a TeX file as the single command-line parameter. my $usage = "Usage: $progname input_file\n"; if (@ARGV > 1) { my $first = shift @ARGV; $usage .= "extra file argument(s): @ARGV\n"; unshift @ARGV, $first; } $usage .= "try --help if you need it.\n"; die $usage unless scalar @ARGV == 1; Getopt::Long::GetOptions( 'help|?' => \&help_handler, 'version' => sub { print version(); exit 0; } ) or die $usage; ## help_handler() sub help_handler { open(my $pipe, '|-', $ENV{PAGER} || 'less -e') or exit 1; pod2usage(-message => version(), -output => $pipe, -verbose => 99, -sections => "SHORT DESCRIPTION|EXAMPLE|COPYRIGHT"); close $pipe; exit 0; } ## version() sub version { return $progname.' $Revision$ $Date$'."\n"; } my $tex = $ARGV[0]; open(TEX, $tex) or die "$0: Could not open input file $tex.\n"; my %mini_index; # storage for index entries of a section my $print_index = 0; # do we collect and print a mini-index? my $collator = Unicode::Collate->new(); # Scroll through the input file and look for blocks like # \mini # [LOCATION KEY TEXPART]* # }\FI # and sort them alphabetically by the KEYs. # # Every KEY contains a single C identifier (variable, type, function, etc.), # either as a single brace-enclosed argument of a TeX control sequence, # or as a single identifier in $math_mode$; the latter come from '@f'ormat # definitions. All internal backslashes are removed from the KEY before it # is used in the storage. foreach my $line () { if ("\\mini\n" eq $line) { # start of mini-index $print_index = 1; %mini_index = (); # reset mini-index storage } elsif ("}\\FI\n" eq $line) { # end of mini-index foreach my $key ($collator->sort(keys %mini_index)) { print $mini_index{$key}; } $print_index = 0; } elsif ($print_index) { # mini-index entry my (undef,$key) = split / /, $line; # 2nd column is the key $key =~ s/\\//g; # strip internal TeX escape(s) $key =~ m/\w*\{(\w+)\}/; # extract plain key from control seq. $key =~ m/\$(\w+)\$/ unless defined $1; # extract @f TeX key $mini_index{$1} = $line; # store index entry next; # print later } print $line; } close(TEX); exit 0; =pod =encoding utf8 =head1 NAME ctwill-proofsort - Sort mini-indexes alphabetically =head1 SHORT DESCRIPTION This small Perl script 'ctwill-proofsort' sorts the mini-indexes for each section in the TeX file created by 'ctwill +P', i.e., prior to formatting with the 'ctproofmac.tex' macros. =over =item Run CTWILL twice on your 'input_file'.w, creating 'input_file'.tex =item Invoke "ctwill-proofsort 'input_file'.tex > 'input_file'-sorted.tex" =item Invoke "mv 'input_file'-sorted.tex 'input_file'.tex" =item Run TeX on 'input_file'.tex =back See also "man ctwill" for more information on how to use the CTWILL system, both with or without the '+P' option. =head1 EXAMPLE Example from MMIX (https://github.com/ascherer/mmix, 'local' branch): =over =item $ tie -c mmotype-twill.ch mmotype.{w,ch} mmotype-mini.ch =item $ ctwill +P -x mmotype mmotype-twill (run this two times) =item $ ctwill-proofsort mmotype.tex > mmotype-sorted.tex =item $ mv mmotype-sorted.tex mmotype.tex =item $ tex mmotype =back =head1 COPYRIGHT Public domain. Originally written by Andreas Scherer, 2023. Contemporary development on https://github.com/ascherer/cwebbin. =cut