5

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 ...
tex.sprint(newLengthCommand);

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

% ***** Doesn't actually execute and set length ... why?
tex.sprint(setLengthCommand);

% ***** 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. – Henri Menke Oct 2 '19 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?) – elika kohen Oct 2 '19 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. – David Carlisle Oct 2 '19 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 – David Carlisle Oct 2 '19 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? – elika kohen Oct 2 '19 at 19:21
6

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:

\documentclass{article}

\newlength\zzz


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

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

\begin{document}

\end{document}

and a more complete example allocating lengths in tex and lua

\documentclass{article}

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

\directlua{
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
\newlength\zzzb
\setlength\zzzb{567pt}
\typeout{\zzzb is \meaning\zzzb, \the\zzzb} 

\begin{document}

\end{document}

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' – David Carlisle Oct 2 '19 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} – David Carlisle Oct 2 '19 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/… – Henri Menke Oct 3 '19 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)) – David Carlisle Oct 4 '19 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 – David Carlisle Oct 5 '19 at 8:18

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.