I am trying to define a length, (not a dimension)—using Lua. But, I am having trouble with the syntax. I think I am supposed to be using the same structures/prototypes as glue_spec in order to still be able to use standard LaTeX length macros on those new lengths.

Question 1: What is the way to define and set new lengths with just Lua?

Question 2: Is it correct that all "lengths" in LaTeX are Skip Nodes / Glue Nodes, and not Dimensions—and can be used with all of the standard length macros? (\addtolength, \setlength, etc.)

From the LuaTeX documentation:

tex.setskip (["global",] <number> n, <node> s)
tex.setskip (["global",] <string> s, <node> s)
<node> s = tex.getskip (<number> n)
<node> s = tex.getskip (<string> s)

The best I have been able to interpret everything I have read is:

local name = "MyLength";

local newLengthCommand =
    "\\newlength{\\" .. name .. "}";

% *** Actually Creates a New Length ...

local setLengthCommand =
    "\\setlength{\\" .. name .. "}{1in}";

% ***** Doesn't actually execute and set length ... why?

% ***** Debug to be sure syntax was right ...
-- tex.sprint("\\par\\verb|" .. newLengthCommand .. "|");
-- tex.sprint("\\verb|" .. setLengthCommand .. "|");

% **** Many Fails trying to hack registers ...
local gluespec = node.new(node.id("glue_spec"));
gluespec.width = tex.sp("1in");
tex.skip[name] = gluespec;

-- tex.setskip("global", name, gluespec);
-- tex.skip[name].width = value .. "in";
-- etc., etc..
  • 1
    Lua and TeX run asynchronously, so everything that you print in tex.sprint will only be seen after the Lua chunk has been processed. Oct 2, 2019 at 8:55
  • @HenriMenke - Is there any way to decouple the "chunk"? Like, could I include a .tex file inside another ... Just wondering if there is some chunk-erific magic I could do where I defined the lengths in one chunk, and set them in another. Could I just \directlua two different files, synchronously, and it magically work? (If I separated out the \newlengths from the \setlengths?) Oct 2, 2019 at 9:45
  • it isn't clear what you want to do, do you want to set the lengths using Lua or do you want to set them using TeX but write the tex from Lua (you can do either) also do you need to allocate a length register and give it a tex name (like \newlength) which you can also do from Lua but that is rather different thing. Oct 2, 2019 at 10:15
  • 1
    for question 1 any lengths defined with \newlength are skip registers although other things that latex calls lengths and that may be set with \setlength are dimen registers eg \textwidth Oct 2, 2019 at 10:17
  • @DavidCarlisle - Okay, I updated the question—hoping to clarify that I do, indeed, want to define and set the lengths using Lua syntax—preferably without having to resort to a tex.sprint or some such thing. Are you saying that I could just use a \gdef to define a length and it will work just like a length, like: token.set_macro("MyLength", "2in", "global"). And, are you saying that Skip Registers are just wrappers around Dimension Registers? Oct 2, 2019 at 19:21

1 Answer 1


The following shows the skip register \zzz being set to a stretchy value from Lua.

It produces a log of

  \zzz has value 5.0pt plus 1.0pt minus 2.0pt

lualatex document:



local sp=65536
tex.setglue("zzz", 5*sp, 1*sp,2*sp,0,0)

\typeout{\zzz has value \the\zzz}



and a more complete example allocating lengths in tex and lua


% a latex length 
\typeout{\zzz is \meaning\zzz, \the\zzz} % happens to be skip register 43

local sp=65536
print ('skip alloc: ' .. tex.getcount(12)) % also 43 here
tex.setcount("global",12,tex.getcount(12)+1) % allocate
local myskipa=tex.getcount(12)
tex.setglue(myskipa, 5*sp, 1*sp,2*sp,0,0)
token.set_char("mylengtha", myskipa)
tex.setcount("global",12,tex.getcount(12)+1) % allocate
local myskipb=tex.getcount(12)
tex.setglue(myskipb, 5*sp, 1*sp,2*sp,2,3)% fil fill % expected 1,2??
token.set_char("mylengthb", myskipb)

% Lua allocated lengths, visible from TeX
\typeout{\skip\mylengtha is \skip\the\mylengtha, \the\skip\mylengtha}
\typeout{\skip\mylengthb is \skip\the\mylengthb, \the\skip\mylengthb}

% tex allocation picks up at 46,
% leaving 44 and 45 which wheer allocated in Lua
\typeout{\zzzb is \meaning\zzzb, \the\zzzb} 



this produces

\zzz is \skip43, 123.0pt
skip alloc: 43
\skip \mylengtha is \skip 44, 5.0pt plus 1.0pt minus 2.0pt
\skip \mylengthb is \skip 45, 5.0pt plus 1.0fil minus 2.0fill
\zzzb is \skip46, 567.0pt

Note I would have expected the stretch and shrink orders 2 and 3 to be fill and filll but they are coming out one less, I'll raise that on luatex list I think. confirmed that luatex is incompatible with etex/ptex/pdftex/xetex here and uses 2,3,4 not 1,2,3 for fil, fill and filll glue stretch orders.

  • @elikakohen do you need a tex csname for the length? You could just use 2000 instead of 'zzz' Oct 2, 2019 at 21:16
  • @elikakohen allocating a tex csname to a count register from lua is tricky, by far the easiest way is to do tex.sprint(\\newlength\\zzz} Oct 2, 2019 at 21:25
  • @elikakohen If you really want to execute TeX code from within Lua immediately rather than delayed, you can use the coroutine technique presented by Hans Hagen in this TUGboat article tug.org/TUGboat/tb39-1/tb121hagen-exec.pdf and applied by me in this answer tex.stackexchange.com/questions/470621/… Oct 3, 2019 at 0:25
  • @elikakohen it isn't clear what else you need apart from this answer, you don't really need to allocate anything, all the skip registers exist all the time so you instead of the tex-declared zzz here you can simply use tex.setglue(200, 5*sp, 1*sp,2*sp,0,0) tex.setglue(201, 50*sp, 1*sp,2*sp,0,0) ... with numbered registers 200 and 2001 in this example. The first free skip register number is available in \count12 (tex.getcount(12)) Oct 4, 2019 at 21:42
  • as I say \newlength is not required at all, all it does is increase count12 by 1 so you know which is the next unused skip register, so if count12 is (say) 157 you can use tex.setglue starting at 158 with no clashes with tex allocated lengths. @elikakohen Oct 5, 2019 at 8:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .