105

I've heard that with LuaTeX, you can embed Lua code in your document that work directly with TeX internals, making it possible to do several things that are hard to do with macros. What is a good specific example of stuff that you can accomplish easily with LuaTeX?

(I see here that LuaLaTeX is already available on Debian testing, and you can write documents like:

\documentclass{article}
\usepackage{luacode}

\begin{document}
A random number:
\begin{luacode}
tex.print(math.random())
\end{luacode}
\end{document}

resulting in something like

A random number: 0.135494265234

so I expect that other useful nontrivial things are possible.)

ShreevatsaR
  • 45,428
  • 10
  • 117
  • 149

5 Answers5

41

Here's an example of something I'm doing.

I'm writing a document which has a lot of sections. At the end of each section is a score, made of 3 numbers. The first number is on a scale of 0-10, and the second two are 0-3. Also the scale of the first is inverted, meaning that 1 is the biggest and 10 is the smallest, but 0 should still be 0. This code outputs each score and the average score it calculates.

\def\score#1#2#3{
    \directlua{
        s1 = #1;
        s2 = #2;
        s3 = #3;

        if s1 > 0 then
            s1 = 11 - s1
        end

        avgscore = (s1 + (10 * s2 / 3) + (10 * s3 / 3)) / 3;

        tex.print("Score 1: ", s1, ", ")
        tex.print("Score 2: ", s2, ", ")
        tex.print("Score 3: ", s3, ", ")
        tex.print("Combined Score: ", string.format("\%0.2f", avgscore))
    }
}

And then I use it multiple places in my document like this:

\section{stuff}
....
\score{8}{3}{0}
....
\section{even more stuff}
....
\score{0}{1}{1}

I'm also dumping these scores to a file (using lua), reading them in later (again with lua), and using pgfplots to create a chart of some things. There may be a much better way to do this, but I'm not willing to spend the rest of my life learning how to do a few calculations.

Shizzmo
  • 533
  • 12
    This is a great example as while TeX has no problem with this sort of programming, there's still a learning curve—having Lua, which is much more sane, to do it makes the idea of "programming a document" more accessible for general technical users, I think. – Will Robertson Oct 13 '10 at 23:05
  • 1
    I believe, in mkiv at least, one might prefer \ctxlua to \directlua and \startlua for blocks. – Brian M. Hunt Jul 26 '14 at 15:29
  • This thing doesn't use any internal of Lua, so you can already do that by running shell commands e.g. with pythontex package. – user202729 Dec 27 '21 at 17:40
  • These days there's lt3luabridge for these kind of tasks, although it intentionally sandboxes each call separately I think. – user202729 Dec 05 '22 at 15:48
27

Programming in TeX is quite complicated as it was never meant to be a general programming language (despite being Turing complete). Adding Lua makes a lot of programming jobs much easier. At the same time, the LuaTeX people are exposing the internals of TeX so they can be altered by Lua. This makes lots of clever stuff possible. Some of the best examples at the moment can be seen on the ConTeXt wiki, as ConTeXt and LuaTeX are very closely linked.

Caramdir
  • 89,023
  • 26
  • 255
  • 291
Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
  • 1
    Thanks, this is what I've heard. But I was hoping for some more specific examples here, which could be voted on and sorted. (I'm embarrassed to say I couldn't find any specific examples on the wiki.contextgarden.net either, but I'm sure I haven't looked properly…) – ShreevatsaR Jul 26 '10 at 20:10
  • 4
    Start with http://wiki.contextgarden.net/Programming_in_LuaTeX, which includes a nice example about automatically generating a table. – Joseph Wright Jul 26 '10 at 20:12
  • @Joseph: Thanks a lot; that table is a great example of the kind of thing I had in mind. – ShreevatsaR Jul 26 '10 at 21:02
  • 2
    Just for kicks: is there any example of an algorithm (like the sieve of eratosthenes) that someone implemented using TeX? – Mateus Araújo Sep 15 '10 at 04:17
  • 1
    @Mateus: Sure. That's a pretty trivial one to write. See here. – TH. Dec 25 '10 at 18:15
  • 3
    @TH.: It is worth mentioning that there's a prime computing macro (without Eratosthenes) in the TeXbook, page 218. – Hendrik Vogt Dec 28 '10 at 16:30
  • @Hendrik: Oops! I meant to mention that in the blog post. Thanks for pointing that out. – TH. Dec 28 '10 at 16:46
  • Even the examples on that page doesn't particularly touch the internal of TeX. You can "easily" do something similar with shell-escape and write18 (see python and pythontex package for example). Perhaps the most interesting part is https://wiki.contextgarden.net/CLD (also linked from that page), but even this one is quite similar to PyLaTeX for writing code that generates TeX code. – user202729 Dec 27 '21 at 17:54
