I got it working with a lua script. Your minimal example becomes:
\documentclass{minimal}
\usepackage{unicode-math}
\setmathfont{XITS Math}
\AtBeginDocument{\directlua{require("combining_preprocessor.lua")}}
\newcommand{\⃗}[1]{\ensuremath{\vec{#1}}}
\begin{document}
$v⃗$
\end{document}
The idea is that it's difficult to make LaTeX handle a command or macro that comes after its argument, which is how Unicode combining characters work, so we use would like a preprocessor to move the accent so it comes before its argument. That is, map v⃗
to \⃗{v}
in a script, and then define whatever action you want \⃗
to have. (That's a backslash followed by a combining arrow, which should be printed above the backslash.)
My lua script does most (all?) of the combining characters, so you just need to define what they should do in the .tex
file. Many accents on the same character is possible. Example:
\documentclass{minimal}
\usepackage{unicode-math}
\setmathfont{XITS Math}
\AtBeginDocument{\directlua{require("combining_preprocessor.lua")}}
\newcommand{\̂}[1]{\ensuremath{\hat{#1}}}
\newcommand{\⃑}[1]{\ensuremath{\vec{#1}}}
\newcommand{\̱}[1]{\ensuremath{\underline{#1}}}
\newcommand{\́}[1]{\ensuremath{\acute{#1}}}
\usepackage{stackrel}
\newcommand{\᷽}[1]{\ensuremath{\stackrel[\approx]{}{#1}}}
\begin{document}
Hello
$ℂ̂$ is hat on $ℂ$, more on $ℂ̂⃑$ (stress test)
$ℂ̂ x̂$
Many combining accents on $x᷽̱̂́⃑$ is cool.
\end{document}
(My browser doesn't do the many combining characters justice here, but it looks nice in the PDF file.)
Not sure if this is the ideal way of doing things, but for what it's worth, here is combining_preprocessor.lua
:
function minornil(a, b)
if a == nil and b == nil then
return nil
elseif a == nil then
return b
elseif b == nil then
return a
else
return math.min(a, b)
end
end
function findfirstcombining(line, n)
local a = string.find(line, "\204[\128-\191]", n) -- From U0300,
local b = string.find(line, "\205[\128-\175]", n) -- to U036F.
a = minornil(a, b)
b = string.find(line, "\226\131[\144-\176]", n) -- U20D0 to U20F0
a = minornil(a, b)
b = string.find(line, "\225\183[\128-\191]", n) -- U1DC0 to U1DFF
a = minornil(a, b)
return a
end
function is_utf8_continuation(byte)
return byte < 191 and byte > 127
end
function find_next_utf8_char(str, n)
while str:byte(n) ~= nil and is_utf8_continuation(str:byte(n)) do
n = n + 1
end
return n
end
function combining_iter(str)
local n = 0
return function ()
n = (n ~= nil) and findfirstcombining(str, n + 1)
return n
end
end
function dobuffer(line)
local n1 = 0
local t = {}
for n2 in combining_iter(line) do
if n2 > n1 then
local n3 = n2
repeat
n3 = n3 - 1
until not is_utf8_continuation(line:byte(n3))
table.insert(t, string.sub(line, n1, n3 - 1))
n1 = find_next_utf8_char(line, n2 + 1)
local comb = {}
table.insert(comb, "\\" .. string.sub(line, n2, n1 - 1) .. "{")
table.insert(comb, string.sub(line, n3, n2 - 1) .. "}")
n2 = findfirstcombining(line, n1)
while n2 == n1 do
n1 = find_next_utf8_char(line, n2 + 1)
table.insert(comb, 1, "\\" .. line:sub(n2, n1 - 1) .. "{")
table.insert(comb, "}")
n2 = findfirstcombining(line, n1)
end
table.insert(t, table.concat(comb))
end
end
table.insert(t, string.sub(line, n1))
return table.concat(t)
end
luatexbase.add_to_callback("process_input_buffer",
dobuffer, "combining_preprocessor", 1)
Well the logical solution is to setup a new math version, which should be independant from the normal math version.
But imho there is today not much chance to get the version
key working in your use case. As long as only real math fonts are involved it works fine, but in the combination with range
and text fonts it is buggy as one math version affects the other.
Currently I would implement a bold mathversion by embolden a real math font. In xelatex this can be done with FakeBold
and version
(as long as no other text fonts are involved). In lualatex you could use a pdfliteral:
\documentclass{article}
\usepackage{fontspec,amsmath}
\setmainfont[Ligatures=TeX]{TeX Gyre Pagella}
\usepackage{unicode-math}
\setmathfont{TeX Gyre Pagella Math}
\begin{document}
\[ \hat f(t) = \int_0^t \hat f'(x)\, dx \]
\pdfliteral direct {2 Tr 0.2 w} %the second factor is the boldness
\[ \hat f(t) = \int_0^t \hat f'(x)\, dx \]
\pdfliteral direct {0 Tr 0 w}%
\end{document}
Best Answer
Update 28-10-2015: This has been fixed in version 0.85 of LuaTeX, see http://tracker.luatex.org/view.php?id=488
Looks something wrong with italic correction of integrals in the absence of super or subscripts, adding an empty superscript
\int^{} f(x)
fixes the spacing. Odd enough, adding empty subscript\int_{} f(x)
makes it even closer! I'd report this to luatex bug tracker.