如何在 LuaTeX 中自动设置连字参数?

如何在 LuaTeX 中自动设置连字参数?

在下面的例子中,我们需要用连字符连接“aa-aa”,但不需要连接“bbbb”。

righthyphenmin=2如果单词的所有字母都是“a”,如何自动设置,并在所有其他情况下保持默认值?

\language255
%\righthyphenmin=2
\hyphenation{aa-aa}
\hyphenation{bb-bb}
\parindent=0pt
\hsize=1pt
\hfuzz=100pt
aaaa
bbbb
\bye

LuaTeX 有tex.righthyphenmin。并且在文章中LuaTEX:如何写一个段落在“插入可自由支配项”部分中,提到了hyphenate回调。是否可以使用这些功能来解决此问题?

答案1

这里有一些完整的示例,它加载所请求语言的连字模式,并可以从字符 unicode 值中检测使用的语言。

languages.lua使用简单的Lua库:

kpse.set_program_name "luatex"
local M = {}
local languages = require "language.dat"
M.languages = languages
local ranges = {default = "english"}



local function load_patterns(pat)
  if not pat then return "" end
  local fname = kpse.find_file(pat)
  if not fname then return "" end
  local file = io.open(fname, "r")
  local patterns = file:read("*all")
  file:close()
  return patterns or ""
end

function M.get_lang(l) 
  local language = languages[l] 
  if not language then return nil end
  local id= language.id
  -- English is built in
  if l == "english" then id = 0 end 
  if id then return language end
  local langobj = lang.new()
  id = lang.id(langobj)
  local patterns = load_patterns(language.patterns)
  lang.patterns(langobj,patterns)
  language.id = id
  languages[l] = language
  return language
end

local function convert_num(num)
  if type(num) == "number" then return num end
  return tonumber(num, 16)
end

function M.add_range(lang, min, max)
  print("add range", lang, min, max)

  ranges[#ranges+1] = {lang = lang, min = convert_num(min), max = convert_num(max)}
end

function M.default(lang)
  ranges.default = lang
end

function M.test_range(ucode)
  for _,v in ipairs(ranges) do
    local min = v.min
    local max = v.max
    if ucode >= min and ucode  <= max then
      return v.lang
    end
  end
  return ranges.default
end

return M

该库加载文件language.dat.lua,该文件是包含有关语言的各种信息的表格:

 ['russian'] = {
    loader = 'loadhyph-ru.tex',
    lefthyphenmin = 2,
    righthyphenmin = 2,
    synonyms = {  },
    patterns = 'hyph-ru.pat.txt',
    hyphenation = 'hyph-ru.hyp.txt',
  },

有用的信息是patternsrighthyphenmin字段。我们必须使用lang.patterns函数加载模式,才能使连字符起作用。

我们需要一些来自 TeX 的辅助宏minilang.tex

\directlua{
languages = require "languages"
}

\def\loadlang#1{%
\directlua{languages.get_lang "#1"}%
}

\def\definerange#1#2#3{%
\directlua{languages.add_range("#1","#2","#3")}%
}

\def\defaultrange#1{\directlua{languages.default "#1"}}

\directlua{
  local GLYF = node.id("glyph")
  local uchar  = unicode.utf8.char
  function show_nodes (head)
    for item in node.traverse(head) do
      local i = item.id
      if i == GLYF then
        local langname = languages.test_range(item.char)
        local l = languages.get_lang(langname) or {}
        item.lang = l.id
        item.right = l.righthyphenmin
        item.left = l.lefthyphenmin
      end
      % texio.write(i .. " ")
    end 
    return head
  end

  luatexbase.add_to_callback("hyphenate",
    function (head, tail)
      head = show_nodes(head)
      % tex.righthyphenmin=2
      lang.hyphenate(head)
      return head
    end, "find script")

luatexbase.add_to_callback("pre_linebreak_filter", function(head)
  for n in node.traverse(head) do
    if n.id == GLYF then
      print(uchar(n.char), n.lang, n.right)
    end
  end
  return head
end, "print nodes")
}

\loadlang定义新语言,\definerange定义语言的 unicode 范围并\defaultrange定义当字符与定义的范围不匹配时要使用的语言。

hyphenate使用了来自测试文件的修改后的回调,我们用languages.test_range(item.char)它来获取角色的语言,然后加载语言数据并将节点和字段languages.get_lang设置为语言数据中的正确值。langright

一些完整的样本:

\nopagenumbers
\input luaotfload.sty

\font\libertine= {Linux Libertine O} at 10pt
\libertine
\input minilang.tex
\loadlang{russian}
\loadlang{english}
\definerange{russian}{0400}{052F}
\defaultrange{english}
\wlog{the language: \the\language}
%\righthyphenmin=2
\hyphenation{aa-aa}
\hyphenation{bb-bb}
\parindent=0pt
\hsize=6em
\hfuzz=100pt

The development of Cyrillic typography passed directly from the medieval stage to the late Baroque, without a Renaissance phase as in Western Europe. Late Medieval Cyrillic letters (still found on many icon inscriptions today) show a marked tendency to be very tall and narrow, with strokes often shared between adjacent letters.

Peter the Great, Czar of Russia, mandated the use of westernized letter forms in the early 18th century. Over time, these were largely adopted in the other languages that use the script. Thus, unlike the majority of modern Greek fonts that retained their own set of design principles for lower-case letters (such as the placement of serifs, the shapes of stroke ends, and stroke-thickness rules, although Greek capital letters do use Latin design principles), modern Cyrillic fonts are much the same as modern Latin fonts of the same font family. The development of some Cyrillic computer typefaces from Latin ones has also contributed to the visual Latinization of Cyrillic type.

Около 863братья Константин (Кирилл) Философ и Мефодий из Солуни (Салоники) по приказу византийского императора Михаила III упорядочили письменность для старославянского языка и использовали новую азбуку для перевода на славянский язык греческих религиозных текстов[2]:44. Долгое время дискуссионным оставался вопрос, была ли это кириллица (и в таком случае глаголицу считают тайнописью, появившейся после запрещения кириллицы) или глаголица — азбуки, различающиеся почти исключительно начертанием. В настоящее время в науке преобладает точка зрения, согласно которой глаголица первична, а кириллица вторична (в кириллице глаголические буквы заменены на известные греческие). Так, большинство учёных склонны считать, что глаголицу создал Константин (Кирилл) Философ, а кириллицу — его ученик Климент Охридский[3]. Глаголица длительное время в несколько изменённом виде употреблялась у хорватов (до XVII в).
bbbb
\bye

我们必须使用luaotfload合适的 opentype 字体来获取西里尔文。重要的部分是:

\input minilang.tex
\loadlang{russian}
\loadlang{english}
\definerange{russian}{0400}{052F}
\defaultrange{english}

定义 unicode 范围内的字符 0400..052F以使用俄语。要使用的值\definerange可以在unicode 块文档

结果:

在此处输入图片描述

答案2

以下代码按要求工作:

callback.register("hyphenate",
  function (head, tail)
    for item in node.traverse(head) do
      if item.id == node.id("glyph") and item.char > 1025 and item.char < 1105 then
        item.right=2
      end
    end
    lang.hyphenate(head)
  end)

相关内容