Atribuindo um valor de xstring

Atribuindo um valor de xstring

Estou tentando escrever alguma validação básica da entrada do usuário para um comando \noinsuitque usa dois parâmetros, um número inteiro em [0, 13] e uma letra indicando o naipe.

Portanto, espero \noinsuit{1}{C}ser válido e ambos \noinsuit{Q}{C}e \noinsuit{1}{Q}ser inválido. Está funcionando bem, mas estou tendo problemas ao usar xstring's \StrLeft{#1}{1}para testar se o primeiro caractere é um número inteiro. O seguinte MWE imprime seu valor corretamente, mas se eu descomentar a linha de teste, ele lança

! Undefined control sequence.
\xs_StrLeft__ ...ef \xs_arg_ii {#2}\edef \xs_call 
                                                  {\noexpand \xs_testopt {\n...

Um problema com a expansão, suponho.

\documentclass{article}

\usepackage{xparse}
\usepackage{xstring}

\newcommand{\singpl}{bad}
\newcommand{\test}{bad}

\NewDocumentCommand\noinsuit{mm}{%
    \renewcommand{\test}{\StrLeft{#1}{1}}
%   \IfInteger{\test}{\renewcommand{\singpl}{cards}}{[\PackageError{BridgeStyle : \noinsuit}{Invalid integer (#1)}{}]}%
    \IfEqCase{#1}{%
        {1}{\renewcommand{\singpl}{card}}%
    }
    \IfEqCase{#2}{%
        {C}{#1 \singpl{}\quad\test in Clubs}%
        {D}{#1 \singpl{} in Diamonds}%
        {H}{#1 \singpl{} in Hearts}%
        {S}{#1 \singpl{} in Spades}%
    }[\PackageError{BridgeStyle : \noinsuit}{Unknown suit (#2)}{}]%
}%

\begin{document}

\noinsuit{1}{C}

\noinsuit{2}{C}

%    \noinsuit{Q}{H}

%    \noinsuit{3}{Q}

    \end{document}  

Responder1

Você não pode usar \StrLeftdentro do argumento to \IfInteger. Você está passando as instruções para construir uma string em vez da string.

Em vez disso, faça

  \StrLeft{#1}{1}[\test]
  \IfInteger{\test}
    {\renewcommand{\singpl}{cards}}
    {\PackageError{BridgeStyle : \noinsuit}{Invalid integer (#1)}{}}%

Por outro lado, você pode obter mais controle usando expl3.

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand\noinsuit{mm}
 {
  \bridgestyle_noinsuit_checknumber:nn { #1 } { #2 }
 }

\cs_new_protected:Nn \bridgestyle_noinsuit_checknumber:nn
 {
  \regex_match:nnTF { \A [0-9]{1,2} \Z } { #1 }
   {% we have one or two digits
    \int_compare:nTF { #1 <= 13 }
     {% the integer is between 0 and 13
      \bridgestyle_noinsuit_checksuit:nn { #1 } { #2 }
     }
     {% error
      \bridgestyle_noinsuit_invalid:nn { integer } { #1 }
     }
   }
   {% invalid input for the integer
    \bridgestyle_noinsuit_invalid:nn { integer } { #1 }
   }
 }

\cs_new_protected:Nn \bridgestyle_noinsuit_checksuit:nn
 {
  \regex_match:nnTF { \A [CDHS] \Z } { #2 }
   {% valid suit
    #1~card\int_compare:nF { #1=1 } {s}~in~\bridgestyle_suit:n { #2 }
   }
   {% invalid suit
    \bridgestyle_noinsuit_invalid:nn { suit } { #2 }
   }
 }

\cs_new:Nn \bridgestyle_suit:n
 {
  \str_case:nn { #1 }
   {
    {C}{Clubs}
    {D}{Diamonds}
    {H}{Hearts}
    {S}{Spades}
   }
 }

\cs_new_protected:Nn \bridgestyle_noinsuit_invalid:nn
 {
  \PackageError{bridgestyle}{(\string\noinsuit)~invalid~#1~(#2)}{}
 }
\ExplSyntaxOff

\begin{document}

\noinsuit{0}{D}

\noinsuit{1}{C}

\noinsuit{2}{C}

\noinsuit{Q}{H}

\noinsuit{3}{Q}

\noinsuit{14}{H}

\end{document}  

A saída do console é

! Package bridgestyle Error: (\noinsuit) invalid integer (Q).

See the bridgestyle package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.65 \noinsuit{Q}{H}

? 

! Package bridgestyle Error: (\noinsuit) invalid suit (Q).

See the bridgestyle package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.67 \noinsuit{3}{Q}

? 

! Package bridgestyle Error: (\noinsuit) invalid integer (14).

See the bridgestyle package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.69 \noinsuit{14}{H}

? 

A saída impressa é

insira a descrição da imagem aqui

informação relacionada