% \iffalse
% $Id: tmacros.sty,v 1.2 1995/01/28 07:48:30 swift Exp $
% tmacros.sty
% Copyright (C) 1994 Matt Swift <[email protected]>
% In the near future this code will become part of a larger package called
% "scholar" that I will release also under the GPL. I want to make certain
% useful parts of the package available before the whole package is released
% because I don't see any reason to withhold them. This is in lieu of a beta
% release that would only be frustrating because I will not have time to
% maintain it until May 1995. If you find this code useful, look for the whole
% package about that time. I welcome comments, suggestions, etc.
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
% \fi
% \date{95/01/26}
% \author{Matt Swift \texttt{<[email protected]>}}
% \title{The \texttt{tmacros} package}
% \maketitle
% \section{Introduction}
% First a general discussion.
% \textsl{Text macros} expand to a piece of text, and insert the proper space
% following, depending on context. If I define a text macro |\foo| to be
% \meta{text}, I can use |\foo| in place of \meta{text} almost anywhere. For
% details of how the spacing is handled, see the macros. Examples that produce
% correct formatting:
% \begin{quote}
% |\newname{ww}{Wordsworth}| \\
% |\newwork{prelude}{The Prelude} % in italic|
%
% |The manuscripts of \ww's \prelude differ|\ldots \\
% |Before beginning \prelude, \ww wrote|\ldots
% \end{quote}
% \textsl{Abbreviation macros} are text macros that expand to something
% different the first time they are used. It is expected that the second be
% an abbreviation of the first, but that need not be the case. Examples:
% \begin{quote}
% |\newname{nixon}{Richard Milhous Nixon}[Nixon]| \\
% |\newname{jekyll}{Dr.~Henry Jekyll}[Jekyll]|\\
% |\newname{ama}{American Medical Association (AMA)}[AMA]| \\
% \end{quote}
% Here are the particular commands. First the primitive ones.
% \DescribeMacro{\NewTextMacro}
% |\NewTextMacro|\marg{command}\marg{text} defines |\|\meta{command} to expand
% to \meta{text} and insert the right space after it, depending on context. To
% \DescribeMacro{\spacebeforelist}
% control behavior explicitly, you can set |\spacebeforelist| analogously to
% |\nocorrlist|.
% \DescribeMacro{\newabbrev}
% |\newabbrev|\marg{command}\marg{initial text}\marg{subsequent text} defines
% |\|\meta{command} to be \meta{initial text} (like a text macro, inserting the
% right following space) the first time it is used, and \meta{subsequent text}
% subsequently. To use one or the other in a particular circumstance, the
% commands |\|\meta{command}|short| and |\|\meta{command}|long| are also
% defined.
% \DescribeMacro{\AbbrevLongSuffix}
% \DescribeMacro{\AbbrevShortSuffix}
% (You can change those suffixes by setting |\AbbrevShortSuffix| and
% |\AbbrevLongSuffix|.)
% \DescribeMacro{\ResetAbbrevs}
% Calling |\ResetAbbrevs| starts all the abbreviation macros over again; their
% next occurrence will be the ``first.'' This command could be put in the
% chapter hook.
% The following user commands are provided.
% \DescribeMacro{\newbook}
% |\newbook|\marg{command}\marg{text}\oarg[abbrev] defines |\|\meta{command} to
% be a text macro with emphasized text. If an optional argument is given, it
% defines an abbreviation with emphasized text.
% \DescribeMacro{\newwork}
% |\newwork| is an alias for a |\newbook| at the moment. In the future,
% ``works'' will be distinguished from books by being listed in a separate
% bibliography, e.g., of primary works which are referred to by short titles.
% The defining command will then need to take a Bib\TeX\ key as an argument
% also. The first use of the work will serve as a citation to that
% bibliography, and all uses of the work will generate an index entry.
% \DescribeMacro{\newname}
% |\newname|\marg{command}\marg{name}\marg{abbrev} defines |\|\meta{command} to
% be a plain abbreviation (no style-changing).
% \section{Implementation}
% \StopEventually{}
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{tmacros}[1995/01/26 v1.0 text and abbrev macros]
\RequirePackage{ifthen}
% \end{macrocode}
% \begin{macro}{\AbbrevLongSuffix}
% \begin{macro}{\AbbrevShortSuffix}
% When a text macro |\foo| is created, two additional commands with these
% suffixes are also created.
% \begin{macrocode}
\newcommand\AbbrevLongSuffix
{long}
\newcommand\AbbrevShortSuffix
{short}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\NewTextMacro}
% I wrote some really nice code to implement text macros in 2.09 sometime early
% in '94 when I was beginning work on my thesis. I thought what I'd done was
% pretty special. On December~2, 1994, though, I read Chris and Frank's code
% for |\DeclareTextFontCommand|, and I have to admit it sure put the chop to
% what I'd done. Go boys go.
% The checking that |\sw@slant| does for skips and penalties on the list is
% going to be superfluous for the applications I imagine. But we trade that
% for a more flexible macro.
% We don't check for |\nocorr| or an empty body; maybe we should when it's
% first defined; but I ran into really hairy expansion troubles trying to do
% that and use |\DeclareRobustCommand|.
% \begin{macrocode}
\newcommand\NewTextMacro[3] % args: \csname, style, body
{\DeclareRobustCommand#1%
{\leavevmode
{\maybe@ic #2\aftergroup \maybe@ic@space #3}}}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\maybe@ic@space}
% \begin{macro}{\maybe@ic@space@}
% When a text macro is followed by a letter or any token in |\spacebeforelist|,
% a following space is inserted. |\spacebeforelist| initially contains only
% |(|, |`|, |[|, |\&|, |\$|, and |\#|, since for all others I can think of
% situations in which a space is not desirable, and it is more familiar to
% users to use \verb*"\ " or |{}| than |\unskip|. It does not make sense to
% have any item in both |\spacebeforelist| and |\nocorrlist|, since an italic
% correction should be inserted before a space. If the same token is in both
% lists by accident, neither a correction or space will be inserted, i.e., its
% presence in |\spacebeforelist| will be ignored.
% Because we want to possibly insert a following space, a single macro
% |\maybe@ic| for both sides of the text is no longer sufficient.
% \begin{macrocode}
\newcommand\maybe@ic@space
{\futurelet\@let@token\maybe@ic@space@}
% \end{macrocode}
% The reason we can use |\test@next| again is that all it is doing is setting
% the switch false if |\@let@token| is in the list |\spaceafter|.
% \begin{macro}{\tm@ifnewformat}
% Here is where a little change occurred in the December release; temporary
% variable |\@tempa| became |\reserved@a| in |\test@next|. For the moment, we
% want to be able to work with both releases, so we define a conditional.
% \begin{macrocode}
\newcommand\tm@ifnewformat
{\@ifl@t@r\fmtversion{1994/06/01}}
% \end{macrocode}
% \end{macro}
% Now we define one or the other version, depending.
% This macro is very similar to |\maybe@ic@|, but we do the checking twice,
% once for |\nocorrlist| and once for |\spacebeforelist|. We skip the check
% through |\spacebeforelist| if the following character is a letter (i.e.,
% catcode of ``A''); otherwise, we'd have to add all the letters to
% |\spacebeforelist|.
% \begin{macrocode}
\tm@ifnewformat
{\newcommand\maybe@ic@space@ % ifnewformat is TRUE
{\ifdim \fontdimen\@ne\font>\z@
\else
\@tempswatrue
\expandafter\@tfor\expandafter\reserved@a\expandafter:\expandafter=%
\nocorrlist
\do \test@next
\if@tempswa
\sw@slant
\ifcat\@let@token A\space
\else
\expandafter\@tfor\expandafter\reserved@a\expandafter:\expandafter=%
\spacebeforelist
\do \test@next % sets switch false if we want a space
\if@tempswa
\else\space
\fi
\fi
\fi
\fi}}
{\newcommand\maybe@ic@space@ % ifnewformat is FALSE
{\ifdim \fontdimen\@ne\font>\z@
\else
\@tempswatrue
\expandafter\@tfor\expandafter\@tempa\expandafter:\expandafter=%
\nocorrlist
\do \test@next
\if@tempswa
\sw@slant
\ifcat\@let@token A\space
\else
\expandafter\@tfor\expandafter\@tempa\expandafter:\expandafter=%
\spacebeforelist
\do \test@next % sets switch false if we want a space
\if@tempswa
\else\space
\fi
\fi
\fi
\fi}}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\spacebeforelist}
% Put these in the order of their frequency.
% Something to check: are these going to be the CHARACTERS, or the versions
% with the special catcodes?
% \begin{macrocode}
\newcommand\spacebeforelist
{(`[\&\$\#}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\newabbrev}
% This command defines a new abbreviation. The optional argument is treated as
% a style-changing command.
% \begin{macrocode}
\newcommand\newabbrev[1][] % oarg: style
{\sc@newabbrev{\NewTextMacro}{#1}}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\ResetAbbrevs}
% Each time an abbreviation is defined, something will be added to the contents
% of this command.
% \begin{macrocode}
\newcommand\ResetAbbrevs{}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\newtokens}
% Here's a silly command to allocate new token registers without stepping on
% existing names. |\newtokens| should definitely be |outer|. Because
% |\newtoks| is |outer|, we have to fool |\def| into allowing it to be in its
% argument by using |\csname|\ldots|\endcsname|.
% |\newtokens| should be |\outer| but for the moment that's a pain because the
% scholar package is in pieces, and you want to be able to load more than one
% piece.
% \begin{macrocode}
\@ifundefined{newtokens}
{\def\newtokens#1%
{\@ifdefinable #1
{\csname newtoks\endcsname#1}}}
{}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\sc@toks@shortcom}
% \begin{macro}{\sc@toks@plaincom}
% \begin{macro}{\sc@toks@longcom}
% The first three of the following toks registers will expand to the three
% |\csname|s we are going to define. The remaining two will be used later.
% \begin{macrocode}
\newtokens\sc@toks@shortcom
\newtokens\sc@toks@longcom
\newtokens\sc@toks@plaincom
\@ifundefined{sc@toks@a}
{\newtokens\sc@toks@a}
{}
\@ifundefined{sc@toks@b}
{\newtokens\sc@toks@b}
{}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% The above are simply holders, to keep what's in them from expanding under the
% |\xdef| below. I tried |\noexpand|s, which might have been clearer, but to
% no avail. What's below is a pain in the neck, but it works. Someday I will
% make another stab at simplifying.
% \begin{macro}{\sc@newabbrev}
% Here is the main abbreviation maker. The first argument is another macro to
% call. It's there to make things simpler, but also because I have in mind
% alternatives to |\NewTextMacro| that are not yet implemented. The second
% argument is expected to be a style command, such as |\em|, or empty. The
% third argument is the main macro name to be created, and the fourth and fifth
% arguments are the initial expansion, and the subsequent expansion for the
% macro.
% The first part sets our three toks variables to the three command sequences
% that this macro is going to define.
% \begin{macrocode}
\newcommand\sc@newabbrev[5] % args: maker style name longtext shorttext
{\sc@toks@shortcom=\expandafter{\csname #3\AbbrevShortSuffix\endcsname}
\sc@toks@longcom=\expandafter{\csname #3\AbbrevLongSuffix\endcsname}
\sc@toks@plaincom=\expandafter{\csname #3\endcsname}
% \end{macrocode}
% The next two lines define the explicitly long version and the explicitly
% short version.
% \begin{macrocode}
\expandafter#1\the\sc@toks@longcom{#2}{#4}
\expandafter#1\the\sc@toks@shortcom{#2}{#5}
% \end{macrocode}
% Perhaps the following should be sent out to its own macro. Would that
% simplify this knotty expansion problem? Anyway, the strategy is to define
% the main command to check its own reserved boolean variable to see whether
% this macro has been called before, and expand to different things according
% to its value.
% \begin{macrocode}
\newboolean{#3 mentioned}
% \end{macrocode}
% This next line is a local change; should it be global?
% \begin{macrocode}
\addto@macro\ResetAbbrevs{\setboolean{#3 mentioned}{false}}
% \end{macrocode}
% Here's the real screwy part. To get the expansion right, I put two
% lines of code into toks registers.
% \begin{macrocode}
\sc@toks@a={\ifthenelse{\boolean{#3 mentioned}}}
\sc@toks@b={\setboolean{#3 mentioned}{true}}
% \end{macrocode}
% And then I use them here. This code defines the main abbreviation macro to a
% simple |\ifthenelse|. The expanded code is given in the comments.
% \begin{macrocode}
\expandafter\@ifdefinable\the\sc@toks@plaincom
{\expandafter\xdef\the\sc@toks@plaincom
{\the\sc@toks@a% I.E.: {\ifthenelse{\boolean{#3 mentioned}}}
{\the\sc@toks@shortcom}
{\the\sc@toks@b% I.E.:{\setboolean{#3 mentioned}{true}}
\the\sc@toks@longcom}}}}
% \end{macrocode}
% The |\csname|s (either |\foolong| or |\fooshort|) \emph{must} be the very
% last thing to occur in the definitions, or the |\futurelet| that checks
% following spacing in |\NewTextMacro| will break. No space must sneak into
% the macros!
% \end{macro}
% From here on out, we are just applying these things to make a few user
% commands.
% \begin{macro}{\newname}
% \begin{macrocode}
\newcommand\newname
{\newabbrev[]}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\newwork}
% \begin{macro}{\sc@newworkabbrev}
% \begin{macrocode}
\newcommand\newwork[2]
{\@ifnextchar [
{\sc@newworkabbrev{#1}{#2}}
{\expandafter\NewTextMacro\csname #1\endcsname{\em}{#2}}}
\newcommand\sc@newworkabbrev{} % reserve the cs
\def\sc@newworkabbrev#1#2[#3]
{\sc@newabbrev{\NewTextMacro}{\em}{#1}{#2}{#3}}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\newbook}
% \begin{macrocode}
\newcommand\newbook[2]
{\newwork{#1}{#2}}
% \end{macrocode}
% \end{macro}
% \Finale
\endinput
|