如何处理 LuaLaTeX 中的逐字材料?

如何处理 LuaLaTeX 中的逐字材料?

在尝试实现自己的工作替代方案时shdoc(其中一个问题参见这里) 我遇到了 LuaLaTeX 的一个有趣的行为,我无法解释。

考虑以下代码:

\documentclass{scrreprt}
\usepackage{xparse}
\usepackage{luacode}

\DeclareDocumentCommand{\terminaloutput}{+v}{
    \directlua{tex.print("\luatexluaescapestring{#1}")}
}

\begin{document}
\terminaloutput{
total 10244
drwxr-xr-x 47 User Users   16384 Mar 31 18:26 .
dr-xr-xr-x  8 User Users    4096 Jun 27  2015 ..
drwxr-xr-x  9 User Users    4096 Dec 23 12:49 .editor
-rw-r--r--  1 User Users    2950 Mar 31 09:01 .bash_history
}
\end{document}

我刚刚使用逐字参数 () 定义了一个函数,由于中\terminaloutput有 ,因此该参数必须是逐字的。我的问题是为什么 LaTeX 能够打印 的全部内容(如预期的那样以连续的方式)而 Lua 却不打印任何内容。_.bash_history#1

答案1

我更愿意参考 Paul Isambert 的精彩文章,并在此基础上进行改进。LuaTEX:如何写一个段落,于2011年在TUGBoat第32卷出版。

在本文中,作者讨论除其他外如何利用 LuaTeX 的process_input_buffer回调以非常强大和灵活的方式处理逐字材料。引用文章中的一段话:

TeX 最神秘的领域之一是 catcode 管理。当想要打印逐字文本时,这一点变得非常重要,即 TeX 应该将代码读取为仅需排版的字符,而没有特殊字符,而当想要排版一段代码并执行它时,事情就会变得非常混乱(通常必须使用外部文件)。使用回调 process_input_buffer,这些限制就消失了:我们通常传递给 TeX 的行可以存储起来,之后以各种方式使用。

下面显示的 MWE 将 Paul 的 TUGBoat 文章代码改编为 LaTeX 编码实践。(Paul 的代码明显是 PlainTEX 风格。)如果您对这个问题感兴趣,您绝对应该阅读 Paul 的原始文章;关于处理逐字材料的段落位于文章的 pdf 文件版本的第 2 页和第 3 页(原始出版期刊卷的第 69 页和第 70 页)。Paul 对这些问题的解释比我好得多。

  • Lua 端代码包括定义一个 Lua 表(用于保存逐字材料)和 3 个完成大部分工作的 Lua 函数。

  • TeX 端代码设置了几个 TeX 宏,用于激活、调用和暂停 Lua 函数的操作。主要的 LaTeX 宏是\printverbatim(您应该能够猜出它的作用……)和\useverbatim;后者执行最近读取的逐字块中的任何内容。

  • 逐字块是夹在分别写着\Verbatim和的行之间的任何\EndVerbatim内容。如果行中有任何内容分别包含字符串\Verbatim\EndVerbatim,它将被忽略。

请注意,我有不是定义一个名为的 LaTeX 环境Verbatim,尽管这样做并不太难。

在此处输入图片描述

% !TEX TS-program = lualatex
\documentclass{scrreprt}
%% Set up a Lua table and 3 Lua functions
\directlua{%
verb_table = {}
function store_lines (str)
   if string.find (str , "\noexpand\\EndVerbatim" ) then
      luatexbase.remove_from_callback (
         "process_input_buffer" , "store_lines")
   else
      table.insert(verb_table, str)
   end
   return ""
end
function register_verbatim ()
   verb_table = {}
   luatexbase.add_to_callback(
      "process_input_buffer" , store_lines , "store_lines")
end
function print_lines ( catcode )
   if catcode then
      tex.print ( catcode , verb_table)
   else
      tex.print ( verb_table )
   end
end
}
%% TeX-side code: define several macros
\def\Verbatim{\directlua{register_verbatim()}}
\def\useverbatim{\directlua{print_lines()}}
\def\printverbatim{%
   \par
   \bgroup
   \setlength{\parindent}{0pt}
   \ttfamily
   \directlua{print_lines(1)}
   \egroup
   }
