如何使从 PDF 复制时列表代码缩进保持不变?

如何使从 PDF 复制时列表代码缩进保持不变?

所以我用listings代码示例包。但是有一个问题。当我从最终的 PDF 文档中复制代码示例时,它们通常不一样 - 缩进消失了,括号后有随机空格等。有人知道如何确保我从最终文档中复制的代码与我在 LaTeX 文档中编写的代码相同吗?

这就是我的意思。编译此文档:

\documentclass[12pt,oneside]{memoir}

\usepackage{listings}
\usepackage[T1]{fontenc}
\usepackage{xcolor}
\usepackage{textcomp}

\definecolor{codebg}{HTML}{EEEEEE}
\definecolor{codeframe}{HTML}{CCCCCC}

\lstset{language=Awk}
\lstset{backgroundcolor=\color{codebg}}
\lstset{frame=single}
\lstset{framesep=10pt}
\lstset{rulecolor=\color{codeframe}}
\lstset{upquote=true}
\lstset{basicstyle=\ttfamily}
\lstset{showstringspaces=false}

\begin{document}

This code example prints out all users on your system:

\begin{lstlisting}[language=c]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LINE_LEN 1024

int main() {
    char line[MAX_LINE_LEN];
    FILE *in = fopen("/etc/passwd", "r");
    if (!in) exit(EXIT_FAILURE);

    while (fgets(line, MAX_LINE_LEN, in) != NULL) {
        char *sep = strchr(line, ':');
        if (!sep) exit(EXIT_FAILURE);
        *sep = '\0';
        printf("%s\n", line);
    }
    fclose(in);
    return EXIT_SUCCESS;
}
\end{lstlisting}

\end{document}

现在编译它,打开它,选择并复制代码示例并将其粘贴到文本编辑器中。这是我得到的结果:

# include <stdio .h>
# include <stdlib .h>
# include <string .h>
# define MAX_LINE_LEN 1024
int main () {
char line [ MAX_LINE_LEN ];
FILE *in = fopen ("/ etc / passwd ", "r");
if (! in) exit ( EXIT_FAILURE );
while ( fgets (line , MAX_LINE_LEN , in) != NULL ) {
char * sep = strchr (line , ':');
if (! sep ) exit ( EXIT_FAILURE );
* sep = '\0 ';
printf ("%s\n", line );
}
fclose (in );
return EXIT_SUCCESS ;
}

天哪!这是什么……缩进不见了。包含的标题中有空格<stdio .h>,括号后也有空格[ MAX_LINE_LEN ]

有人知道如何解决这个问题吗?我希望书中的代码示例可以复制/粘贴到文本编辑器中,以便人们可以轻松尝试它们。

答案1

为了防止从列表复制文本时出现随机空格,您需要使用

\lstset{columns=flexible}

但是你现在会注意到文本不再整齐对齐;为了解决这个问题,你还需要使用

\lstset{keepspaces=true}

这无法解决复制时行首空格消失的问题。以下技巧将产生可见的空格,然后通过将其着色为背景颜色使其不可见:

\makeatletter
\def\lst@outputspace{{\ifx\lst@bkgcolor\empty\color{white}\else\lst@bkgcolor\fi\lst@visiblespace}}
\makeatother

但是,这种技巧并不完美,因为排版的字符实际上是可见空格,而不是空格(因此在 pdf 中搜索char line将不起作用),并且某些 PDF 阅读器(如 Mac 的预览)会复制可见空格。它在 Acrobat Reader 下工作,能够快速复制/粘贴代码而不会出现问题,这非常令人愉快(也许可以通过编写直接 PDF 代码来告诉它是一个空格来规避这个问题,我从来没有时间尝试)。它也可能不适用于所有打字机字体。

以下是示例的完整代码:

\documentclass[12pt,oneside]{memoir}

\usepackage{listings}
\usepackage[T1]{fontenc}
\usepackage{xcolor}
\usepackage{textcomp}

\definecolor{codebg}{HTML}{EEEEEE}
\definecolor{codeframe}{HTML}{CCCCCC}

\lstset{language=Awk}
\lstset{backgroundcolor=\color{codebg}}
\lstset{frame=single}
\lstset{framesep=10pt}
\lstset{rulecolor=\color{codeframe}}
\lstset{upquote=true}
\lstset{basicstyle=\ttfamily}
\lstset{showstringspaces=false}

\lstset{columns=flexible}
\lstset{keepspaces=true}
\makeatletter
\def\lst@outputspace{{\ifx\lst@bkgcolor\empty\color{white}\else\lst@bkgcolor\fi\lst@visiblespace}}
\makeatother

