动机

动机

抱歉,标题太长(问题也更长),但这是一个相当复杂的主题,需要稍微详细说明一下。

目标:我想定义一对乳胶宏,我可以在源代码中编写它们来界定文本区域,使其“出现在下一页,景观化,在此页填满之后”。这些宏不能是一种新的环境(但可以基于一种环境)

动机

我有一份用 markdown 编写的文档,需要pandoc将其转换为 LaTeX。每个 markdown 表都转换为longtable。一切都自动进行,并且运行正常。

但是,有些表格对于页面宽度来说太宽了(自动生成的表格longtables没有p-type 列,我无法控制这一点)。所以我想把这些表格放在一边。现在问题来了。我会告诉你迄今为止的(失败的)尝试。

第一次尝试。使用pdflscape

我可以编辑 pandoc 使用的 latex 模板,并将包和我自己的命令添加到序言中。所以我添加了\usepackage{pdflscape}。此外,如果 latex 宏出现在 markdown 源中,pandoc 会将它们不加改变地传递给生成的 latex 文件,因此我尝试在我的 markdown 文档中写入以下内容:

\begin{landscape}
 ... markdown code for the long table
 ...
\end{landscape}

生成的 latex 编译没有问题,但结果并不如我所料。不仅宏没有\begin/\end改变就传递了,而且它们之间的所有内部 markdown 代码也没有改变。即:markdown 表没有被翻译成合适的 latex 表,而是“逐字”传递了。

在阅读 pandoc 文档后,我发现这是预期的行为。当 pandoc 检测到一对\begin{something}/\end{something}时,会假定该 latex 环境的内容也是 latex,因此这种方法不起作用。

第二次尝试。伪造landscape环境

由于问题在于 pandoc 对特殊语法进行了硬编码\begin{}/\end{},因此我尝试避免使用该语法。

我在 Latex 模板的前言中定义了以下宏:

\usepackage{pdflscape}
\def\startlandscape{\begin{landscape}}
\def\stoplandscape{\end{landscape}}

并在markdown源中写入以下内容:

\startlandscape
 ... markdown code for the long table
 ...
\stoplandscape

这有效!这些宏“按原样”传递给 latex 文档,编译时没有问题。宽表现在以横向排版。

问题是这longtable不是一个浮动环境,因此当出现那个长表格时,当前页面被中止(填充白色),表格被放入下一页,横向显示。所以我的文本中有很大空白。

为了变得更聪明,我做了以下事情:

第三次尝试。通过以下方式推迟 longtable 的输出:afterpage

afterpage软件包提供了命令\afterpage{},它将收到的文本作为参数保存起来,并仅在当前页面写满后输出。这将在下一页排版表格之前用更多文本填充当前页面。

现在的问题是:如何将完整的landscape环境传递给\afterpage

简单的方法:

\newenvironment{postponelandscape}{%
   \afterpage{\begin{landscape}
}{%
    \end{landscape}}
}

显然是错误的,因为 的两个参数中的括号不平衡\newenvironment

第四次尝试。使用environ

此包能够创建“捕获”内容并将其存储在名为 的宏中的环境\BODY,该宏稍后可以作为参数传递给任何其他命令(\afterpage在我的情况下)。因此,我在序言中添加了以下几行:

\usepackage{pdflscape}
\usepackage{afterpage}
\usepackage{environ}
\NewEnviron{postponelandscape}{%
   \afterpage{\begin{landscape}\BODY\end{landscape}}
}

这定义了新的环境postponelandscape。我在纯 latex 源代码中测试了这个环境,例如:

Text before the table

\begin{postponelandscape}
  \begin{longtable}{...}
     ...
  \end{longtable}
\end{postponelandscape}

More text after the table

效果非常好。整个长表格以横向显示在下一页中,当前页面则显示“表格后面有更多文本”,而不是空白。

因此,只需像我之前所做的那样,将此环境“伪造”为一对\start/\stop命令即可欺骗 pandoc。我在序言中添加了以下内容:

\def\startlandscape{\begin{postponelandscape}}
\def\stoplandscape{\end{postponelandscape}} 

所以我尝试了:

\startlandscape
  \begin{longtable}{...}
     ...
  \end{longtable}
\stoplandscape

但此操作失败并出现错误:

! LaTeX Error: \begin{postponelandscape} on input line XX ended by \end{document}.

所以,(最后!)我的问题是:

  1. 为什么会发生这种情况?为什么这个\start/\stop技巧对landscapeenv 有效(第二次尝试),但对postponedlandscapeenv 无效(第四次尝试)?

  2. 有什么办法可以解决我的问题吗?欢迎使用任何其他方法。

让我重申一下目标:我想定义一对乳胶宏,我可以在源代码中写入它们来界定一个文本区域,如“在这一页写满之后,出现在下一页,以景观形式显示”。

答案1

使用

\afterpage{\clearpage\input{mytable}}

mytable 的位置

\begin{landscape}
\begin{longtable}
...
\end{longtable}
\end[landscape}

这很可能会在 Latex 中做正确的事情,并且大概可以做相当于

\input{mytable}

在任何 pandoc 转换为其他格式时。

答案2

仅供将来参考,我报告现在 pandoc 还可以识别以和开头的命令\start作为\stopLaTeX 代码块,因此我将其重命名\startlandscape\blandscape\stoplandscape\elandscape,现在横向页面开始和结束命令之间的 markdown 代码可以编译为 LaTeX。

我在 LaTeX 模板头中声明了它们,如下所示:

\usepackage{pdflscape}
\newcommand{\blscape}{\begin{landscape}}
\newcommand{\elscape}{\end{landscape}}

现在这段 markdown + LaTeX 代码

\blandscape

![Image.](assets/image.svg){#fig:image}

\elandscape

正确编译为

\begin{landscape}

\begin{figure}
\hypertarget{fig:image}{%
\centering
\includegraphics{assets/image.svg}
\caption{Image.}\label{fig:image}
}
\end{figure}

相关内容