% This is the macro package used by OpTeX, see http://petr.olsak.net/optex % vlna.opm, Petr Olšák , 2021 % Vlna prevents breaks in spaces after single-letter prepositions, after (or % before) degrees, and between value and SI units. It enables or disables % split hyphens too. All folks are done at the postprocessing phase before TeX splits % the typesetting material into the paragraph lines. % vlna.opm is based on Lua code from the package `luavlna` (by Michal Hoftich % and Miro Hrončok). See `texdoc luavlna` or end of this file for more information. \_codedecl \singlechars {Preventing single-chars prepositions and more <2023-06-23>} \_namespace{vlna} \_doc ----------------------------- We declare new attribute, register callbacks, and define Lua functions that point to Lua functions from `luavlna.lua` package. We need this package installed. We need not `require ltluatex` because `luatexbase.callbacks` are defined in the `optex.lua` file and it is part of the OpTeX format. \_cod ----------------------------- \_newattribute \.preventsinglestatus \_directlua{% luavlna = require "luavlna" luatexbase.add_to_callback("pre_linebreak_filter", luavlna.preventsingle,"LuaVlna") luatexbase.add_to_callback("hyphenate", luavlna.split_hyphens, "allow hyphen breaks") luavlna.preventsingleid = \_the\_attributealloc set_singlechars = function(lang,chars) if (lang == "") then return nil end local chars = chars or "" local singlechars = {} for pos, char in utf8.codes(chars) do singlechars[utf8.char(char)] = true end luavlna.singlechars(lang,singlechars) end set_compounds = function(lang, compounds) if (lang == "") then return nil end local c = compounds:explode(",+") % match multiple colons as one local compoundstable = {} for _, compound in pairs(c) do compoundstable[compound] = true end luavlna.initials(lang, compoundstable) end set_main_language = function(lang) if (lang == "") then return nil end luavlna.set_main_language(tonumber(lang)) end enable_split_hyphens = function(lang) if (lang == "") then return nil end luavlna.split_hyphen_langs[tonumber(lang)] = true end disable_split_hyphens = function(lang) if (lang == "") then return nil end luavlna.split_hyphen_langs[tonumber(lang)] = nil end } \_doc ----------------------------- We need not `require luavlna-langno` because of the conversion from language name to the `\language` number is done by the macro `\.langtonum``={}` defined here. It does `\def{}` or `\def\sequence{}` if is unknown. The is case insensitive and these names are declared in the hyphen-lan.opm file, section 2.37.2 in OpTeX documentation. \_cod ----------------------------- \_def\.langtonum#1=#2{\_lowercase{\_edef#1{\_trycs{_ulan:#2}{}}}% \_ifx#1\_empty \_opwarning{vlna: unknown language "#2", ignored}% \_else \_edef#1{\_the\_cs{_#1Patt}}\_fi} \_doc ----------------------------- `\singlechars``{}{}` sets for given language.\nl `\compoundinitials``{}{}` sets compound characters from the list for given language. \_cod ----------------------------- \_def\.singlechars#1#2{\.langtonum\.l={#1}\_directlua{set_singlechars("\.l","#2")}} \_def\.compoundinitials#1#2{\.langtonum\.l={#1}\_directlua{set_compounds("\.l","#2")}} \_doc ----------------------------- `\enablesplithyphens` and `\disablesplithyphens` are dependent on the language. \_cod ----------------------------- \_def\.enablesplithyphens#1{\.langtonum\.l={#1}\_directlua{enable_split_hyphens("\.l")}} \_def\.disablesplithyphens#1{\.langtonum\.l={#1}\_directlua{disable_split_hyphens("\.l")}} \_doc ----------------------------- By default, the language-dependent features of the `luavlna` depend on the current `\language` value, i.e. on the currently selected hyphenation. `\preventsinglelang``{}` activates the language-dependent features regardless of the current `\language` value. \_cod ----------------------------- \_def\.preventsinglelang#1{\.langtonum\.l={#1}\_directlua{set_main_language("\.l")}} \_doc ----------------------------- Switching on/off `luavlna` preposition features should be done using attribute setting. It will allow you to switch them on/off in the middle of the paragraph. \_cod ----------------------------- \_def\.preventsingleon{\.preventsinglestatus=2 } \_def\.preventsingleoff{\.preventsinglestatus=1 } \_doc ----------------------------- Switching on/off the other `luavlna` features is implemented only by setting a special `luavlna` variable. \_cod ----------------------------- \_def\.preventsingledebugon{\_directlua{luavlna.debug(true)}} \_def\.preventsingledebugoff{\_directlua{luavlna.debug(false)}} \_def\.nopredegrees{\_directlua{luavlna.no_predegrees = true}} \_def\.nosufdegrees{\_directlua{luavlna.no_sufdegrees = true}} \_def\.nounits{\_directlua{luavlna.no_unit = true}} \_def\.noinitials{\_directlua{luavlna.no_initials = true}} \_nspublic \singlechars % declare single-letter prepositions per language \compoundinitials % declare compound characters per language \enablesplithyphens % enable split hyphens per language \disablesplithyphens % disable split hyphens per language \preventsinglelang % declare main language independent of current hyphenation \preventsingleon % switch on the prepositions feature (default) \preventsingleoff % switch off the prepositions feature \nopredegrees % switch off pre-degrees feature (default is on) \nosufdegrees % switch off post-degrees feature (default is on) \nounits % switch off SI units feature (default is on) \noinitials % switch off initials feature (default is on) \preventsingledebugon % switch on debug printing (purple squares) \preventsingledebugoff % switch off debug printing (default) ; \_endnamespace % Default values: \singlechars{Czech}{AIiVvOoUuSsZzKk} \singlechars{Slovak}{AIiVvOoUuSsZzKk} \compoundinitials{Czech}{Ch,CH} % doesn't work in version v0.1g of luavlna \enablesplithyphens{Czech} \enablesplithyphens{Slovak} % + predegrees, sufdegrees, units, initials (they are independent of language value) \_endcode What should be done automatically after `\load[vlna]`: Prepositions feature: v lese -> v~lese, (A taky zde) -> (A~taky zde). Pre-degrees feature: Mgr. Bown -> Mgr.~Brown. Post-degrees feature: John Brown, PhD. -> John Brown,~PhD. SI units feature: 42 cm -> 42~cm (with thin space) Initials feature: J. Brown -> J.~Brown Split hyphens feature: propan-butan -> propan\discretionary{-}{-}{-}butan. The prepositions and split-hyphens features are language-dependent, the other features are language-independent. A testing file: \begtt \load[vlna] \fontfam[LMfonts] \cslang \preventsingledebugon Mgr. J. Brown, PhD., zkusí v lese (A taky v závorce) zkontrolovat rozměr 42 m. Obejde se bez propan-butanových lahví. \bye \endtt Note, that versinon v0.1g 2020-06-02 of the luavlna package is an experimental code. It seems that `\compoundinitials` does not work in this version and when you use `\hbox{-}` in a paragraph when `\enablesplithyphens` then LuaTeX hangs.