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)
Best Answer
There is no accented character in the "math" part of Unicode, because diacritics can be confused with math specific ornaments, such as the dot/dots for denoting derivatives.
According to a well established tradition, an ê in a formula is read as e hat even if the document is in Portuguese and usually it is interpreted as "some functional transformation on the variable e" (such a functional transformation would have previously been defined).
Therefore I don't find it a good idea to use ü for denoting a variable by itself. I'd use u and, if u is already used with another meaning, I would not adopt ü for the other one, in order to avoid any ambiguity.
This said, if you really want to use ü as a variable, you can try
and $ü=12$ will result in an italic "ü" and "Flügel" in text would print correctly as well.
Choose between the two versions according to which one renders better. But you've been warned. :)