19

Triggered by the Epub question: here is something useful you can easily do with luatex:

{\catcode`\#=12
\directlua {
local words = io.open('hyphens-' .. tex.jobname .. '.txt', 'w');
local outchar = unicode.utf8.char
local function dumphyphens (head)
   local data = {}
   for v in node.traverse(head) do
       if v.id == node.id('glyph') then
         data[#data+1] = outchar(v.char);
       elseif v.id == node.id('disc') then
          data[#data+1] = '-'
       elseif v.id == node.id('glue') then
         data[#data+1] = outchar(32)
       elseif v.id == node.id('hlist') then
         data[#data+1] = dumphyphens(v.list)
       end
   end
   return table.concat(data)
end
callback.register ('hyphenate', function (head,tail)
   lang.hyphenate(head, tail) 
   words:write (dumphyphens(head) .. outchar(10))
   end)
}}

\input knuth
\bye

This will write to hyphens-\jobname.txt a dump of all the characters that luatex has been asked to add hyphenation points to from this point on in the source, with the output of each callback call on a single line.

Although you cannot use this to generate Epub (mostly because macros like \TeX create two lines of output, once 'E' only for the lowered hbox and once 'TEX' for the actual macro use) the output is still useful because you can check to make sure there are no potential bad breaks allowed by the hyphenation patterns you are using.

Taco Hoekwater
  • 13,724
  • 43
  • 67
18

LuaLaTeX and circuitikz example: A one-phase transformer approximately equivalent circuit (T-cicuit). Give the equivalent circuit parameters manually in the code.

\documentclass{article}
\usepackage[utf8x]{inputenc}
\usepackage{luacode}
\usepackage{amsmath,graphicx}
\usepackage{circuitikz}

\begin{document}
\luaexec{
tp=tex.print
local R1 = 0.1
local X1 = 0.3
local R2 = 0.13
local X2 = 0.35
local RC = 100
local XM = 40
tp("\\begin{figure}[h]")
tp("\\begin{circuitikz}")
tp("\\draw (0,0) to[short,*-*] (10.5,0);")
tp("\\draw (0,4) to[short,*-,i=$I_1$] (1,4);")
tp("\\draw (1,4) to[R,l=$"..R1.."\\Omega$] (3,4);")
tp("\\draw (3,4) to[L,l=j$"..X1.."\\Omega$] (5,4);")
tp("\\draw (5,4) to[short] (5.5,4);")
tp("\\draw (5.5,4) to[L,l=j$"..X2.."\\Omega$] (7.5,4);")
tp("\\draw (7.5,4) to[R,l=$"..R2.."\\Omega$] (9.5,4);")
tp("\\draw (9.5,4) to[short,-*,i=$I_2'$] (10.5,4);")
tp("\\draw (5.25,4) to[short,*-*,,i=$I_0$] (5.25,3);")
tp("\\draw (5.25,3) to[short] (4.5,3)to [short] (4.5,2.75);")
tp("\\draw (5.25,3) to[short] (6,3) to [short] (6,2.75);")
tp("\\draw (4.5,2.75) to[R,l=$"..RC.."\\Omega$] (4.5,1.65);")
tp("\\draw (6,2.75) to[L,l=j$"..XM.."\\Omega$] (6,1.65);")
tp("\\draw (4.5,1.65) to[short] (4.5,1.4);")
tp("\\draw (6,1.65) to[short] (6,1.4) to [short] (4.5,1.4);")
tp("\\draw (5.25,1.4) to[short,*-*] (5.25,0);")
tp("\\draw (0,4) to [open,v=$V_1$] (0,0);")
tp("\\draw (10.5,4) to [open,v^=$V_2'$] (10.5,0);")
tp("\\end{circuitikz}")
tp("\\caption{One-phase transformer equivalent circuit (T-circuit)}")
tp("\\end{figure}")
}

\end{document}

enter image description here

  • 5
    finally, an example showing its output so one can see what the code is supposed to do ! – Nasser Apr 03 '14 at 01:02
  • 18
    To be fair, for something as simple as text substitution, you can also use standard TeX macros. \def\ROne{0.1}, \def\RTwo{0.3} etc. – Aditya Aug 23 '14 at 12:46
5

Check out those examples. Even if "normal" users might see no need for a general purpose language in LaTeX they will benefit from packages using Lua scripts internally.

thiagowfx
  • 260
  • 2
  • 6
h0b0
  • 5,437
  • 7
  • 35
  • 34