这个问题与我之前由 Jubobs 回答的问题相关这里。我使用 TeX Live 2013 和 TeX Live 2014 预测试编译了下面给出的代码。两者产生相同的结果。
情况1
预期结果autounindent
如下。
案例 2
当我加载时hyperref
,autounindent
不再按如下方式工作。
案例 3
最糟糕的情况是,当我同时加载hyperref
和时hypcap
,出现了以下一些错误。
平均能量损失
\documentclass[12pt]{article}
%TODO
% - handle tabs
\usepackage{accsupp}
\newcommand*{\noaccsupp}[1]{\BeginAccSupp{ActualText={}}#1\EndAccSupp{}}
\usepackage{xcolor}
\usepackage{listings}
\makeatletter
% -------- ugly details --------
% custom key
\lst@Key{autounindent}f[t]{\lstKV@SetIf{#1}\lst@ifautounindent}
% --- accumulation of tokens ---
\toks@={
\lst@DefSaveDef{`\ }\lsts@myspace{\processmyspace}
%\lst@DefSaveDef{`\^^I}\lsts@mytab{\processmytab}
}
% --- egreg's helper function for accumulating tokens ---
\def\add@savedef#1#2{%
\begingroup\lccode`?=#1\relax
\lowercase{\endgroup
\edef\@temp{%
\noexpand\lst@DefSaveDef{\number#1}%
\expandafter\noexpand\csname lsts@?\endcsname{\noexpand#2% % I had to swap things around to fix a bug here;
\expandafter\noexpand\csname lsts@?\endcsname}% % otherwise, comment highlighting would be broken.
}}%
\toks@=\expandafter{\the\expandafter\toks@\@temp}%
}
\count@=33
\loop
\add@savedef\count@\processchar
\ifnum\count@<127
\advance\count@\@ne
\repeat
% --- to keep track of the state ---
\newcount\spacesToGobble
\newcount\spacesGobbledSoFar
\newif\ifafterindent
\newif\ifonBasisLine
\newif\ifPostponeCountToNextLine
\lst@AddToHook{Init}
{%
\lst@ifautounindent%
% patch hook macros
\let\@ddedToInitVarsBOLhook\@@ddedToInitVarsBOLhook%
\let\@ddedToEOLhook\@@ddedToEOLhook%
% initialise things
\global\onBasisLinetrue%
\global\afterindentfalse%
\global\spacesToGobble=0%
\lst@ifincluderangemarker%
\ifnum9999999=\lst@firstline% (i.e. if firstline option not used)
\global\PostponeCountToNextLinetrue%
\fi
\fi
\fi
}
\lst@AddToHook{SelectCharTable}
{%
\lst@ifautounindent%
\lst@lAddTo\lst@DeveloperSCT{\the\toks@}%
\fi
}
\lst@AddToHook{InitVarsBOL}{\@ddedToInitVarsBOLhook}
\newcommand\@ddedToInitVarsBOLhook{}
\newcommand\@@ddedToInitVarsBOLhook
{%
\global\afterindentfalse%
}
\lst@AddToHook{EOL}{\@ddedToEOLhook}
\newcommand\@ddedToEOLhook{}
\newcommand\@@ddedToEOLhook
{%
\ifonBasisLine%
\ifPostponeCountToNextLine%
\else
\global\onBasisLinefalse%
\fi
\fi
\global\spacesGobbledSoFar=0%
\global\PostponeCountToNextLinefalse%
}
\lst@AddToHook{DeInit}
{%
\lst@ifautounindent%
% undo patches
\def\@ddedToInitVarsBOLhook{}%
\def\@ddedToEOLhook{}%
\fi
}
% --- helper macros ---
\newcommand\processchar
{%
\global\afterindenttrue%
}
\newcommand\processmyspace
{%
\ifafterindent%
\lsts@myspace%
\else
\ifonBasisLine%
\global\advance\spacesToGobble\@ne\relax%
\else
\ifnum\spacesGobbledSoFar<\spacesToGobble\relax%
\global\advance\spacesGobbledSoFar\@ne\relax%
\else
\lsts@myspace%
\fi
\fi
\fi
}
\makeatother
% ---------- end of ugly details ----------
\usepackage{filecontents}
\begin{filecontents*}{Program.cs}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Delegate
{
class Program
{
// start
sdfgsd fgdsfg static void Main(string[] args)
{
for (int x = 0; x < 10; x++)
Console.WriteLine(x);
}
/* sdflkjhsdf */
// stop
}
}
\end{filecontents*}
% --- general style definition ---
\lstdefinestyle{Common}
{
language={[Sharp]C},
numbers=left,
numbersep=1em,
numberstyle=\tiny\noaccsupp,
frame=single,
framesep=\fboxsep,
framerule=\fboxrule,
rulecolor=\color{red},
xleftmargin=\dimexpr\fboxsep+\fboxrule,
xrightmargin=\dimexpr\fboxsep+\fboxrule,
breaklines=true,
breakindent=0pt,
tabsize=2,
columns=flexible,
%includerangemarker=false,
rangeprefix=//\ ,
}
\lstdefinestyle{A}
{
style=Common,
backgroundcolor=\color{yellow!10},
basicstyle=\scriptsize\ttfamily,
keywordstyle=\color{blue}\bf,
identifierstyle=\color{black},
stringstyle=\color{red},
commentstyle=\color{green},
}
%\usepackage[colorlinks,bookmarksnumbered,bookmarksopen]{hyperref} % makes autounindent no longer work
%\usepackage[all]{hypcap}% causes errors.
\begin{document}
\section*{Using \texttt{linerange} with \texttt{autounindent}}
\lstinputlisting[style=A,linerange=start-stop,autounindent]{Program.cs}
\end{document}
问题
如何解决这些问题?
答案1
问题不在于软件包顺序。修补的代码listings
使用令牌寄存器\toks@
(临时暂存寄存器)作为永久令牌寄存器。因此,令牌寄存器也被其他软件包(如或)\toks@
使用,并且它们随后会留下垃圾。然后,这些垃圾被“自动取消缩进”功能内部调用,从而导致不必要的意外效果(如错误消息)。hyperref
hypcap
lstlisting
\toks@
是一个临时的临时令牌寄存器,任何包或命令都可以使用它。如果在使用前清除该寄存器,也无济于事,因为前言中的令牌寄存器的设置将因“自动取消缩进”功能而丢失。
以下修复\toks@
由新分配的令牌寄存器替换:
\documentclass[12pt]{article}
%TODO
% - handle tabs
\usepackage{accsupp}
\newcommand*{\noaccsupp}[1]{\BeginAccSupp{ActualText={}}#1\EndAccSupp{}}
\usepackage{xcolor}
\usepackage{listings}
\makeatletter
% -------- ugly details --------
\newtoks\mylsttoks
% custom key
\lst@Key{autounindent}f[t]{\lstKV@SetIf{#1}\lst@ifautounindent}
% --- accumulation of tokens ---
\mylsttoks={
\lst@DefSaveDef{`\ }\lsts@myspace{\processmyspace}
%\lst@DefSaveDef{`\^^I}\lsts@mytab{\processmytab}
}
% --- egreg's helper function for accumulating tokens ---
\def\add@savedef#1#2{%
\begingroup\lccode`?=#1\relax
\lowercase{\endgroup
\edef\@temp{%
\noexpand\lst@DefSaveDef{\number#1}%
\expandafter\noexpand\csname lsts@?\endcsname{\noexpand#2%
% I had to swap things around to fix a bug here;
\expandafter\noexpand\csname lsts@?\endcsname}%
% otherwise, comment highlighting would be broken.
}}%
\mylsttoks=\expandafter{\the\expandafter\mylsttoks\@temp}%
}
\count@=33
\loop
\add@savedef\count@\processchar
\ifnum\count@<127
\advance\count@\@ne
\repeat
% --- to keep track of the state ---
\newcount\spacesToGobble
\newcount\spacesGobbledSoFar
\newif\ifafterindent
\newif\ifonBasisLine
\newif\ifPostponeCountToNextLine
\lst@AddToHook{Init}
{%
\lst@ifautounindent%
% patch hook macros
\let\@ddedToInitVarsBOLhook\@@ddedToInitVarsBOLhook%
\let\@ddedToEOLhook\@@ddedToEOLhook%
% initialise things
\global\onBasisLinetrue%
\global\afterindentfalse%
\global\spacesToGobble=0%
\lst@ifincluderangemarker%
\ifnum9999999=\lst@firstline% (i.e. if firstline option not used)
\global\PostponeCountToNextLinetrue%
\fi
\fi
\fi
}
\lst@AddToHook{SelectCharTable}
{%
\lst@ifautounindent%
\lst@lAddTo\lst@DeveloperSCT{\the\mylsttoks}%
\fi
}
\lst@AddToHook{InitVarsBOL}{\@ddedToInitVarsBOLhook}
\newcommand\@ddedToInitVarsBOLhook{}
\newcommand\@@ddedToInitVarsBOLhook
{%
\global\afterindentfalse%
}
\lst@AddToHook{EOL}{\@ddedToEOLhook}
\newcommand\@ddedToEOLhook{}
\newcommand\@@ddedToEOLhook
{%
\ifonBasisLine%
\ifPostponeCountToNextLine%
\else
\global\onBasisLinefalse%
\fi
\fi
\global\spacesGobbledSoFar=0%
\global\PostponeCountToNextLinefalse%
}
\lst@AddToHook{DeInit}
{%
\lst@ifautounindent%
% undo patches
\def\@ddedToInitVarsBOLhook{}%
\def\@ddedToEOLhook{}%
\fi
}
% --- helper macros ---
\newcommand\processchar
{%
\global\afterindenttrue%
}
\newcommand\processmyspace
{%
\ifafterindent%
\lsts@myspace%
\else
\ifonBasisLine%
\global\advance\spacesToGobble\@ne\relax%
\else
\ifnum\spacesGobbledSoFar<\spacesToGobble\relax%
\global\advance\spacesGobbledSoFar\@ne\relax%
\else
\lsts@myspace%
\fi
\fi
\fi
}
\makeatother
% ---------- end of ugly details ----------
\usepackage{filecontents}
\begin{filecontents*}{Program.cs}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Delegate
{
class Program
{
// start
sdfgsd fgdsfg static void Main(string[] args)
{
for (int x = 0; x < 10; x++)
Console.WriteLine(x);
}
/* sdflkjhsdf */
// stop
}
}
\end{filecontents*}
% --- general style definition ---
\lstdefinestyle{Common}
{
language={[Sharp]C},
numbers=left,
numbersep=1em,
numberstyle=\tiny\noaccsupp,
frame=single,
framesep=\fboxsep,
framerule=\fboxrule,
rulecolor=\color{red},
xleftmargin=\dimexpr\fboxsep+\fboxrule,
xrightmargin=\dimexpr\fboxsep+\fboxrule,
breaklines=true,
breakindent=0pt,
tabsize=2,
columns=flexible,
%includerangemarker=false,
rangeprefix=//\ ,
}
\lstdefinestyle{A}
{
style=Common,
backgroundcolor=\color{yellow!10},
basicstyle=\scriptsize\ttfamily,
keywordstyle=\color{blue}\bf,
identifierstyle=\color{black},
stringstyle=\color{red},
commentstyle=\color{green},
}
\usepackage[colorlinks,bookmarksnumbered,bookmarksopen]{hyperref}
\usepackage[all]{hypcap}
\begin{document}
\section*{Using \texttt{linerange} with \texttt{autounindent}}
\lstinputlisting[style=A,linerange=start-stop,autounindent]{Program.cs}
\end{document}
答案2
更改顺序:如果你的文档以
\documentclass[12pt]{article}
\usepackage[colorlinks,bookmarksnumbered,bookmarksopen]{hyperref}
\usepackage[all]{hypcap}
并将其余部分保持原样,您应该会得到预期的结果。