listingsutf8 的选项 inputencoding=utf8/latin1 导致每次使用列表时都会读取 latin1.def

listingsutf8 的选项 inputencoding=utf8/latin1 导致每次使用列表时都会读取 latin1.def

编辑: inputencoding=latin1最初写的选项应该inputencoding=utf8/latin1

如果listingsutf8's 选项inputencoding=utf8/latin1导致latin1.def每次使用列表时读取文件,如以下 MWE 所指出的那样:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{listingsutf8}
\usepackage{multido}
\usepackage{filecontents}

\begin{filecontents}{\jobname.code}
Foo
\end{filecontents}

% \lstset{inputencoding=utf8/latin1}

\begin{document}
\multido{}{1000}{%
  \lstinputlisting{\jobname.code}
}
\end{document}

这可能会导致大量时间的浪费:time pdflatex test此 MWE 的编译结果如下\lstset{inputencoding=utf8/latin1}

  • 评论道:

    pdflatex 测试 1,68s 用户 1,49s 系统 99% cpu 3,189 总计

  • 不是评论道:

    pdflatex 测试 2,66s 用户 2,26s 系统 99% cpu 4,956 总计

latin1.def您能找到让文件只被读取一次的方法吗?

答案1

listingsutf8将列表文件从 UTF-8 重新编码为指定的 8 位编码,然后再将其传递给listings。由于编码实际上发生了变化,包会从文件 ( )\inputencoding中加载编码的活动字符的新定义。每次更改编码时都必须重复这些重新定义。.deflatin1.def

以下代码侵入宏\inputencoding,捕获 的调用\input并临时重新定义它。新定义通过包 将文件加载到宏中catchfile。然后下一次,将使用此全局宏而不是加载文件。由于.def的文件inputenc不应包含类别代码更改等奇怪的东西,因此可以在此处使用一个简单的宏。否则,内容必须通过较慢的 传递\scantokens

例子:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{listingsutf8}
\usepackage{multido}
\usepackage{filecontents}

\begin{filecontents}{\jobname.code}
Foo
\end{filecontents}

\lstset{inputencoding=utf8/latin1}

%%% Begin hack
\usepackage{catchfile}
\let\SavedInputEncoding\inputencoding
\renewcommand*{\inputencoding}{%
  \let\TempSavedInput\input
  \let\input\CachedInput
  \SavedInputEncoding
}
\newcommand*{\CachedInput}[1]{%
  \let\input\TempSavedInput
  \ifcsname CachedInput@#1\endcsname
  \else
    \CatchFileDef\TempCachedInput{#1}{}%
    \global\expandafter\let\csname CachedInput@#1\endcsname\TempCachedInput
  \fi
  \let\TempSavedEndinput\endinput
  \let\endinput\relax
  \csname CachedInput@#1\endcsname
  \let\endinput\TempSavedEndinput
}
%%% End hack %%%

\begin{document}
\multido{}{1000}{%
  \lstinputlisting{\jobname.code}
}
\end{document}

答案2

\inputencoding{XXX}Listings(utf8) 使用包中的标准接口inputenc来更改各种编码相关定义。\inputencoding从 XXX.def 文件加载定义。虽然可以将定义存储在宏中而不是从中重新加载它们,但.def我认为inputenc默认情况下不应该这样做。文档经常切换输入编码的情况相当罕见。listings 包含非 ascii 字符的情况也相当罕见。

对于你的情况,你可以做这样的事情:

\newcommand\latinonedef[1]{%
 % definitions from latin1.def
 % with/without the \providecommands as needed
 % carefully remove all spurious spaces!
 }

\usepackage{etoolbox}
\makeatletter
\preto\lsthk@Init{\let\inputencoding\latinonedef}{}{}
\makeatother

相关内容