![使用 switch-case 环境评估自定义包中的键值选项字符串](https://linux22.com/image/312863/%E4%BD%BF%E7%94%A8%20switch-case%20%E7%8E%AF%E5%A2%83%E8%AF%84%E4%BC%B0%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8C%85%E4%B8%AD%E7%9A%84%E9%94%AE%E5%80%BC%E9%80%89%E9%A1%B9%E5%AD%97%E7%AC%A6%E4%B8%B2.png)
我正在尝试编写一个自定义包我的Unicode字体我想在其中存储各种字体设置数学字体和罗马字体(后来还有mono和sans)。
在我的文档中,我打算使用键值选项来选择字体,例如:
\documentclass{article}
\usepackage[math=xits,roman=myriad]{MyUnicodefonts}
\usepackage{blindtext}
\begin{document}
\blindmathpaper
\end{document}
对于包文件我的Unicode字体我使用了这个答案对我来说,它似乎很方便,而且我不明白其他答案。我尝试将它应用于字符串比较。
使用kv选项我的打包文件最终如下所示:
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{MyUnicodefonts}[2015/06/21 Load fonts]
\RequirePackage{fontspec}
\RequirePackage{kvoptions}
\DeclareStringOption[minion]{roman}
\DeclareStringOption[xits]{math}
\ProcessKeyvalOptions*
\RequirePackage{xifthen}
\newcommand{\ifequals}[3]{\ifthenelse{\ifstrequal{#1}{#2}{TRUE}{}}{#3}{}}
\newcommand{\case}[2]{#1 #2} % Dummy, so \renewcommand has something to overwrite...
\newenvironment{switch}[1]{\renewcommand{\case}{\ifequals{#1}}}{}
\begin{switch}{\MyUnicodefonts@roman}
\case{minion}{\setmainfont[Numbers = OldStyle,
Ligatures = TeX,
]{Minion Pro}}
\case{myriad}{\setmainfont[Numbers={Uppercase,OldStyle},
]{Myriad Pro}}
\end{switch}
\begin{switch}{\MyUnicodefonts@math}
\case{xits}{%
\RequirePackage{unicode-math}
\setmathfont{XITS Math}
\setmathfont[range={"002B,"002D,"003A-"003E} ]{MnSymbol} % + - < = >
}
\case{iwona}{%
\RequirePackage[math]{iwona}
\RequirePackage[mathscr]{eucal}
}
\end{switch}
\endinput
作为kvoptions 手册缺乏全面的例子,我无法确定出现的原因未定义的控制序列错误。
如果我在切换之前也加载,错误就会消失unicode-math
,但我不希望这样,因为在某些情况下,我不想使用 unicode-math 字体。然而出现了一个新错误:
!缺失数字,视为零。\begingroup l.18 \case{myriad}{\setmainfont{Myriad Pro}} 这里应该有一个数字;我插入了“0”。(如果您不明白我为什么需要看到一个数字,请在 TeXbook 索引中查找“奇怪的错误”。)
我不明白这一点,因为我用\equal{#1}{#2}
原始开关(参见链接答案)替换了\ifstrequal{#1}{#2}{TRUE}{}
。
我希望您能帮助我找出错误或者建议一种完全不同的方法。
答案1
问题中的代码存在一些问题:
\ifstrequal
未定义,如错误消息所示。它由包定义etoolbox
。环境
switch
组成一个组,环境结束后所有本地设置都会丢失。
有很多方法可以实现“开关”,这是不是由包覆盖kvoptions
,力求简单且易于使用。
实现基于简单文本字符串的开关的经典方法是使用 TeX 的哈希表。以下示例将选项值的实现放在名称形式为 的宏中\<prefix>@<option>@<value>
。 的选项设置kvoptions
将值存储在 中\<prefix>@<option>
。然后使用 进行简单测试检查\@ifundefined
选项/值实现是否存在,如果选项值不受支持或未知,则抛出错误。
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{MyUnicodefonts}[2015/06/21 Load fonts]
\RequirePackage{fontspec}
\RequirePackage{kvoptions}
\DeclareStringOption[minion]{roman}
\DeclareStringOption[xits]{math}
\ProcessKeyvalOptions*
% Implementations for option "roman"
\@namedef{MyUnicodefonts@roman@minion}{%
\setmainfont[
Numbers = OldStyle,
Ligatures = TeX,
]{Minion Pro}%
}
\@namedef{MyUnicodefonts@roman@myriad}{%
\setmainfont[
Numbers={Uppercase,OldStyle},
]{Myriad Pro}%
}
% Implementations for option "math"
\@namedef{MyUnicodefonts@math@xits}{%
\RequirePackage{unicode-math}%
\setmathfont{XITS Math}%
\setmathfont[range={"002B,"002D,"003A-"003E}]{MnSymbol}%
}
\@namedef{MyUnicodefonts@math@iwona}{%
\RequirePackage[math]{iwona}%
\RequirePakcage[mathscr]{eucal}%
}
% Evaluate option settings
\newcommand*{\MyUnicodefonts@evaluate}[1]{%
% Check, if option value in \<prefix>@<option> exists
\@ifundefined{MyUnicodefonts@#1}{%
% Should not happen
\PackageError{MyUnicodefonts}{Evaluating unknown option `#1'}\@ehc
}{%
% Check, if there is an implementation for the value of the option
% in macro \<prefix>@<option>@<value>
\@ifundefined{MyUnicodefonts@#1@\csname MyUnicodefonts@#1\endcsname}{%
\PackageError{MyUnicodefonts}{%
Unknown option setting: #1=%
\csname MyUnicodefonts@#1\endcsname
}\@ehc
}{%
% Call the implementation for the value
\csname MyUnicodefonts@#1@%
\csname MyUnicodefonts@#1\endcsname
\endcsname
\relax
}%
}%
}
\MyUnicodefonts@evaluate{roman}
\MyUnicodefonts@evaluate{math}
\endinput
答案2
您可以使用l3keys2e
。
文件myunicodefonts.sty
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{myunicodefonts}[2015/06/21 Load fonts]
\RequirePackage{fontspec}
\RequirePackage{l3keys2e}
\ExplSyntaxOn
\bool_new:N \g_myunicodefonts_mathfont_bool
\tl_new:N \g_myunicodefonts_textfont_tl
\tl_new:N \g_myunicodefonts_mathfont_tl
\keys_define:nn { myunicodefonts }
{
textfont .choice:,
textfont/minion .code:n = \tl_gset:Nn \g_myunicodefonts_textfont_tl {Minion~Pro},
textfont/myriad .code:n = \tl_gset:Nn \g_myunicodefonts_textfont_tl {Myriad~Pro},
textfont .initial:n = minion,
textoptions .tl_gset:N = \g_myunicodefonts_textfont_options_tl,
mathfont .choice:,
mathfont/xits .code:n =
{
\bool_gset_true:N \g_myunicodefonts_mathfont_bool
\tl_gset:Nn \g_myunicodefonts_mathfont_tl {XITS~Math}
},
mathfont/asana .code:n =
{
\bool_gset_true:N \g_myunicodefonts_mathfont_bool
\tl_gset:Nn \g_myunicodefonts_mathfont_tl {Asana~Math}
},
mathoptions .tl_gset:N = \g_myunicodefonts_mathfont_options_tl,
}
\ProcessKeysPackageOptions{myunicodefonts}
\use:x
{
\setmainfont{\g_myunicodefonts_textfont_tl}[\g_myunicodefonts_textfont_options_tl]
}
\bool_if:NT \g_myunicodefonts_mathfont_bool
{
\RequirePackage{unicode-math}
\use:x
{
\setmathfont[\g_myunicodefonts_mathfont_options_tl]{\g_myunicodefonts_mathfont_tl}
}
}
\ExplSyntaxOff
\endinput
myunicodefonts.tex
测试文件
\documentclass{article}
\usepackage[
mathfont=xits,
textfont=myriad,
textoptions={Scale=0.8},
]{myunicodefonts}
\usepackage{blindtext}
\begin{document}
\blindmathpaper
\end{document}
我们可以通过对错误选项进行错误检查来补充这一点。
不同的代码
如果您想自己设置字体选项,只需在.case:n
代码中进行设置即可。
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{MyUnicodefonts}[2015/06/21 Load fonts]
\RequirePackage{fontspec}
\RequirePackage{l3keys2e}
\ExplSyntaxOn
\keys_define:nn { myunicodefonts }
{
textfont .choice:,
textfont/minion .code:n =
{
\setmainfont{Minion~Pro}[
Numbers = OldStyle,
Ligatures = TeX,
]
},
textfont/myriad .code:n =
{
\setmainfont{Myriad~Pro}[
Numbers={Uppercase,OldStyle},
]
},
textfont .initial:n = minion,
mathfont .choice:,
mathfont/xits .code:n =
{
\RequirePackage{unicode-math}
\setmathfont{XITS~Math}
\setmathfont[range={"002B,"002D,"003A-"003E}]{MnSymbol} % + - < = >
},
mathfont/iwona .code:n =
{
\RequirePackage[math]{iwona}
\RequirePackage[mathscr]{eucal}
},
}
\ProcessKeysPackageOptions{myunicodefonts}
\ExplSyntaxOff
\endinput