#!/usr/bin/perl -w # texdef # History: tired of typing "\newcommand{\foo}{bar}" instead of just "foo bar" # and I wanted a method to automatically a symbol table for my book. # # Usage: # texdef # -tab table.tex # output for symbol table # files[s] # input files # > deffile.tex # stdout with definitions # # Each line of the form FIRST{tab[s]}REST in def.raw is replaced # in the output file with \newcommand{\FIRST}{REST}. # If the subsuquent line is nonempty and does not have a {tab}\ in it, # then that line is treated as a symbol table entry. # # If the definition is "!" then just add it to glossary. (I forget why.) # Other exceptions based on first letter: # * use \renewcommand instead # + use \providecommand instead # # comments are ignored # % comments copied to output # # Copyright 2002-9-11, Jeff Fessler, The University of Michigan $files[0] = ""; #"def.raw"; $nfiles = 0; $filetab = ""; #"def,tab.tex"; while ($#ARGV >= 0) { if (($ARGV[0] eq "-tab") & ($#ARGV > 0)) { $filetab = $ARGV[1]; shift(@ARGV); } else { $files[$nfiles] = $ARGV[0]; $nfiles += 1; } shift(@ARGV); } die "no files?" if ($nfiles == 0); # # open each file and process it # $ntab = 0; # how many entries in symbol table $table_key[0] = ""; # start with empty table of keys $table_exp[0] = ""; # start with empty table of explanations $keepblank = 1; $ii = 0; while ($ii < $nfiles) { $file = $files[$ii]; $ii += 1; open(File, $file) || die "cannot open `$file' error: $!"; print "% from $file\n\n"; $lastkey = ""; $lastarg = ""; while () { next if /^#/; # skip '#' comments if (/^%/) { # echo '%' comments print; next; } if (/^\s*$/) { # replicate blank lines if ($keepblank) { print "\n"; } else { # unless right after an explanation line $keepblank = 1; } next; } chop; s/([^\\])%.*$/$1/; # strip tailing comments # parse 'key TAB rest' with tab(s) separator undef(@rest); ($key, @rest) = split(/\t+/); # split on one-or-more tabs # # if no tab, then it is a symbol explanation line! # if (!defined(@rest)) { # die "bad line `$_'" unless defined(@rest); die "bad line `$_'" unless ($lastkey ne "98765431"); $table_key[$ntab] = $lastkey; $table_arg[$ntab] = $lastarg; $table_exp[$ntab] = $_; $ntab += 1; $lastkey = "98765431"; $lastarg = ""; $keepblank = 0; next; } die "typo: `$_' should not start with /\n" if /^\\/; $_ = "@rest"; # rejoin in case more tabs in "rest" # next if ($_ eq "!"); # ignore (just for glossary) die "'!' not implemented" if ($_ eq "!"); # # first letter is "*" means use renewcommand # first letter is "+" means use providecommand # otherwise ordinary newcommand # if ($key =~ /^\*/) { ($key) = $key =~ /\*(.*)/; $command = "\\renewcommand"; } elsif ($key =~ /^\+/) { ($key) = $key =~ /\+(.*)/; $command = "\\providecommand"; } else { $command = "\\newcommand"; # default } # # deal with optional arguments # $arg = ""; if ($key =~ /\[/) { $arg = "TODO?"; # bug alert ($key, $arg) = $key =~ /(\w+)(.*)/; print "$command" . "{\\$key}$arg\t{$_}\n"; } else { print "$command" . "{\\$key}\t{$_}\n"; } $lastkey = $key; $lastarg = $arg; } close(File); } # # print explanations to glossary file, if any. # for the commands that go in the glossary # exit if ($filetab eq ""); # done if no table file open(Tab, "> $filetab") || die "cannot write `$filetab' error: $!"; $ii = 0; while ($ii < $nfiles) { print Tab "% from $files[$ii]\n\n"; $ii += 1; } # # header for symbol table # #print Tab "\\providecommand{\\defitem}[3]{\\ty{#1} & #2 & #3\\\\}\n"; print Tab "\\providecommand{\\defitem}[3]{\\makebox[10em][l]{\\ty{#1}} " . " \\makebox[20em][l]{#2} #3\\\\}\n"; print Tab "\\providecommand{\\defstart}{\n"; #print Tab "\t\\begin{tabular}{l|l|l}\n"; print Tab "\t\\defitem{Macro}{Symbol}{Meaning}\n"; print Tab "}\n"; #print Tab "\\providecommand{\\defstop}{\\end{tabular}}\n"; print Tab "\\providecommand{\\defstop}{}\n"; print Tab "\n\\defstart\n"; $ii = 0; while ($ii < $ntab) { # if ($rest eq "!") { # print "\\defitem{$key}{\\$key}{$what}\n"; $key = $table_key[$ii]; $what = $table_exp[$ii]; if ($table_arg[$ii] ne "") { print Tab "\\defitem{$key}{\\$key\{\}{}{}{}}{$what}\n"; } else { print Tab "\\defitem{$key}{\\$key}{$what}\n"; } $ii += 1; } print Tab "\\defstop\n"; close(Tab); exit(0);