1

I would like to implement the following in Lua, for various reasons. Recursion in a macro language is bad idea - the definition below exceeds the input stack size. I want to avoid TeX for a bisection font size search. Etc.

You can ignore this. The MWE is further down.

% Exceeds input stack size. \newbox\fittedtextbox % {1 width} {2 height} {3 starting font size} {4 font step} {5 minimum font size} \def\startfittedtext#1#2#3#4#5{% \def\boxsize#1#2#3#4#5{% \setbox\fittedtextbox\vbox{% \definebodyfontenvironment[#3] \switchtobodyfont[#3] \hsize=#1 \emergencystretch=1ex \tolerance=4000 \hyphenpenalty=8000 \getbuffer[fittedtext]}} \def\stopfittedtext{% \stopfittedtextargs{#1}{#2}{#3}{#4}{#5}} \ruledvbox to #2{\unvbox\fittedtextbox}} \def\stopfittedtextargs#1#2#3#4#5{% \boxsize{#1}{#2}{#3}{#4}{#5} \ifdim\ht\fittedtextbox>#2 \stopfittedtextargs{#1}{#2}{\dimexpr#3-#4\relax}{#4}{#5} \fi} \dostartbuffer[fittedtext][startfittedtext][stopfittedtext]} \startfittedtext{7cm}{7cm}{12pt}{1pt}{1pt} \input knuth \stopfittedtext 

The core operation is the assignment to a box register. This is what I need to replicate in Lua.

\setbox0=\vbox{...} 

As far as I can tell ConTeXt doesn't provide the appropriate Lua API. The context.* function are output functions. The vbox will be outputted and tex.box[0] receives the return value of context.vbox, probably nil (haven't checked).

\startluacode tex.box[0] = context.vbox(function() context.input("knuth") end) \stopluacode 

This is more subtle. The TeX stream is only executed when the Lua code block exits. So tex.box[0] references the value from before the Lua code block.

\def\coreop#1{\setbox0=\vbox{#1}} \startluacode context.coreop(function() context.input("knuth") end) context("%spt", tex.box[0].height/65536) \stopluacode 

Same problem with this:

\startluacode context("\\setbox0=\\vbox{\\input knuth }") context("%spt", tex.box[0].height/65536) \stopluacode 

I did find this email[1] but wow, that's not what I want. It did mention that a higher-level API is on the horizon. Hopefully similar to context.vbox but returning a node (is this what a register is?) rather than outputting a box. If it has materialized, I'd appreciate an example. If not, there must be some workaround. A way to flush the TeX stream, or anything else.

[1] lua equivalent of vbox...ht

1 Answer 1

2

There is a function tex.runtoks which runs a local TeX loop:

\starttext \def\coreop#1{\setbox0=\vbox{#1}} \startluacode tex.runtoks(function() context.coreop(function() context.input("knuth") end) end) context("%spt", tex.box[0].height/65536) \stopluacode \stoptext 
4
  • Interesting. Re. tex.runtoks: You have to make sure that at the end TEX is in a sane state and this is not always trivial. I wonder what this means in terms of a function that should accept any valid TeX. Commented Mar 26, 2020 at 1:10
  • @user19087 Well, as long as you "only" do \coreop where everything is wrapped in \vbox{...} anyway it should be safe. Commented Mar 26, 2020 at 1:16
  • Ironically I am keeping as much TeX out of Lua as possible. Otherwise I have to deal with nested runtoks for converting ex to sp at the proper font size. Also searching for how to convert 1ex to sp isn't easy. Possibly put an "x" in a vbox and measure the height, but there are probably lots of gotchas for conforming to TeX's conversion. Could be another question if I used this approach. Commented Mar 26, 2020 at 17:27
  • tex.runtoks(context.delayed.coreop(context.delayed.input("knuth"))) Commented Mar 27, 2020 at 6:34

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.