Quantcast
Channel: Check for group as argument (expandable) - TeX - LaTeX Stack Exchange
Viewing all articles
Browse latest Browse all 5

Answer by Joseph Wright for Check for group as argument (expandable)

$
0
0

Based on the expandable loop code in expl3, but as requested using no packages:

\documentclass{article}\makeatletter\newcommand\MyIfGroupTF[1]{%  \MyIfGroup@loop@i#1\q@mark\q@stop}\long\def\MyIfGroup@loop@i#1\q@stop{%  \MyIfGroup@if@brace{#1}%    {\MyIfGroup@brace@i}    {%      \MyIfGroup@if@normal{#1}        {\MyIfGroup@end}        {\MyIfGroup@space@i}%    }%      #1\q@stop}\expandafter\long\expandafter\def\expandafter\MyIfGroup@space@i\space#1\q@stop{%  \MyIfGroup@loop@i#1\q@stop}\newcommand\MyIfGroup@brace@i[1]{\MyIfGroup@loop@ii}\long\def\MyIfGroup@loop@ii#1\q@stop{%  \MyIfGroup@if@brace{#1}%    {\MyIfGroup@end}    {%      \MyIfGroup@if@normal{#1}        {\MyIfGroup@normal@ii}        {\MyIfGroup@space@ii}%    }%      #1\q@stop}\newcommand\MyIfGroup@normal@ii[1]{%  \ifx#1\q@mark    \expandafter\MyIfGroup@normal@cleanup  \else    \expandafter\MyIfGroup@end  \fi}\long\def\MyIfGroup@normal@cleanup#1\q@stop{\@firstoftwo}\expandafter\long\expandafter\def\expandafter\MyIfGroup@space@ii\space#1\q@stop{%  \MyIfGroup@loop@ii#1\q@stop}\long\def\MyIfGroup@end#1\q@stop{\@secondoftwo}\newcommand\MyIfGroup@if@brace[1]{%  \ifcat\expandafter\@gobble\expandafter{\expandafter{\string#1?}}**%    \expandafter\@secondoftwo  \else    \expandafter\@firstoftwo  \fi}\newcommand\MyIfGroup@if@normal[1]{%  \ifcat\iffalse{\fi\MyIfGroup@if@normal@aux?#1 }%    \expandafter\@gobble\expandafter{\expandafter{\string#1?}}**%    \expandafter\@firstoftwo  \else    \expandafter\@secondoftwo  \fi}\long\def\MyIfGroup@if@normal@aux#1 {% \if\relax\detokenize\expandafter{\@gobble#1}\relax   ^% \fi \expandafter\@gobble\expandafter{\iffalse}\fi}\newcommand*\q@mark{\q@mark}\newcommand*\q@stop{\q@stop}\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}.Works: \MyIfGroupTF{{}{}}{true}{false}.Works: \MyIfGroupTF{{} }{true}{false}.\end{document}

The basic idea is to use a delimited argument to allow us to test the head of the input as one of space/group/'normal', then to branch as required. (See l3tl.dtx and in particular 'Token by token changes' in the code for more.) There are two loops, the first to check we have a brace group, the second to make sure it's the only one and that there are no other tokens outside of it. One could extend the code to expand any macros, though this makes life more 'interesting'.


One could also use a version of David's answer combined with a space-trimming approach (see https://tex.stackexchange.com/a/69771):

\documentclass{article}\makeatletter\long\def\trim@spaces#1{%  \@@trim@spaces{\q@mark#1}%}\def\@tempa#1{%  \long\def\@@trim@spaces##1{%    \@@trim@spaces@i##1\q@nil\q@mark#1{}\q@mark      \@@trim@spaces@ii      \@@trim@spaces@iii      #1\q@nil      \@@trim@spaces@iv      \q@stop  }%  \long\def\@@trim@spaces@i##1\q@mark#1##2\q@mark##3{%    ##3%    \@@trim@spaces@i    \q@mark    ##2%    \q@mark#1{##1}%  }%  \long\def\@@trim@spaces@ii\@@trim@spaces@i\q@mark\q@mark##1{%    \@@trim@spaces@iii    ##1%  }%  \long\def\@@trim@spaces@iii##1#1\q@nil##2{%    ##2%    ##1\q@nil    \@@trim@spaces@iii  }%  \long\def\@@trim@spaces@iv##1\q@nil##2\q@stop{%    \unexpanded\expandafter{\@gobble##1}%  }%  }\@tempa{ }\def\zz#1\relax{#1}\newcommand\MyIfGroup[1]{%\ifnum\expandafter\pdfstrcmp\expandafter  {\expandafter\zz\romannumeral-`0\trim@spaces{#1}\relax}%  {\trim@spaces{#1}}%    =0 %\expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi}\begin{document}\MyIfGroup{{}}{true}{false}\MyIfGroup{ {}}{true}{false}\MyIfGroup{{} }{true}{false}\MyIfGroup{ {} }{true}{false}\MyIfGroup{ }{true}{false}\MyIfGroup{a}{true}{false}\MyIfGroup{{}a}{true}{false}\MyIfGroup{{a}}{true}{false}\end{document}

Viewing all articles
Browse latest Browse all 5

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>