Changes

Jump to navigation Jump to search
3,294 bytes added ,  07:15, 13 July 2023
m
→‎Undefined Commands in Lua Comments: Fix a broken link. And add enough information to be able to re-fix it easily. (I guess this last part could go in a footnote reference, but I am not sure how to do that properly…)
The interweaving of ConTeXt and Lua consists of two elements: first you tell TeX that you're starting some Lua code; then, once inside Lua, you need to use the appropriate functions to put things into the TeX stream.
There are two main ways to execute Lua code in a ConTeXt document: The command <code>\{{cmd|ctxlua</code>}}, and the environment <code>\{{cmd|startluacode...\}}…{{cmd|stopluacode</code>}}. Both are wrappers around the LuaTeX primitive <code>\{{cmd|directlua</code>}}, which you should never need to use. In general, you will define a function inside a <code>\{{cmd|startluacode</code> }} block, and then define a TeX command that calls the function using <code>\{{cmd|ctxlua</code>, especially because <code>\{{cmd|ctxlua</code> }} has a few idiosyncracies.
<blockquote>The main thing about Lua code in a TeX document is this: the code is expanded by TeX ''before'' Lua gets to it. '''This means that all the Lua code, even the comments, must be valid TeX!''' A string like "\{{cmd|undefined" }} will cause an immediate failure.</blockquote>
== Calling a bit of Lua inline: \{{cmd|ctxlua }} ==
The command <code>\{{cmd|ctxlua</code> }} is for short inline snippets of Lua, such
as
</texcode>
<code>\{{cmd|ctxlua</code> }} operates under the normal TeX catcodes (category codes). This means the following two things for the Lua code inside:
* all newlines get treated as spaces
* special TeX characters like &, #, $, {, }, etc., need to be escaped.
</texcode>
== A larger Lua block: \startluacode...\stopluacode ==
Inside == Calling a lua function with {{cmd|cldcontext}} and get the <return == One can execute a Lua code>\startluacodefrom within TeX and get back the result in TeX by using {{cmd|cldcontext}}.Thus, if {{code|myfunction}} is a function of a variable {{code|x}} defined in Lua, {{cmd|cldcontext|{myfunction(5)}}} returns the value {{code|myfunction(5)}} in TeX.This is equivalent to {{cmd|ctxlua|{context(myfunction(5))}}}.\  == A larger Lua block: {{cmd|startluacode}}…{{cmd|stopluacode}} == Inside the {{cmd|startluacode}}…{{cmd|stopluacode</code> }} environment, newlines and special characters behave normally. This solves the catcode problem that <code>\{{cmd|ctxlua</code> }} suffers from. Apart from these special characters, the main warning remains in force: all the Lua code, even the comments, must be valid TeX.
<texcode>
-- The unknown command \undefined will cause this entire block to fail.
-- Print a countdown '10, 8, ..., 0!'
-- `..` is Lua for string concatenation
for i = 10, 2, -2 do
-- Look! we can use # and $ with impunity!
context("Unless we print them, then we must \\#\\$\\& print the escape characters, too.")
\stopluacode
</texcode>
 
== Putting Lua code in an external file ==
 
You can put your lua code in an external file (with the <code>.lua</code> extension) and include it with the <code>require</code> command:
 