\def\createcatcodes{%
   \bgroup
   \catcode`\\=12 \catcode`\{=12 \catcode`\}=12
   \catcode`\$=12 \catcode`\&=12 \catcode`\^^M=13
   \catcode`\#=12 \catcode`\^=12 \catcode`\_=12
   \catcode`\ =13 \catcode`\~=12 \catcode`\%=12
   \savecatcodetable 1 % '\savecatcodetable' is a LuaTeX primitive
   \egroup}
\createcatcodes
\def\Space{ }
\bgroup
\catcode`\^^M=13\gdef^^M{\quitvmode\par}%
\catcode`\ = 13\gdef {\quitvmode\Space}%
\egroup

\begin{document}

\Verbatim
total 10244
drwxr-xr-x 47 User Users   16384 Mar 31 18:26 .
dr-xr-xr-x  8 User Users    4096 Jun 27  2015 ..
drwxr-xr-x  9 User Users    4096 Dec 23 12:49 .editor
-rw-r--r--  1 User Users    2950 Mar 31 09:01 .bash_history
\EndVerbatim
\printverbatim

\bigskip
\Verbatim
\def\lululu{%
Lua\kern-.01em
\TeX
}%
\EndVerbatim
\printverbatim

\bigskip
\useverbatim % this "registers" the macro "\lululu"
\noindent\lululu
\end{document}

答案2

Mico 的回答非常好,并展示了 LuaTeX 中逐字缓冲区的低级实现是什么样子。

ConTeXt 附带此功能,并且使用起来非常简单。

\starttext

\startbuffer[terminal]
total 10244
drwxr-xr-x 47 User Users   16384 Mar 31 18:26 .
dr-xr-xr-x  8 User Users    4096 Jun 27  2015 ..
drwxr-xr-x  9 User Users    4096 Dec 23 12:49 .editor
-rw-r--r--  1 User Users    2950 Mar 31 09:01 .bash_history
\stopbuffer

\typebuffer[terminal]

\startbuffer[logo]
\def\lululu{%
Lua\kern-.01em
\TeX
}%
\stopbuffer

\typebuffer[logo]

\getbuffer[logo]
\lululu

\stoptext

输出与 Mico 的答案类似。

答案3

另一种方法是模仿 ConTeXt緩衝器scontents包。获得的输出与Mico的响应相同,当然不是“防弹”,但是,请允许我verbatim使用和自定义输出fancyvrbtcolorbox正如我在您的评论中读到的那样。

包的主要功能是存储内容,但尝试\typebuffer使用来模仿verbatim,无论如何,这是我的答案:

\documentclass{article}
\usepackage{scontents}
\setlength{\parindent}{0pt}
\pagestyle{empty}
\begin{document}
\section{default}
% stored in terminal
\begin{scontents}[store-env=terminal]
total 10244
drwxr-xr-x 47 User Users   16384 Mar 31 18:26 .
dr-xr-xr-x  8 User Users    4096 Jun 27  2015 ..
drwxr-xr-x  9 User Users    4096 Dec 23 12:49 .editor
-rw-r--r--  1 User Users    2950 Mar 31 09:01 .bash_history
\end{scontents}
\typestored[1]{terminal}

% stored in logo
\begin{scontents}[store-env=logo]
\def\lululu{
Lua\kern-.01em
\TeX
}
\end{scontents}
\typestored[1]{logo}
\getstored[1]{logo}
\lululu
\end{document}

输出默认值

\typestored使用fancyvrb和自定义输出tcolorbox

\documentclass{article}
\usepackage{scontents}
\makeatletter
\let\verbatimsc\@undefined
\let\endverbatimsc\@undefined
\makeatother
\usepackage{fancyvrb,tcolorbox}
\newenvironment{verbatimsc} %
{\VerbatimEnvironment
\begin{tcolorbox}[colback=gray!25, boxsep=0pt, arc=0pt, boxrule=0pt]
\begin{Verbatim}[fontsize=\small]} %
{\end{Verbatim} %
\end{tcolorbox}}
\setlength{\parindent}{0pt}
\pagestyle{empty}
\begin{document}
\section{Using tcolorbox and fancyvrb}
% stored in terminal
\begin{scontents}[store-env=terminal]
total 10244
drwxr-xr-x 47 User Users   16384 Mar 31 18:26 .
dr-xr-xr-x  8 User Users    4096 Jun 27  2015 ..
drwxr-xr-x  9 User Users    4096 Dec 23 12:49 .editor
-rw-r--r--  1 User Users    2950 Mar 31 09:01 .bash_history
\end{scontents}
\typestored[1]{terminal}

% stored in logo
\begin{scontents}[store-env=logo]
\def\lululu{
Lua\kern-.01em
\TeX
}
\end{scontents}
\typestored[1]{logo}
\getstored[1]{logo}
\lululu

\end{document}

输出自定义

相关内容