复制粘贴列表包中的前导空格和空行(pdf)

复制粘贴列表包中的前导空格和空行(pdf)

我正在尝试使用该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

我找到了解决前导空格问题的办法!
编辑:实际上,它在 Adob​​e 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

相关内容