olsak/OpTeX

Unexpected whitespace when using `\crx` / `\crtop` via autoload

robertbachmann opened this issue · 6 comments

Example to reproduce:

\fontfam[lm]
%\loadtrick\crx \loadtrick\crtop

\frame{\table{ll}{\crx 
1&2\crx 
3&4 \crx
5&6
}}

\bigskip \bigskip

\frame{\table{ll}{\crtop
1&2\crmid
3&4 \cr
5&6\crbot
}}

\bye

Result:

image

Note: If we uncomment line 2, everything works as expected.

olsak commented

IMHO, this problem hasn't simple solution. The core of the problem can be demonstrated in the following example. Compare:

\hrule
\halign{#\cr \crcr
aha\cr
}
\bye

and

\hrule
\halign{#\cr \relax \crcr
aha\cr
}
\bye

The macro \crtop (or \crx) have to be started by \crcr primitive, because it can be used after \cr (and we needn't to create a new row in the table) or it can be used at the end of the row and we want to close this row. As soon as we add an unexpandable primitive command (\relax in the example above) between \cr and \crcr then the new row is created. This is feature of the \halign primitive. You can replace the \relax in the example by \def\a{} and you get the same empty row. On the other hand \immediateassignment\def\a{} doesn't create empty row. But we want to run \_loadtrick macro if an autoloaded macro is firstly used and \_loadtrick runs \setbox. The \setbox assignment cannot be prefixed by \immediateasignment.

I can add a comment to these two optex tricks that the autoloading doesn't work inside the table (under certain circumstances) but I am unable to solve this problem by an elegant macro set.

I think documenting this restriction should be good enough.

Maybe we can use tex.runtoks?

\fontfam[lm]

\_def\_regtrick#1{\_ifx#1\_undefined\_def#1{%
	\_directlua{tex.runtoks(token.get_next)}%
	\_loadtrick#1\_endlocalcontrol#1}\_else\_badtrick\_fi}

\_let \crx \_undefined
\_let \crtop \_undefined

\_xargs \_regtrick \crx \crtop ;

\frame{\table{ll}{\crx 
1&2\crx 
3&4 \crx
5&6
}}

\bigskip \bigskip

\frame{\table{ll}{\crtop
1&2\crmid
3&4 \cr
5&6\crbot
}}

\bye

It is also possible to define a new "pseudoprimitive" based on tex.runtoks, that will allow to create blocks of code that gets executed (not just expanded) during the expansion stage. For example, here I define \_beglocalcontrol, which starts the block (\_endlocalcontrol is already defined in LuaTeX ):

\fontfam[lm]

\_directlua{
optex.define_lua_command("_beglocalcontrol", function()
	return tex.runtoks(token.get_next)
end)
}

\_def\_regtrick#1{\_ifx#1\_undefined\_def#1{%
        \_beglocalcontrol\_loadtrick#1\_endlocalcontrol#1}%
	\_else\_badtrick\_fi}

\_let \crx \_undefined
\_let \crtop \_undefined

\_xargs \_regtrick \crx \crtop ;

\frame{\table{ll}{\crx 
1&2\crx 
3&4 \crx
5&6
}}

\bigskip \bigskip

\frame{\table{ll}{\crtop
1&2\crmid
3&4 \cr
5&6\crbot
}}

\bye
olsak commented

Thank you very much for noticing about tex.runtoks. I'll experiment with it and use it for autoloading optex tricks.

olsak commented

I hope that my last commit solves this issue. Thanks you very much Udi Fogiel.