\def 以该行的其余部分作为参数

\def 以该行的其余部分作为参数

我知道如何定义一个将段落的其余部分作为参数的宏。只需写入即可\def\a#1\par{\textbf{#1}}

但是,我该如何编写一个其参数将延伸到行尾的宏呢?

答案1

这个答案建立在 Martin Scharrer 的更新解决方案之上(该解决方案基于我的,基于他的......;-p)。

\documentclass{article}
\begin{document}
\newcommand*{\newlinecommand}[2]{%
  \newcommand*{#1}{%
    \begingroup%
    \escapechar=`\\%
    \catcode\endlinechar=\active%
    \csname\string#1\endcsname%
  }%
  \begingroup%
  \escapechar=`\\%
  \lccode`\~=\endlinechar%
  \lowercase{%
    \expandafter\endgroup
    \expandafter\def\csname\string#1\endcsname##1~%
  }{\endgroup#2\space}%
}

%%% USAGE:
\newlinecommand{\emphline}{\emph{#1}}

First words \emphline rest of line
some more text

\end{document}

\emphline将行末字符的 catcode 设置为活动状态(我们可以使用其他一些选项,只要它是一致的)。然后它调用\\emphline,它负责抓取直到行末的参数,并应用于\emph{ }它(这是#2的定义\newlinecommand)。

我们使用\begingroup\endgroup将 catcode 的更改范围限制\endlinechar在 的内部\emphline

为了获取行尾,我们使用了分隔参数,但为此,我们需要有一个活动的行尾字符。两种可能性:

  • 在本地更改 catcode,然后在定义中使用这个活动的行尾,但这在我们的例子中失败了,因为我们已经在定义(的\newlinecommand)内部,并且 catcode 不能再更改

  • \lowercase{~}在定义小写字母~作为行尾字符后使用。

最后,构造在我们的例子中\csname\string#1\endcsname生成控制序列(因为是)。我们通过将转义字符(TeX 用于)设置为实际为来确保生成。\\emphline#1\emphline\string\emphline\string\

答案2

TeX 中的行尾字符是 ASCII 13回车符可以用 (M=字母表中的第 13 个字符) 表示的字符^^M。这与实际输入文件格式无关 (即 DOS/Windows 与 Unix 与 Mac 行尾字符)。

但是你不能简单地这样写,\def\a#1^^M{\textbf{#1}}因为 TeX 不喜欢这样。一种方法是重新定义它的 catcode(参见 TeXBook):

\def\restofline{%
    \begingroup
    \catcode`\^^M=\active
    \irestofline
}
\begingroup
\catcode`\^^M=\active %
\gdef\irestofline#1^^M{%
  \iirestofline{#1}%
  \endgroup %
  \space % Readd effective space from removed end-of-line
}%
\endgroup %

\def\iirestofline#1{\textbf{#1}}

%%% USAGE:
First words \restofline rest of line

这在我的测试中有效,但可能存在某种缺陷,并且可能有更好/更有效的方法来做到这一点。

请注意,可以使用注释掉行尾,%在这种情况下该宏也会读取下一行。


这是 Bruno Le Floch 解决方案的一个变体(基于我上面的解决方案),其中#不必#1加倍。诀窍是使用第二个宏来实现这一点。请注意 会从\csname\string#1\endcsname生成命令序列。\\foo\foo

\documentclass{article}
\begin{document}
\makeatletter
\newcommand*{\newlinecommand}[1]{%
  \newcommand*{#1}{%
    \begingroup%
    \lccode`\~=\endlinechar%
    \lowercase{\def\restofline@aux####1~}{\endgroup\csname\string#1\endcsname{####1}\space}%
    \catcode\endlinechar=\active%
    \restofline@aux%
  }%
  \expandafter\def\csname\string#1\endcsname##1%
}
\makeatother

%%% USAGE:
\newlinecommand{\emphline}{\emph{#1}}

First words \emphline rest of line
some more text

\end{document}

另请注意parselines可能会用到的包。对这类解析感兴趣的人来说,它的代码可能值得一读。

答案3

这是一个依赖于改变 catcode 的粗略解决方案:

\def\TEST
  {\begingroup
   \catcode`\^^M=13
   \doTEST}

\begingroup
\catcode`\^^M=13
\gdef\doTEST#1^^M%
  {\endgroup The line argument is :#1:}
\endgroup

\TEST this is a command that takes on line
as an argument

some more text

\bye

相关内容