我正在尝试设计软件包并通过pgfkeys
软件包处理软件包选项pgfopts
。但是当选项中包含格式化命令时,整个过程就会失败,我无法获得预期的结果。
这是我的测试包:pgfoptstest.sty
\NeedsTeXFormat{LaTeX2e}[1994/06/01]
\ProvidesPackage{pgfoptstest}[2020/01/01 pgfopts test]
\RequirePackage{pgfopts}
\pgfkeys{
/pgfoptstest/.cd,
format/.store in = \format,
format = \textit,
example/.store in = \example,
example = {This is an \format{example}.},
}
\ProcessPgfPackageOptions{/pgfoptstest}
\newcommand{\makeexample}{\example}
\newcommand{\maketest}[1]{\format{#1}}
这是我的测试文件:pgfoptstest.tex
\documentclass{article}
\usepackage{pgfoptstest} % OK
%\usepackage[format =]{pgfoptstest} % OK
%\usepackage[example = {Another example.}]{pgfoptstest} % NO SPACES
%\usepackage[example = {{Another example.}}]{pgfoptstest} % OK
%\usepackage[example = {{Another \textbf{example}.}}]{pgfoptstest} % ERROR
%\usepackage[format = \textbf]{pgfoptstest} % ERROR
\begin{document}
\noindent
\makeexample{}\\
\maketest{This is a test.}
\end{document}
如何修复它(最好是在软件包方面,以便用户不必以棘手的方式编写他们的选项)以便标记为的行ERROR
正常工作?
另外,有没有办法让标记为NO SPACES
正常工作的行,以便用户不必输入两对括号?
答案1
嗯,恐怕我有个坏消息。这不是由pgfkeys
或引起的pgfopts
,而是由 LaTeX 本身处理包选项的方式引起的。它会在传递选项之前删除空格并执行几次扩展。在包级别上对此几乎无能为力,因为当包看到它们时已经太晚了。
:(
不幸的是,\textbf
用\protect\textbf
and替换\noexpand\textbf
也无济于事。 有用的方法是用 替换\textbf
,\noexpand\noexpand\noexpand\textbf
但这并不是一个特别有吸引力的语法……
我原本以为这个问题会定期出现,但快速搜索后只出现了这个,这与kvoptions
。(也许我没有使用正确的搜索词。)有一个好消息是,David 说“可能计划改变这一点[期权处理期间的规范化]”他的回答。
建议 #1
在这次编辑之前,我曾开玩笑地提到,编写一个包来修补 LaTeX 处理选项的方式也是一个选择。我搜索了一下,发现不出所料,有人已经这样做了。如果你加载kvoptions-patch
包(在kvoptions
文档) 在加载您自己的包之前,带有空格或您不想扩展的宏的选项将会起作用!
这是您的 MWE,其中添加了一行:
\begin{filecontents}[overwrite]{pgfoptstest.sty}
\NeedsTeXFormat{LaTeX2e}[1994/06/01]
\ProvidesPackage{pgfoptstest}[2020/01/01 pgfopts test]
\RequirePackage{pgfopts}
\pgfkeys{
/pgfoptstest/.cd,
format/.store in = \format,
format = \textit,
example/.store in = \example,
example = {This is an \format{example}.},
}
\ProcessPgfPackageOptions{/pgfoptstest}
\newcommand{\makeexample}{\example}
\newcommand{\maketest}[1]{\format{#1}}
\end{filecontents}
\documentclass{article}
\usepackage{kvoptions-patch} %% <- added
\usepackage[example = Another \textbf{example}.]{pgfoptstest} % OK now
\begin{document}
\noindent
\makeexample{}\\
\maketest{This is a test.}
\end{document}
建议 #2
或者您可以创建一个设置函数,用户必须调用该函数来设置您的包。这不是一个好选择,但可能比要求用户使用\noexpand\noexpand\noexpand
不可扩展的宏要好。
\begin{filecontents}{pgfoptstest2.sty}
\NeedsTeXFormat{LaTeX2e}[1994/06/01]
\ProvidesPackage{pgfoptstest2}[2020/01/01 pgfopts test]
\RequirePackage{pgfopts}
\pgfkeys{
/pgfoptstest/.cd,
format/.store in = \format,
format = \textit,
example/.store in = \example,
example = {This is an \format{example}.},
}
\ProcessPgfPackageOptions{/pgfoptstest} %% <- optional (badum, tss)
\newcommand*\pgfoptstestsetup[1]{\pgfqkeys{/pgfoptstest}{#1}}
\newcommand{\makeexample}{\example}
\newcommand{\maketest}[1]{\format{#1}}
\end{filecontents}
\documentclass{article}
\usepackage{pgfoptstest2}
\pgfoptstestsetup{
format=\underline,
example = \textbf{Another example.}
}
\begin{document}
\noindent
\makeexample{}\\
\maketest{This is a test.}
\end{document}
附录(实验)
这里有一个小实验来证明在包级别没有办法避免这种情况。
\begin{filecontents}{stop.sty}
\stop %% <- abort immediately
\end{filecontents}
\documentclass{article}
% \usepackage{stop} %% <- successfully produces nothing
\usepackage[example = {{Another \textbf{example}.}}]{stop} %% <- errors
\begin{document}
\end{document}
- 如果没有传递任何选项
stop.sty
,一切都很好:TeX 在加载包的过程中停止并且不产生任何输出(也没有错误)。 - 如果将(例如)
example=\textbf{example}
作为选项传递,则一切都会变得很糟糕。错误消息与 MWE 中的消息相同。