![如何自动将命令行会话输出包含在文档中?](https://linux22.com/image/241537/%E5%A6%82%E4%BD%95%E8%87%AA%E5%8A%A8%E5%B0%86%E5%91%BD%E4%BB%A4%E8%A1%8C%E4%BC%9A%E8%AF%9D%E8%BE%93%E5%87%BA%E5%8C%85%E5%90%AB%E5%9C%A8%E6%96%87%E6%A1%A3%E4%B8%AD%EF%BC%9F.png)
当我编写包含源代码示例和代码片段的文档时列表package 是包含此类内容的绝佳解决方案。特别是使用\lstinputlisting
命令和firstline
/lastline
选项,您无需进行复制/粘贴,并且可以轻松测试示例。
但是命令行会话的集成怎么样?例如bash
,Haskell 解释器中的会话hugs
或 Python shell 中的会话?
理想情况下,我希望能够用 LaTeX 编写类似这样的内容:
\begin{hugs}[nostartbanner]
take 3 [1..]
reverse "hello world"
\end{hugs}
并在我的文档中获得以下输出:
拥抱> 拍摄 3 [1..] [1,2,3] 拥抱>反向“你好世界” “dlrow olleh”
(或许加上一些语法高亮)
这意味着这样的环境应该自动启动一个外部 shell(例如 hugs)并将会话输出粘贴到文档中。此外,为了获得加分,它还应该对输出进行一些缓存。
这种方法有助于减少预期输出中的拼写错误和复制粘贴的现象(当然这很容易出错)。
另外,在为注释行程序或仍处于快速开发阶段的 shell 编写文档时,当输出自动集成到 LaTeX 文档中时,您不必手动检查所有现有示例。
我怎样才能用 LaTeX 解决这个问题?
我发现“屏幕会话”的列表语言,但这个问题只是关于语法高亮部分。
答案1
正如@egreg所建议的,包裹bashful
是专门为此设计的。引用用户手册:
...bashful 为 TEX 的原语提供了一个方便的接口
\write18
— 从输入文件中执行 shell 命令,也称为 shell escape。\bash
和之间的文本\END
由流行的 Unix 命令行解释器 bash 执行。 各种标志控制执行的命令及其输出是否显示在打印文档中,以及是否将它们保存到文件中。尽管已经规定可以使用 bash 以外的 shell,但是此软件包可能无法在 Microsoft 操作系统上不经修改而运行。
请注意,这需要-shell-escape
指定选项。
这里我只使用了基本bash
命令。我想你也可以用 Haskell 解释器做类似的事情。
bash 脚本文件的第一行以 开头%
,因此我从第 2 行开始列出清单,并将第一行留空。启动命令时,您需要为bash 文件和输出文件\bash
提供文件名。然后使用将该文件的内容重新合并到文件中。.sh
lstinputlisting
.tex
\documentclass{standalone}
\usepackage{xcolor}
\usepackage{bashful}
\usepackage{listings}
\lstdefinestyle{BashInputStyle}{
language=bash,
firstline=2,% Supress the first line that begins with `%`
basicstyle=\small\sffamily,
numbers=left,
numberstyle=\tiny,
numbersep=3pt,
frame=tb,
columns=fullflexible,
backgroundcolor=\color{yellow!20},
linewidth=0.9\linewidth,
xleftmargin=0.1\linewidth
}
\lstdefinestyle{BashOutputStyle}{
basicstyle=\small\ttfamily,
numbers=none,
frame=tblr,
columns=fullflexible,
backgroundcolor=\color{blue!10},
linewidth=0.9\linewidth,
xleftmargin=0.1\linewidth
}
\begin{document}
\bash[verbose,scriptFile=hello.sh,stdoutFile=hello.tex]
echo "Hello World!"
echo "Today is" `date`
echo ""
echo "Disk usage is:"
df
\END
\par\noindent
Executing the following code in \textbf{bash}
\lstinputlisting[style=BashInputStyle]{hello.sh}
%
yields the following output:
\lstinputlisting[style=BashOutputStyle]{hello.tex}
\end{document}
答案2
在 ConTeXt 中,筛选模块允许您运行任何外部程序并读取其输入。基本设置是(我使用的是ghci
而不是hugs
因为我没有hugs
安装)。
\usemodule[filter]
\defineexternalfilter
[ghci]
[
filtercommand={cat \externalfilterinputfile\space | ghci > \externalfilteroutputfile},
readcommand=\typefile,
output=\externalfilterbasefile.out,
]
此后,的内容\startghci ... \stopghci
将被传递给 ConTeXt ghci
,并将其输出重新输入到 ConTeXt。您可以使用以下方式进一步配置
更改
readcommand
为\typefile[range={6,-2}]
。这将仅排版从第 6 行到输出文件的倒数第二行。对于 Hugs,这可用于删除横幅。添加
continue=yes
。使用此选项,结果将被缓存,并且仅当文件的 md5sum 已更改时才重新运行。但continue=yes
不适用于包含 的命令|
。您可以创建运行重定向的.sh
或文件,或者,如果提供了命令行参数来指定输入文件,请使用该文件。.cmd
ghci
添加
directory=...
将临时文件重定向到不同的目录。使用
before
和after
键在环境之前或之后添加一些内容。如果您想要排版语法高亮的输入文件,这将非常有用。
下面是一个完整的例子:\usemodule筛选 \使用模块[vim]
\definevimtyping[haskell][syntax=haskell]
\defineexternalfilter
[ghci]
[
filtercommand={cat \externalfilterinputfile\space | ghci > \externalfilteroutputfile},
readcommand={\typefile[range={6,-2}]},
output=\externalfilterbasefile.out,
before={\typehaskellfile{\externalfilterinputfile}},
]
\starttext
\startTEXpage
\startghci
take 3 [1..]
reverse "hello world"
\stopghci
\stopTEXpage
\stoptext
这使
请注意,输出与您想要的并不完全相同,因为ghci
没有回显输入行。我不知道是否有命令行选项可以更改这一点。