在 LaTeX 中,可以使用命令生成希腊语表达式 Ἑλληνικὴ γλώσσα
\textgreek{<Ellhnik`h gl'wssa}
即,在 TeX 文件中仅使用拉丁字符,而不必使用任何希腊字母。
此特定命令在 XeLaTeX 中不起作用。
有没有办法在 XeLaTeX 中将拉丁字符转换为希腊字符?
我不是说必须写类似的东西
$\gamma\lambda\'\omega\sigma\sigma\alpha$.
答案1
由于这个问题与 XeTeX 有关,我认为您的文档可以毫不费力地迁移到 LuaTeX。首先,我必须说我知道没有什么关于希腊语,但至少根据 Davislor 在评论中分享的文件,我了解了一点需要做的事情。我想到的解决方案如下所示。
- 目前,
\textgreek
仅支持文本,这意味着几乎没有 LaTeX 命令可以在里面正常工作。 L2G_VARIANT_GRAVE
我只定义了、L2G_VARIANT_ROUGH
和的字符映射。您必须在表L2G_VARIANT_ACUTE
中填写新的映射。_l2g_variant_indicator
\documentclass{exam}
\usepackage{fontspec}
\usepackage{luacode}
\usepackage{expl3}
\setmainfont{DejaVu Serif}
\begin{luacode*}
L2G_VARIANT_ACUTE = 0x00000001
L2G_VARIANT_CIRCUM = 0x00000002
L2G_VARIANT_DIA = 0x00000004
L2G_VARIANT_DIACIRCUM = 0x00000008
L2G_VARIANT_DIAGRAVE = 0x00000010
L2G_VARIANT_GRAVE = 0x00000020
L2G_VARIANT_IOTASUB = 0x00000040
L2G_VARIANT_ROUGH = 0x00000080
L2G_VARIANT_SMOOTH = 0x00000100
l2g_variants = {
"acute", "circum", "dia", "diacircum", "diagrave", "grave", "iotasub", "rough", "smooth"
}
l2g_char_mapping = {
[97]=945,[98]=946,[99]=958,[100]=948,[101]=949,[102]=966,
[103]=947,[104]=951,[105]=953,[107]=954,[108]=955,[109]=956,
[110]=957,[111]=959,[112]=960,[113]=952,[114]=961,[116]=964,
[117]=965,[118]=989,[119]=969,[120]=958,[121]=968,[122]=950,
[65]=913,[66]=914,[67]=926,[68]=916,[69]=917,[70]=934,
[71]=915,[72]=919,[73]=921,[75]=922,[76]=923,[77]=924,
[78]=925,[79]=927,[80]=928,[81]=920,[82]=929,[84]=932,
[85]=933,[86]=988,[87]=937,[88]=926,[89]=936,[90]=918
}
_l2g_variant_indicator = {
["`"] = L2G_VARIANT_GRAVE,
["<"] = L2G_VARIANT_ROUGH,
["'"] = L2G_VARIANT_ACUTE
}
-- an integer version of _l2g_variant_indicator will be generated right away
l2g_variant_indicator = {}
for key, val in pairs(_l2g_variant_indicator) do
local ind = key:byte(1)
l2g_variant_indicator[ind] = val
end
l2g_variant_mapping = {
[97]={[256]=7936,[288]=7938,[352]=8066,[128]=7937,[160]=7939,[224]=8067,[257]=7940,[321]=8068,[129]=7941,[193]=8069,[258]=7942,[322]=8070,[130]=7943,[194]=8071,[320]=8064,[192]=8065,[32]=8048,[96]=8114,[1]=940,[65]=8116,[2]=8118,[66]=8119,[64]=8115},
[65]={[256]=7944,[288]=7946,[352]=8074,[128]=7945,[160]=7947,[224]=8075,[257]=7948,[321]=8076,[129]=7949,[193]=8077,[258]=7950,[322]=8078,[130]=7951,[194]=8079,[320]=8072,[192]=8073,[1]=902,[32]=8122,[64]=8124},
[104]={[256]=7968,[288]=7970,[352]=8082,[128]=7969,[160]=7971,[224]=8083,[257]=7972,[321]=8084,[129]=7973,[193]=8085,[258]=7974,[322]=8086,[320]=8080,[192]=8081,[1]=942,[65]=8132,[2]=8134,[66]=8135,[32]=8052,[64]=8131},
[72]={[256]=7976,[288]=7978,[352]=8090,[128]=7977,[160]=7979,[224]=8091,[257]=7980,[321]=8092,[129]=7981,[193]=8093,[258]=7982,[322]=8094,[320]=8088,[192]=8089,[1]=905,[32]=8138,[64]=8140},
[119]={[256]=8032,[288]=8034,[352]=8098,[128]=8097,[160]=8035,[224]=8099,[257]=8036,[321]=8100,[129]=8037,[193]=8101,[258]=8038,[322]=8102,[130]=8039,[194]=8103,[320]=8096,[192]=8097,[32]=8060,[96]=8178,[1]=974,[65]=8180,[2]=8182,[66]=8183,[64]=8179},
[87]={[256]=8040,[288]=8042,[352]=8106,[128]=8041,[160]=8043,[224]=8107,[257]=8044,[321]=8108,[129]=8045,[193]=8109,[258]=8046,[322]=8110,[130]=8047,[194]=8111,[320]=8104,[192]=8105,[1]=911,[32]=8186,[64]=8188},
[105]={[4]=970,[5]=912,[256]=7984,[288]=7986,[128]=7985,[160]=7987,[257]=7988,[129]=7989,[258]=7990,[130]=7991,[36]=8146,[16]=8146,[6]=8151,[8]=8151,[1]=943,[32]=8054,[2]=8150},
[117]={[4]=971,[5]=944,[256]=8016,[288]=8018,[128]=8017,[160]=8019,[257]=8020,[129]=8021,[258]=8022,[130]=8023,[36]=8162,[16]=8162,[6]=8167,[8]=8167,[1]=973,[32]=8058,[2]=8166},
[101]={[256]=7952,[288]=7954,[128]=7953,[160]=7955,[257]=7956,[129]=7957,[1]=941,[32]=8050},
[69]={[256]=7960,[288]=7962,[128]=7961,[160]=7963,[257]=7964,[129]=7965,[1]=904,[32]=8136},
[73]={[256]=7992,[288]=7994,[128]=7993,[160]=7995,[257]=7996,[129]=7997,[258]=7998,[130]=7999,[1]=906,[4]=938,[32]=8154},
[111]={[256]=8000,[288]=8002,[128]=8001,[160]=8003,[257]=8004,[129]=8005,[1]=972,[32]=8056},
[79]={[256]=8008,[288]=8010,[128]=8009,[160]=8011,[257]=8012,[129]=8013,[1]=908,[32]=8184},
[85]={[128]=8017,[160]=8027,[129]=8029,[130]=8031,[1]=910,[4]=939,[32]=8170},
[114]={[256]=8164,[128]=8165},
[82]={[128]=8172}
}
-- assume Lua 5.3 is used, otherwise may need to use bit32 library
-- https://stackoverflow.com/questions/5977654/how-do-i-use-the-bitwise-operator-xor-in-lua
function l2g_bitwise_or(a, b)
return a | b
end
function l2g_print_warning(s)
tex.print(string.format([[\PackageWarning{l2g}{%s}]], s))
end
function l2g_code_to_char(c)
return utf8.char(c)
end
l2gstate = {
["variant_flag"] = 0,
["variant_storage"] = -1,
["result"] = -1
}
function l2gstate:new()
local obj = {}
setmetatable(obj, self)
self.__index = self
self.result = {}
self.variant_storage = {}
return obj
end
function l2gstate:get_last_variant()
local len = #self.variant_storage
if len == 0 then
return -1
end
local last_char = self.variant_storage[len]
return utf8.codepoint(last_char)
end
function l2gstate:register_variant(var_ccode)
local var_flag = l2g_variant_indicator[var_ccode]
self.variant_flag = l2g_bitwise_or(self.variant_flag, var_flag)
table.insert(self.variant_storage, l2g_code_to_char(var_ccode))
end
function l2gstate:discard_variant()
self.variant_flag = 0
self.variant_storage = {}
end
function l2gstate:add_variant_char()
for _, val in ipairs(self.variant_storage) do
table.insert(self.result, val)
end
end
function l2gstate:add_char(code)
table.insert(self.result, l2g_code_to_char(code))
end
function l2g(s)
local pos = 1
local cur_byte = -1
local cur_char = nil
local variant_state = l2gstate:new()
local char_find = nil
local inner_find = nil
local inner_char_find = nil
while pos <= utf8.len(s) do
cur_byte = utf8.codepoint(s, pos)
cur_char = utf8.char(cur_byte)
variant_find = l2g_variant_indicator[cur_byte]
if variant_find ~= nil then
if cur_byte == variant_state:get_last_variant() then
-- escaping current sequence
variant_state:add_char(cur_byte)
variant_state:discard_variant()
else
variant_state:register_variant(cur_byte)
end
goto continue
end
char_find = l2g_char_mapping[cur_byte]
if char_find ~= nil then
-- try to resolve variants
if variant_state.variant_flag > 0 then
inner_find = l2g_variant_mapping[cur_byte]
if inner_find ~= nil then
inner_char_find = inner_find[variant_state.variant_flag]
if inner_char_find ~= nil then
variant_state:add_char(inner_char_find)
else
l2g_print_warning(string.format("letter '%s' does not have variant type %d", cur_char, variant_state.variant_flag))
variant_state:add_variant_char()
variant_state:add_char(cur_byte)
end
else
l2g_print_warning(string.format("letter '%s' does not have any variant", cur_char))
variant_state:add_variant_char()
variant_state:add_char(cur_byte)
end
variant_state:discard_variant()
else
-- no variant set for this character
variant_state:add_char(char_find)
end
else
-- unable to find this character in mapping
variant_state:add_variant_char()
variant_state:add_char(cur_byte)
variant_state:discard_variant()
end
::continue::
pos = pos + 1
end
if variant_state:get_last_variant() ~= -1 then
variant_state:add_variant_char()
variant_state:discard_variant()
end
return table.concat(variant_state.result, "")
end
\end{luacode*}
\newcommand{\textgreek}[1]{
\directlua{
local res = l2g("\luaescapestring{#1}")
tex.print(res)
}
}
\begin{document}
\par \textgreek{<Ellhnik`h gl'wssa}
\par \textgreek{<Ellhnik<`h gl<'wssa}
\par \textgreek{<<Ellhnik``h gl''wssa}
\end{document}
结果是:
Ἑλληνικὴ γλώssα
Ἑλληνικἣ γλὥssα
<Ελληνικ‘η γλ’ωssα
答案2
虽然你没有提供完整的 MWE,但看起来你正在使用teubner
包,直接或间接通过babel
。这与 beta 代码或直接映射到 LGR 不同。
最好转换您的源
我的第一个建议是,如果可行的话,将输入转换为 Unicode,这样您就可以使用通常用于希腊语的任何输入法进行搜索、复制、粘贴、拼写检查、编辑等。如果是多音调希腊语,尤其如此,因为无重音希腊字母与其拉丁音译的映射就会中断。
使用外部脚本解析 LaTeX 源并生成新的 UTF-8 源文件有多困难取决于表达式的复杂程度\textgreek
。如果它们都像您的示例一样,则可以用正则表达式来完成。如果它们只能包含行为良好的非嵌套命令(例如)\textbf{<Ellhnik`h}
,则仍然可以机械地执行而无需编写更复杂的解析器。如果您的输入可以包含任意嵌套的命令,那么您至少需要编写一个可以匹配括号的解析器,如果命令可以执行诸如更改语言之类的复杂操作,则需要扫描该操作。如果您将以编程方式生成的字符串传递给\textgreek
,则需要手动重写它。
请注意,自 2020 年起,XeTeX 和 LuaTeX 仅支持预组合 (NFC) 希腊字符,不支持组合希腊重音符号。软件包维护人员告诉我,语言babel
文件可能会在 Unicode 连字算法之前修复此问题。
在 XeTeX 中
可以编写一个.tec
映射文件,将 Teubner 代码转换为 Unicode,类似于我为测试版代码编写的那个。 您可以用 来编译它,然后使用 的字体功能teckit_compile
来激活它。Mapping=
fontspec
除其他差异外,Teubner 代码可以包含诸如 之类的 LICR 宏\~{e}
,这些宏将生成组合重音符号,并且必须将这些宏规范化为 NFC 形式才能正常工作。
在 LuaTeX 中
Alan Xiang 提出了一个使用 Lua 的答案,但我还没有测试过。
作为后备方案
作为最后的手段,可以使用 加载 LGR 字体luainputenc
。也许可以继续加载teubner
那些 8 位字体,但由于不知道您的要求,我无法告诉您这是否适合您。