Erro estranho no pacote personalizado em vez do erro que tentei lançar?

Erro estranho no pacote personalizado em vez do erro que tentei lançar?

Estou criando um pacote personalizado para todos os meus comandos pessoais e tentando passar alguns argumentos de palavras-chave para o pacote, conforme descrito na seção 4.4 doclsguide. Meu caso de uso é que faço cursos de matemática e física e muitas vezes preciso alterar as notações por causa disso (por exemplo, em matemática é comum denotar o conjugado complexo com uma barra, enquanto em física a notação mais comum é asterik). Fiz este pequeno modelo que quase funciona como eu queria:

% 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}

Ao atribuir um valor válido como physicsou math, funciona como eu esperava. No entanto, se eu fornecer um valor inválido, como engineer, recebo um erro, mas não é o erro que especifiquei:

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.

Com esse erro, não consigo ver qual era o valor inválido nem ver minha mensagem de erro ou ajuda. Por que isso acontece e como posso gerar um erro corretamente ao obter um argumento inválido?

Responder1

Você tem um espaço entre os casos de comparação em \IfStrEqCaseque xstringnão gosta.

\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}

Você pode simplificar um pouco seu código usando uma chave de escolha (também será mais eficiente, pois a comparação não acontecerá para cada uso de \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}

Responder2

Você pode usar mais propriedades-chave do que as documentadas em clsguide, as outras estão documentadas na interface3.pdfseção 27.1, uma das quais é .choices:nn, para a qual um exemplo de uso é fornecido na seção 27.3.

A mensagem de erro não será exatamente igual à que você especificou em seu código, mas espero que seja boa o suficiente.

% 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}}%
    }%
}

Semelhante ao @UdiFogiel, isso aqui propõe um uso ligeiramente diferente do valor e também converte seu pacote para usar a linguagem de programação L3 em vez de 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}

Você também pode usar a expkvfamília de pacotes para análise de opções (da qual sou o autor). Algumas coisas podem ser mais fáceis expkv, outras são mais difíceis (ou melhor, não incorporadas). Caso contrário, é mais sobre qual sintaxe você prefere.

% 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}

informação relacionada