10

I'm trying to mark the end of "words" (including punctuation) with luatex callbacks. (At the end I want to inject space chars at this positions, but the example uses rules for the visualization).

With some code based on \countwords from the chickenize package it works quite fine. I only have a problem with math: I would like to avoid to get marks there. Trying to do it with an attribute set in \everymath doesn't work as can be seen in the code below: It also affects other places like e.g. tabulars where math mode is used internally.

Has someone an idea how to exclude only "real" math from the mark function?

\documentclass{article}
\usepackage{luacode,amsmath}

\newattribute\mathattr

\begin{luacode}

local MATHATTR         = luatexbase.registernumber ("mathattr")
local nodetraverseid   = node.traverse_id
local nodegetattribute = node.get_attribute
local GLUE             = node.id("glue")
local GLYPH            = node.id("glyph")

local function insertmark (head,current)
 local pdfstring = node.new("whatsit","pdf_literal")
       pdfstring.data =
       string.format("q 1 0 0 RG 1 0 0 rg 0.4 w 0 %g m 0 %g l S Q",-3,10)
       head = node.insert_after(head,current,pdfstring)
 return head
end

local markwords = function(head)
  for glyph in nodetraverseid(GLYPH,head) do
   if glyph.next and (glyph.next.id == GLUE) 
      and not nodegetattribute(glyph,MATHATTR)
   then
      insertmark(head,glyph)
   end
  end
  return head
end


luatexbase.add_to_callback("pre_linebreak_filter",markwords,"markwords")

luatexbase.add_to_callback("hpack_filter",markwords,"markwords")

\end{luacode}
\usepackage{lipsum}
\begin{document}


\begin{tabular}{l}
xxx xxx
\end{tabular}

$a=b \int f(x) =0\quad  \text{abc abc abc abc} $

\everymath{\setattribute\mathattr{1}}

\begin{tabular}{l}
xxx xxx
\end{tabular}

$a=b \int f(x) =0\quad \text{abc abc abc abc} $

\bigskip

VA VA 
\lipsum[1]

\end{document}

enter image description here

8

The math content is enclosed by math nodes, with subtype 0 marking beginning, and subtype 1 marking closing of the math:

\documentclass{article}
\usepackage{luacode,amsmath}

\newattribute\mathattr

\begin{luacode}

local MATHATTR         = luatexbase.registernumber ("mathattr")
local nodetraverseid   = node.traverse_id
local nodetraverse     = node.traverse
local nodegetattribute = node.get_attribute
local GLUE             = node.id("glue")
local GLYPH            = node.id("glyph")
local MATH             = node.id("math")
local HLIST            = node.id("hlist")
local VLIST            = node.id("vlist")


local function insertmark (head,current)
 local pdfstring = node.new("whatsit","pdf_literal")
       pdfstring.data =
       string.format("q 1 0 0 RG 1 0 0 rg 0.4 w 0 %g m 0 %g l S Q",-3,10)
       head = node.insert_after(head,current,pdfstring)
 return head
end

local function markwords(head)
  local inside_math = false
  for n in nodetraverse(head) do
    local id = n.id
    if id == GLYPH then
      local glyph = n
      if glyph.next and (glyph.next.id == GLUE) 
        and not (inside_math or nodegetattribute(glyph,MATHATTR))
      then
        insertmark(head,glyph)
      end
    elseif id == MATH then
      inside_math = (n.subtype == 0)
    end
  end
  return head
end


luatexbase.add_to_callback("pre_linebreak_filter",markwords,"markwords")

luatexbase.add_to_callback("hpack_filter",markwords,"markwords")

\end{luacode}
\usepackage{lipsum}
\begin{document}


\begin{tabular}{l}
xxx xxx
\end{tabular}

$a=b \int f(x) =0\quad  \text{abc abc abc abc} $


\everymath{\setattribute\mathattr{1}}

\begin{tabular}{l}
xxx xxx
\end{tabular}

$a=b \int f(x) =0\quad \text{abc abc abc abc} $

\bigskip

VA VA 
\lipsum[1]

\end{document}

Contrary to your screenshot, the code in your question doesn't put bar behind last word in \text{abc abc abc abc} and at the end of a paragraph:

enter image description here

  • elseif id == MATH then inside_math =(n.subtype == 0) end is a bit shorter – user2478 Jan 1 at 20:09
  • Thanks, that seems to do exactly what I want. And I don't have a bar after the last abc in \text too, but you can't see it, as my screenshot has been clipped and shows only the first tree words. – Ulrike Fischer Jan 1 at 23:17
  • @UlrikeFischer ah, it is good to know that it is not an issue – michal.h21 Jan 1 at 23:20
  • I also removed the attribute from the test, it is not needed with your code, and I added a test for the glyph width, to avoid that 0-space gets marked: glyph.next and (glyph.next.id == GLUE) and not inside_math and (glyph.next.width >0). – Ulrike Fischer Jan 1 at 23:24

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.