-1

I would like to use Lua and LaTeX to determine the current column number when typesetting a table. I would prefer a Lua-based solution as I'm not as capable with plain TeX or expl3.

Example below:

The & col & is & \colNum

produces

The & col & is & 4

Some issues I foresee: If I wanted to exploit the input buffer to attempt this, I believe it is processed one line at a time. If I want to count the number of & without a leading \ for example, I would need to use the column counting macro on a new line. Is there any internal tex variables or counters that I could exploit?

Would it possibly be harmful to re-write & to bump up a counter, and re-write \\ to reset it?

  • 3
    you have not given a test file which makes it hard to answer. You mention \\ which suggests you are using latex, but you mention plain tex in your text. if you need to do this for arbitrary primitive/plain tex \halign structures (with rows ended by \cr) that is rather different from specifying a column count in latex tabular constructs. – David Carlisle Apr 12 '21 at 22:11
  • This can use LaTeX. I didn't include a MWE because I felt the task was pretty self explanatory. – likethevegetable Apr 12 '21 at 22:23
  • it is not clear at all really but even self explanatory questions benefit from a test file, if you want to help people to test their answers. but the simplest is to use \begin{tabular}{>{\setcounter{foo}{1}}c >{\stepcounter{foo}}c >{\stepcounter{foo}}c>{\stepcounter{foo}}c} – David Carlisle Apr 12 '21 at 22:29
  • Is it possible do by default set and step the counter, for every tabular, without having to add the >{}? – likethevegetable Apr 12 '21 at 22:51

1 Answers1

3

You can use LuaTeX's node library to count the existing columns in the hlist corresponding to the current row:

\documentclass{article}
\directlua{
  local funcs = lua.get_functions_table()
  local glue_t, unset_t, tabskip_st = node.id'glue', node.id'unset'
  for subid, name in ipairs(node.subtypes'glue') do
    if name == 'tabskip' then
      tabskip_st = subid
      break
    end
  end
  assert(tabskip_st)
  local colNumFunc = luatexbase.new_luafunction'colNum'
  token.set_lua('colNum', colNumFunc)
  funcs[colNumFunc] = function()
    local nest
    % Find the nesting level corresponding to the alignment row
    for i = tex.nest.ptr, 1, -1 do
      local tail = tex.nest[i].tail
      % We identify alignments by testing the last node:
      % In an alignment row it will always be a tabskip and tabskips can't appear
      % outside of alignments (except if people write crazy Lua code, but then all bets are off anyway)
      if tail.id == glue_t and tail.subtype == tabskip_st then
        nest = tex.nest[i]
        break
      end
    end
    if nest then
      % We found an alignment, now just count the existing boxes
      % Every column is a unset node, the subtype contains the number of additionally spanned columns
      local col = 1
      for _, sub in node.traverse_id(unset_t, nest.head) do
        col = col + sub + 1
      end
      tex.sprint(-2, tostring(col))
    else
      % There was no alignment. The user is trying to mess with us again
      tex.error'Attempt to get column number outside of alignment'
      tex.sprint(-2, '0')
    end
  end
}
% Based on a learnlatex.org example since the OP couldn't be bothered to include a MWE
\usepackage{array}

\begin{document} \begin{tabular}{cp{9cm}} Column \colNum: Tier & Beschreibung \ Hund & Column \colNum: Der Hund ist ein Mitglied der Gattung Canis, welche Teil der Familie Canidae ist, und das weitverbreitetste Landraubtier. \ Column \colNum: Katze & Column \colNum: Katzen sind eine domestizierte Art kleiner fleischfressender Säugetiere. Sie ist die einzige domestizierte Art der Familie Felidae und wird häufig als Hauskatze bezeichnet, um sie von den wildlebenden Mitglieder dieser Familie abzugrenzen. \ \end{tabular} \end{document}

enter image description here

  • local tabskip_st = table.swapped(node.subtypes'glue').tabskip – Henri Menke Apr 14 '21 at 12:25
  • Also tex.write will produce numbers with catcode 11. That might or might not be an issue. – Henri Menke Apr 14 '21 at 12:32
  • This is great, very, very helpful. Just curious: is there a benefit to using lua.get_functions_table(), luatexbase.new_luafunction(), and token.set_lua() like you did, vs. say defining a function in the "plain" lua way, and instead of using tex.write() rather return the col variable from the function, and setting a new command \newcommand{\colNum}{\directlua{tex.print(get_colNum())}}? I've modified the code to make it work in the way I suggested as I understand that more readily, but I am eager to learn more about LuaTeX. – likethevegetable Apr 14 '21 at 13:21
  • 1
    @likethevegetable It's slightly faster and expands in a single step which can sometimes be nice, but mostly it's a matter of personal preference. When I use LuaTeX functionality I often think of it as adding additional "primitives" which build a clear interface between the Lua and TeX parts, while IMO such \directlua uses often tend to mix them in odd ways. – Marcel Krüger Apr 14 '21 at 14:10
  • 1
    @Henri That would work, but I normally avoid using lualibs functionality if there's no good reason. I agree that tex.write is probably not the best choice here, I changed it to tex.sprint(-2,. – Marcel Krüger Apr 14 '21 at 14:22
  • @MarcelKrüger, just to confirm, tex.write is suitable for printing letters and spaces only, correct (my interpretation of the LuaTeX manual)? Any use-cases I should be aware of? Perhaps it is just quicker if you know the content is chars+spaces only? – likethevegetable Apr 14 '21 at 14:47
  • @likethevegetable It's like the documentation says: It's "suitable for use as a quick way to dump information". It's mostly useful when you just want to print the output and want to avoid that TeX tries to interpret it in any way. Then it an be a bit nicer than the other functions since it doesn't take a catcode table as argument, so you can't accidentially get wrong behavior when passing numbers you intent to print and it uses reasonable catcodes without forcing you to think about them too much. – Marcel Krüger Apr 14 '21 at 14:56
  • It's also fine for simply dumping numbers, but when you use it for numbers (or symbols) which you don't just want to dump to the output but actually interpret in your TeX code, it can sometimes have unexpected behavior. Especially when you print some longer stuff which might contain numbers then it's unlikely to make a difference, but since we are explicitly printing a number here it's cleaner to use the same catcodes TeX uses for other numbers. – Marcel Krüger Apr 14 '21 at 15:01