\begin{document}

This code example prints out all users on your system:

\begin{lstlisting}[language=c]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LINE_LEN 1024

int main() {
    char line[MAX_LINE_LEN];
    FILE *in = fopen("/etc/passwd", "r");
    if (!in) exit(EXIT_FAILURE);

    while (fgets(line, MAX_LINE_LEN, in) != NULL) {
        char *sep = strchr(line, ':');
        if (!sep) exit(EXIT_FAILURE);
        *sep = '\0';
        printf("%s\n", line);
    }
    fclose(in);
    return EXIT_SUCCESS;
}
\end{lstlisting}

\end{document}

答案2

你可以使用以下修改

\newlength{\lstcolumnwidth}
\settowidth{\lstcolumnwidth}{\ttfamily M}
\lstset{basicstyle=\ttfamily,basewidth=\lstcolumnwidth,columns=fixed, fontadjust=true} 

行首的缩进不是 LaTeX 的问题,这是读者的问题,没有针对这种情况的设置。你可以用以下代码得到一个奇怪的解决方案:

\lstset{showspaces=true}
\makeatletter
\def\lst@visiblespace{\textcolor{codebg}{-}}
\makeatother

使用类似的包attachefile2您可以附加原始的c文件。

答案3

我的回答不会回答你的问题。:-) 但我有一个很好的方法来管理代码片段的包含,以便读者轻松访问。与其从 pdf 中复制代码,不如让读者通过单击超链接打开底层代码文件。

尝试编译以下代码。我使用 latex-dvips-ps2pdf 编译步骤。当然你也可以使用 pdflatex,但不要忘记删除dvips中的选项\documentclass

为了易于维护,请按如下方式创建您自己的包:

\NeedsTeXFormat{LaTeX2e}[1994/06/01] 
\ProvidesPackage{xport}[2011/06/05 v0.01 LaTeX package for my own purpose]  
\RequirePackage[utf8x]{inputenc}
\RequirePackage{xcolor}

\RequirePackage{caption}
\captionsetup
{%
   font={small,rm},
   labelfont={color=Maroon,bf},
   justification=justified%
}

\RequirePackage{listings}
\AtBeginDocument
{%
    \renewcommand*{\lstlistlistingname}{Code List}%
    \renewcommand*{\lstlistingname}{Code}%
}

\lstset
{%
        %linewidth=\linewidth,  
        breaklines=true,
        tabsize=3, 
        showstringspaces=false%      
}


\lstdefinestyle{Common}
{%
        extendedchars=\true,
        language={[Sharp]C},
        %alsolanguage={PSTricks},
        frame=single,   
        %===========================================================
        framesep=3pt,%expand outward.
        framerule=0.4pt,%expand outward.
        xleftmargin=3.4pt,%make the frame fits in the text area. 
        xrightmargin=3.4pt,%make the frame fits in the text area.
        %=========================================================== 
        rulecolor=\color{Red}%
}

\lstdefinestyle{A}%
{%
        style=Common,
        backgroundcolor=\color{Yellow!10},
        basicstyle=\scriptsize\color{Black}\ttfamily,
        keywordstyle=\color{Orange},
        identifierstyle=\color{Cyan},
        stringstyle=\color{Red}, 
        commentstyle=\color{Green}% 
}

\newcommand{\IncludeCSharp}[2][style=A]%
{%
    \lstinputlisting[#1,caption={\href{#2}{#2}}]{#2}%
}

%for beamer, use \hypersetup instead.
\RequirePackage[colorlinks=true,bookmarksnumbered=true,bookmarksopen=true]{hyperref}

%to make hyperlinks point to the top of figure or table.
%it must be loaded after hyperref.
\RequirePackage[all]{hypcap}% cannot be used in beamer.

\endinput 

在主输入文件中,可以\IncludeCSharp按如下方式调用:

\documentclass[dvips,dvipsnames,cmyk,12pt]{article}
\usepackage[a4paper,margin=2cm]{geometry}
\usepackage{xport}
\begin{document}

\IncludeCSharp[style=A]{Codes/Program.cs}    

\end{document}

导入的C#文件在子目录Program.cs中命名。Codes/

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");//This is a comment.
            /*This is a comment too.*/
        }
    }
}

答案4

(请参考此帖子:如何制作一个 LaTeX 文档,使其生成 PDF,以便复制粘贴空行和前导空格缩进能够正确进行?,试图将对这个问题的不同部分讨论的所有智慧汇集到一个地方。

相关内容