2

直到今天,我一直在将 knitr 与 Rstudio 中的 .Rnw 文件结合使用来生成 pdf 和 docx 文件,没有任何问题。pdf 转换使用 Rstudio 本地运行,对于 docx 转换,我只需通过将 .tex 文件提供给“编织”.Rnw 文件而在后台调用 pandoc。到目前为止,我一直在使用 pandoc 版本 1.19.2.1 并且工作得很好。但是,在与同事分享我的一些代码以执行此操作后,我意识到在使用更新版本的 pandoc (2.7.3) 时该策略会失败。

到目前为止,我已经尝试更新 knitr 并理解错误,但没有取得多大成功。该问题似乎仅在需要生成的 .tex 文件的阴影区域时出现,通常是在设置 echo=TRUE 之后。

这是我的 Rnw 文件 (min_reproducible_example.Rnw)

\documentclass{article}
\usepackage{multirow}
\setlength\parindent{0pt}
\usepackage{geometry}
\usepackage{longtable}
\usepackage{float}
\usepackage{verbatim}
\usepackage{hyperref}
\geometry{left=1.5cm,right=1.5cm,top=1.5cm,bottom=1.5cm}

\title{Docx from tex file example}

\begin{document}

\maketitle

<<chunk1,echo=TRUE,message=FALSE>>=
library(survival) 

str(lung)
@

\end{document}

在 Rstudio 中点击“编译 PDF”后会生成文件:min_reproducible_example.pdf 和 min_reproducible_example.tex。

以防万一,.Rnw 文件 (min_reproducible_example.tex) 的 .tex 输出为

\documentclass{article}\usepackage[]{graphicx}\usepackage[]{color}
% maxwidth is the original width if it is less than linewidth
% otherwise use linewidth (to make sure the graphics do not exceed the margin)
\makeatletter
\def\maxwidth{ %
  \ifdim\Gin@nat@width>\linewidth
    \linewidth
  \else
    \Gin@nat@width
  \fi
}
\makeatother

