[NTG-context] upload

Hans Hagen j.hagen at freedom.nl
Fri Jul 8 16:20:44 CEST 2022

On 7/8/2022 9:40 AM, Max Chernoff via ntg-context wrote:
>> This is because you need to pass a list that conforms to what the 
>> builder expects and the callback that you use doesn't do that for you 
>> (after all, it also gets hbox content).
> Isn't "processors/after" the same as "pre_linebreak_filter"? I thought 
> that only "hpack_filter" gets \hbox content? Anyways, my actual function 
> has this guard at the very start:
>      if (head.id ~= par_id and context) or -- Ensure that we were 
> actually given a par
>          status.output_active or -- Don't run during the output routine
>          tex.nest.ptr > 1 -- Don't run inside boxes
>      then
>          return head
>      end
> so I think that I'm only processing actual top-level paragraphs here.
>> There is no 'callback sequence handler' for the par builder (currently 
>> i see no need for it, also given the extra overhead involved) but this 
>> what what you can do:
>> \startluacode
>>      function builders.paragraphs.constructors.methods.preroll_a(head)
>>          local result, info = tex.linebreak(head)
>>          tex.prevdepth = info.prevdepth
>>          tex.prevgraf = info.prevgraf
>>          return result
>>      end
>>      function builders.paragraphs.constructors.methods.preroll_b(head)
>>          local result, info = tex.linebreak(nodes.nuts.copylist(head))
>>          inspect(info)
>>          return true
>>      end
>> \stopluacode
>> \defineparbuilder[preroll_a]
>> \defineparbuilder[preroll_b]
>> \starttext
>>      \setmainparbuilder[default]   \input tufte \par \input tufte \page
>>      \setmainparbuilder[preroll_a] \input tufte \par \input tufte \page
>>      \setmainparbuilder[preroll_b] \input tufte \par \input tufte \page
>> \stoptext
> I think that that code is for replacing the linebreaker entirely, like 
> with using "linebreak_filter"? My goal isn't to replace the linebreaker; 
> I just want to be able to inspect the paragraph before it is broken, 
> without modifying anything.

as long as you return true the built in will do the work but you can 
still do the preroll so basically nothing gets replaced .. it's just a 
more natural hook;l keep in mind that if someone replaces the linebreak 
your code woudl fail to do its work anyway

> What I'm trying to do *very* roughly looks like the following:
>      paragraphs = {}
>      attribute = 1234
>      function pre_linebreak_filter(head)
>          if head.id ~= node.id"par" then
>              return head
>          end
>          local nat_node, nat_info = tex.linebreak(node.copylist(head))
>          node.freelist(nat_node)
>          local long_node, long_info = tex.linebreak(
>              node.copylist(head), {looseness = 1}
>          )
>          if long_info.prevgraf == nat_info.prevgraf + 1 then
>              table.insert(paragraphs, long_node)
>          end
>          return head
>      end
>      function post_linebreak_filter(head)
>          node.setattribute(head, attribute, #paragraphs)
>          node.setattribute(node.slide(head), attribute, #paragraphs)
>          return head
>      end
>      function pre_output_filter(head)
>          if tex.outputpenalty ~= tex.widowpenalty then
>              return head
>          end
>          -- Pick a paragraph from `paragraphs` somehow
>          -- Replace that paragraph on the page with the one
>          -- from `paragraphs`
>          -- Move the last line of the page onto the top of
>          -- tex.lists.contributehead
>          return head
>      end
> (The full implementation is in the module "lua-widow-control" on CTAN, 
> TeX Live, and modules.contextgarden.net, or directly at 
> "https://github.com/gucci-on-fleek/lua-widow-control/blob/master/source/lua-widow-control.lua". 
> It's pretty long though, so I'm just trying to summarize here.)
> This works pretty well with Plain LuaTeX, LuaLaTeX, OpTeX, MkIV, and 
> MkXL before the latest upload, but something broke with the latest 
> upload in MkXL. I understand that I'm mucking around with volatile 
> interfaces, and I have no problem making a bunch of changes whenever the 
> engine/format changes; the problem is that I'm not too sure what changed 
> in the engine, so I don't know what I need to change in my code.

the tricky part is probably to make sure that it doesn't interfere with 
what other functions hooked into the callbacks are doing because who 
knows what gets injected in those lists

>> On the to do is a to add a 'prepare' helper that adds the mandate 
>> nodes (par fillers etc) 
> Maybe that's all that I need? If that's the case, I have no problem 
> coding my own "prepare helper" if you think that it'll be awhile before 
> you get around to it; the problem is that I'm not entirely sure what 
> nodes I would need to add. These new nodes aren't added until after 
> "pre_linebreak_filter", and they're gone after the linebreaker runs, so 
> I can't inspect a "regular" paragraph to see where these nodes belong.

there will be (untested on what you do)


that will add the additional stuff needed (and bark if something is 
there already).

btw, a par builder - even in luatex - needs a parfillskip to properly do 
its work, some penalty and in the case of context lmtx also a 
leftparfill skip and optionally initleft and right skip

                                           Hans Hagen | PRAGMA ADE
               Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
        tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl

More information about the ntg-context mailing list