Asignar un valor desde xstring

Asignar un valor desde xstring

Estoy intentando escribir una validación básica de la entrada del usuario para un comando \noinsuitque toma dos parámetros, un número entero en [0, 13] y una letra que indica el traje.

Entonces espero \noinsuit{1}{C}ser válido y ambos \noinsuit{Q}{C}y \noinsuit{1}{Q}ser inválido. Eso funciona bien, pero tengo problemas al usar xstring's \StrLeft{#1}{1}para probar si el primer carácter es un número entero. El siguiente MWE imprime su valor correctamente pero si descomento la línea de prueba arroja

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

Un problema con la expansión, supongo.

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

Respuesta1

No puedes usarlo \StrLeftdentro del argumento to \IfInteger. Estás pasando las instrucciones para construir una cadena en lugar de la cadena.

Más bien hazlo

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

Por otro lado, puedes obtener más control 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}  

La salida de la consola es

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

? 

La salida impresa es

ingrese la descripción de la imagen aquí

información relacionada