[comp.text.tex] Redefining a macro in terms of itself

kjg@bcat1.prime.com (Ken Gartner) (01/15/91)

   While trying to create a private LaTeX style file, I stumbled while attempting
to redefine \tableofcontents and \marginpar in terms of themselves. This is what
my intention is:

PSEUDOCODE

\renewcommand{\tableofcontents}{\parskip 0in \tableofcontents}
\renewcommand{\marginpar}{#1}{\scriptsize \marginpar{#1}}

  Unfortunately (for me) is that renewcommand seems to do the
assignment such that the first use of the newly defined command
endlessly loops when used.  I think the \let is what I want since there is
an indication that it copies the current definition -- unfortunately
(again for me) the following generate some noise about

% Try to get table of contents tighter for article:
\let\k1\tableofcontents
\renewcommand{\tableofcontents}{\parskip 0in \k1}


   ! Missing \begin{document}.
   \@latexerr ...for immediate help.}\errmessage {#1}

   ...
   l.53 \let\k1\tableofcontents
   ? ^D


I would be most appreciative if someone could give pointers on profitable
use of \let including use with macros that take arguments.  I am not any
kind of [*]TeXpert at this point so try to be gentle ...

kjg


-- 
Kenneth J. Gartner                      |   kjg@s49.prime.com
Prime Computer (CPU Group)              |   1-508-620-2800 x3287
500 Old Connecticut Path, MS 10A-04
Framingham Mass, 01701

"Cursedbehewho thinks my opinions reflect Prime Official policy"

anita@chopin.udel.edu (Anita Marie Hoover) (01/16/91)

In article <1991Jan15.061451@bcat1.prime.com> kjg@s49.prime.com writes:
>
>   While trying to create a private LaTeX style file, I stumbled while attempting
>to redefine \tableofcontents and \marginpar in terms of themselves. This is what
>my intention is:
>
>PSEUDOCODE
>
>\renewcommand{\tableofcontents}{\parskip 0in \tableofcontents}
>\renewcommand{\marginpar}{#1}{\scriptsize \marginpar{#1}}
>

The way to redefine such macros is to go to the style file and get the
definition and make it part of your private LaTeX style file.  So
you would want to go to which ever style file your private LaTeX style
is based on and copy that code and modify it.  For example,  I took the
\tableofcontents from the report.sty and modified it for our UDThesis
purposes.   Anyway here is the changes

\def\tableofcontents{\@restonecolfalse\if@twocolumn\@restonecoltrue\onecolumn
 \fi\chapter*{Table of Contents\@mkboth{CONTENTS}{CONTENTS}}
%  This adds more space after the title Table of Contents
 \vspace*{\baselineskip}
%  This sets up some environment changes like read a \linebreak as
%  a \space, set \parskip 0pt, no hyphenation, and no justification
 {\let\linebreak=\space\parskip=0pt\pretolerance=10000\raggedright
 \advance\hsize by -\@pnumwidth
%  Set spacing back to 1 since UDThesis sets it to 1.5
 \def\baselinestretch{1}\large\normalsize
 \@starttoc{toc}\if@restonecol\twocolumn\fi}}


Anita Hoover
University of Delaware

rph@cs.brown.edu (Richard Hughey) (01/16/91)

In article <16221@chopin.udel.edu> anita@chopin.udel.edu (Anita Marie Hoover) writes:
>In article <1991Jan15.061451@bcat1.prime.com> kjg@s49.prime.com writes:
>>I stumbled while attempting
>>to redefine \tableofcontents and \marginpar in terms of themselves. 
>>This is what my intention is:
>>
>>\renewcommand{\tableofcontents}{\parskip 0in \tableofcontents}
>
>The way to redefine such macros is to go to the style file and get the
>definition and make it part of your private LaTeX style file.  So

To make it less style file dependent (in case the style file is
updated), a better command would be

\let\original@tableofcontents=\tableofcontents
\renewcommand{\tableofcontents}{\parskip 0pt \original@tableofcontents}

This won't work for changes which cannot be placed at the start
or end of a command, in which case defining the whole macro
will be required.


    	- Richard








--------------------------------------- Richard Hughey              
INTERNET:  rph@cs.brown.edu	        Brown University            
BITNET:    rph@browncs		        Box 1910                    
(decvax, allegra, ...)!brunix!rph       Providence, RI 02912        

raymond@math.berkeley.edu (Raymond Chen) (01/16/91)

In article <1991Jan15.061451@bcat1.prime.com> kjg@s49.prime.com writes:
>my intention is:
>\renewcommand{\tableofcontents}{\parskip 0in \tableofcontents}

In article <16221@chopin.udel.edu>, anita@chopin (Anita Marie Hoover) writes:
>The way to redefine such macros is to go to the style file and get the
>definition and make it part of your private LaTeX style file.  

Another way is save the old value into a separate csname, e.g.

    \let\oldtableofcontents=\tableofcontents
    \def\tableofcontents{\parskip0in \oldtableofcontents}

This has the advantage of automatically changing when your LaTeX version
changes, or if you change style files.

Of course, if you want to show off, you could use some clever
hacks involving \edef and \toks.  Something like

    \toks0=\expandafter{\tableofcontents}
    \edef\tableofcontents{\parskip0in \the\toks0}

References:  The TeXbook, page 216, in particular, exercise 20.15.

eijkhout@s41.csrd.uiuc.edu (Victor Eijkhout) (01/16/91)

anita@chopin.udel.edu (Anita Marie Hoover) writes:

>In article <1991Jan15.061451@bcat1.prime.com> kjg@s49.prime.com writes:
>>
>>This is what
>>my intention is:
>>
>>\renewcommand{\tableofcontents}{\parskip 0in \tableofcontents}
>>\renewcommand{\marginpar}{#1}{\scriptsize \marginpar{#1}}
>>

>The way to redefine such macros is to go to the style file and get the
>definition and make it part of your private LaTeX style file.  

That's *a* way, not *the* way.

\let\xtableofcontents\tableofcontents
\renewcommand{\tableofcontents}{\parskip 0in \xtableofcontents}


Victor.

jg@prg.ox.ac.uk (Jeremy Gibbons) (01/16/91)

kjg@bcat1.prime.com (Ken Gartner) asks

> attempting
> to redefine \tableofcontents and \marginpar in terms of themselves
[...]
> % Try to get table of contents tighter for article:
> \let\k1\tableofcontents
> \renewcommand{\tableofcontents}{\parskip 0in \k1}

As others have pointed out, this is the (or a) right idea, but of course you
can't use digits in control sequences (without a bit of catcode hackery). Try

> % Try to get table of contents tighter for article:
> \let\kone\tableofcontents
> \renewcommand{\tableofcontents}{\parskip 0in \kone}

(Of course, if you put this in a style file that subsequently gets read in
twice, you'll still get caught in a loop, but that would serve you right...)

You also have to be careful not to use \kone for anything else; the solution
using \toks (raymond@math.berkeley.edu (Raymond Chen)) avoids this since it
doesn't use any new control sequences.

*-----------------------------------------------------------------------*
|  Jeremy Gibbons (jg@uk.ac.oxford.prg)   Funky Monkey Multimedia Corp  |
*-----------------------------------------------------------------------*

fj@iesd.auc.dk (Frank Jensen) (01/17/91)

In article <6547.2794b1a0@csv.viccol.edu.au> Douglas.Miller@viccol.edu.au (Douglas Miller) writes:

   In article <1991Jan15.061451@bcat1.prime.com>, kjg@bcat1.prime.com (Ken
   Gartner) writes:

   > While trying to create a private LaTeX style file, I stumbled while attempting
   > to redefine \tableofcontents and \marginpar in terms of themselves. 

   > I think the \let is what I want since there is
   > an indication that it copies the current definition

   Yes --- here is what I do to atomatically insert a table of contents
   in a document style:

   \let\old@document=\document
   \def\document{\old@document\tableofcontents}

   > -- unfortunately
   > (again for me) the following generate some noise about
   > 
   > % Try to get table of contents tighter for article:
   > \let\k1\tableofcontents
   > \renewcommand{\tableofcontents}{\parskip 0in \k1}
   > 
   > 
   >    ! Missing \begin{document}.
   >    \@latexerr ...for immediate help.}\errmessage {#1}
   > 
   >    ...
   >    l.53 \let\k1\tableofcontents
   >    ? ^D

   Nearly right, but you used an invalid macro name "\k1" --- digits are not
   allowed!   The 1 got interpreted as text to be typeset, hence the error
   message.

Almost right!  \k is let equal to 1, and the \tableofcontents command
generates text to be typeset.

yxoc@fb14vax.cs.uni-sb.de (Ralf Treinen) (01/17/91)

From article <16221@chopin.udel.edu>, by anita@chopin.udel.edu (Anita Marie Hoover):
> In article <1991Jan15.061451@bcat1.prime.com> kjg@s49.prime.com writes:
>>
>>   While trying to create a private LaTeX style file, I stumbled while attempting
>>to redefine \tableofcontents and \marginpar in terms of themselves. This is what
>>my intention is:
>>
>>PSEUDOCODE
>>
>>\renewcommand{\tableofcontents}{\parskip 0in \tableofcontents}

You may also use the following TeXnical trick:

\let\TMP\tableofcontents
\renewcommand{\tableofcontents}{\parskip 0in \TMP}

Take care, this will redefine \TMP without any warning.

Ralf.

-- 
 Ralf Treinen                         | email: treinen@cs.uni-sb.de          
 FB 14 - Informatik (Dept. of CS)     |
 Universitaet des Saarlandes          | phone: +49 681 302 2065
 W-6600 Saarbruecken , Germany        | fax:   +49 681 302 4421

Douglas.Miller@viccol.edu.au (Douglas Miller) (01/17/91)

In article <1991Jan15.061451@bcat1.prime.com>, kjg@bcat1.prime.com (Ken
Gartner) writes:

> While trying to create a private LaTeX style file, I stumbled while attempting
> to redefine \tableofcontents and \marginpar in terms of themselves. 

> I think the \let is what I want since there is
> an indication that it copies the current definition

Yes --- here is what I do to atomatically insert a table of contents
in a document style:

\let\old@document=\document
\def\document{\old@document\tableofcontents}

> -- unfortunately
> (again for me) the following generate some noise about
> 
> % Try to get table of contents tighter for article:
> \let\k1\tableofcontents
> \renewcommand{\tableofcontents}{\parskip 0in \k1}
> 
> 
>    ! Missing \begin{document}.
>    \@latexerr ...for immediate help.}\errmessage {#1}
> 
>    ...
>    l.53 \let\k1\tableofcontents
>    ? ^D

Nearly right, but you used an invalid macro name "\k1" --- digits are not
allowed!   The 1 got interpreted as text to be typeset, hence the error
message.