1

Is it possible to write a macro, that takes the rest of the current group as an argument?

Usecase

I want to write a macro that can be used as

\section{\TODO Introduction $of$ \textsc{The Topic}}

such that \TODO is passed Introduction of the topic as its first argument. The \textsc and $of$ is there in order to clarify, that I need support for general latex constructs, not only for plain-text sequences.

Why not \TODO{Intro...}?

Normally I'd be the first to advocate justusing \TODO{Intro...} instead, but this reduces the readability of software-provided document outlines. E.g. in TeXStudio:

enter image description here

kdb
  • 1,889
  • Does the outline use the same mechanism as the toc? If so, you could use \section[TODO Introduction $of$ \textsc{The Topic}]{\TODO {Introduction $of$ \textsc{The Topic}}} – Steven B. Segletes Jul 26 '18 at 12:59
  • 2
    it's possible but very fragile (in particular you would probably need to know whether the implicit group for the section heading ends with } or \egroup or \endgroup – David Carlisle Jul 26 '18 at 13:02
  • Without braces,\TODO will pass I as its first argument, n as its second,... – John Kormylo Jul 26 '18 at 13:26

2 Answers2

2

Although there are more complicated ways to provide intelligence to the command, here is a basic alternative

\def\TODO#1\TODO{#1}

and then use

\section{\TODO Introduction $of$ \textsc{The Topic}}\TODO}

If you don't like to use \TODO as the right delimiter, you can use whatever you want

\def\TODO#1!!!{#1}
\section{\TODO Introduction $of$ \textsc{The Topic}}!!!}

or may be you just want the \TODO to be in TeXStudio and do not want to output anything in the document? In that case a simple

\def\TODO{} % or \let\TODO\relax
\section{\TODO Introduction $of$ \textsc{The Topic}}}

would be enough.

Manuel
  • 27,118
0

kdb asked:

Is it possible to write a macro, that takes the rest of the current group as an argument?


What do you mean by "rest of the current group"?

Writing a macro that takes the remainder of a brace group is easy.

But there must be a brace group at the time when that macro gets carried out.

In your case, the argument of the \section-macro will be inserted as part of the <replacement text> at the time of expanding the \section-macro.
When the <replacement text> with the arguments is inserted into the token-stream, surrounding braces will be stripped from undelimited arguments, thus there won't be a brace-group any more denoting start and end of the section's title.
Thus when further processing leads to carrying out \TODO, \TODO will not find a brace group.

(Besides this, with a \TODO-macro you'd need to introduce precautions in order to ensure that it behaves correctly when being part of a moving argument (as would be the case when using it inside the argument of a \section-command which also pushes its arguments towards the table of contents and into the bookmarks of the pdf-file) and when being used inside a pdf-string (as would be the case with bookmarks). )

The following macro \CopyBehindGroup is not of any use when the pair of braces in question denotes a macro argument.

But it is an example of how to put tokens outside a pair of braces forming a local scope.

The following macro \CopyBehindGroup takes an undelimited argument and the remainder of a brace group and pushes both outside the brace-group. Hereby the argument is removed from the brace-group. The remainder is just copied.

\documentclass{article}

\makeatletter
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\expandafter\expandafter\@firstoftwo{ }{}%
  \@secondoftwo}{\expandafter\expandafter\@firstoftwo{ }{}\@firstoftwo}%
}%
%%----------------------------------------------------------------------
%% \UD@PullOutFirstUndelimitedArgument{<action>}%
%%                                    {<action if list is empty>}%
%%                                    {{<e_k>}{<e_(k+1)>}..{<e_n>}}%
%% yields either
%%  <action>{<e_k>}{{<e_(k+1)>}..{<e_n>}}
%% or
%%  <action if list is empty>
%%   (   The "list" in question is {<e_k>}{<e_(k+1)>}..{<e_n>}   )
%%......................................................................
\newcommand\UD@Exchange[2]{#2#1}%
\newcommand\UD@KeepFirstTillSelDOM{}%
\long\def\UD@KeepFirstTillSelDOM#1#2\UD@SelDOM{{#1}}%
\newcommand\UD@PullOutFirstUndelimitedArgument[3]{%
  \UD@CheckWhetherNull{#3}{#2}{%
    \expandafter\UD@Exchange
    \expandafter{%
    \expandafter{%
    \@firstoftwo{}#3}}{\UD@ExtractFirstListElementLoop{#3\UD@SelDOM}{#1}}%
  }%
}%
\newcommand\UD@ExtractFirstListElementLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}%
  {\UD@Exchange{#1}}%
  {%
    \expandafter\UD@ExtractFirstListElementLoop
    \expandafter{%
    \UD@KeepFirstTillSelDOM#1}%
  }%
}%
%%----------------------------------------------------------------------
%% \CopyBehindGroup
%%
%%   {<token sequence A>\CopyBehindGroup{<tokens to appear only behind group}<tokens to be copied behind group>}
%% yields:
%%   {<token sequence A><tokens to be copied behind group>}<tokens to appear only behind group>{<tokens to be copied behind group>}
%%......................................................................
\newcommand\CopyBehindGroup[1]{%
  \romannumeral0%
  \expandafter\expandafter\expandafter\UD@PullOutFirstUndelimitedArgument
  \expandafter\expandafter\expandafter\@CopyBehindGroup
  \expandafter\expandafter\expandafter{%
  \expandafter\expandafter\expandafter}%
  \expandafter\expandafter\expandafter{%
  \expandafter\@secondoftwo\string}{}%
  {#1}%
}%
\newcommand\@CopyBehindGroup[2]{%
   \expandafter\@secondoftwo\string{{ }#2}#1{#2}%
}%
\makeatother

\begin{document}

\frenchspacing

{%<--This starts the boldface-group
 \bfseries This is boldface.
 \CopyBehindGroup{This is to appear only outside the boldface-group. \textit}%
 This is to be copied outside the boldface-group.
}%<--This ends the boldface-group

\end{document}

enter image description here

Ulrich Diez
  • 28,770