我正在尝试使用该listings
包在 PDF 文档中排版一些代码,以便我可以复制粘贴生成的代码。如果basicstyle=\ttfamily,columns=flexible
按照此处的建议使用,这种方法通常效果很好:列表中的幻影空间 (pdf)
问题是前导空格没有被正确复制粘贴。当然,视觉上在 PDF 中正确显示,但选择并复制粘贴它会省略前导空格和空行。
\documentclass{article}
\usepackage{listings}
\lstset{basicstyle=\ttfamily, columns=flexible}
\begin{document}
Some text.
\begin{lstlisting}
def f(x):
return x+1
Previous line intentionally left blank.
\end{lstlisting}
\end{document}
我可以做些什么来使其正确复制粘贴?我更喜欢使用列表,除非这个包绝对不可能。(我正在处理的文档库非常大,所以我想尽可能少地进行更改,以防止出现不可预见的错误。)
答案1
我找到了解决前导空格问题的办法!
编辑:实际上,它在 Adobe Reader 中不起作用。但在 SumatraPDF 中起作用。
感谢 Daniel 和 cgnieder 的上述评论。
正如所描述的马丁·蒙佩鲁斯您可以使用该accsupp
包来区分您复制粘贴的文本和排版文本。
请注意,链接的页面不是开箱即用的。按照那里的书写方式,在 accsupp 替换期间会引入多余的空格。删除 \newcommand 中的所有空格似乎可以解决这个问题。这是一个可以正常工作的最小示例:
\documentclass{article}
\usepackage{listings}
\lstset{
basicstyle=\ttfamily,
columns=fullflexible,
literate={\ }{{\copyablespace}}1
}
\usepackage[space=true]{accsupp}
% requires the latest version of package accsupp
\newcommand{\copyablespace}{\BeginAccSupp{method=hex,unicode,ActualText=00A0}\ \EndAccSupp{}}
\begin{document}
Some text.
\begin{lstlisting}
def f(x):
return x+1
Previous line intentionally left blank.
\end{lstlisting}
\end{document}
注意:
basicstyle=\ttfamily 和 columns=fullflexible 是使字体等宽所必需的,并防止在代码中间引入对齐空格,详情如下这里。
空白换行符仍然无法复制粘贴。有人知道是否也可以使用 accsupp 来实现这一点吗?
我暂时忽略了 Martin Monperrus 谈到的特殊 Unicode 字符等。如果您对此有任何问题,请参阅该页面。(使用“upquotes=true”可解决最常见的问题)
如果您不想使用 accsupp 包,下面这个也可以:
如果设置 showspaces=true,它会将所有空格变成可见的空格字符,包括前导空格。这看起来不太好看,但它们确实是可复制的。
listings 包允许您自己设置可见tab
字符,但不幸的是不允许您设置可见空格字符。也许对 LaTeX 有更多了解的人可以提供一些建议,说明如何用某种形式的不可见空格字符替换可见空格字符。我认为复制粘贴功能将得以保留。
这也不能解决空白换行符的问题。
概念证明:
\documentclass{article}
\usepackage{listings}
\lstset{basicstyle=\ttfamily, columns=flexible, showspaces=true}
\begin{document}
Some text.
\begin{lstlisting}
def f(x):
return x+1
Previous line intentionally left blank.
\end{lstlisting}
\end{document}
答案2
\BeginAccSupp{method=hex,ActualText=0A}\EndAccSupp{}
我看不出任何复制空白行的方法(仅当在同一行某处有复制非空格字符时,使用插入换行符才有效)。
但是,下面我将介绍另一种(更复杂)方法来复制行首的“不可见”空格。注释提供了一些有关可以组合加载哪些包的信息。我相信它有更广泛的查看器支持(请参阅下面的兼容性表)。
%http://tex.stackexchange.com/questions/142617
\documentclass{article}
%\usepackage[resetfonts]{cmap}% BAD: \textvisiblespace will be copied as ?. wrap \textvisiblespace in appropriate accsupp to fix
\usepackage[T1]{fontenc}
%\usepackage{lmodern}
\usepackage{textcomp}% for upquote
\usepackage{listings}
\lstset{
basicstyle=\ttfamily,
columns=fullflexible,
tabsize=4,
upquote=true,
showstringspaces=true,
%showspaces=true,% show all spaces except those at the beginning of a line
}
% from MinionPro manual, page 7 (http://www.tex.ac.uk/CTAN/fonts/minionpro/MinionPro.pdf)
%\input{glyphtounicode}
%\pdfgentounicode=1% BAD: \textvisiblespace will be copied as ?. wrap \textvisiblespace in appropriate accsupp to fix
\usepackage{xcolor}
\makeatletter
%an invisible visible space
% is a visible space character
% in the same font color as the listings background
% (or white if no background color is set)
% similiar to [How to make listings code indentation remain unchanged when copied from PDF?](http://tex.stackexchange.com/a/19978)
\newcommand{\lst@invisiblevisiblespace}{%
\textcolor{white}{\lst@bkgcolor{\lst@visiblespace}}}%
% save old definitions
\AtBeginDocument{%delay in case any other package patches these
\let\lst@newlineold@ProcessSpace\lst@ProcessSpace
\let\lst@newlineold@ProcessTabulator\lst@ProcessTabulator
\let\lst@newlineold@Append\lst@Append
}
\newcommand*{\lst@beginline}{%activate special whitespace handling
\lst@ifdisplaystyle% but only for display listings, not for inline/TextStyle listings
\let\lst@ProcessSpace\lst@newline@ProcessSpace
\let\lst@ProcessTabulator\lst@newline@ProcessTabulator
\let\lst@Append\lst@newline@Append
\fi
}
% at the end of every line, prepare to deal with whitespace at the beginning of the next line
\lst@AddToHook{EOL}{%
\lst@beginline
}
% spaces at the start of a line are made into visible spaces
% which are hidden by the choice of font color
\newcommand*{\lst@newline@ProcessSpace}{%
% pretend keepspaces=true at the moment
% but always use invisiblevisiblespace instead of outputspace
% regardless of the setting of showspaces
\lst@PrintToken
\lst@whitespacetrue
\lst@AppendOther\lst@invisiblevisiblespace
\lst@PrintToken
}
% tabs at the start of a line are treated like consecutive spaces
% note that these will copy-paste as spaces instead of tabs
\newcommand*{\lst@newline@ProcessTabulator}{%
\@tempcnta=\lst@tabsize\relax
\loop
\ifnum\@tempcnta>\z@
\lst@newline@ProcessSpace
\advance\@tempcnta\m@ne
\repeat
}
\newcommand*{\lst@newline@Append}[1]{%
\ifx#1\lst@invisiblevisiblespace
\else
% as soon as we append something to the output line
% that isn't our special space, go back to the normal processing of spaces and tabulators
\let\lst@Append\lst@newlineold@Append
\let\lst@ProcessSpace\lst@newlineold@ProcessSpace
\let\lst@ProcessTabulator\lst@newlineold@ProcessTabulator
\fi
\lst@newlineold@Append{#1}%
}
% the start of every listing is the beginning of a line
\lst@AddToHook{Init}{%
\lst@beginline
}
\makeatother
%\lstset{backgroundcolor=\color{gray}}
\begin{document}
\pagestyle{empty}
\begin{lstlisting}[language=C++]
int test(int x)
{
std::cout << "Hello world"; // print
return x +1; // return
}
// Previous line intentionally left blank.
\end{lstlisting}
Note that spaces are still ignored at the start of inline listings: \lstinline^ test(5);^
\end{document}
并非所有查看器都适用。对于已测试过的查看器,请参阅下面的兼容性表。请随意添加您自己的观察结果。添加accsupp
似乎会进一步降低查看器兼容性,而不是提高它。
支持的查看器:
- Adobe Reader 十一
- PDF-XChange 查看器 2.5.213
不支持的查看器:
- Firefox 25.0 pdf.js 内置查看器
- SumatraPDF v2.4
- 福祉阅读器 5.3
- PDF转换器专业版 7.1