19

How, in general, can I (re)define commands based on in which other command they are nested?

A more specific example: I have a custom latex command (say, \code{}) that makes text appear bold. However, when used inside another custom command (such as in \question{Will you use \code{command 1} or \code{command 2}?}), I want the \code{} text to be NOT bold. So I want to redefine \code{} when inside another command.

BTW: When using CSS to format HTML pages, it would go something like this:

.code {font-weight: bold;}
.question .code {font-weight: normal;}
doncherry
  • 54,637
Rabarberski
  • 6,459

3 Answers3

20

Yes, you can.

\newcommand\question[1]{{% extra brace
  \renewcommand\code[1]{\textit{##1}}% double #
  whatever you want for #1}}
Leo Liu
  • 77,365
  • Real application of this trick can be seen here too : http://tex.stackexchange.com/questions/6547/how-to-include-all-files-within-a-directory-relative-to-the-edited-tex-file/6548#6548 – Display Name Jan 04 '11 at 14:23
  • Note that above link is to an answer which has been deleted. – Peter Grill Feb 14 '13 at 20:41
7

Personally, I find the brace too easy to overlook most of the time so I use \begingroup\endgroup instead:

\newcommand\question[1]{%
  \begingroup
    \renewcommand\code[1]{\textit{##1}}% double #
    whatever you want for #1%
  \endgroup}
Konrad Rudolph
  • 39,394
  • 22
  • 107
  • 160
  • I agree, and the distinction can be important when defining material to be used in math mode. BTW, no comment char is required after the \begingroup. – Will Robertson Jan 05 '11 at 05:15
  • @Will: I’m never sure where the newline is swallowed so when in doubt, I add it. – Konrad Rudolph Jan 05 '11 at 07:51
  • 6
    Just consider a newline to be a space — in which case, the rule is that spaces after multi-letter control sequences are always swallowed. (And spaces between macro arguments.) – Will Robertson Jan 05 '11 at 07:55
5
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}

\let\code\textbf
\newcommand\question[1]{{\itshape#1}}
\begin{document}

\question{Will you use \code{command 1} or \code{command 2}?}

\question{\let\code\textnormal Will you use \code{command 1} or \code{command 2}?}

\question{Will you use \code{command 1} or \code{command 2}?}

\end{document}

enter image description here

Werner
  • 603,163
  • This will globally change the definition of code, won't it? That wouldn't be good. – Hendrik Vogt Jan 04 '11 at 14:14
  • 2
    @Hendrik: then explain me why the third line is the same as the first line. –  Jan 04 '11 at 14:59
  • 1
    I really should switch my brain on before leaving such comments. You're right, of course; sorry! – Hendrik Vogt Jan 04 '11 at 15:22
  • I think it should be mentioned that this method depend on #1 being in a group in the \question command. I.e. there are double curly brackets on the \newcommand-line. The outer for delimiting the content of the command (not making a group) and the inner to actually make a group. If #1 was not used within a group, the \let in the second use would have “spilled over” to the third use. – Johan_E Feb 14 '13 at 23:29
  • (cont. from last comment) So, for example, if the definition was \newcommand\question[1]{{\itshape #1}~#1} (This writes it’s argument twice. once in italic and once in the surrounding style) the \let would always spill over, if not enclosed in a group when calling the command. This shows that you need to know how a command is defined if you want to use \let inside an argument to it. – Johan_E Feb 14 '13 at 23:33