summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/xifthen
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/xifthen
Initial commit
Diffstat (limited to 'macros/latex/contrib/xifthen')
-rw-r--r--macros/latex/contrib/xifthen/README27
-rw-r--r--macros/latex/contrib/xifthen/xifthen.pdfbin0 -> 476484 bytes
-rw-r--r--macros/latex/contrib/xifthen/xifthen.sty223
-rw-r--r--macros/latex/contrib/xifthen/xifthen.tex497
4 files changed, 747 insertions, 0 deletions
diff --git a/macros/latex/contrib/xifthen/README b/macros/latex/contrib/xifthen/README
new file mode 100644
index 0000000000..8ec50f662c
--- /dev/null
+++ b/macros/latex/contrib/xifthen/README
@@ -0,0 +1,27 @@
+This package implements new commands to go within the first argument of
+\ifthenelse to test whether a string is void or not, if a command is
+defined or equivalent to another. It includes also the possibility to make
+use of the complex expressions introduced by the package calc, together
+with the ability of defining new commands to handle complex tests. This
+package requires the e-TEX features.
+
+What's new
+
+v.1.
+- \cnttest and \dimtest now accept <= and >= comparisons.
+- I renames \terminateswith in \endswith.
+
+v1.2
+- Corrected a bug with \newtest
+
+v1.3
+- Removed a spurious space in the code.
+
+v1.4.0
+- Removed the reliance on the \cmd{etex} package, following an exmail
+ exchange with David Carlisle and Maïeul Rouquette. (I also updated
+ the documentation and pushed the files on GitHub.)
+
+This material is subject to the LaTeX Project Public License.
+See http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html
+for the details of that license.
diff --git a/macros/latex/contrib/xifthen/xifthen.pdf b/macros/latex/contrib/xifthen/xifthen.pdf
new file mode 100644
index 0000000000..10a01d5692
--- /dev/null
+++ b/macros/latex/contrib/xifthen/xifthen.pdf
Binary files differ
diff --git a/macros/latex/contrib/xifthen/xifthen.sty b/macros/latex/contrib/xifthen/xifthen.sty
new file mode 100644
index 0000000000..247546fabd
--- /dev/null
+++ b/macros/latex/contrib/xifthen/xifthen.sty
@@ -0,0 +1,223 @@
+\def \filedate {2015/11/05}%
+\def \fileversion {v1.4.0}%
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{xifthen}%
+ [\filedate \space \fileversion \space Extended ifthen features]
+
+% v1.4 Removed the etex package for compatibility reasons
+
+\RequirePackage{calc}
+\RequirePackage{ifthen}
+\RequirePackage{ifmtarg}
+
+% First of all, \TE@repl (ifthen) needs to be patched. (v1.2)
+% (viz. \newtest{\superlogique}[1]{\(\NOT#1\AND\boolean{true}\)})
+% Pointed out by MPG and Pierre Albar\`ede [19 Mar 2009]
+
+\def \TE@repl #1#2{%
+ \long \def \@tempc ##1#1##2{%
+ \def \@tempb{\@tempc}%
+ \begingroup % Thanks MPG
+ \toks@ {##2}%
+ \edef \@tempa {\the \toks@}% <- UF v1.3
+ \expandafter \endgroup
+ \ifx \@tempa \@tempb
+ \toks@ \expandafter {\the \toks@ ##1}%
+ \expandafter \@gobble
+ \else
+ \toks@ \expandafter {\the \toks@ ##1#2}%
+ \expandafter \@tempc
+ \fi
+ ##2%
+ }%
+ \toks@ \expandafter {\expandafter}%
+ \expandafter \@tempc \the \toks@ #1\@tempc
+}
+
+% \cnttest {<counter expression>} {<relation>} {<counter expression>}
+%
+\newcommand*{\TE@cnttest}[4]{%
+ \TE@throw
+ \noexpand \calc@assign@count{\@tempcnta}{\unexpanded{#1}}%
+ \noexpand \calc@assign@count{\@tempcntb}{\unexpanded{#3}}%
+ \noexpand \if \noexpand \TE@cnttest@ {#2}%
+ #4%
+}
+
+\newcommand*{\TE@cnttest@}[1]{%
+ \ifcsname TE@cnttest@@#1\endcsname
+ \csname TE@cnttest@@#1\expandafter\expandafter\expandafter \endcsname
+ \expandafter \@gobble
+ \else
+ \expandafter \@firstofone
+ \fi
+ {FF\PackageError{xifthen}{Not a valid comparison operator "#1"}%
+ {Valid comparisons are <, =, >, <=, and =>.}}%
+}
+
+\@namedef{TE@cnttest@@<}{\ifnum \@tempcnta<\@tempcntb AA\else AB\fi}
+\@namedef{TE@cnttest@@>}{\ifnum \@tempcnta>\@tempcntb AA\else AB\fi}
+\@namedef{TE@cnttest@@=}{\ifnum \@tempcnta=\@tempcntb AA\else AB\fi}
+\@namedef{TE@cnttest@@<=}{%
+ \ifnum \@tempcnta<\@tempcntb AA\else
+ \ifnum \@tempcnta=\@tempcntb AA\else AB\fi
+ \fi
+}
+\@namedef{TE@cnttest@@>=}{%
+ \ifnum \@tempcnta>\@tempcntb AA\else
+ \ifnum \@tempcnta=\@tempcntb AA\else AB\fi
+ \fi
+}
+
+% \dimtest {<dimension expression>} {<relation>} {<dimension expression>}
+%
+\newcommand*{\TE@dimtest}[4]{%
+ \TE@throw
+ \noexpand \calc@assign@skip{\@tempskipa}{\unexpanded{#1}}%
+ \noexpand \calc@assign@skip{\@tempskipb}{\unexpanded{#3}}%
+ \noexpand \if \noexpand \TE@dimtest@ {#2}%
+ #4%
+}
+
+\newcommand*{\TE@dimtest@}[1]{%
+ \ifcsname TE@dimtest@@#1\endcsname
+ \csname TE@dimtest@@#1\expandafter\expandafter\expandafter \endcsname
+ \expandafter \@gobble
+ \else
+ \expandafter \@firstofone
+ \fi
+ {FF\PackageError{xifthen}{Not a valid comparison operator "#1"}%
+ {Valid comparisons are <, =, >, <=, and =>.}}%
+}
+
+\@namedef{TE@dimtest@@<}{\ifdim \@tempskipa<\@tempskipb AA\else AB\fi}
+\@namedef{TE@dimtest@@>}{\ifdim \@tempskipa>\@tempskipb AA\else AB\fi}
+\@namedef{TE@dimtest@@=}{\ifdim \@tempskipa=\@tempskipb AA\else AB\fi}
+\@namedef{TE@dimtest@@<=}{%
+ \ifdim \@tempskipa<\@tempskipb AA\else
+ \ifdim \@tempskipa=\@tempskipb AA\else AB\fi
+ \fi
+}
+\@namedef{TE@dimtest@@>=}{%
+ \ifdim \@tempskipa>\@tempskipb AA\else
+ \ifdim \@tempskipa=\@tempskipb AA\else AB\fi
+ \fi
+}
+
+% \isnamedefined {<command name>}
+%
+\newcommand*{\TE@isnamedefined}[2]{%
+ \TE@throw
+ \noexpand \ifcsname #1\endcsname
+ #2%
+}
+
+% \isempty {<content>}
+%
+\newcommand*{\TE@isempty}[2]{%
+ \TE@throw
+ \noexpand \if FF\noexpand \@nameuse{fi}%
+ \noexpand \@ifmtarg{\unexpanded{#1}}{%
+ \noexpand \@nameuse{iftrue}%
+ }{%
+ \noexpand \@nameuse{iffalse}%
+ }%
+ #2%
+}
+
+% \isequivalentto {<command>} {<command>}
+%
+\newcommand*{\TE@isequivalentto}[3]{%
+ \TE@throw
+ \noexpand \ifx \noexpand #1\noexpand#2%
+ #3%
+}
+
+% \isin {<substring>} {<string>}
+%
+\newcommand*{\TE@isin}[3]{%
+ \TE@throw
+ \unexpanded {\in@{#1}{#2}}%
+ \noexpand \ifin@
+ #3%
+}
+
+% \endswith {<string>} {<substring>}
+%
+\newcommand*{\TE@endswith}[3]{%
+ \TE@throw
+ \unexpanded {\in@{#2\@nil}{#1\@nil}}%
+ \noexpand \ifin@
+ #3%
+}
+
+% \newtest <command> [<number>] {<definition>}
+%
+\newcommand*{\newtest}[1]{%
+ \@ifnextchar[{%
+ \@newtest{#1}%
+ }{%
+ \@newtest{#1}[0]%
+ }%
+}%
+
+\newcommand*{\@newtest}{}
+\def \@newtest #1[#2]#3{%
+ \toks@ = {\(#3\)}%
+ \TE@repl \or \TE@or
+ \TE@repl \and \TE@and
+ \TE@repl \not \TE@neg
+ \TE@repl \OR \TE@or
+ \TE@repl \AND \TE@and
+ \TE@repl \NOT \TE@neg
+ \edef \@tempa {%
+ \unexpanded{\newcommand*{#1}[{#2}]}{\the \toks@}%
+ }%
+ \@tempa
+}%
+
+\newcommand*{\TE@hook}{%
+ \let \isequivalentto = \TE@isequivalentto
+ \let \terminateswith = \TE@endswith % For compability reasons (deprecated)
+ \let \endswith = \TE@endswith
+ \let \isnamedefined = \TE@isnamedefined
+ \let \isempty = \TE@isempty
+ \let \cnttest = \TE@cnttest
+ \let \dimtest = \TE@dimtest
+ \let \isin = \TE@isin
+}
+
+\renewcommand{\ifthenelse}[1]{%
+ \toks@{#1}%
+ \TE@repl \or \TE@or
+ \TE@repl \and \TE@and
+ \TE@repl \not \TE@neg
+ \TE@repl \OR \TE@or
+ \TE@repl \AND \TE@and
+ \TE@repl \NOT \TE@neg
+ \begingroup
+ \let \protect = \@unexpandable@protect
+ \def \@setref ##1##2##3{\ifx ##1\relax \z@ \else \expandafter ##2##1\fi}%
+ \def \value ##1{\the \csname c@##1\endcsname}%
+ \let \equal = \TE@equal
+ \let \( = \TE@lparen
+ \let \) = \TE@rparen
+ \let \isodd = \TE@odd
+ \let \lengthtest = \TE@length
+ \let \isundefined = \TE@undef
+ \TE@hook
+ \begingroup
+ \let \@tempa = \relax
+ \let \@tempb = \relax
+ \xdef \@gtempa {\expandafter \TE@eval \the \toks@ \TE@endeval}%
+ \endgroup
+ \@gtempa
+ \expandafter \endgroup
+ \ifTE@val
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+
+\endinput
diff --git a/macros/latex/contrib/xifthen/xifthen.tex b/macros/latex/contrib/xifthen/xifthen.tex
new file mode 100644
index 0000000000..053a9fc8eb
--- /dev/null
+++ b/macros/latex/contrib/xifthen/xifthen.tex
@@ -0,0 +1,497 @@
+\documentclass{article}
+
+\usepackage{etex}
+\usepackage{xifthen}
+\usepackage[utf8]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage[warn]{textcomp}
+\usepackage[a4paper, pdftex, margin=1.5in]{geometry}
+\usepackage{lmodern}
+\usepackage{microtype}
+\usepackage{xcolor}
+\usepackage{url}
+\usepackage[bottom,hang]{footmisc}
+\usepackage[babel]{csquotes}
+\usepackage[british]{babel}
+\usepackage{hyperref}
+
+\newcommand*{\cmd}[1]{\tex{\textbackslash #1}}
+\newcommand*{\tex}{\texttt}
+\newenvironment*{texcode}{\list{}{}\item\ttfamily}{\endlist}
+\newcommand*{\marg}[1]{\{\meta{#1}\}}
+\newcommand*{\oarg}[1]{[\meta{#1}]}
+\newcommand*{\meta}[1]{\textnormal{\textlangle#1\textrangle}}
+
+\setcounter{secnumdepth}{-\maxdimen}
+
+\makeatletter
+\newcommand*{\1}{$_1\m@th$}
+\newcommand*{\2}{$_2\m@th$}
+
+% Borrowed from doc.sty
+\newcommand*{\getfileinfo}[1]{%
+ \def \filename {#1}%
+ \def \@tempb ##1 ##2 ##3\relax ##4\relax {%
+ \def \filedate {##1}%
+ \def \fileversion {##2}%
+ \def \fileinfo {##3}%
+ }%
+ \edef \@tempa {\csname ver@#1\endcsname}%
+ \expandafter \@tempb \@tempa \relax ? ? \relax \relax
+}
+\makeatother
+
+\newenvironment*{texdescription}{%
+ \list{}{%
+ \setlength{\labelwidth}{0pt}%
+ \setlength{\itemindent}{-\leftmargin}%
+ \setlength{\itemsep}{0pt}%
+ \renewcommand*{\makelabel}[1]%
+ {\hspace{\labelsep}\normalfont\tex{\texmonospaces ##1}}%
+ }%
+}{%
+ \endlist
+}
+
+\newcommand*{\pack}{\textsf}
+\newcommand*{\true}{\emph{true}}
+\newcommand*{\false}{\emph{false}}
+
+\newtest \condition [2]{%
+ \cnttest{(#1)*(#2)}>{100}%
+ \AND
+ \cnttest{((#1)+(#2))*2}<{60}%
+}
+
+\getfileinfo{xifthen.sty}
+\title {The \pack{xifthen} package}
+\author {Josselin Noirel\footnote{This document corresponds to version
+ \fileversion\ (\filedate) of \pack{\filename}.}\\%
+\url{https://github.com/JosselinNoirel/xifthen}}
+
+\begin{document}
+
+\maketitle
+
+\begin{abstract}
+ This package implements new commands that can be used within the
+ first argument of \pack{ifthen}'s \cmd{ifthenelse} to test whether a
+ string is void or not, if a command is defined or equivalent to
+ another. It includes also the possibility to make use of the
+ complex expressions introduced by the package~\pack{calc}, together
+ with the ability of defining new commands to handle complex tests.
+ This package requires the \eTeX{} features.
+\end{abstract}
+
+\tableofcontents
+
+\section{What's new}
+
+\begin{itemize}
+\item [1.1] Now \cmd{cnttest} and \cmd{dimtest} accept \tex{<=} and \tex{>=}.
+\item I~renamed \cmd{terminateswith} in \cmd{endswith}.
+
+\addvspace{\baselineskip}
+
+\item [1.2] Corrected a~bug related to a~bad interaction between
+ new~tests and ifthen's replacement macro (credits go to MPG \&
+ P.~Albar\`ede).
+
+\addvspace{\baselineskip}
+
+\item [1.3] Removed a spurious space (thanks to Ulrike Fisher).
+
+\item [1.4.0] Removed the reliance on the \cmd{etex} package, following
+ an exmail exchange with David Carlisle and Maïeul Rouquette.
+ (I also updated the documentation and pushed the files on GitHub.)
+\end{itemize}
+
+\section{\pack{ifthen}'s interface}
+
+\subsection{Declaring and setting booleans}
+
+You can declare boolean (presumably in the preamble of your document) with
+%
+\begin{texcode}
+\cmd{newboolean}\marg{boolean}
+\end{texcode}
+%
+where \meta{boolean} is a name made up of alphanumeric characters.
+For instance,
+%
+\begin{texcode}
+\cmd{newboolean}\{appendix\}\\
+\cmd{first}\{appendix\}
+\end{texcode}
+%
+Then your boolean is ready to be set with
+%
+\begin{texcode}
+\cmd{setboolean}\marg{boolean}\marg{truth value}
+\end{texcode}
+%
+where \meta{truth value} can be \tex{true} or \tex{false}.
+
+\subsection{Executing conditional code}
+
+The general syntax is inherited of that of the package~\pack{ifthen}:
+%
+\begin{texcode}
+ \cmd{ifthenelse}\marg{test expression}\marg{true code}\marg{false code}
+\end{texcode}
+%
+Evaluates the \meta{test expression} and executes \meta{true code} if the
+test turns out to be true and \meta{false code} otherwise. \pack{ifthen}
+provides the tests explained in the next paragraphs.
+
+\paragraph{Value of a~boolean}
+
+You can use the value of a~boolean you declared, or the value of
+a~primitive boolean of \TeX\footnote{The primitive booleans include:
+ \tex{mmode} (Are we in math mode?), \tex{hmode} (Are we in
+ horizontal mode?), \tex{vmode} (Are we in vertical mode?),~etc.}
+%
+\begin{texcode}
+ \cmd{boolean}\marg{boolean}
+\end{texcode}
+
+\paragraph{Tests on integers}
+
+To test whether an~integer is equal to, strictly less than, or
+strictly greater than, you write the expression straightforwardly.
+%
+\begin{list}{}{}
+\item \tex{\meta{value\1} = \meta{value\2}}
+\item \tex{\meta{value\1} < \meta{value\2}}
+\item \tex{\meta{value\1} > \meta{value\2}}
+\item \tex{\textbackslash isodd\marg{number}}
+\end{list}
+
+\paragraph{Tests on lengths}
+
+There exist similar tests for the lengths, but you need in this case
+to surround the whole expression with \cmd{lengthtest}.
+%
+\begin{list}{}{}
+\item \tex{\cmd{lengthtest}\{\meta{dimen\1} = \meta{dimen\2}\}}
+\item \tex{\cmd{lengthtest}\{\meta{dimen\1} < \meta{dimen\2}\}}
+\item \tex{\cmd{lengthtest}\{\meta{dimen\1} > \meta{dimen\2}\}}
+\end{list}
+
+\paragraph{Tests on commands}
+
+You can test if a command is undefined\footnote{This test differs from
+ \cmd{@ifundefined} in that it takes a~real command---and not
+ a~command name---as argument, and also in that command which is let
+ equal to \cmd{relax} is not considered undefined.}.
+%
+\begin{list}{}{}
+\item \tex{\cmd{isundefined}\marg{command}}
+\end{list}
+
+\paragraph{Tests on character strings}
+
+You want to know whether two character strings are equal? Use:
+%
+\begin{texcode}
+\cmd{equal}\marg{string\1}\marg{string\2}
+\end{texcode}
+%
+Remark that the two arguments are fully expanded. In other words, it
+is the result of the expansion of the macros that is compared. This
+behaviour also entails a~moving argument and you should protect
+fragile command to avoid bizarre errors\footnote{Practically, the
+ fact that the content is expanded, means that if the macro \cmd{bar}
+ is defined as \tex{\cmd{baz}\{o\}}, and the command \cmd{baz} is defined
+ as \tex{f\#1\#1}, then \tex{\cmd{equal}\{\cmd{bar}\}\{foo\}} turns out to
+ be true, because \cmd{bar} eventually expands into \tex{foo}. This is
+ usually the desired behaviour.}.
+
+\paragraph{Building more elaborated expressions}
+
+You can build more sophisticated expressing using the \cmd{AND}
+(conjunction), \cmd{OR} (disjunction), and \cmd{NOT} (negation)
+operators\footnote{Lowercase versions of these commands also exist but
+ we advise the user to stick to the uppercase ones because \cmd{or}
+ is part of \TeX's syntax.}.
+%
+\begin{list}{}{}
+\item \meta{expression\1} \cmd{AND} \meta{expression\2}
+\item \meta{expression\1} \cmd{OR} \ \meta{expression\2}
+\item \cmd{NOT} \meta{expression}
+\end{list}
+%
+The evaluation is lazy, meaning that if you write
+%
+\begin{texcode}
+\meta{expression\1} \cmd{AND} \meta{expression\2}
+\end{texcode}
+%
+then \meta{expression\2} won't be evaluated if \meta{expression\1} is
+true\footnote{The devil is in the details, however: \pack{ifthen} works by
+ reading its argument twice. The tests are evaluated on the second
+ pass, but the expansion is performed on the first one, regardless of
+ the truth value.}.
+
+There is not precedence rules: the argument is read from left to right
+and \cmd{NOT} applies to the very next test. When the precedence must
+be changed you can use the parentheses:
+%
+\begin{texcode}
+\cmd{(}\meta{expression}\cmd{)}
+\end{texcode}
+
+\section{New tests}
+
+After this brief review of \pack{ifthen}'s principles, we introduce
+the new tests provided by \pack{xifthen}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\paragraph{Tests on integers}
+
+One of the drawback of \TeX's tests and of \cmd{ifthen}'s as well, is
+the impossibility to use \pack{calc}'s syntax in it. The
+\cmd{numexpr} primitive of \eTeX\ somehow allows to overcome this
+difficulty but it is not well documented and normal users are
+certainly more familiar with the capabilities offered by \pack{calc}.
+The \pack{xifthen} package allows to use \pack{calc}-valid expressions
+via the new test \cmd{cnttest}. The syntax is as follows:
+%
+\begin{texcode}
+ \cmd{cnttest}\marg{counter expression\1}\marg{comparison}%
+ \marg{counter expression\2}
+\end{texcode}
+%
+It evaluates the two counter expressions, compares them, and returns
+the value of the test. The comparison can be one of the following
+sequences \tex{<}, \tex{>}, \tex{=}, \tex{<=},~or~\tex{>=}.
+
+\paragraph{Tests on lengths}
+
+The similar test has been designed for the lengths and dimensions:
+%
+\begin{texcode}
+ \cmd{dimtest}\marg{dimen expression\1}\marg{comparison}%
+ \marg{dimen expression\2}
+\end{texcode}
+%
+It evaluates the two dimension expressions, compares them, and returns
+the value of the test. The comparison can be one of the following
+sequences \tex{<}, \tex{>}, \tex{=}, \tex{<=},~or~\tex{>=}.
+
+\paragraph{Tests on commands}
+
+We define a~companion of \cmd{isundefined} that uses a~command name
+rather than a~command\footnote{If you are stuck with the distinction
+ between `command' and `command name', let me explain it further with
+ an example: the command name of the command \cmd{foo} is \tex{foo}.
+ This is sometimes more convenient to use the command name than the
+ name. Still, this functionality is probably intended more for
+ experienced programmers who want to use the niceties of
+ \pack{ifthen} and \pack{xifthen}.}.
+%
+\begin{texcode}
+ \cmd[1,syntax]{isnamedefined}{command name}
+\end{texcode}
+%
+Returns \true\ if the command \cmd{\meta{command name}} is defined\footnote{%
+ Uses \tex{\cmd{ifcsname}\dots\allowbreak\cmd{endcsname}} internally
+ and not \cmd{@ifundefined}.}.
+
+Sometimes, you need to compare two macros \cmd{foo} and \cmd{bar} and
+test whether they are actually the same macro.
+%
+\begin{texcode}
+ \cmd{isequivalentto}\marg{command\1}\marg{command\2}
+\end{texcode}
+%
+Corresponds to the \cmd{ifx} test: it returns \true\ when the two
+commands are exactly equivalent (same definition, same number of
+arguments, same prefixes, etc., otherwise \false\ is returned).
+
+\paragraph{Tests on character strings}
+
+Very often, we see people using \cmd[2]{equal}{\#1}{} in their command
+definitions (for instance, to test whether an optional argument had
+been passed to their macro). A~more efficient test can be used:
+%
+\begin{texcode}
+ \cmd{isempty}\marg{content}
+\end{texcode}
+%
+Returns \true\ if \meta{content} is empty. It is essentially equivalent to
+\tex{\cmd{equal}\{\meta{content}\}\{\}} except that the argument of
+\cmd{isempty} isn't expanded and therefore isn't affected by fragile
+commands\footnote{Internally, it uses \cmd{unexpanded} and \pack{ifmtarg}.}.
+
+It is possible to test whether a~substring appears within another
+string\footnote{Uses \cmd{in@} and \cmd{ifin@} internally.}.
+%
+\begin{texcode}
+ \cmd{isin}\marg{substring}\marg{string}
+\end{texcode}
+
+Sometimes, you need to check whether a~string ends with a particular
+substring. This can be achieved using\footnote{For compatibility
+ reasons, there exist a~command unfortunately called
+ \cmd{terminateswith} that performs the same test but it is
+ deprecated.}:
+%
+\begin{texcode}
+ \cmd{endswith}\marg{string}\marg{substring}
+\end{texcode}
+
+\paragraph{Building more elaborated expressions}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+It is then possible to create new tests with:
+%
+\begin{texcode}
+ \cmd{newtest}\marg{command}[$n$]\marg{test expression}
+\end{texcode}
+%
+Surprisingly, a~simple \cmd{newcommand} would not work. The
+\cmd{newtest} macro defines a command \meta{command} taking
+$n$~arguments (no optional argument is allowed\footnote{No optional
+ argument is allowed because the macro needs to be expanded in the
+ first pass and that optional arguments avoid that.} consisting of
+the test as specified by \meta{test expression} that can be used in
+the argument of \cmd{ifthenelse}.
+
+\section{Examples}
+
+Let's illustrate the most important features of \pack{xifthen} with
+the following problem: if we want to test whether a rectangle having
+dimensions $l$~and~$L$ meets the two following conditions: $S = l
+\times\nobreak L > 100$ and~$P = 2 (l +\nobreak L) < 60$\footnote{Note
+ that, because within the arguments of \cmd{cnttest} the \pack{calc}
+ is used, you must use real parentheses \tex{(}~and~\tex{)} and not
+ \cmd{(}~and~\cmd{)}.}:
+%
+\begin{texcode}
+\cmd{newtest}\{\cmd{condition}\}[2]\{\%\\
+\mbox{}\ \ \cmd{cnttest}\{(\#1)*(\#2)\}>\{100\}\%\\
+\mbox{}\ \ \cmd{AND}\\
+\mbox{}\ \ \cmd{cnttest}\{((\#1)+(\#2))*2\}<\{60\}\%\\
+\}
+\end{texcode}
+%
+Then \tex{\cmd{ifthenelse}\{\cmd{condition}\{14\}\{7\}\}\{TRUE\}\{FALSE\}}
+returns \ifthenelse{\condition{14}{7}}{TRUE}{FALSE} because $14\times 7 =
+98$ and $2\times (14 +\nobreak 7) = 42$, while
+\tex{\cmd{ifthenelse}\{\cmd{condition}\{11\}\{11\}\}\{TRUE\}\allowbreak
+ \{FALSE\}} returns \ifthenelse{\condition{11}{11}}{TRUE}{FALSE} because
+$11 \times 11 = 121$ and $2\times (11 +\nobreak 11) = 44$.
+
+\bigbreak
+
+Now a~list of typical uses of \pack{xifthen}'s capabilities:
+
+\small
+\begin{list}{}{\setlength{\leftmargin}{0pt}%
+ \setlength{\rightmargin}{-\oddsidemargin}%
+ \setlength{\partopsep}{0pt}%
+ \setlength{\topsep}{\medskipamount}%
+ \setlength{\parsep}{0pt}}%
+\item \newcommand*{\TRUE}{%
+ \ifthenelse{\equal{\csname f@family\endcsname}{lmtt}}{true}%
+ {\makebox[\widthof{false}][l]{\bfseries true}}%
+ }
+ \newcommand*{\FALSE}{false}
+ \newcommand*{\pt}{\ifmmode \,\mathrm{pt}\else pt\fi}
+
+$4 - 1< 4$: \ifthenelse{\cnttest{4 - 1}{<}{4}}{\TRUE}{\FALSE}\quad
+$4< 4$: \ifthenelse{\cnttest{4}{<}{4}}{\TRUE}{\FALSE}\quad
+$4 + 1< 4$: \ifthenelse{\cnttest{4 + 1}{<}{4}}{\TRUE}{\FALSE}
+
+$4 - 1\leq 4$: \ifthenelse{\cnttest{4 - 1}{<=}{4}}{\TRUE}{\FALSE}\quad
+$4\leq 4$: \ifthenelse{\cnttest{4}{<=}{4}}{\TRUE}{\FALSE}\quad
+$4 + 1\leq 4$: \ifthenelse{\cnttest{4 + 1}{<=}{4}}{\TRUE}{\FALSE}
+
+$4 - 1= 4$: \ifthenelse{\cnttest{4 - 1}{=}{4}}{\TRUE}{\FALSE}\quad
+$4= 4$: \ifthenelse{\cnttest{4}{=}{4}}{\TRUE}{\FALSE}\quad
+$4 + 1= 4$: \ifthenelse{\cnttest{4 + 1}{=}{4}}{\TRUE}{\FALSE}
+
+$4 - 1\geq 4$: \ifthenelse{\cnttest{4 - 1}{>=}{4}}{\TRUE}{\FALSE}\quad
+$4\geq 4$: \ifthenelse{\cnttest{4}{>=}{4}}{\TRUE}{\FALSE}\quad
+$4 + 1\geq 4$: \ifthenelse{\cnttest{4 + 1}{>=}{4}}{\TRUE}{\FALSE}
+
+$4 - 1> 4$: \ifthenelse{\cnttest{4 - 1}{>}{4}}{\TRUE}{\FALSE}\quad
+$4> 4$: \ifthenelse{\cnttest{4}{>}{4}}{\TRUE}{\FALSE}\quad
+$4 + 1> 4$: \ifthenelse{\cnttest{4 + 1}{>}{4}}{\TRUE}{\FALSE}
+
+\medskip
+
+$4\pt - 1\pt< 4\pt$: \ifthenelse{\dimtest{4\pt - 1\pt}{<}{4\pt}}{\TRUE}{\FALSE}\quad
+$4\pt< 4\pt$: \ifthenelse{\dimtest{4\pt}{<}{4\pt}}{\TRUE}{\FALSE}\quad
+$4\pt + 1\pt< 4\pt$: \ifthenelse{\dimtest{4\pt + 1\pt}{<}{4\pt}}{\TRUE}{\FALSE}
+
+$4\pt - 1\pt\leq 4\pt$: \ifthenelse{\dimtest{4\pt - 1\pt}{<=}{4\pt}}{\TRUE}{\FALSE}\quad
+$4\pt\leq 4\pt$: \ifthenelse{\dimtest{4\pt}{<=}{4\pt}}{\TRUE}{\FALSE}\quad
+$4\pt + 1\pt\leq 4\pt$: \ifthenelse{\dimtest{4\pt + 1\pt}{<=}{4\pt}}{\TRUE}{\FALSE}
+
+$4\pt - 1\pt= 4\pt$: \ifthenelse{\dimtest{4\pt - 1\pt}{=}{4\pt}}{\TRUE}{\FALSE}\quad
+$4\pt= 4\pt$: \ifthenelse{\dimtest{4\pt}{=}{4\pt}}{\TRUE}{\FALSE}\quad
+$4\pt + 1\pt= 4\pt$: \ifthenelse{\dimtest{4\pt + 1\pt}{=}{4\pt}}{\TRUE}{\FALSE}
+
+$4\pt - 1\pt\geq 4\pt$: \ifthenelse{\dimtest{4\pt - 1\pt}{>=}{4\pt}}{\TRUE}{\FALSE}\quad
+$4\pt\geq 4\pt$: \ifthenelse{\dimtest{4\pt}{>=}{4\pt}}{\TRUE}{\FALSE}\quad
+$4\pt + 1\pt\geq 4\pt$: \ifthenelse{\dimtest{4\pt + 1\pt}{>=}{4\pt}}{\TRUE}{\FALSE}
+
+$4\pt - 1\pt> 4\pt$: \ifthenelse{\dimtest{4\pt - 1\pt}{>}{4\pt}}{\TRUE}{\FALSE}\quad
+$4\pt> 4\pt$: \ifthenelse{\dimtest{4\pt}{>}{4\pt}}{\TRUE}{\FALSE}\quad
+$4\pt + 1\pt> 4\pt$: \ifthenelse{\dimtest{4\pt + 1\pt}{>}{4\pt}}{\TRUE}{\FALSE}
+
+\medskip
+
+\tex{\cmd{ifthenelse}\{\cmd{isempty}\{\}\}\{\TRUE\}\{\FALSE\}}
+\ifthenelse{\isempty{}}{\TRUE}{\FALSE}
+
+\tex{\cmd{ifthenelse}\{\cmd{isempty}\{ \}\}\{\TRUE\}\{\FALSE\}}
+\ifthenelse{\isempty{ }}{\TRUE}{\FALSE}
+
+\tex{\cmd{ifthenelse}\{\cmd{isempty}\{ foo \}\}\{\TRUE\}\{\FALSE\}}
+\ifthenelse{\isempty{ foo }}{\TRUE}{\FALSE}
+
+\medskip
+
+\tex{\cmd{ifthenelse}\{\cmd{endswith}\{foo.\}\{.\}\}\{\TRUE\}\{\FALSE\}}
+\ifthenelse{\endswith{foo.}{.}}{\TRUE}{\FALSE}
+
+\tex{\cmd{ifthenelse}\{\cmd{endswith}\{foo!\}\{.\}\}\{\TRUE\}\{\FALSE\}}
+\ifthenelse{\endswith{foo!}{.}}{\TRUE}{\FALSE}
+
+\medskip
+
+\tex{\cmd{ifthenelse}\{\cmd{isin}\{foo\}\{foobar\}\}\{\TRUE\}\{\FALSE\}}
+\ifthenelse{\isin{foo}{foobar}}{\TRUE}{\FALSE}
+
+\tex{\cmd{ifthenelse}\{\cmd{isin}\{Foo\}\{foobar\}\}\{\TRUE\}\{\FALSE\}}
+\ifthenelse{\isin{Foo}{foobar}}{\TRUE}{\FALSE}
+
+\medskip
+
+\tex{\cmd{ifthenelse}\{\cmd{cnttest}\{10 * 10 + 1\}>\{100\}\}\{\TRUE\}\{\FALSE\}}
+\ifthenelse{\cnttest{10 * 10 + 1}>{100}}{\TRUE}{\FALSE}
+
+\tex{\cmd{ifthenelse}\{\cmd{cnttest}\{10 * 10 + 1\}>\{100 * 100\}\}\{\TRUE\}\{\FALSE\}}
+\ifthenelse{\cnttest{10 * 10 + 1}>{100 * 100}}{\TRUE}{\FALSE}
+
+\medskip
+
+\tex{\cmd{ifthenelse}\{\cmd{isequivalentto}\{\cmd{usepackage}\}\{\cmd{RequirePackage}\}\}\{\TRUE\}\{\FALSE\}}
+\ifthenelse{\isequivalentto{\usepackage}{\RequirePackage}}{\TRUE}{\FALSE}
+
+\tex{\cmd{ifthenelse}\{\cmd{isequivalentto}\{\cmd{usepackage}\}\{\cmd{textit}\}\}\{\TRUE\}\{\FALSE\}}
+\ifthenelse{\isequivalentto{\usepackage}{\textit}}{\TRUE}{\FALSE}
+
+\medskip
+
+\tex{\cmd{ifthenelse}\{\cmd{isnamedefined}\{@foo\}\}\{\TRUE\}\{\FALSE\}}
+\ifthenelse{\isnamedefined{@foo}}{\TRUE}{\FALSE}
+
+\tex{\cmd{ifthenelse}\{\cmd{isnamedefined}\{@for\}\}\{\TRUE\}\{\FALSE\}}
+\ifthenelse{\isnamedefined{@for}}{\TRUE}{\FALSE}
+\end{list}
+
+\end{document}