![私がスローしようとしたエラーではなく、カスタム パッケージで奇妙なエラーが発生しましたか?](https://rvso.com/image/472717/%E7%A7%81%E3%81%8C%E3%82%B9%E3%83%AD%E3%83%BC%E3%81%97%E3%82%88%E3%81%86%E3%81%A8%E3%81%97%E3%81%9F%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%8F%E3%80%81%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%20%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%A7%E5%A5%87%E5%A6%99%E3%81%AA%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E7%99%BA%E7%94%9F%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F%E3%81%8B%3F.png)
私はすべての個人コマンド用のカスタムパッケージを作成しており、セクション4.4で説明されているように、いくつかのキーワード引数をパッケージに渡そうとしています。clsガイド私の使用例は、数学と物理学のコースを受講しており、そのために表記法を変更する必要があることが多いことです (たとえば、数学では複素共役をバーで表すのが一般的ですが、物理学ではアスタリスクの表記法がより一般的です)。私は、ほぼ希望どおりに機能するこの小さなテンプレートを作成しました。
% demo-pkg.sty
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{demo-pkg}[Demo]
\RequirePackage{xstring}
\DeclareKeys[demo]
{
notation.store = \@demo@notation,
notation.usage = load
}
\SetKeys[demo]{notation=physics} % Default to physics notation
\ProcessKeyOptions[demo]
\IfStrEqCase{\@demo@notation}{
{physics}{}
{math}{}
}[
\PackageError{demo-pkg}{Invalid notation value: \@demo@notation}
{Choose value of: physics, math}
]
\RequirePackage{xparse}
\NewDocumentCommand{\Conjugate}{ m }{
\IfStrEqCase{\@demo@notation}{
{physics}{{#1}^{\ast}}
{math}{\overline{#1}}
}
}
% main.tex
\documentclass{article}
\usepackage[notation=math]{demo-pkg}
\begin{document}
\[ z = x + iy \Longleftrightarrow \Conjugate{z} = x - iy \]
\end{document}
physics
または のような有効な値を指定するとmath
、期待どおりに動作します。ただし、 のような無効な値を指定するとengineer
、エラーが発生しますが、それは指定したエラーではありません。
Runaway argument?
\PackageError {demo-pkg}{Invalid notation value: \@demo@notation } {\ETC.
! File ended while scanning use of \xs_testcase.
<inserted text>
\par
l.4
I suspect you have forgotten a `}', causing me
to read past where you wanted me to stop.
I'll try to recover; but if the error is serious,
you'd better type `E' or `X' now and fix your file.
このエラーから、無効な値が何であったかを確認できず、エラー メッセージやヘルプも表示されません。なぜこのようなことが起こるのでしょうか。また、無効な引数を取得したときにエラーを正しくスローするにはどうすればよいでしょうか。
答え1
比較ケースの間にスペースがあり、\IfStrEqCase
それがxstring
気に入らないのです。
\begin{filecontents*}[overwrite]{demo-pkg.sty}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{demo-pkg}[Demo]
\RequirePackage{xstring}
\DeclareKeys[demo]
{
notation.store = \@demo@notation,
notation.usage = load
}
\SetKeys[demo]{notation=physics} % Default to physics notation
\ProcessKeyOptions[demo]
\IfStrEqCase{\@demo@notation}{
{physics}{}%
{math}{}%
}[
\PackageError{demo-pkg}{Invalid notation value: \@demo@notation}
{Choose value of: physics, math}
]
\RequirePackage{xparse}
\NewDocumentCommand{\Conjugate}{ m }{%
\IfStrEqCase{\@demo@notation}{%
{physics}{{#1}^{\ast}}%
{math}{\overline{#1}}%
}%
}
\end{filecontents*}
\documentclass{article}
\usepackage[notation=aa]{demo-pkg}
\begin{document}
\[ z = x + iy \Longleftrightarrow \Conjugate{z} = x - iy \]
\end{document}
選択キーを使用すると、コードを少し簡略化できます ( を使用するたびに比較が行われないため、効率も向上します\Conjugate
)。
\begin{filecontents*}[overwrite]{demo-pkg.sty}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{demo-pkg}[Demo]
\DeclareKeys[demo]
{
notation.choice:,
notation/physics.code = \DeclareDocumentCommand\Conjugate{ m }{{##1}^{\ast}},
notation/math.code = \DeclareCommandCopy\Conjugate\overline,
notation/unknown.code =
\PackageError{demo-pkg}{Invalid notation value: #1}
{Choose value of: physics, math},
notation.initial:n = physics,
notation.usage = load
}
\ProcessKeyOptions[demo]
\end{filecontents*}
\documentclass{article}
\usepackage[notation=math]{demo-pkg}
\begin{document}
\[ z = x + iy \Longleftrightarrow \Conjugate{z} = x - iy \]
\end{document}
答え2
に記載されているキー プロパティ以外にも、キー プロパティを使用できますclsguide
。その他のキー プロパティはinterface3.pdf
セクション 27.1 に記載されています。そのうちの 1 つは で.choices:nn
、その使用例はセクション 27.3 に記載されています。
エラー メッセージはコードで指定したものとまったく同じにはなりませんが、十分なものになると思います。
% demo-pkg.sty
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{demo-pkg}[Demo]
\RequirePackage{xstring}
\DeclareKeys[demo]
{
notation .choices:nn =
{physics,math}
{\ExpandArgs{Nc}\let\@demo@notation{l_keys_choice_tl}}
,notation.usage = load
}
\SetKeys[demo]{notation=physics} % Default to physics notation
\ProcessKeyOptions[demo]
% \RequirePackage{xparse} % not needed with recent kernel versions
\NewDocumentCommand{\Conjugate}{ m }{%
\IfStrEqCase{\@demo@notation}{%
{physics}{{#1}^{\ast}}%
{math}{\overline{#1}}%
}%
}
@UdiFogiel と同様に、ここでは値の若干異なる使用法を提案し、パッケージを の代わりに L3 プログラミング言語を使用するように変換しますxstring
。
% demo-pkg.sty
\NeedsTeXFormat{LaTeX2e}
\ProvidesExplPackage{demo-pkg} {2024-01-06} {0.0} {Demo}
% assuming that you always need only two different notations, the following
% changes it to a boolean variable
\bool_new:N \l__demopkg_notation_physics_bool
\DeclareKeys[demo]
{
notation .choice:
,notation / physics .code:n =
\bool_set_true:N \l__demopkg_notation_physics_bool
,notation / maths .code:n =
\bool_set_false:N \l__demopkg_notation_physics_bool
,notation .usage:n = load
,notation .initial:n = physics
}
\ProcessKeyOptions[demo]
% since `load` doesn't allow changes after the package got loaded, we can just
% hard code the implementations here, instead of deciding on each call
\bool_if:NTF \l__demopkg_notation_physics_bool
{ \NewDocumentCommand \Conjugate { m } { #1 \sp { \ast } } }
{ \NewDocumentCommand \Conjugate { m } { \overline {#1} } }
\begin{advertisement}
オプション解析には、パッケージの -familyを使用することもできますexpkv
(これは私が作成したものです)。 では簡単なものもあればexpkv
、難しいものもあります (または、組み込まれていません)。それ以外の場合は、どの構文を好むかによります。
% demo-pkg.sty
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{demo-pkg}[2024-01-06 v0.0 Demo]
\RequirePackage{expkv-def,expkv-opt}
\ekvdefinekeys{demo}
{
choice notation =
{
% expkv allows much freedom regarding the protected prefix because it
% can work by expansion only (if it's not processing package
% options...), therefore we need to set the protected prefix ourselves
% here if we want to play nice.
protected physics = \let\@demo@physicsTF\@firstoftwo
,protected maths = \let\@demo@physicsTF\@secondoftwo
}
,initial notation = physics
}
\ekvoProcessGlobalOptions{demo} % options provided to \documentclass
\ekvoProcessLocalOptions{demo} % options provided while loading this package
% future options will throw an option conflict error, since we only have a
% single load-time only option this is to be preferred over manually handling
% this. Else we could use `\ekvoProcessFutureOptions` (or combine all three
% calls by using `\ekvoProcessOptions` instead), but we'd need to redefine all
% the keys we don't want to be usable on a second time usage, because there is
% nothing like the `.usage`-property in `expkv`. This could look like the
% following:
% \newcommand\@demo@aux[1]
% {%
% \protected\long\ekvdef{demo-pkg}{#1}
% {%
% \PackageError{demo-pkg}
% {Option `#1' only usable on first package load}{}%
% }%
% }
% \ekvcsvloop\@demo@aux{notation}% if you
% \let\@demo@aux\@demo@undefined
% since `load` doesn't allow changes after the package got loaded, we can just
% hard code the implementations here, instead of deciding on each call
\@demo@physicsTF
{\NewDocumentCommand \Conjugate { m } {#1^{\ast}}}
{\NewDocumentCommand \Conjugate { m } {\overline{#1}}}
\end{advertisement}