![宏扩展的问题](https://linux22.com/image/314746/%E5%AE%8F%E6%89%A9%E5%B1%95%E7%9A%84%E9%97%AE%E9%A2%98.png)
以下代码有效,但如果您注释第 20 行并取消注释第 21 行,LaTeX 会抱怨 \endmap 未定义。我真的不明白为什么会这样,更不明白该怎么做。
\documentclass{article}
\usepackage[]{a4wide}
\usepackage[left]{lineno}
\newcommand{\define}{\newcommand}
\def\speakify#1:#2\par{{\itshape#1}: #2\par}
\def\map#1\par{\ifx\endmap#1\else\do#1\par\expandafter\map\fi}
\def\interviewstart{\linenumbers\let\do\speakify\map}
\def\interviewstop{\par\endmap\par\nolinenumbers}
\begin{document}
%\linenumbers\let\do\speakify\map
\interviewstart
I: I have a question for you that I would really like to know the answer to. Could you please explain it in your own words while the moon is still high in the sky? That would be lovely thank you very much!
L: Of course I will answer gladly all questions you might have no matter how silly I feel they may be provided payment is made in full before commencement of the answering phase.
\par\endmap\par\nolinenumbers % line 20
%\interviewstop % line 21
\end{document}
答案1
您的\map
命令有一个以 分隔的参数\par
。
当你这样做
\interviewstart
I: I have a question ...
L: Of course I will answer ...
\interviewstop % line 21
\end{document}
该宏\interviewstart
被替换为
\linenumbers\let\do\speakify\map
并且的论点\map
被认为是
I: I have a question ...
由于I
不等于\endmap
,因此遵循错误分支,最终导致另一个\map
宏。
现在发生的\map
是
L: Of course I will answer ... \interviewstop
因为 TeX 在吸收宏时不会扩展标记,并且之前的空行\end{document}
提供了\par
分隔符。
同样,L
不是\endmap
,因此遵循错误分支,在扩展标记的过程中,TeX 到达\interviewstop
,其替换文本包含\endmap
未定义的。
当您有显式的 时\par\endmap\par\nolinenumbers
,不会出现问题,因为第一个\par
是参数分隔符,下一个\map
命令将作为其参数吸收\endmap
。由于您比较了两个未定义的标记,因此遵循 true 分支,从而获得幸福结局。
你要做的是吸收从\interviewstart
到的整个文本\interviewstop
,然后对吸收的标记进行处理。
\documentclass{article}
\usepackage[left]{lineno}
\def\speakify#1: #2\par{\textit{#1}: #2\par}
\long\def\map#1\par{%
\ifx\interviewstart#1%
\else
\speakify#1\par
\expandafter\map
\fi
}
\long\def\interviewstart#1\interviewstop{%
\linenumbers
\map#1\par\interviewstart\par
\nolinenumbers
}
\begin{document}
\interviewstart
I: I have a question ...
L: Of course I will answer ...
\interviewstop
\end{document}
此版本允许任意数量的空行
\documentclass{article}
\usepackage[left]{lineno}
\def\speakify#1: #2\par{\textit{#1}: #2\par}
\long\def\map#1\par{%
\ifx\hfuzz#1\hfuzz
\let\next\map
\else
\ifx\interviewstart#1%
\let\next\relax
\else
\speakify#1\par
\let\next\map
\fi
\fi
\next
}
\long\def\interviewstart#1\interviewstop{%
\linenumbers
\map#1\par\interviewstart\par
\nolinenumbers
}
\begin{document}
\interviewstart
I: I have a question ...
L: Of course I will answer ...
\interviewstop
\end{document}
但环境要好得多。
\documentclass{article}
\usepackage[left]{lineno}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentEnvironment{interview}{m}
{
\par
\linenumbers
\keys_set:nn { hkbst/interview } { #1 }
}
{
\par
}
\NewDocumentCommand{\Q}{}{\par\textit{\l_hkbst_questioner_tl}:~}
\NewDocumentCommand{\A}{}{\par\textit{\l_hkbst_answerer_tl}:~}
\keys_define:nn { hkbst/interview }
{
q .tl_set:N = \l_hkbst_questioner_tl,
a .tl_set:N = \l_hkbst_answerer_tl,
}
\ExplSyntaxOff
\begin{document}
\begin{interview}{q=I,a=L}
\Q I have a question ...
\A Of course I will answer ...
\end{interview}
\end{document}
答案2
对于这个环境,正常的乳胶语法是:
\documentclass{article}
\usepackage[]{a4wide}
\usepackage[left]{lineno}
\newenvironment{interview}{\linenumbers\everypar{\additalic}}{\par}
\def\additalic#1:{\textit{#1}:}
\begin{document}
\begin{interview}
I: I have a question for you that I would really like to know the answer to. Could you please explain it in your own words while the moon is still high in the sky? That would be lovely thank you very much!
L: Of course I will answer gladly all questions you might have no matter how silly I feel they may be provided payment is made in full before commencement of the answering phase.
\end{interview}
\end{document}
实际上我会使用如下语法
\item[L] I have a question....
那么你就不需要任何低级分隔宏或\everpar
技巧。
在评论中,您要求将段落设置为斜体,将标签设置为粗体。
\newenvironment{interview}{\linenumbers\itshape\everypar{\additalic}}{\par}
\def\additalic#1:{\textup{\textbf{#1}}:}