Wow, that works like a charm! Thank you, Max! It's also a very insightful example of how to use and inject Lua code in the TeX output routine. Do you mind if I add it to the wiki? (Probably under "Wrapping".)
Many thanks again! Benjamin > On Jun 24, 2022, at 01:44, Max Chernoff <mse...@telus.net> wrote: > >> I've been confronted with the following 'intriguing' formatting requirement >> for a document: > > "Intriguing" is definitely right here. I suspect these guidelines were made > for typewriters and haven't been updated since. > >> to limit the number of glyphs per line to 112. > > 112 characters per line sounds much too long anyways. > > From "The Elements of Typographic Style": > > Anything from 45 to 75 characters is widely regarded as a satisfactory > > length of line for a single-column page set in a serifed text face > > in a text size. The 66-character line (counting both letters and > > spaces) is widely regarded as ideal. For multiple-column work, a > > better average is 40 to 50 characters. > > > > If the type is well set and printed, lines of 85 or 90 characters > > will pose no problem in discontinuous texts, such as bibliographies, > > or, with generous leading, in footnotes. But even with generous > > leading, a line that averages more than 75 or so characters is likely > > to be too long for continuous reading. > > If you use something like > > \setuplayout[width=80\averagecharwidth] > > then your lines will for sure have fewer than 112 characters and will > probably be more readable too. > >> I'm nevertheless curious if there is a Lua/TeX solution to this "problem"? > > Option 1: Use a monospaced font. Then 112 characters per line <=> page width > = 112em. > > Option 2: A hacky Lua solution > > \startluacode > local max_length = 112 > > local glyph_id = node.id "glyph" > local disc_id = node.id "disc" > local glue_id = node.id "glue" > > function userdata.limiter(head) > language.hyphenate(head) > > local chars = 0 > local width = 0 > local n = head > while n do > if n.id == glyph_id or n.id == glue_id then > chars = chars + 1 > width = width + n.width - (n.shrink or 0) > end > > if chars >= max_length or width > tex.hsize then > local back_chars = 0 > local end_disc = nil > > while n do > if n.id == glue_id then > local penalty = node.new "penalty" > penalty.penalty = -10000 > node.insertbefore(head, n, penalty) > break > end > > if not end_disc and n.id == disc_id then > end_disc = n > end > > if end_disc and back_chars >= 5 then > end_disc.penalty = -10000 > break > end > > if n.id == glyph_id then > back_chars = back_chars + 1 > end > > n = n.prev > end > > width = 0 > chars = 0 > end > > n = n.next > end > > return head > end > > nodes.tasks.appendaction( > "processors", > "before", > "userdata.limiter" > ) > \stopluacode > > \setuppapersize[landscape,letter] > \showframe > > \starttext > \setupalign[flushleft] > > \setupbodyfont[14pt] > \samplefile{knuth} > > \setupbodyfont[12pt] > \samplefile{knuth} > > \setupbodyfont[10pt] > \samplefile{knuth} > > \page > \setupalign[normal] > > \setupbodyfont[14pt] > \samplefile{knuth} > > \setupbodyfont[12pt] > \samplefile{knuth} > > \setupbodyfont[10pt] > \samplefile{knuth} > \stoptext > > This code will ensure that no line ever exceeds "max_length" characters. It > uses a greedy algorithm instead of the standard TeX algorithm for line > breaking, but it still produces mostly decent results. > > -- Max ___________________________________________________________________________________ If your question is of interest to others as well, please add an entry to the Wiki! maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context webpage : http://www.pragma-ade.nl / http://context.aanhet.net archive : https://bitbucket.org/phg/context-mirror/commits/ wiki : http://contextgarden.net ___________________________________________________________________________________