# xstring test for numbers within a range

I'm working on a document command that has a variety of optional arguments for different results. I need to add an option that yields 'true' for an optional argument within a range of numbers, for example 100-200. The command is as follows (MWE):

\documentclass{article}
\usepackage{xparse,xstring,xspace}

\NewDocumentCommand{\Foo}{ o }{%
\IfNoValueTF{#1} {%
\emph{Foo}\xspace}{%
\IfBeginWith{#1}%
{b}{\emph{Foo} Bar\xspace}{%
\IfStrEqCase{#1}{%
{f}{\emph{Foo}\xspace}%
}%
[\emph{Foo}~#1\xspace]%
}%
}%
}

\begin{document}

\Foo

\Foo[b]

\Foo[3]

\end{document}


xstring does not appear to have a range option.

-
If you know the argument to be a number, would it not be easier to put the number into a counter, and test the counter within a range? After all, xstring works with strings, not numbers. – Steven B. Segletes Feb 11 '14 at 14:38
Could you be more specific about the allowed values? – egreg Feb 11 '14 at 14:41
Steven: the argument can also be a letter (b). egreg: actually, in my specific case it just has to be above 343 rather than in a range, but I wanted to make the question more general/applicable. – David Rowthorn Feb 11 '14 at 14:44
So, if the optional argument starts with b something should be done, otherwise it should be a number and this number should be examined? – egreg Feb 11 '14 at 14:49
Use @steven B. Segletes to direct your comment to my attention, FYI. The "at" sign is important. – Steven B. Segletes Feb 11 '14 at 14:50

Here is the xstring version:

## Code:

\documentclass{article}
\usepackage{xstring}
\usepackage{pgf}

% http://tex.stackexchange.com/questions/50111/how-to-check-if-the-value-of-a-parameter-is-a-number
\newcommand*{\IsInteger}[3]{%
\IfStrEq{#1}{ }{%
#3% is a blank string
}{%
\IfInteger{#1}{#2}{#3}%
}%
}%

% http://tex.stackexchange.com/questions/15297/how-to-test-if-a-number-is-negative
\newcommand{\IsZeroOrPositive}[3]{%
% #1 = number to test
% #2 = code to executer if positive
% #3 = code to execute if non-postiive
\pgfmathsetmacro{\varX}{#1}%
\pgfmathparse{ifthenelse(\varX>=0,1,0)}%
\if\pgfmathresult 1 \relax%
#2%
\else%
#3%
\fi%
}%

\newcommand*{\RangeMin}{100}%
\newcommand*{\RangeMax}{200}%
\newcommand*{\IsInRange}[3]{%
% #1 = number to test
% #2 = code to execute if in range
% #3 = code to execute if NOT in range, or #1 NOT an integer
\IsInteger{#1}{%
\IsZeroOrPositive{#1-\RangeMin}{%
\IsZeroOrPositive{\RangeMax-#1}{%
#2% Number is in range
}{%
#3% Number not in range
}%
}{%
#3% Number not in range
}%
}{%
#3% Not a number
}%
}

\begin{document}
Character a" is \IsInRange{a}{in range}{not in range}.\par
Empty string is \IsInRange{}{in range}{not in range}.\par
Blank string is \IsInRange{       }{in range}{not in range}.\par

\medskip
2 is \IsInRange{2}{in range}{not in range}.\par
99 is \IsInRange{99}{in range}{not in range}.\par
100 is \IsInRange{100}{in range}{not in range}.\par
111 is \IsInRange{111}{in range}{not in range}.\par
200 is \IsInRange{200}{in range}{not in range}.\par
201 is \IsInRange{201}{in range}{not in range}.
\end{document}

-
\documentclass{minimal}
\usepackage{xspace}
\newcommand\isnum[3]{%
\if!\ifnum9<1#1!\else_\fi       % a number or something else?
\ifnum#1>99\relax             % we have a number > 99
\ifnum#1<201\relax #2       % it is in [100;200]
\else #3\fi         % not a number or not in [100;200]
\else #3\fi
\else #3\fi\xspace}
\newcommand\Foo[1][a]{\isnum{#1}{true}{false}}

\begin{document}

\Foo, \Foo[b], \Foo[3], \Foo[155]

\end{document}


-

My proposal is to test the first token in the optional argument; if it's a digit, we assume it's a number:

\documentclass{article}
\usepackage{xparse,xspace}

\ExplSyntaxOn
\NewDocumentCommand{\foo}{ o }
{
\IfNoValueTF{#1}
{
\emph{Foo}\xspace
}
{
\rowthorn_check_arg:n { #1 }
}
}
\cs_new_protected:Npn \rowthorn_check_arg:n #1
{
\tl_if_in:nfTF {0123456789} { \tl_head:n { #1 } }
{
\rowthorn_numeric_arg:n { #1 }
}
{
\rowthorn_string_arg:n { #1 }
}
}
\cs_generate_variant:Nn \tl_if_in:nnTF { nf }
\cs_new_protected:Npn \rowthorn_numeric_arg:n #1
{
\int_compare:nTF { #1 > 343 }
{
\emph{Foo}~(#1)
}
{
\emph{Foo}
}
}
\cs_new_protected:Npn \rowthorn_string_arg:n #1
{
\emph{Foo}~[#1]
}

\ExplSyntaxOff

\begin{document}
\foo test

\foo[bxx] test

\foo[f] test

\foo[fx] test

\foo[3] test

\foo[400] test
\end{document}


It's up to you completing the specification.

-