我是 LaTeX 的初学者,正在阅读 Leslie Lamport 的《文档准备系统》。在他的书中,他将 LaTeX 源代码放在了通过对源代码运行 latex 获得的输出旁边。更有趣的是,为了使页面上的源代码和输出保持相同的高度,一些源代码被省略了。我想知道他是如何做到省略源代码片段的正确部分的,以便逐字源代码占据与输出相同的高度的。
我已经在 Google 上搜索了各种逐字包。但似乎没有一个包能够足够智能地让逐字源代码占据与输出相同的垂直距离。我现在怀疑是否存在这样的包,或者你必须手动完成。
编辑 我截取了一个例子。我想知道作者是否手动完成了逐字部分,或者是否有一个包可以在要求逐字文本(示例右侧)的高度与实际输出(示例左侧)相同时用省略号替换文本。
答案1
以下是 Herbert 解决方案的改编版。宏\DisplayAsLdots{}
用于包装要替换的源代码内容...
。它使用通过脚本\immediate\write18
预处理文件(感谢 David Carlisle 和 egreg)以生成显示在右侧的源代码:\jobname.vrb
sed
笔记:
- 这只在 Unix 操作系统上有效。
- 正如 Stephen Lehmke 指出的那样,宏内不能有任何换行符
\DisplayAsLdots{}
。 由于
sed
是贪婪的它将有效地吞噬所有其他以同一行开始和结束的宏(以及其间的任何内容)。因此,代码如下:\DisplayAsLdots{foo} xyz \label{bar}
将被视为(注意参数 to 的
\DisplayAsLdots
结束位置):\DisplayAsLdots{foo xyz \label{bar}}
进一步增强:
- 适应在非unix操作系统上工作(也许是不需要临时文件的纯LaTeX解决方案)。
- 使用
\ldots
而不是三个句点。 - 增强的正则表达式以
sed
允许在中换行\DisplayAsLdots
,并使用正确匹配的右括号终止替换(以修复中的第 3 点笔记部分)。
评论此演示风格:
正如评论中提到的,我真的不喜欢这种呈现方式。这是因为这个文档看起来好像是为了itemize
向新手用户说明如何使用列表——我的感觉是,任何可能分散读者注意力的东西都应该尽量减少。在这个例子中,我想到两个问题:
- (以及相关的缺失文本)的使用
. . .
。 - 事实上,输入和输出之间存在一致性。
使用 LaTeX 时,实际上不存在逐行比较输入和输出这一操作,因此,要展示一个看似对齐的示例,读者需要付出额外的努力才能理解。
我宁愿看到完整的输入文本和输出,这样我就可以看到输入和输出之间的对应关系。
请记住,这只是个人观点,其他人可能更喜欢这种风格。
代码:
\documentclass{article}
\usepackage{enumitem}
\usepackage{blindtext}
\usepackage{fancyvrb}
\usepackage{listings}
\setlist[itemize]{leftmargin=*}%
\newcommand*{\DisplayAsLdots}[1]{#1}%
\newlength\CodeWidth
\makeatletter
\newenvironment{ShowCode}[2][]
{\lstset{#1}\VerbatimEnvironment%
\global\CodeWidth=#2%
\begin{VerbatimOut}{\jobname.vrb}}
{\end{VerbatimOut}\settowidth\@tempdima{\lstinputlisting{\jobname.vrb}}%
\ReplaceDisplayedLdots%
\noindent%
\minipage[t]{\CodeWidth}\vspace{0pt}\input{\jobname.vrb}\endminipage\hfill%
\minipage[t]{\dimexpr\@tempdima-2\fboxsep-2\fboxrule\relax}
\vspace{0pt}\lstinputlisting{\jobname.vrb.new}\endminipage}
\newcommand{\ReplaceDisplayedLdots}{%
\immediate\write18{%
cat \jobname.vrb%
| sed -e 's|\string\\DisplayAsLdots{.*}|...|'%
> ./\jobname.vrb.new%
}%
}%
\makeatother
\begin{document}
\blindtext
\begin{ShowCode}[language={[LaTeX]TeX},frame=single,columns=fixed,
basicstyle=\small\ttfamily,breaklines,
keywordstyle=\bfseries,
]{0.50\linewidth}
\begin{itemize}
\item Each list is \DisplayAsLdots{marked with a \emph{label}. The labels in this itemized list are} bullets.
\item List can be \DisplayAsLdots{nested within} one another.
\begin{enumerate}
\item The item labels \DisplayAsLdots{in an enumerated list are numberals or} letters.
\item A list should \DisplayAsLdots{have at least} two items.
\end{enumerate}
\LaTeX\ permits at least four levels \DisplayAsLdots{of nested lists, which is} more than enough.
\item Blank lines \DisplayAsLdots{before an item} have no effect.
\end{itemize}
\end{ShowCode}
\end{document}
答案2
这是一个环境的简单示例:
\documentclass[a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage[scaled=0.82]{beramono}
\usepackage{blindtext}
\usepackage{fancyvrb}
\usepackage{listings}
\newlength\CodeWidth
\makeatletter
\newenvironment{ShowCode}[2][]
{\lstset{#1}\VerbatimEnvironment%
\global\CodeWidth=#2%
\begin{VerbatimOut}{\jobname.vrb}}
{\end{VerbatimOut}%
\noindent%
\minipage[t]{\CodeWidth}\vspace{0pt}\input{\jobname.vrb}\endminipage%
\minipage[t]{\dimexpr\linewidth-\CodeWidth-2\fboxsep-2\fboxrule\relax}
\vspace{0pt}\lstinputlisting{\jobname.vrb}\endminipage}
\makeatother
\begin{document}
\blindtext
\begin{ShowCode}[language={[LaTeX]TeX},frame=single,columns=fixed,
basicstyle=\small\ttfamily,breaklines,postbreak=\mbox{$\hookrightarrow$},
keywordstyle=\bfseries]{0.6\linewidth}
\begin{itemize}
\item This is a item with no sense in its text
\item another one
\end{itemize}
\end{ShowCode}
\end{document}