\definecolor{fgcolor}{rgb}{0.345, 0.345, 0.345}
\newcommand{\hlnum}[1]{\textcolor[rgb]{0.686,0.059,0.569}{#1}}%
\newcommand{\hlstr}[1]{\textcolor[rgb]{0.192,0.494,0.8}{#1}}%
\newcommand{\hlcom}[1]{\textcolor[rgb]{0.678,0.584,0.686}{\textit{#1}}}%
\newcommand{\hlopt}[1]{\textcolor[rgb]{0,0,0}{#1}}%
\newcommand{\hlstd}[1]{\textcolor[rgb]{0.345,0.345,0.345}{#1}}%
\newcommand{\hlkwa}[1]{\textcolor[rgb]{0.161,0.373,0.58}{\textbf{#1}}}%
\newcommand{\hlkwb}[1]{\textcolor[rgb]{0.69,0.353,0.396}{#1}}%
\newcommand{\hlkwc}[1]{\textcolor[rgb]{0.333,0.667,0.333}{#1}}%
\newcommand{\hlkwd}[1]{\textcolor[rgb]{0.737,0.353,0.396}{\textbf{#1}}}%
\let\hlipl\hlkwb

\usepackage{framed}
\makeatletter
\newenvironment{kframe}{%
 \def\at@end@of@kframe{}%
 \ifinner\ifhmode%
  \def\at@end@of@kframe{\end{minipage}}%
  \begin{minipage}{\columnwidth}%
 \fi\fi%
 \def\FrameCommand##1{\hskip\@totalleftmargin \hskip-\fboxsep
 \colorbox{shadecolor}{##1}\hskip-\fboxsep
     % There is no \\@totalrightmargin, so:
     \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth}%
 \MakeFramed {\advance\hsize-\width
   \@totalleftmargin\z@ \linewidth\hsize
   \@setminipage}}%
 {\par\unskip\endMakeFramed%
 \at@end@of@kframe}
\makeatother

\definecolor{shadecolor}{rgb}{.97, .97, .97}
\definecolor{messagecolor}{rgb}{0, 0, 0}
\definecolor{warningcolor}{rgb}{1, 0, 1}
\definecolor{errorcolor}{rgb}{1, 0, 0}
\newenvironment{knitrout}{}{} % an empty environment to be redefined in TeX

\usepackage{alltt}
\usepackage{multirow}
\setlength\parindent{0pt}
\usepackage{geometry}
\usepackage{longtable}
\usepackage{float}
\usepackage{verbatim}
\usepackage{hyperref}
\geometry{left=1.5cm,right=1.5cm,top=1.5cm,bottom=1.5cm}

\title{Docx from tex file example}
\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
\begin{document}

\maketitle

\begin{knitrout}
\definecolor{shadecolor}{rgb}{0.969, 0.969, 0.969}\color{fgcolor}\begin{kframe}
\begin{alltt}
\hlkwd{library}\hlstd{(survival)}
\end{alltt}
\end{kframe}
\end{knitrout}

\end{document}

接下来,我可以调用一个在命令行中运行以下代码的包装函数来生成 docx 文件:

path/to/pandoc/pandoc -o min_reproducible_example.docx min_reproducible_example.tex

我在 Windows 中工作,因此,我没有检查此问题是否仍然存在于其他操作系统中。

我认为有几行可以提供信息:

这条线是罪魁祸首,我相信:

Error at "source" (line 68, column 67):
unexpected end of input
\definecolor{shadecolor}{rgb}{0.969, 0.969, 0.969}\color{fgcolor}\begin{kframe}

其中,我一直在挖掘的“kframe”来自于 knitr 在进行“编织”时创建的乳胶环境。此行从 pandoc 生成以下错误:

Warning message:
In shell(command) :
  '"C:/pandoc/pandoc" -o min_reproducible_example.docx min_reproducible_example.tex --default-image-extension=png' execution failed with error code 65

我不知道这个错误代码 65 是什么意思。我已经从 pandoc 的先前问题中看到了建议直接查看代码以了解错误的线程。如果需要,我可以这样做,但对我来说,以前的 pandoc 版本可以正常工作而新版本正在崩溃对我来说很奇怪。我决定在这里发布这个,想知道是否有人遇到过同样的问题。

4

1 回答 1

1

我将根据 pandoc-discuss 上的另一个对话发布一个可能的解决方案以供将来参考。

在与 John MacFarlane 反复讨论之后,他好心地建议我重新定义给 pandoc 带来麻烦的环境:kframe。他建议将其重新定义为:

\renewenvironment{kframe}{}{}

所以,我所做的是重新定义我拥有的自定义 R 函数,该函数在内部调用 pandoc。我只包括下面的相关行。

  ## read the original .tex file (.Rnw output)
  tx  <- readLines(paste0(fname, '.tex'),warn=FALSE)
  ## rename the environment to something simpler as suggested by John MacFarlane in the pandoc-discuss thread
  tx2 <- gsub(pattern = "\\begin{document}", 
              replace = "\\renewenvironment{kframe}{}{}\\begin{document}", 
              x = tx, fixed = TRUE)
  ## create a file with the workaround for the kframe environment and use it in the pandoc call below 
  zz <- file(paste0(fname, '_cp.tex'), "wb")
  writeLines(tx2, con=zz)
  close(zz)

  command <- paste0('"',pdwd,'/pandoc" -o ', fname, '.docx ', fname, '_cp.tex ',
                    "--default-image-extension=png ")
  shell(command)
  # remove the file 
  file.remove(paste0(fname, '_cp.tex')) 

之后 pandoc 能够毫无怨言地执行。我注意到 pandoc 的早期版本(1.19.2.1)虽然执行没有错误,但输出的 docx 文件缺少 kframe 环境中的内容,而此修复程序可以更准确地表示 pdf。

我没有广泛尝试过这个修复,所以如果你发现任何问题,请留下评论。

于 2019-07-19T16:18:42.650 回答