5

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. – DavidR 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
3

Here is the xstring version:

enter image description here

Notes:

Code:

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


% https://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}%
    }%
}%

% https://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}
5

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.

enter image description here

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

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.