如何自动将命令行会话输出包含在文档中?

如何自动将命令行会话输出包含在文档中?

当我编写包含源代码示例和代码片段的文档时列表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提供文件名。然后使用将该文件的内容重新合并到文件中。.shlstinputlisting.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或文件,或者,如果提供了命令行参数来指定输入文件,请使用该文件。.cmdghci

  • 添加directory=...将临时文件重定向到不同的目录。

  • 使用beforeafter键在环境之前或之后添加一些内容。如果您想要排版语法高亮的输入文件,这将非常有用。

下面是一个完整的例子:\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没有回显输入行。我不知道是否有命令行选项可以更改这一点。

相关内容