<texcode>
\startluacode
-- include the file my-lua-lib.lua
require("my-lua-lib")
\stopluacode
</texcode>
function u.myfunction()
-- do stuff
end
\stopluacode
</texcode>
The full list of canonical namespaces, taken from [httphttps://minimalsdistribution.contextgarden.net/current/context/alphalatest/tex/context/base/mkxl/luat-ini.lua lmt luat-ini.lualmt]:
<code><pre>
end
</pre></code>
 
== Undefined Commands in Lua Comments ==
 
Lua code invoked inside TeX doesn’t allow TeX undefined commands ''even inside comments''.
 
<texcode>
\starttext
\startluacode
--\undefinedcommandfromme
\stopluacode
Hello
\ctxlua{--\undefinedcommandfromme}
\stoptext
</texcode>
 
To get the sample above working (as [https://www.mail-archive.com/ntg-context@ntg.nl/msg103892.html explained by Hans in a NTG-context thread from jan. 2023 entitled “Minor bug in Lua or ConTeXt”]), you would need a fallback definition:
 
<texcode>
\ifdefined\undefinedcommandfromme \else \let\undefinedcommandfromme\relax \fi
</texcode>
 
{{cmd|undefinedcommandfromme}} gets only defined (as {{cmd|relax}}, to do nothing), if and only if it is undefined.
 
= Calling TeX from Lua =
 
Being a topic on itself, pages are dedicated:
* '''[[CLD|ConTeXt Lua Documents]]''', or CLD, are way to access TeX from inside Lua scripts. A page give clues about [[CLD_passing_variables|passing variables]] within CLD (2018).
* [[Lua|Wiki page dedicated to Lua]]
** [[Extensions to the Lua I/O library]]
** [[String manipulation]]
** [[Table manipulation]]
= Putting stuff in your TeX document from Lua =
== Simple printing: context(), tex.print(), and tex.sprint() ==
Use <code>context(...)</code> for most things. It is equivalent to <code>tex.print(string.format(...))</code>, so
<texcode>
</texcode>
For a fuller account of the context.commands, see the [http://www.pragma-ade.comnl/general/manuals/cld-mkiv.pdf ConTeXt Lua document] manual. It is old, but most of it still applies.
One final note: arguments can also be specified in the form of nested functions. Because LuaTeX evaluates the deepest-nested argument first, this may cause the <code>context()</code> calls to be evaluated in the wrong order. For more on this, see the article on [[cldCLD|ConTeXt Lua documents]], and also, again, the [http://www.pragma-ade.comnl/general/manuals/cld-mkiv.pdf CLD manual].
= Passing arguments and buffers: ConTeXt commands that hook into Lua =
</texcode>
Then define the TeX command that expands to a <code>\{{cmd|ctxlua</code> }} call:
<texcode>
\def\surroundwd#1%
{\ctxlua{userdata.surroundwithdashes([==[#1]==])}}
</texcode>
''NB'': quoting with <code>[==[#1]==]</code>
([http://www.lua.org/manual/5.2/manual.html#3.1 long strings])
works just like <code>"#1"</code> in most cases, but in addition
it is robust against <code>#1</code> containing the quotation mark
<code>"</code> which would terminate the Lua string prematurely.
Inside {{cmd|protect}}…{{cmd|unprotect}} the macros {{cmd|!!bs}}
and {{cmd|!!es} are at your disposition.
They are equivalent to <code>[===[</code> and <code>]===]</code> and --
being single tokens to TeX -- parsed faster.
(See [http://repo.or.cz/w/context.git/blob/refs/heads/origin:/tex/context/base/luat-ini.mkiv#l174 <code>luat-ini.mkiv</code>].)
== Making \{{cmd|startenv...\}}…{{cmd|stopenv }} hook into Lua ==
The first job is, as ever, to have the Lua function at the ready
<texcode>
</texcode>
Lastly, we define the <code>\{{cmd|stopverynarrow</code> }} command such that it passes the recently-complated buffer to our <code>verynarrow</code> Lua function:
<texcode>
or, if you want less precision:
<texcode>
$\pi = \ctxlua{context("\%letterpercent.6f", math.pi)}$
</texcode>
Notice that the percent sign is escapedwith letterpercent=== mathexpr with LMTX === In LMTX there is a new way to use calculated expressions with mathexpr through ([https://github.com/contextgarden/context-mirror/blob/7fd782dace8f90e7e032ca8f449f8ca4eada450b/doc/context/sources/general/manuals/math/math-fun.tex math-fun]). Some examples are:
<texcode>
$ \pi = \mathexpr[.40N]{pi} $
$ \pi = \mathexpr[.80N]{sqrt(11)} $
$ \pi = \decimalexpr[.80N]{sqrt(11)} $
$ \pi = \decimalexpr{sqrt(11)} $
$ c = \complexexpr{123 + new(456,789)} $
</texcode>
== Loops without worrying about expansion ==
As an example, let's consider typesetting chemical molecules in TeX. Normally, molecules should be typeset in text mode rather than math mode.
If we want
:H<sub>43</sub>SO<sub>4</sub><sup>+</sup>,
we must type
:<code>H\{{cmd|low|{3}}}SO\{{cmd|lohi|{4}}}{{{\cmd|textplus}}}</code>,
but we'd much rather type
:<code>\{{cmd|molecule|{H_3SO_4^+}</code>}}.
So, we need a function that can take a string like that, parse it, and turn it into the appropriate TeX code. LuaTeX includes a general parser based on PEG (parsing expression grammar) called [http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html lpeg], and it makes writing little parsers positively joyful. (Once you've got the knack of it, at least.) For example, the above <code>\{{cmd|molecule</code> }} macro can be written as follows.
<texcode>
== Manipulating verbatim text ==
''This example demonstrates defining a custom \{{cmd|start...\}}…{{cmd|stop }} buffer that gets processed through Lua in its entirety.''
Suppose we want to write an environment <code>\{{cmd|startdedentedtyping</code> ... <code>\}} … {{cmd|stopdedentedtyping</code> }} that removes the indentation of the first line from every line. Thus, the output of ...
<texcode>
\stopdedentedtyping
</texcode>
... should be the same as the output of ...
<texcode>
\stoptyping
</texcode>
... even though the leading whitespace is different.
Defining an environment in TeX that removes the leading spaces but leaves
</texcode>
Here is the code for defining the <code>\{{cmd|startdedentedtyping...\}} … {{cmd|stopdedentedtyping</code> }} pair:
<texcode>
That's all. Finally, we will go into a little more detail on how TeX and Lua communicate with each other.
 
== Other examples ==
 
* [[Calculations_in_Lua|Calculations in Lua]] (warning date 2012)
* [[LPeg|Writing a parser with LPeg]] (Lua Parsing Expression Grammars)
* [[Random|Random numbers]] in ConTeXt and MetaPost
* [[SQL|An example with SQL database]]
* [[Pascal's Triangle]]
= In detail: the interaction between TeX and Lua =
To a first approximation, the interaction between TeX and Lua is straightforward. When TeX (i.e., the LuaTeX engine) starts, it loads the input file in memory and processes it token by token. When TeX encounters <code>\{{cmd|directlua</code>}}, it stops reading the file in memory, <em>fully expands the argument of <code>\{{cmd|directlua</code>}}</em>, and passes the control to a Lua instance. The Lua instance, which runs with a few preloaded libraries, processes the expanded arguments of <code>\{{cmd|directlua</code>}}. This Lua instance has a special output stream which can be accessed using <code>tex.print(...)</code>. The function <code>tex.print(...)</code> is just like the Lua function <code>print(...)</code> except that <code>tex.print(...)</code> prints to a <em>TeX stream</em> rather than to the standard output. When the Lua instance finishes processing its input, it passes the contents of the <em>TeX stream</em> back to TeX.<ref>The output of <code>tex.print(...)</code> is buffered and not passed to TeX until the Lua instance has stopped.</ref> TeX then inserts the contents of the <em>TeX stream</em> at the current location of the file that it was reading; expands the contents of the <em>TeX stream</em>; and continues. If TeX encounters another <code>\{{cmd|directlua</code>{{cmd|, the above process is repeated.
As an exercise, imagine what happens when the following input is processed by LuaTeX. The answer is in the footnotes. <ref>In this example, two different kinds of quotations are used to avoid escaping quotes. Escaping quotes inside <code>\{{cmd|directlua</code> }} is tricky. The above was a contrived example; if you ever need to escape quotes, you can use the <code>\{{cmd|startluacode ... }}…{{cmd|\stopluacode</code> {{cmd| syntax.</ref>
<texcode>
{{note | This article is originally based on [https://www.tug.org/members/TUGboat/tb30-2/tb95mahajan-luatex.pdf this TugBoat article ]. Feel free to modify it.}}
[[Category:Lua]][[Category:LuaTeX]][[Category:Programmingand Databases]]
2

edits

Navigation menu