This seems to have come up a couple times, but I cannot glean an answer to the generic question of how one might protect an arbitrary string in Lua to ensure its characters are printed.
In other words, given some code in a .lua
file:
local i_can_be_anything = '&\\%*_'
context(i_can_be_anything)
This balks for any number of reasons, because the characters have special meaning in TeX when ConTeXt pushes them out to the TeX compiler.
The most apparent option to me would be to convert the string in Lua so that it contains the proper escaping or substitutions that can be passed to TeX to achieve the desired outcome, which would be in this case along the lines of:
\&\textbackslash{}\%\&\_
I believe the full list of replacements one would be looking for would be along the lines of (and this is from some Python I wrote):
tex_replacements = [
(u'{', ur'\{'),
(u'}', ur'\}'),
(u'[', ur'{[}'),
(u']', ur'{]}'),
(u'\\', ur'\textbackslash{}'),
(u'$', ur'\$'),
(u'%', ur'\%'),
(u'&', ur'\&'),
(u'#', ur'\#'),
(u'_', ur'\_'),
(u'~', ur'\textasciitilde{}'),
(u'^', ur'\textasciicircum{}'),
]
tex_mapping = {ord(char):rep for char, rep in tex_replacements}
def escape(s):
return unicode(s).translate(tex_mapping)
Is there no function in Lua or LuaTeX to achieve this set of substitutions (or otherwise) so that an arbitrary string could be printed?
A straightforward iteration over the characters with a substitution along the lines of the tex_replacements
above could do the trick, but I would expect that someone had already written a solution to this problem.
EDIT
It is worth noting that @phg posed a plausible solution of changing the catcodes to vrbcatcode (i.e. \verbatim
, or context.sprint(catcodes.numbers.vrbcatcodes, i_can_be_anything)
). This does perform the escaping desired, however it seems to have serious issues with line breaking that make it essentially unusable.
vrbcatcodes
should suffice for most literal printing, but if you like you can skim the list for a more appropriate one: git.contextgarden.net/context/context/blob/master/tex/context/… (Btw. there is no such thing as a “TeX compiler”.)\pushcatcodetable \setcatcodetable \somecatcodetable
to set the table and\popcatcodetable
to drop it again (that’scontext.pushcatcodetable() context.setcatcodetable(catcodes.numbers.vrbcatcodes)
/context.popcatcodetable()
at the Lua end, or usecontext.sprint(n, ...)
with the catcode table as the first argument). As for the terminology: TeX is interpreted by a TeX engine.context(catcodes.numbers.vrbcatcodes, i_can_be_anything)
should also work.tex.sprint()
explicitly with the currently active catcode table. There iscontext.verbatim()
, though, which sets thevrbcatcodes
table.