#! /usr/bin/env perl ################################################ # Generate a README file for the Comprehensive # # LaTeX Symbol List. # # # # Author: Scott Pakin # ################################################ use POSIX; use warnings; use strict; ########################################################################### # Center a string within a given field length. sub center_string ($$) { my ($string, $fieldlen) = @_; my $prespaces = int (($fieldlen - length($string)) / 2); my $postspaces = $fieldlen - length($string) - $prespaces; return (" " x $prespaces) . $string . (" " x $postspaces); } # Format a list to a given number of columns. sub format_list ($$@) { my ($numcols, $textwidth, @list) = @_; my $itemwidth = int (($textwidth-4) / $numcols); my $col = 0; foreach my $item (@list) { print " " if $col%$numcols==0; printf "%-${itemwidth}.${itemwidth}s", $item; print "\n" if ++$col%$numcols==0; } print "\n"; } # Return the human-readable name of a PostScript font file. sub find_pfb_name ($) { my $pfb = $_[0]; my $pfbfile = `kpsewhich $pfb`; die "${0}: Failed to locate $pfb\n" if !defined $pfbfile; chomp $pfbfile; local $/ = undef; open (PFBFILE, "<$pfbfile") || die "open(\"$pfbfile\"): $!\n"; my $entirefile = ; close PFBFILE or die "close(\"$pfbfile\"): $!\n"; my $fullname; if ($entirefile =~ /FullName\s*\(([^\)]*)\)/) { # Best choice: FullName $fullname = $1; $fullname =~ s/\\(\d\d\d)/chr(oct($1))/ge; $fullname =~ s/^\s+//; $fullname =~ s/\s+$//; } elsif ($entirefile =~ m,FontName\s*/(\S+),) { # Tolerable: FontName $fullname = $1; } else { die "${pfbfile}: FullName not found\n"; } return $fullname; } # Return the human-readable name of a TrueType font file. sub find_ttf_name ($) { my $ttf = $_[0]; my $ttffile = `kpsewhich $ttf`; die "${0}: Failed to locate $ttf\n" if !defined $ttffile; chomp $ttffile; my %key_value; local $/ = "\n"; open(TTFFILE, "otfinfo --info $ttffile|") || die "open(\"$ttffile\"): $!\n"; while (my $ln = ) { chomp $ln; next if $ln !~ /^([^:]+):\s*(.*)$/; $key_value{$1} = $2; } close TTFFILE or die "close(\"$ttffile\"): $!\n"; foreach my $key ("Full name", "Preferred family", "Family", "PostScript name") { my $val = $key_value{$key}; return $val if $val ne ""; } die "${ttffile}: Font information not found\n"; } # Output all PostScript and TrueType font files and their associated, # human-readable font name. sub format_scalable_list ($\@) { my $itemwidth = $_[0]; foreach my $fname (@{$_[1]}) { my $fullname; if ($fname =~ /\.pfb$/) { $fullname = find_pfb_name $fname; } elsif ($fname =~ /\.ttf$/) { $fullname = find_ttf_name $fname; } else { die "${0}: Unrecognized file type for $fname\n"; } printf " %-${itemwidth}.${itemwidth}s (%s)\n", $fname, $fullname; } } # Sort a list and discard duplicates. sub sort_unique (@) { my %uniq; foreach my $e (@_) { $uniq{$e} = 1; } return sort keys %uniq; } ########################################################################### # Check the command-line arguments. die "Usage: $0 <.log file> <.ind file>\n" if $#ARGV<1; my ($logfilename, $indfilename) = @ARGV; # Get the symbol count from the index file. my $numsymbols = 0; open (INDFILE, "<$indfilename") || die "open(): $!\nStopped"; while () { /\\item \\(sp)?verb/ && $numsymbols++; } close INDFILE; my $roundnumsymbols = int($numsymbols/100) * 100; # Read an entire pdflatex log file. open (LOGFILE, "<$logfilename") || die "open(): $!\nStopped"; undef $/; my $logfile = ; $logfile =~ s/\n//g; close LOGFILE; # Get a list of .mf files (indirectly via corresponding .pk files), .pfb, # and .ttf files referenced by the log file. my @mffiles = sort_unique map {"$_.mf"} ($logfile =~ m!<(?:[^>]+/)?([^/<>.]+)\.\d+pk>!g); my @scalable_files = sort_unique ($logfile =~ m!<(?:[^>]+/)?([^/<>.]+\.(?:pfb|ttf))>!g); # Tally the number of unique typefaces in @mffiles and @scalable_files. my %allfonts; foreach (@mffiles, @scalable_files) { my $fname = $_; $fname =~ s/\.(ttf|pfb|mf)$//; $fname =~ s/\d+$//; $allfonts{$fname} = 1; } my $numtypefaces = keys %allfonts; # Write the README header. my $date = strftime "%d %B %Y", localtime; $date =~ s/\b0+/ /g; my $headerwidth = 40; my $linewidth = 75; my $centerspace = " " x int(($linewidth-$headerwidth)/2); printf "%s+-%s-+\n", $centerspace, ("-" x ($headerwidth-4)); printf "%s| %s |\n", $centerspace, center_string("THE COMPREHENSIVE LATEX SYMBOL LIST", $headerwidth-4); printf "%s| %s |\n", $centerspace, center_string("By Scott Pakin, scott+clsl\@pakin.org", $headerwidth-4); printf "%s| %s |\n", $centerspace, center_string("", $headerwidth-4); printf "%s| %s |\n", $centerspace, center_string($date, $headerwidth-4); printf "%s+-%s-+\n", $centerspace, ("-" x ($headerwidth-4)); # Output some text. print <<"EOF1"; The Comprehensive LaTeX Symbol List is an organized list of over $roundnumsymbols symbols commonly available to LaTeX users. Some of these symbols are guaranteed to be available in every TeX distribution. Others require font files that come with some, but not all, TeX distributions. The rest require font files that must be downloaded explicitly from CTAN (http://www.ctan.org/) and installed. The Comprehensive LaTeX Symbol List currently showcases symbols from $numtypefaces separate typefaces. The same directory that contains this README file also contains SYMLIST (an ASCII list of symbols that appear in the symbols list) and prebuilt versions of the symbol list for both A4 and U.S. Letter sized paper. If you'd like to build symbols.tex yourself (not recommended for normal use), a Makefile is provided. symbols.tex tries to be smart about fonts; it omits tables of symbols that require (seemingly) unavailable fonts. The "Document Characteristics" table at the end of the document lists the packages that were unavailable during the build. The prebuilt versions of the symbol list use primarily Type 1 fonts. Type 1 fonts are scalable and should look good at any resolution and on any output device. However, some of the fonts used by symbols.tex are available only in a METAFONT-generated bitmap format. The prebuilt symbol lists utilize 1200 DPI versions of all of the bitmapped fonts as 1200 DPI is a reasonably high printer resolution and therefore should obscure the artifacts of bitmap rendering. The following bitmapped fonts were used to typeset the symbol list: EOF1 format_list (3, $linewidth, @mffiles); print <<"EOF2"; For completeness, the following scalable fonts (some converted from OpenType to PostScript Type 1) were used to typeset the symbol list: EOF2 format_scalable_list (22, @scalable_files);