1

I'd like to pass some ConTeXt references to a Lua function. Like in the following MWE, the idea is to have tables name passed to a function via context.currentstructurereference. The MWE fails to compile if I uncomment the line calling context.currentstructurereference, and returns the reference if I uncomment next line (). Playing with braces did not help.

\startluacode 
userdata = userdata or {}
   function userdata.Test (t)
      for key,value in table.sortedhash(t)
      do
         tex.print (value)
      end
   end

Paris = {
pays = "France",
région = "Ile-de-France",
megapole = "oui"
}

\stopluacode

\starttext

\startsection[title={Paris},reference={Paris}]

\startluacode
context(context.currentstructurereference)
context.par()
userdata.Test(Paris)
-- userdata.Test(context.currentstructurereference) --does not compile
-- userdata.Test(context.currentstructurereference()) --not the expected result
\stopluacode
\stopsection

\stoptext

What should I do to get the same result as userdata.Test(Paris) calling context.currentstructurereference?

1
  • I don't think this will work. Keep in mind that using context.<whatever> accesses TeX and communication between Lua and TeX is asynchronous. Aug 10, 2020 at 22:12

1 Answer 1

1

You can get something like this to work, but there are two conceptual mistakes in your code.

First, the function userdata.Test(...) expects the name of a Lua table as the argument. No matter what you do, context.currentstructurereference will never point to a Lua table. So, the first thing that you need to do is to change the argument of the userdata.Test(...). The simplest way to change it is such that it expects a string, which is the key in a table which stores the relevant data. One option is as follows:

\startluacode 
userdata = userdata or {}

local references = {
  ["Paris"] = {
                pays = "France",
                région = "Ile-de-France",
                megapole = "oui"
              },
}


function userdata.Test (ref)
  local tbl = references[ref]
  for key, value in table.sortedhash(tbl)
  do
     tex.print (value)
  end
end
\stopluacode

Now, if we can somehow pass the value of context.currentstructurerefence (which is a TeX macro), as a string to Lua, we are good. Your attempt of using userdata.Test(context.currentstructurereference) still does not work. Why?

The context. namespace is uses a metaprogramming trick: when you call context.something, it is roughly equivalent to tex.print("\\something"), with some fancy features:

  • context.something("arg") is equal to tex.print("\\something{arg}")
  • context.something({key=value}, "arg") is equal to tex.print("\\something[key=value]{arg}")

One of the fancy things which the context macro does is called delayed processing (which is needed when passing control back and forth between TeX and Lua). At a high-level,

  • context.something(function ... end) is equal to output of function.

You can check this by running the following code:

\startluacode
  context(function() context("Hello") end)
\stopluacode

So, context.currentstructurereference() is a function, which effectively calls tex.sprint("\\currentstructurereference{}") which prints the expanded value of \currentstructurereference to the TeX stream. So,

\startluacode
  context(context.currentstructurereference)
\stopluacode

is roughly same as simply calling[^1] context.currentstructurereference. Of course, this doesn't work with the userdata.Test function because: (i) it expects a Lua table (or a Lua string in our modified version above); (ii) context.something is equal to tex.print("\\something") so it writes the TeX string and the value is not seen by Lua at all. What you can do, is the surprisingly simple:

\startluacode
   userdata.Test("\currentstructurereference")
\stopluacode

Note that I am using "\currentstructurereference" rather than "\\currentstructureference". So, \currentstructurereference gets expanded right away, so you will get the value of \currentstructurereference at the time \startluacode is encountered. This works in the minimal example that you had, but might fail if your actual usecase was more complicated.

[^1]: Strictly speaking, this is not true. There is a notion of a delayed call, but I'll not go into that here. See the CLD manual for details.

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.