具有 OpenType 功能的“原生”数学连字

具有 OpenType 功能的“原生”数学连字

使用 包semantic,可以很容易地通过连字符生成特殊数学符号(例如->变成\rightarrow)。然而,在 OpenType 中也有类似的东西。例如,Fira Code 字体为编程提供了连字符。如何在 TeX 方程式中实现这样的功能?

其实这个功能可能需要OpenType字体的支持,不过现有的OpenType数学字体好像没有这个功能,希望可以自己做一个。

答案1

既然您愿意使用 OpenType 字体,我假设您也愿意考虑基于 LuaLaTeX 的解决方案。以下代码设置了一个 Lua 函数,该函数 (a) 扫描所有输入行,(b) 自动“动态”用->和分别替换和的所有实例。<-\rightarrow\leftarrow

我相信弄清楚如何定义额外的“智能连字符”很简单。

\SmartligOff可以使用 LaTeX 宏和分别禁用 Lua 函数的操作,然后重新启用\SmartligOn。如果您的参考书目包含可能具有包含子字符串->和的 URL 字符串的 bib 条目,这可能会派上用场<-:显然,人们不想用\rightarrow和替换这些子字符串\leftarrow,对吧?

enter image description here

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{unicode-math} % optional
\setmathfont{Asana Math}  % optional

\usepackage{luacode}
\begin{luacode}
function smartlig ( s )
    -- Use '%-' to search for '-'
    -- Write '\\' to output a (single) backslash character
    s = s:gsub ( "%->", "\\rightarrow " )
    s = s:gsub ( "<%-", "\\leftarrow " )
  return s
end
\end{luacode}
\newcommand\SmartligOn{\directlua{luatexbase.add_to_callback (
     "process_input_buffer", smartlig, "smartlig" )}}
\newcommand\SmartligOff{\directlua{luatexbase.remove_from_callback (
     "process_input_buffer", "smartlig" )}}
\AtBeginDocument{\SmartligOn} % enabled by default

\begin{document}
$a->b$, $c<-d$

\SmartligOff
$a->b$, $c<-d$

\SmartligOn
$a->b$, $c<-d$
\end{document}

答案2

ConTeXt 有一个功能叫做崩塌其中,多个预定义的字形组合被折叠成一个,可以通过字体连字(内部称为特价商品), 例如

′′′(3次‎0x2032 PRIME)至0x2034 TRIPLE PRIME

或者通过查找表数学列表,其中定义了箭头之类的东西。最近有一个相关问题,如何关闭这些

\starttext
$a->b$ $b<-a$
\stoptext

enter image description here

答案3

这是个不错的挑战。到目前为止,此解决方案仅适用于文本和显示样式,并且仅替换右箭头。

\directlua{
  local rightarrow = node.new("noad",5) % subtype 5 = "rel"
  rightarrow.nucleus = node.new("math_char")
  rightarrow.nucleus.fam = 2
  rightarrow.nucleus.char = 33
  %
  local function is_minus(v)
     return v and v.nucleus and v.nucleus.fam == 2 and v.nucleus.char == 0
  end
  %    
  local function is_gt(v)
     return v and v.nucleus and v.nucleus.fam == 1 and v.nucleus.char == 62
  end
  %    
  callback.register('mlist_to_hlist',
     function(head,style,penalties)
        local v = head
        local delete_next = false
        while v do
           if delete_next then
              node.insert_after(head, v, node.copy(rightarrow))
              head = node.remove(head, v)
              delete_next = false
           end
           if is_minus(v) and is_gt(v.next) then
              head = node.remove(head, v)
              delete_next = true
           end
           v = v.next
        end
        return node.mlist_to_hlist(head,style,penalties)
     end)
}
$a->b$
\bye

相关内容