Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

If I redefine a command that has a starred variant, will this always effectively disable the starred variant, as a side effect of redefining the unstarred variant?

A related question: Do starred commands eat up space after them? (The information contained therein strongly suggests a "yes", but it'll be good to hear a confirmation from an expert.)

Notes:

  • This question was meant to be generic.
  • I mean the redefining act per se. That is, let's assume that I might not include a starred variant in my redefinition.
  • Some examples I had in mind (for which it would actually make sense to redefine the starred version with them, unless one is short of time and doesn't need to for one's local document):
    • I was thinking of redefining \hspace or \vspace to be visible (for draft compilation runs).
    • In some earlier drafts of documents of mine, \chapter was redefined to contain a call to \pagestyle.
share|improve this question
    
Short answer: yes. Less short answer: it depends on how you do the redefinition. Can you give a couple of examples of what you're redefining? If not, the question seems to be too generic. –  egreg Feb 18 '13 at 15:08
    
@egreg Not sure this will change any answers, but I've added some examples so that the question isn't too abstract. –  Lover of Structure Feb 18 '13 at 15:17
1  
For making glue "visible", you can try the very clever visual-lua-debug package. –  egreg Feb 18 '13 at 17:16

3 Answers 3

up vote 13 down vote accepted

There are basically two ways of defining commands with a *-variant.

Traditional way

\newcommand{\foo}{\@ifstar\@sfoo\@foo}
\newcommand{\@sfoo}{something for the *-version}
\newcommand{\@foo}{something for the plain version}

where \@sfoo and \@foo may have arguments; the names are arbitrary, of course: they are two other commands. Many variations are encountered; here's an example:

\newcommand{\foo}{\@ifstar{\@tempswatrue\@foo}{\@tempswafalse\@foo}}
\newcommand{\@foo}{%
  \if@tempswa
     we're with the *-version
  \else
     we're with the plain version
  \fi}

\newcommand\chapter{%
   <code that's irrelevant for the example>%
   \secdef\@chapter\@schapter}

In the second example, the lookup for a following * is delegated to \secdef.

In many cases, \newcommand{\foo}{...} is changed into \DeclareRobustCommand{\foo}{...} to avoid problems with \foo in moving arguments; the auxiliary macros \@sfoo or \@foo can be still defined with \newcommand (or \def, if one prefers).

xparse way

\NewDocumentCommand{\foo}{s...}
  {\IfBooleanTF{#1}
     {Code for the *-version}
     {Code for the plain version}%
  }

where ... stands for other argument types, possibly none.

Redefining

If you have \foo defined in one of those ways, saying

\renewcommand{\foo}{bar}

will of course remove any possibility that \foo* works as before, because the new \foo doesn't check for a * following it, which is in any case the key for a *-variant to work.

Thus, if you want to redefine a command with a *-variant, you should know how it was defined in the first place. In the most common case, with \@ifstar choosing between two different commands, just redefine the one you need, so \@foo or \@sfoo. The same applies for the \chapter example, where you can work on \@schapter or \@chapter. It would be more difficult in the \if@tempswa case, but one should know what the intention is.

If you want to redefine \section, then you find yourself in a more complicated situation, then the problem is more difficult; the definition is usually in terms of \@startsection which is the macro doing the \@ifstar test, so the approaches outlined above don't work. In this case a simple way out is to say

\let\latexsection\section
\renewcommand{\section}{\@ifstar{\latexsection*}{\mynewsection}}

and to define \mynewsection for the "non *" case, probably in terms of \latexsection.

Watch out, though, and always check how the command is defined: in case of doubt, the \let should be replaced with \LetLtxMacro from the letltxmacro package.

Redefining xparse based commands should be done with \RenewDocumentCommand and the proper argument types. Don't use \let or \LetLtxMacro in this case.


Just for fun, here are some patches that make glue inserted with \hspace, \vspace or \addvspace "visible". However they are not guaranteed to always work and to give the same breaks.

\usepackage{regexpatch}
\makeatletter
\xpatchcmd{\@hspace}{\hskip}{\leaders\hrule\hskip}{}{}
\xpatchcmd{\@hspacer}{\hskip}{\leaders\hrule\hskip}{}{}
\xpatchcmd*{\@vspace}{\vskip#1}{\leaders\vrule\vskip#1}{}{}
\xpatchcmd*{\@vspacer}{\nobreak\vskip}{\nobreak\leaders\vrule\vskip}{}{}
\xpatchcmd{\addvspace}{\vskip}{\leaders\vrule\vskip}{}{}
\xpatchcmd*{\@xaddvskip}{\vskip\@tempskipb}{\leaders\vrule\vskip\@tempskipb}{}{}
\makeatother
share|improve this answer
    
Which of the two ways does the suffix way (= the third method I'm aware of) of defining a starred variant fall into? –  Lover of Structure Feb 18 '13 at 20:12
    
@LoverofStructure suffix uses a completely different method, which I'm not expert of. –  egreg Feb 18 '13 at 20:14

It depends how you redefine the command. At the TeX level there is no such thing as a starred variant the base command just looks ahead for a star and acts accordingly. So if you redefine it such that it still looks ahead for the star then it will do so, otherwise it won't.

Alternatvely you can save the old command of course.

Here the \section commands use the new \fbox definition but \oldsection* works as before.

\documentclass{article}

\let\oldsection\section

\def\section#1{\fbox{#1}}

\begin{document}

\section{abc}
One

\oldsection*{xyz}

One two

\section{zzz}
One Two three

\end{document}

Or this version which makes the same output but allows you to use \section for the new definition and \section* for the old star form.

\documentclass{article}

\let\oldsection\section

\makeatletter
\def\section{\@ifstar{\oldsection*}\fbox}
\makeatother

\begin{document}

\section{abc}
One

\section*{xyz}

One two

\section{zzz}
One Two three

\end{document}

A comment on the examples that you added. Redefining \hspace and \vspace to be visible without changing the document spacing is hard (probably impossible in general) so whatever redefinition you had in mind, the extra work of adding \@ifstar and redefining the * form at the same time would not be your main problem.

For redefining chapter, most definitions of chapter (eg the ones in book and report) already have a thispagestyle but ignoring that you could probably just put your definition at the front and leave the old definition still looking for *:

\let\oldchapter\chapter
\def\chapter{\cleardoublepage\thispagestyle{foo}\oldchapter}

(egreg points out correctly that in real life you can't ignore the fact there is already a \thispagestyle as the existing one will overwrite the one added)

share|improve this answer
    
About your last point: this might be relevant for memoir. –  Lover of Structure Feb 18 '13 at 20:03

For plain macros, the starred and unstarred variants are actually the same macro in which the * plays the role of an optional argument; the xparse mechanics that egreg describes make this much clearer. However, for environments, the starred and unstarred variants are completely different: there are actually separate environments called, say, equation and equation* (from amsmath), and redefining equation will do absolutely nothing to equation*. The reason for this is that while a starred macro will do something like

\def\macro{\@ifnextchar*{<yes>}{<no>}}

a starred environment actually has the star in its name. Recall that an environment is actually a pair of macros, so:

\def\equation{...}
\def\endequation{...}

and therefore for equation* we would have, if * were made a letter:

\catcode`*=11
\def\equation*{...}
\def\endequation*{...}

However, the way it's actually done is that \begin just feeds its argument to \csname...\endcsname, which means that environment names can be much weirder than macro names:

\begin{equation*} --> \csname equation*\endcsname
\end{equation*}   --> \csname endequation*\endcsname
% plus other stuff, of course

So for environments, the relation between the starred and unstarred variants is a matter of convention that is not enforced by the code, while for macros, in fact, the starred variant is created by the expansion/parsing process.

share|improve this answer
    
+1 for a valuable contribution (environments as opposed to commands) –  Lover of Structure Feb 18 '13 at 20:10

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.