自訂包中出現奇怪的錯誤,而不是我試圖拋出的錯誤?

自訂包中出現奇怪的錯誤,而不是我試圖拋出的錯誤?

我正在為我的所有個人命令製作自訂包,我正在嘗試將一些關鍵字參數傳遞給該包,如第 4.4 節所述類別指南。我的用例是,我參加數學和物理課程,因此我經常需要更改符號(例如,在數學中,通常用橫線表示複共軛,而在物理中,更常見的符號是星號)。我製作了這個小模板,它幾乎可以按照我想要的方式工作:

% 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 節中記錄,其中之一是.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}

您也可以使用expkv-family 套件進行選項解析(我是其中的作者)。有些事情可能在 中更容易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}

相關內容