olsak / OpTeX

OpTeX - LuaTeX format with extended Plain TeX macros
http://petr.olsak.net/optex/
33 stars 13 forks source link

expandability of a macro defined with \optdef #161

Closed Udi-Fogiel closed 5 months ago

Udi-Fogiel commented 5 months ago

the following code produce, IMO, undesired result

\optdef\foo[default] {\the\opt}
\foo[a]
\edef\bar{\foo[b]}
\bar
\bye

It can be fixed by adding \_immediateassigned in the correct places in the definition of \optdef:

\def\optdef#1[#2]{%
    \_def#1{\_immediateassigned{\_opt={#2}}\_isnextchar[{\_cs{_oA:\_csstring#1}}{\_cs{_oB:\_csstring#1}}}%
    \_sdef{_oA:\_csstring#1}[##1]{\_immediateassigned{\_opt={##1}}\_cs{_oB:\_csstring#1\_nospaceafter}}%
    \_sdef{_oB:\_csstring#1\_nospaceafter}%
    }
\optdef\foo[default] {\the\opt}
\foo[a]
\edef\bar{\foo[b]}
\bar
\bye

or by making the macro protected:

\def\optdef#1[#2]{%
    \_protected\_def#1{\_opt={#2}\_isnextchar[{\_cs{_oA:\_csstring#1}}{\_cs{_oB:\_csstring#1}}}%
    \_sdef{_oA:\_csstring#1}[##1]{\_opt={##1}\_cs{_oB:\_csstring#1\_nospaceafter}}%
    \_sdef{_oB:\_csstring#1\_nospaceafter}%
    }
\optdef\foo[default] {\the\opt}
\foo[a]
\edef\bar{\foo[b]}
\bar
\bye

or maybe simply mention in the documentation the expected output. Personally I like the first option, but it is not my call :)

olsak commented 5 months ago

The \isnextchar macro was not originally expandable, but now it is. So, it makes sense now to create macros defined by \optdef expandable. Thank you for noticing. I'll prepare a commit which modifies \optdef using \immediateassigment.

Udi-Fogiel commented 5 months ago

Great, thanks!