![如果 .dtx 文件是 \DocInput,则 \inputencoding{latin1} 不能用于该文件的用户文档中](https://linux22.com/image/307242/%E5%A6%82%E6%9E%9C%20.dtx%20%E6%96%87%E4%BB%B6%E6%98%AF%20%5CDocInput%EF%BC%8C%E5%88%99%20%5Cinputencoding%7Blatin1%7D%20%E4%B8%8D%E8%83%BD%E7%94%A8%E4%BA%8E%E8%AF%A5%E6%96%87%E4%BB%B6%E7%9A%84%E7%94%A8%E6%88%B7%E6%96%87%E6%A1%A3%E4%B8%AD.png)
第三次编辑:(正如 Ulrike 指出的那样,我的问题实际上并不涉及listingsutf8
而只涉及inputenc
,因此我通过赋予问题另一个标题和另一个 MWE 来反映这一点。)
以下 MWE 指出,在一个.dtx
文件中,同时:
- 该
ltxdoc
文件\DocInput
是.dtx
文件本身, - 用户文档(即注释部分)选择
latin1
使用 进行编码\inputencoding{latin1}
,
一个奇怪的错误:
***************************
* Character table correct *
***************************
(/usr/local/texlive/2014/texmf-dist/tex/latex/base/latin1.def
! Package doc Error: Character table corrupted.
See the doc package documentation for explanation.
Type H <return> for immediate help.
...
l.53 %% Right brace \} Tilde \~}
?
在编译期间被抛出pdfLaTeX
。
% \iffalse
%<*driver>
\documentclass{ltxdoc}
\usepackage[utf8]{inputenc}
\begin{document}
\DocInput{\jobname.dtx}
\inputencoding{latin1}
Foo bar.
\end{document}
%</driver>
% \fi
%
% \inputencoding{latin1}
%
% \Finale
\endinput
我不知道发生了什么事。
请注意,在以下情况下不会发生这种奇怪的错误:
要么
\DocInput{\jobname.dtx}
被移除,或者将
\inputencoding{latin1}
声明直接插入ltxdoc
文档主体中而不是用户文档中。
原始编辑:以下 MWE 指出,在一个.dtx
文件中,同时:
- 文件
ltxdoc
:- 加载
listingsutf8
包, \DocInput
是.dtx
文件本身,
- 加载
- 用户文档包含一个
lstlisting
环境:- 使用
listingsutf8
的inputencoding=utf8/latin1
选项, - 包含
utf8
编码字符,
- 使用
一个奇怪的错误:
***************************
* Character table correct *
***************************
(/usr/local/texlive/2014/texmf-dist/tex/latex/base/latin1.def
! Package doc Error: Character table corrupted.
See the doc package documentation for explanation.
Type H <return> for immediate help.
...
l.53 %% Right brace \} Tilde \~}
?
在编译期间被抛出pdfLaTeX
。
% \iffalse
%<*driver>
\documentclass{ltxdoc}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{listingsutf8}
\begin{document}
\DocInput{\jobname.dtx}
\begin{lstlisting}
ü
\end{lstlisting}
\end{document}
%</driver>
% \fi
%
% \begin{lstlisting}[inputencoding=utf8/latin1]
% ü
% \end{lstlisting}
%
% \Finale
\endinput
我不知道发生了什么事。
请注意,在以下情况下不会发生这种奇怪的错误:
- 要么
\DocInput{\jobname.dtx}
被移除, - 或者环境
inputencoding=utf8/latin1
选项lstlisting
被删除(在这种情况下,Package inputenc Error: Unicode char
会发生正常情况),
- 要么
lstlisting
with选项inputencoding=utf8/latin1
中含有utf8
编码字符的字符直接插入到ltxdoc
文档主体中,\usepackage[T1]{fontenc}
和\usepackage[utf8]{inputenc}
被删除,listingsutf8
由 替换listings
,并使用和XeLaTeX
或编译。LuaLaTeX
第二次编辑:同样的问题也出现在更符合规范的使用方式中listingsutf8
:
% mylistings.txt file
\begin{lstlisting}
ü
\end{lstlisting}
和:
% .dtx file
% \iffalse
%<*driver>
\documentclass{ltxdoc}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{listingsutf8}
\begin{document}
\DocInput{\jobname.dtx}
\lstinputlisting[inputencoding=utf8/latin1]{mylisting.txt}
\end{document}
%</driver>
% \fi
%
% \lstinputlisting[inputencoding=utf8/latin1]{mylisting.txt}
%
% \Finale
\endinput
答案1
错误的字符表来自错误的设置\endlinechar
,请参阅 Ulrike 的评论。在 中设置\endlinechar
是为了防止在水平模式下使用时行尾出现额外的空格和空行出现标记。因此,这个 的设置是必要的,而不是错误。-1
\inputencoding
\par
\inputencoding
\endlinechar
因此,问题反而是,为什么首先检查注释中的字符表。latin1.def
不是 的参数\DocInput
。原因是百分号的类别代码发生了变化,它是活动的,而不是注释字符。因此,\inputencoding
通过确保百分号字符的类别代码,可以使其更加健壮。
应用修复的最小示例:
% \iffalse
%<*driver>
\documentclass{ltxdoc}
\usepackage[utf8]{inputenc}
\usepackage{etoolbox}
\makeatother
\pretocmd\inputencoding{%
\xdef\saved@percent@catcode{\the\catcode`\%}%
\catcode`\%14\relax
}{}{%
\errmessage{Cannot patch \string\inputencoding}%
}
\apptocmd\inputencoding{%
\catcode`\%\saved@percent@catcode\relax
}{}{%
\errmessage{Cannot patch \string\inputencoding}%
}
\makeatother
\begin{document}
\DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% Hello\inputencoding{latin1} World
%
% \Finale
\endinput
如果 LaTeX3 类别代码有效(\ExplSyntaxOn
或隐含地\ProvidesExplPackage
,请参阅评论),它们必须被禁用,因为\inputencoding
它们没有被expl3
宏编码:
\RequirePackage{expl3}
\RequireExplPackage{...}
...
\ExplSyntaxOff
\pretocmd ...
\apptocmd ...
\ExplSyntaxOn
其他修补方法:
\newcommand{\org@inputencoding}{}
\let\org@inputencoding\inputencoding
\def\inputencoding#1{%
\xdef\saved@percent@catcode{\the\catcode`\%}%
\catcode`\%14\relax
\org@inputencoding{#1}%
\catcode`\%\saved@percent@catcode\relax
}
或者更优雅的是,包inputenc
提供了两个钩子,分别在开始和结束时调用\inputencoding
:
\inpenc@prehook=\expandafter{\the\inpenc@prehook
\xdef\saved@percent@catcode{\the\catcode`\%}%
\catcode`\%14\relax
}
\inpenc@posthook=\expandafter{\the\inpenc@posthook
\catcode`\%\saved@percent@catcode\relax
}