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.

6
  • 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. Commented Feb 11, 2014 at 14:38
  • Could you be more specific about the allowed values?
    – egreg
    Commented Feb 11, 2014 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
    Commented Feb 11, 2014 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
    Commented Feb 11, 2014 at 14:49
  • Use @steven B. Segletes to direct your comment to my attention, FYI. The "at" sign is important. Commented Feb 11, 2014 at 14:50

3 Answers 3

4

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .