Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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.

share|improve this question
    
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 at 14:38
    
Could you be more specific about the allowed values? –  egreg Feb 11 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 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 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 at 14:50
show 1 more comment

3 Answers

up vote 4 down vote accepted

Here is the xstring version:

enter image description here

Notes:

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}
share|improve this answer
add comment
\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

share|improve this answer
add comment

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

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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