在编写带有键值接口的包时,我有很多重复的键定义。自然,人们想用循环来表达这些定义。当定义包含更复杂的东西时\PassOptionsToPackage
,事情就会变得混乱。混乱程度取决于用于循环的包。etoolbox
抱怨很多,forarray
但不是那么多。的最小工作示例forarray
:
\NeedsTeXFormat{LaTeX2e}[1994/12/01]
\ProvidesPackage{package}
[2012/09/18 Example]
\RequirePackage{keyreader}
\RequirePackage{forarray}
\DeclareOptionX*{%
\PackageWarningNoLine{}{Cant understand option(s): \CurrentOption}%
}
\CommandForEach{,}{%
\krdDeclareOption{#1}{\PassOptionsToPackage{##1}{#1}}%
}%
{todonotes}
\krdProcessOptions
这是包,latex文件是
\documentclass{article}
\usepackage[todonotes=shadow]{package}
\usepackage{todonotes}
\begin{document}
\todo{2 do}
\end{document}
这会产生警告
! LaTeX Error: Missing \begin{document}.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.13 {todonotes}
?
没有造成更大的伤害,紧迫返回结束。只有待办事项文档中的问题仍然存在,但待办事项框有一个漂亮的阴影。这里出了什么问题?
答案1
解决方案\comma@parse
使用kvsetkeys
:
\NeedsTeXFormat{LaTeX2e}[1994/12/01]
\ProvidesPackage{package}[2012/09/18 Example]
\RequirePackage{keyreader}
\RequirePackage{kvsetkeys}
\DeclareOptionX*{%
\PackageWarningNoLine{}{Cant understand option(s): \CurrentOption}%
}
\def\TempDefOption#1{%
\krdDeclareOption{#1}{\PassOptionsToPackage{##1}{#1}}%
}
\comma@parse{todonotes}\TempDefOption
\krdProcessOptions
答案2
另一个(或者更准确地说,相同的)解决方案是etoolbox
:
\NeedsTeXFormat{LaTeX2e}[1994/12/01]
\ProvidesPackage{package}
[2012/09/18 Example]
\RequirePackage{keyreader}
\RequirePackage{etoolbox}
\renewcommand*{\do}[1]{%
\krdDeclareOption{#1}{\PassOptionsToPackage{##1}{#1}}%
}
\docsvlist{todonotes}
\krdProcessOptions
当我测试 Heikos 解决方案时,我意识到之前使用 时etoolbox
,我只是在重新定义 时忘记了右花括号\do
。抱歉给您带来麻烦,我仍然希望它有用。
答案3
你真正需要的是类似下面的内容。你不必加载电子工具箱或任何用于处理列表的包。键盘阅读器包有自己的列表处理器。
\NeedsTeXFormat{LaTeX2e}[2011/06/27]
\ProvidesPackage{ulysis}[2012/09/18 Example package]
\RequirePackage{keyreader}
\krdDeclareOption*{%
\PackageWarningNoLine{ulysis}{Unknown option `\CurrentOption' ignored}%
}
\newif\ifuly@verbose
\krdDeclareOption{verbose}[true]{\@nameuse{uly@verbose#1}}
% Declare options with default values that will be used when the options
% are called without user values:
\protected\def\DeclarePassedOptions#1{%
\edef\uly@tempa{\unexpanded{#1}}%
\krdkvnormalize\uly@tempa
% The looping macro used here is \krdfor, but the list has to be first normalized.
\def\do##1{%
\def\@do####1=####2=####3\@nil{%
\krdDeclareOption{####1}[####2]{%
\PassOptionsToPackage{########1}{####1}%
}%
% To avoid passing options to eventually unloaded packages:
\AtBeginDocument{%
\ifuly@verbose
\krdifcsndef{ver@####1.sty}{}{%
\@latexerr{Package '####1' wasn't loaded}
{There are specified but unloaded packages}%
}%
\fi
}%
}%
\@do##1==\@nil
}%
\expandafter\krdfor\expandafter{\uly@tempa}%
}
\DeclarePassedOptions{%
todonotes={backgroundcolor=gray!15},xcolor=svgnames
}
\krdProcessOptions*
\endinput
测试文档:
\documentclass[12pt]{article}
\usepackage[
verbose,
todonotes={shadow,linecolor=red,backgroundcolor=white},
xcolor=dvipsnames
]{ulysis}
\usepackage{todonotes}
\usepackage{xcolor}
\begin{document}
\textcolor{MidnightBlue}{%
\todo{{\bf\large 1 do}}
}
\textcolor{ForestGreen}{%
\todo{\bf\large 2 do}
}
\end{document}