101

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.)

5

5 Answers 5

37

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.

3
  • 10
    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. Oct 13, 2010 at 23:05
  • 1
    I believe, in mkiv at least, one might prefer \ctxlua to \directlua and \startlua for blocks. Jul 26, 2014 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, 2021 at 17:40
26

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.

8
  • 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…) Jul 26, 2010 at 20:10
  • 4
    Start with wiki.contextgarden.net/Programming_in_LuaTeX, which includes a nice example about automatically generating a table.
    – Joseph Wright
    Jul 26, 2010 at 20:12
  • 2
    Just for kicks: is there any example of an algorithm (like the sieve of eratosthenes) that someone implemented using TeX? Sep 15, 2010 at 4:17
  • 1
    @Mateus: Sure. That's a pretty trivial one to write. See here.
    – TH.
    Dec 25, 2010 at 18:15
  • 3
    @TH.: It is worth mentioning that there's a prime computing macro (without Eratosthenes) in the TeXbook, page 218. Dec 28, 2010 at 16:30
18

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.

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

2
  • 5
    finally, an example showing its output so one can see what the code is supposed to do !
    – Nasser
    Apr 3, 2014 at 1:02
  • 16
    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, 2014 at 12:46
6

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.

3
  • 2
    I see "500 - Internal Server Error"
    – Sharpie
    Jul 31, 2010 at 22:50
  • @Sharpie The page seems to be down. Just try it another time.
    – h0b0
    Aug 1, 2010 at 20:32
  • 2
    The new wiki for LuaTeX is at wiki.luatex.org
    – topskip
    Dec 25, 2010 at 19:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.