Я пытаюсь написать простую проверку пользовательского ввода для команды \noinsuit
, которая принимает два параметра: целое число в диапазоне [0, 13] и букву, обозначающую масть.
Итак, я ожидаю, \noinsuit{1}{C}
что будет допустимым и оба \noinsuit{Q}{C}
, и \noinsuit{1}{Q}
недопустимым. Это работает нормально, но у меня возникла проблема с использованием xstring
's \StrLeft{#1}{1}
для проверки того, является ли первый символ целым числом. Следующий MWE печатает свое значение правильно, но если я раскомментирую тестовую строку, он выдает
! Undefined control sequence.
\xs_StrLeft__ ...ef \xs_arg_ii {#2}\edef \xs_call
{\noexpand \xs_testopt {\n...
Полагаю, проблема с расширением.
\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}
решение1
Вы не можете использовать \StrLeft
внутри аргумента to \IfInteger
. Вы передаете инструкции по созданию строки, а не саму строку.
Скорее сделай
\StrLeft{#1}{1}[\test]
\IfInteger{\test}
{\renewcommand{\singpl}{cards}}
{\PackageError{BridgeStyle : \noinsuit}{Invalid integer (#1)}{}}%
С другой стороны, вы можете получить больше контроля, используя 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}
Вывод консоли:
! 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}
?
Печатный вывод: