使用 pgfopts 在 pgfkeys 中传递格式选项

使用 pgfopts 在 pgfkeys 中传递格式选项

我正在尝试设计软件包并通过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\textbfand替换\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 中的消息相同。

相关内容