I want to check whether an argument of a command is fully contained in a pair of curly braces without using any extra packages. For this I define two macros containing {
and }
with catcode 12, respectively. Then I turn the input into a string using \detokenize
and compare the first and the last token I find.
The macro should either ignore leading and trailing spaces around the group or treat them as false (ignoring has higher priority -- two versions one ignoring one not would be best).
So the following should be outputted for the ignoring version:
\MyIfGroup{{}}{true}{false} -> true
\MyIfGroup{ {}}{true}{false} -> true
\MyIfGroup{{} }{true}{false} -> true
\MyIfGroup{ {} }{true}{false} -> true
\MyIfGroup{ }{true}{false} -> false
\MyIfGroup{a}{true}{false} -> false
\MyIfGroup{{}a}{true}{false} -> false
The not ignoring version should return true only for the first of the above cases. Anything inside the inner pair of braces (even nested braces) shouldn't make a difference (except for unmatched braces). The case \MyIfGroup{{}{}}
is considered an edge case (by myself) and doesn't have to be detected correctly -- it would be nice though.
The following code is an ignoring version which detects everything except {}{}
(that's ok) and if there is space after the pair of braces, in which case it throws a "Runaway argument"-error.
\documentclass[]{article}
\makeatletter
\newcommand\MyIfEmptyTF[1]
{%
\if\relax\detokenize{#1}\relax
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
\newcommand\MyIfGroupTF[1]
{%
\MyIfEmptyTF{#1}{\@secondoftwo}
{%
\expandafter\MyIfGroup@preopen\expandafter{\detokenize{#1}}%
}%
}
\newcommand\MyIfGroup@preopen[1]
{%
\MyIfDetSpaceTF{#1}
{\@secondoftwo}
{\MyIfGroup@open#1\end@MyIfGroup}%
}
\long\def\MyIfGroup@open#1#2\end@MyIfGroup%
{%
\if\Mylbraceother#1%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\MyIfGroup@close#2\end@MyIfGroup}
{\@secondoftwo}%
}
\long\def\MyIfGroup@close#1#2\end@MyIfGroup
{%
\MyIfEmptyTF{#2}
{%
\MyIfDetSpaceTF{#1}
{\@secondoftwo}
{%
\if\Myrbraceother#1%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}%
}
{\MyIfGroup@close#2\end@MyIfGroup}
}
\newcommand\MyIfDetSpaceTF[1]
{%
\if#1\detokenize{ }%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
\bgroup
\catcode`\{=12
\catcode`\}=12
\catcode`\(=1
\catcode`\)=2
\gdef\Mylbraceother({)
\gdef\Myrbraceother(})
\egroup
\makeatother
\begin{document}
Works: \MyIfGroupTF{{i}}{true}{false}.
Works: \MyIfGroupTF{ {}}{true}{false}.
Works: \MyIfGroupTF{ }{true}{false}.
Works: \MyIfGroupTF{ a }{true}{false}.
Works: \MyIfGroupTF{a}{true}{false}.
Wrong: \MyIfGroupTF{{}{}}{true}{false}.
%Doesn't compile (fails in @close): \MyIfGroupTF{{} }{true}{false}.
\end{document}
\def\whatever#1#{...}
?