解决方案(来源)

解决方案(来源)

我想分享一下我遇到的一个问题的解决方案。(这是“回答你自己的问题”的事情之一,而且,这样,人们可以改进它——双重许可MirOS 许可证请。也欢迎对问题类的其他解决方案。

当您有一个列表(使用包lstlisting中的列表listings,这似乎是目前推荐的列表)时,有时无法从 PDF 中正确复制和粘贴它。有多种解决方案,但为什么不将列表作为纯文本文件发送呢?

如果您的列表在单独的文件中,解决方案很简单 - \lstinputlisting- 但这排除了替换,例如......

\newcommand{\myversion}{1.2}

\begin[escapeinside={〈}{〉}]{lstlisting}
tar -xzf myprogram-〈\myversion{}〉.tgz
\end{lstlisting}

...以及在与周围文本相同的文件中管理列表(以防止它们过时),并且有些人可能更喜欢将单个 PDF 中的所有列表包含在单个列表文件中。

答案1

解决方案(来源)

我深入研究了 Teχ SE 和listings源代码,最终得出了以下 SSCCE:

% © 2015 mirabilos <[email protected]>, published also under The MirOS Licence
\documentclass{scrartcl}

% used packages
\RequirePackage[utf8]{inputenc}
\RequirePackage[LY1,TS1,T1]{fontenc}
% font for listings
\RequirePackage[varqu,varl]{inconsolata}
% the listings package
\RequirePackage[writefile]{listings}

% some useful basic definitions
\lstset{
    basicstyle=\ttfamily,
    upquote=true,
    keepspaces,
literate=
    {á}{{\'a}}1 {é}{{\'e}}1 {í}{{\'i}}1 {ó}{{\'o}}1 {ú}{{\'u}}1
    {Á}{{\'A}}1 {É}{{\'E}}1 {Í}{{\'I}}1 {Ó}{{\'O}}1 {Ú}{{\'U}}1
    {à}{{\`a}}1 {è}{{\`e}}1 {ì}{{\`i}}1 {ò}{{\`o}}1 {ù}{{\`u}}1
    {À}{{\`A}}1 {È}{{\'E}}1 {Ì}{{\`I}}1 {Ò}{{\`O}}1 {Ù}{{\`U}}1
    {ä}{{\"a}}1 {ë}{{\"e}}1 {ï}{{\"i}}1 {ö}{{\"o}}1 {ü}{{\"u}}1
    {Ä}{{\"A}}1 {Ë}{{\"E}}1 {Ï}{{\"I}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1
    {â}{{\^a}}1 {ê}{{\^e}}1 {î}{{\^i}}1 {ô}{{\^o}}1 {û}{{\^u}}1
    {Â}{{\^A}}1 {Ê}{{\^E}}1 {Î}{{\^I}}1 {Ô}{{\^O}}1 {Û}{{\^U}}1
    {æ}{{\ae}}1 {Æ}{{\AE}}1 {ß}{{\ss}}1 {œ}{{\oe}}1 {Œ}{{\OE}}1
    {ő}{{\H{o}}}1 {Ő}{{\H{O}}}1 {ű}{{\H{u}}}1 {Ű}{{\H{U}}}1
    {å}{{\r a}}1 {Å}{{\r A}}1 {ç}{{\c c}}1 {Ç}{{\c C}}1 {ø}{{\o}}1
    {©}{{\textcopyright}}1 {™}{\texttrademark}1 {–}{-}1 {§}{\S}1
    {£}{{\pounds}}1 {°}{\textdegree{}}1 {„}{{\quotedblbase}}1
    {“}{{\textquotedblleft}}1 {”}{{\textquotedblright}}1
    {‘}{{\textquoteleft}}1 {’}{{\textquoteright}}1
    {«}{\guillemotleft}1 {»}{\guillemotright}1
    {…}{{\fontencoding{LY1}\selectfont\symbol{'205}}}1,
    columns=flexible,
    showstringspaces=false,
    extendedchars=true,
    breaklines=true,
    prebreak=\raisebox{0ex}[0ex][0ex]{\ensuremath{\hookleftarrow}},
    frame=single,
    showtabs=false,
    showspaces=false,
    showstringspaces=false,
    escapeinside={〈}{〉},
}

% lst dumps definitions
\makeatletter
\newcounter{lstdumps}
\setcounter{lstdumps}{0}
\newcommand{\lstdumpname}{}
\lstnewenvironment{lstdump}[3][]
    {\lst@TestEOLChar{#3}%
     \lstset{#1}%
     \csname\@lst @SetFirstNumber\endcsname%
     \stepcounter{lstdumps}%
     \renewcommand{\lstdumpname}{ (#2)}%
     \lst@BeginAlsoWriteFile{\jobname.lst}%
     \immediate\write\lst@WF{-----BEGIN LISTING \thelstdumps\lstdumpname-----}%
    }
    {
     \immediate\write\lst@WF{-----END LISTING \thelstdumps\lstdumpname-----}%
     \immediate\write\lst@WF{}%
     \endgroup%
     \csname\@lst @SaveFirstNumber\endcsname%
    }
\lstnewenvironment{lstdumpx}[2][]
    {\lst@TestEOLChar{#2}%
     \lstset{#1}%
     \csname\@lst @SetFirstNumber\endcsname%
     \stepcounter{lstdumps}%
     \renewcommand{\lstdumpname}{ [unnamed]}%
     \lst@BeginAlsoWriteFile{\jobname.lst}%
     \immediate\write\lst@WF{-----BEGIN LISTING \thelstdumps\lstdumpname-----}%
    }
    {
     \immediate\write\lst@WF{-----END LISTING \thelstdumps\lstdumpname-----}%
     \immediate\write\lst@WF{}%
     \endgroup%
     \csname\@lst @SaveFirstNumber\endcsname%
    }
% usage: \lstdumpesc[file]{pdf} or \lstdumpesc{bothfileandpdf}
\def\lstdumpesc{\@ifnextchar[{\lstdumpesc@two}{\lstdumpesc@one}}
\def\lstdumpesc@one#1{\lst@WFAppend{#1}#1}
\def\lstdumpesc@two[#1]#2{\lst@WFAppend{#1}#2}
\makeatother

% document body

\newcommand{\myversion}{1.2}

\begin{document}

This is the MyProgram \myversion{} installation manual.
You need to have \texttt{myprogram-\myversion{}.tgz}
downloaded already. Start with:

\begin{lstdump}[language=sh]{extract}
tar -xzf myprogram-〈\lstdumpesc{\myversion}〉.tgz
cd 〈\lstdumpesc[myprogram-\myversion]{my*/«tab»}〉
\end{lstdump}

Oh, by the way, check this out:

\begin{lstdumpx}
zcat /usr/share/doc/mksh/examples/uhr.gz | mksh
\end{lstdumpx}

The second listing has no name in the \texttt{.lst} file.

\end{document}

解决方案(输出)

PDF 输出如下所示:

在此处输入图片描述

当保存为demo.tex名为的文件时demo.lst将生成以下内容:

-----BEGIN LISTING 1 (extract)-----
tar -xzf myprogram-1.2.tgz
cd myprogram-1.2
-----END LISTING 1 (extract)-----

-----BEGIN LISTING 2 [unnamed]-----
zcat /usr/share/doc/mksh/examples/uhr.gz | mksh
-----END LISTING 2 [unnamed]-----

基本上,所有lstdumplstdumpx列表都已编号(我没有在 PDF 中显示这些编号,将它们以浅灰色打印在页边距上可能很有用——我们的页边距非常小,因为 PDF 主要用于在线使用,我们不使用列表编号,但它们很便宜,有些人可能喜欢它们),并且所有lstdump列表都有名称,它们显示在纯文本文件中。此外,我们可以从列表中退出到 Teχ(用于替换),并且\lstdumpesc命令可确保转义的文本写入文件(如果给出了可选参数,则写入)。

额外的信息

literate部分允许使用一些列表中的 Unicode 字符,但它们只是从文件中省略.lst- ASCII 之外的任何内容都不会显示,或者(例如在lstdump环境的列表名称中)导致输出中出现随机的 8 位字符。

更多功能

列出数字

如果您希望列表编号另外显示在 PDF 中(这使交叉引用更容易),请添加marginnote和可能的xcolor包并插入行...

        \marginnote{{\Huge\color{Gray}\thelstdumps}}%

stepcounter在每个定义的行后面。

列表文件中的文件和章节简介行

这个答案我找到了一种方法,每次当前章节/节/小节编号不同时,都将其包含在输出文件中,但这需要hyperref加载包。请注意,这可能需要第三次pdflatex运行,以修复LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.警告并在页面右侧获取边注。

包含这两个功能的第一个转储定义(再次完整)如下:

% lst dumps definitions
\makeatletter
\newcounter{lstdumps}
\setcounter{lstdumps}{0}
\newcommand{\lstdumpname}{}
\xdef\lstdumpsection{\@empty}%
\lstnewenvironment{lstdump}[3][]
    {\lst@TestEOLChar{#3}%
     \lstset{#1}%
     \csname\@lst @SetFirstNumber\endcsname%
     \stepcounter{lstdumps}%
     \marginnote{{\huge\color{Gray}\thelstdumps}}%
     \renewcommand{\lstdumpname}{ (#2)}%
     \lst@BeginAlsoWriteFile{\jobname.lst}%
     \ifx\lstdumpsection\@currentlabel\else%
      \ifx\lstdumpsection\@empty%
       \immediate\write\lst@WF{Listing dump for \jobname.tex}%
       \immediate\write\lst@WF{}%
      \fi%
      \immediate\write\lst@WF{>>> (\@currentlabel) \@currentlabelname}%
      \immediate\write\lst@WF{}%
     \fi%
     \immediate\write\lst@WF{-----BEGIN LISTING \thelstdumps\lstdumpname-----}%
    }
    {
     \immediate\write\lst@WF{-----END LISTING \thelstdumps\lstdumpname-----}%
     \immediate\write\lst@WF{}%
     \endgroup%
     \csname\@lst @SaveFirstNumber\endcsname%
     \xdef\lstdumpsection{\@currentlabel}%
    }
\lstnewenvironment{lstdumpx}[2][]
    {\lst@TestEOLChar{#2}%
     \lstset{#1}%
     \csname\@lst @SetFirstNumber\endcsname%
     \stepcounter{lstdumps}%
     \marginnote{{\huge\color{Gray}\thelstdumps}}%
     \renewcommand{\lstdumpname}{ [unnamed]}%
     \lst@BeginAlsoWriteFile{\jobname.lst}%
     \ifx\lstdumpsection\@currentlabel\else%
      \ifx\lstdumpsection\@empty%
       \immediate\write\lst@WF{Listing dump for \jobname.tex}%
       \immediate\write\lst@WF{}%
      \fi%
      \immediate\write\lst@WF{>>> (\@currentlabel) \@currentlabelname}%
      \immediate\write\lst@WF{}%
     \fi%
     \immediate\write\lst@WF{-----BEGIN LISTING \thelstdumps\lstdumpname-----}%
    }
    {
     \immediate\write\lst@WF{-----END LISTING \thelstdumps\lstdumpname-----}%
     \immediate\write\lst@WF{}%
     \endgroup%
     \csname\@lst @SaveFirstNumber\endcsname%
     \xdef\lstdumpsection{\@currentlabel}%
    }
% usage: \lstdumpesc[file]{pdf} or \lstdumpesc{bothfileandpdf}
\def\lstdumpesc{\@ifnextchar[{\lstdumpesc@two}{\lstdumpesc@one}}
\def\lstdumpesc@one#1{\lst@WFAppend{#1}#1}
\def\lstdumpesc@two[#1]#2{\lst@WFAppend{#1}#2}
\makeatother

相关内容