无分隔符的宏

无分隔符的宏

我想定义一个行为类似的宏\ttfamily,即它应该读取所​​有内容直到}(或\endgroup?)作为参数。

即这个

{\mynewmacro lorem ipsum
 dolores
}

应该相当于这个

\mymacro{lorem ipsum
 dolores
}

这可能吗?

答案1

该宏\ttfamily不会读取}:它是一个声明,设置(本地)当前字体并且其操作持续到当前组结束。

你可以这样做,但从概念上来说这从一开始就是错误的。

\long\def\mymacro#1{--#1--}
\long\def\mynewmacro{\egroup\iftrue\expandafter\mymacro\expandafter{\else}\fi}

\mymacro{lorem ipsum
 dolores
}

{\mynewmacro lorem ipsum
 dolores
}

\bye

平衡\egroup初始的{;然后我们有一个问题,就是让\mymacro看到一个明确的{,并摆脱必要的}(因为\def不会接受不平衡的标记列表)。\iftrue测试遵循真正的分支;实际上它所做的只是消失,留下

\expandafter\mymacro\expandafter{\else}\fi

在输入流中,但 TeX 知道它应该忽略该\else部分。\expandafter我们得到了这个\else,它的扩展删除了直到的所有内容\fi。所以最后我们剩下

\mymacro{\fi

因此,按照一般规则,\mymacro将读取匹配的}。其余部分\fi将扩展,不留任何内容。

但请注意,你不能将其称为\begingroup\mynewmacro ...\endgroup也不使用\bgroup\egroup

答案2

使用以下示例

  • 该宏\FetchTillCloseBrace{\macro}获取所有内容直到下一个不匹配的右括号,并将其作为未限定的参数传递给 \macro,重新插入该不匹配的右括号。

  • 该宏\CopyBehindCloseBrace是一个示例,说明如何从一对括号内放置/复制标记,从而在该范围的结束括号后面形成一个本地范围。

请注意,通过宏/宏参数进行处理会破坏依赖于在不同 catcode-régime 下读取和标记事物的事物,例如,\verb等等。

\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>}%
%%                                    {{<e_k>}{<e_(k+1)>}..{<e_n>}}%
%% yields
%%  <action>{<e_k>}{{<e_(k+1)>}..{<e_n>}}
%% It must be ensured that list is not empty!
%%......................................................................
\newcommand\UD@Exchange[2]{#2#1}%
\newcommand\UD@KeepFirstTillSelDOM{}%
\long\def\UD@KeepFirstTillSelDOM#1#2\UD@SelDOM{{#1}}%
\newcommand\UD@PullOutFirstUndelimitedArgument[2]{%
    \expandafter\UD@Exchange
    \expandafter{%
    \expandafter{%
    \@firstoftwo{}#2}}{\UD@ExtractFirstListElementLoop{#2\UD@SelDOM}{#1}}%
}%
\newcommand\UD@ExtractFirstListElementLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}%
  {\UD@Exchange{#1}}%
  {%
    \expandafter\UD@ExtractFirstListElementLoop
    \expandafter{%
    \UD@KeepFirstTillSelDOM#1}%
  }%
}%
%%----------------------------------------------------------------------
%% \CopyBehindCloseBrace
%%
%%   {<token sequence A>\CopyBehindCloseBrace{<tokens to appear only behind closing brace}<tokens to be copied behind closing brace>}
%% yields:
%%   {<token sequence A><tokens to be copied behind closing brace>}<tokens to appear only behind closing brace>{<tokens to be copied behind closing brace>}
%%......................................................................
\newcommand\FetchTillCloseBraceStart[2]{%
  \expandafter\expandafter\expandafter\UD@PullOutFirstUndelimitedArgument
  \expandafter\expandafter\expandafter#1%
  \expandafter\expandafter\expandafter{%
  \expandafter\@secondoftwo\string}{}%
  {#2}%
}%
\newcommand\CopyBehindCloseBrace{%
  \romannumeral0%
  \FetchTillCloseBraceStart{\@CopyBehindCloseBrace}%
}%
\newcommand\@CopyBehindCloseBrace[2]{%
   \expandafter\@secondoftwo\string{{ }#2}#1{#2}%
}%
%%----------------------------------------------------------------------
%% \FetchTillCloseBrace{\macro}
%%
%%   {<token sequence A>\FetchTillCloseBrace{\macro}<remaining tokens in brace group>}
%% yields:
%%   {<token sequence A>\macro{<remaining tokens in brace group>}}
%%......................................................................
\newcommand\FetchTillCloseBrace{%
  \romannumeral0%
  \FetchTillCloseBraceStart{\@PassToMacroInsideScope}%
}%
\newcommand\@PassToMacroInsideScope[2]{%
   \expandafter\@secondoftwo\string{{ }#1{#2}}%
}%
%%----------------------------------------------------------------------
%%
%% {ABC \LowercaseTillCloseBrace DEF}
%%   -> {ABC \lowercase{DEF}}
%%
%%......................................................................
\newcommand\LowercaseTillCloseBrace{%
   \FetchTillCloseBrace{\lowercase}%
}%

\makeatother

\begin{document}

\frenchspacing

{This is rmfamily. \FetchTillCloseBrace{\textsf}This is sffamily.}
This is rmfamily.

\bigskip

{ABC \LowercaseTillCloseBrace DEF}
GHI

\bigskip

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

\bigskip

\def\tempa{This is tempa outside the local scope. }%
{%
  \def\tempa{This is tempa inside the local scope. }%

  \CopyBehindCloseBrace{}\tempa
}

% This does _not(!) work:
% {Text\CopyBehindCloseBrace{Bla}\verb$verbatim text?$}
%
% Nor does this work:
%
% {Text \FetchTillCloseBrace{\textbf}\verb&verbatim \TeX t&}
%
% While this works:
% {Text \bfseries\selectfont \verb&verbatim \TeX t&}

\end{document}

在此处输入图片描述

相关内容