我知道如何定义一个将段落的其余部分作为参数的宏。只需写入即可\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