我想打印一份针对不同操作系统的 TeX 安装指南,但大多数文本对于所有操作系统都是相同的。因此我构建了以下内容
\documentclass{article}
\usepackage{environ}
\newcommand{\mlw}[3]{}
\NewEnviron{multichaps}{%
\renewcommand{\mlw}[3]{##1}%
\BODY
\renewcommand{\mlw}[3]{##2}%
\BODY
\renewcommand{\mlw}[3]{##3}%
\BODY
}
\begin{document}
\begin{multichaps}
\section{Installation on \mlw{Mac}{Windows}{Linux}}
Now it's time to test the system. Create a file
test.tex with the follwoing content.
\begin{verbatim}
\documentclass{article}
\begin{document}
Hallo World!
\end{document}
\end{verbatim}
Now open your \mlw{Terminal}{Command Promt}{Terminal}
and call \verb+pdflatex test+
\end{multichaps}
\end{document}
我\mwl
可以将文本设置为仅出现在一个操作系统的文本中,或者为不同的操作系统设置不同的文本。一切正常,但当我尝试verbatim
在正文中使用时,它会崩溃。
是否可以做到这一点或者是否有其他方法可以做这样的事情?
答案1
环境environ
像宏一样一次性读取其内容,因此不是“真实”环境,而是伪环境(看起来像环境,工作方式像宏)。这不允许像普通宏一样逐字内容。在启用逐字模式之前会读取内容,因此所有代码都已解析和分类。
为了解决这个问题,您需要使用正常环境,然后多次复制内容。通常可以通过将内容存储在保存箱中来完成此操作,但您的三种替代方案不允许这样做,因为装箱将修复内容。相反,您应该将内容写入外部文件并多次读取。这可以自动完成,而无需手动filecontents
环境。包提供了一种简单的方法,listings
如我在将环境主体逐字写入文件。
\documentclass{article}
\makeatletter
\RequirePackage{listings}
\lst@RequireAspects{writefile}
\newcommand{\mlw}[3]{}
\newcommand{\mlwa}[3]{#1}
\newcommand{\mlwb}[3]{#2}
\newcommand{\mlwc}[3]{#3}
\lstnewenvironment{multichaps}{%
% Write file to given filename
\lst@BeginWriteFile{\jobname.mul}%
}
{%
\lst@EndWriteFile% closes output file
\let\mlw\mlwa
\input{\jobname.mul}%
\let\mlw\mlwb
\input{\jobname.mul}%
\let\mlw\mlwc
\input{\jobname.mul}%
}
\makeatother
\begin{document}
\begin{multichaps}
\section{Installation on \mlw{Mac}{Windows}{Linux}}
Now it's time to test the system. Create a file
test.tex with the follwoing content.
\begin{verbatim}
\documentclass{article}
\begin{document}
Hallo World!
\end{document}
\end{verbatim}
Now open your \mlw{Terminal}{(Eingabeaufforderung)}{Terminal}
and call \verb+pdflatex test+
\end{multichaps}
\end{document}
或者,您可以将内容逐字存储在宏中,然后使用 e-TeX 的 重新评估它\scantokens
,这与将其写入外部文件并重新读取基本相同,但效率更高。这里的一个问题似乎是行尾 (EOF) 字符的处理。例如,可以使用我的newverbs
包将内容存储在宏中。但是,它尚未提供环境变体,因此您需要使用宏版本:
\documentclass{article}
\usepackage{newverbs}
\newcommand{\mlw}[3]{}
\newcommand{\mlwa}[3]{#1}
\newcommand{\mlwb}[3]{#2}
\newcommand{\mlwc}[3]{#3}
\makeatletter
\newcommand{\multichaps}{%
\begingroup
\expandafter\Collectverb\expandafter\@multichaps\expandafter
}
% The EOL character must be active to work with 'verbatim'.
% By default it should produce a space.
% This will break implicit paragraphs!
\begingroup
\catcode13=\active%
\gdef\activenl{%
\catcode13=\active%
\let^^M\space%
}%
\endgroup%
\newcommand{\@multichaps}[1]{%
\activenl
\let\mlw\mlwa
\scantokens{#1}%
\let\mlw\mlwb
\scantokens{#1}%
\let\mlw\mlwc
\scantokens{#1}%
\endgroup
}
\makeatother
\begin{document}
\multichaps=
\section{Installation on \mlw{Mac}{Windows}{Linux}}
Now it's time to test the system. Create a file
test.tex with the follwoing content.
\begin{verbatim}
\documentclass{article}
\begin{document}
Hallo World!
\end{document}
\end{verbatim}
Now open your \mlw{Terminal}{(Eingabeaufforderung)}{Terminal}
and call \verb+pdflatex test+
=
\end{document}
答案2
在 ConTeXt 中,存储和操作主体环境(不将其存储为宏)的标准方法是使用buffers
。例如,这是在 ConTeXt 中编写相同宏的方式,并且它可以按预期工作。
\let\mlw\gobblethreearguments
\def\startmultichapters
{\grabbufferdata[multichapters][startmultichapters][stopmultichapters]}
\def\stopmultichapters
{\let\mlw\firstofthreearguments
\getbuffer[multichapters]%
\let\mlw\secondofthreearguments
\getbuffer[multichapters]%
\let\mlw\thirdofthreearguments
\getbuffer[multichapters]%
\let\mlw\gobblethreearguments}
\starttext
\startmultichapters
\startsection[title={\mlw{foo}{bar}{baz}}]
This is some text in section \mlw{foo}{bar}{baz}
\starttyping
Crash
\stoptyping
\stopsection
\stopmultichapters
\stoptext
笔记:如果您使用的是旧版本的 ConTeXt(2012 年 2 月之前),则需要将其替换\grabbufferdata
为\dostartbuffer
。
据我所知,LaTeX 没有与 ConTeXt 缓冲区等效的缓冲区。最接近的方法是使用环境filecontents
将内容写入外部文件(在 MkII 中,ConTeXt 缓冲区也将内容写入外部文件;但在 MkIV 中,内容保存在内存中)。请参阅 Taco Hoekwater 对LaTeX 相当于 ConTeXt 缓冲区。
答案3
有时候,人们会只见树木不见森林……我没有想过将内容放入外部文件并将其包含三次……
\begin{filecontents}{multichapsbody.tex}
\section{Installation on \mlw{Mac}{Windows}{Linux}}
Now it's time to test the system. Create a file
test.tex with the follwoing content.
\begin{verbatim}
\documentclass{article}
\begin{document}
Hallo World!
\end{document}
\end{verbatim}
Now open your \mlw{Terminal}{(Eingabeaufforderung)}{Terminal}
and call \verb+pdflatex test+
\end{filecontents}
\documentclass{article}
\newcommand{\mlw}[3]{}
\begin{document}
\renewcommand{\mlw}[3]{#1}
\input{multichapsbody}
\renewcommand{\mlw}[3]{#2}
\input{multichapsbody}
\renewcommand{\mlw}[3]{#3}
\input{multichapsbody}
\end{document}
答案4
您的另一个答案,但无需编写外部文件:)
\documentclass{article}
\usepackage{scontents}
\begin{scontents}[store-env=multichapsbody]
\section{Installation on \mlw{Mac}{Windows}{Linux}}
Now it's time to test the system. Create a file
test.tex with the follwoing content.
\begin{verbatim}
\documentclass{article}
\begin{document}
Hallo World!
\end{document}
\end{verbatim}
Now open your \mlw{Terminal}{(Eingabeaufforderung)}{Terminal}
and call \verb+pdflatex test+
\end{scontents}
\setlength{\parindent}{0pt}
\pagestyle{empty}
\newcommand{\mlw}[3]{}
\begin{document}
\renewcommand{\mlw}[3]{#1}
\getstored[1]{multichapsbody}
\renewcommand{\mlw}[3]{#2}
\getstored[1]{multichapsbody}
\renewcommand{\mlw}[3]{#3}
\getstored[1]{multichapsbody}
\end{document}