我正在寻找一个可以提供角色名称的宏/包。以下是一些可能行为的示例:
\namethatchar{A} → A
\namethatchar{À} → Agrave
\namethatchar{a} → a
\namethatchar{\`A} → Agrave
这些名称不必特别指定,只需使用 ASCII 字符即可。是否有一个基本的宏或包可以做到这一点?
编辑:
需要澄清的是,这种需求来自lettrine.4ht
TeX4HT 的设置。目前,在排版首字下沉时,它会创建一个lettrine-<letter>
CSS 类,例如lettrine-A
。只要字符没有被重音,这种方法就很好,在这种情况下,你会得到类似lettrine-À
CSS 类的东西。由于我使用 LuaTeX 进行编译,我使用的浏览器似乎已经在 CSS 类中实现了对重音的支持(早于规格),对我来说是可行的。但对其他人来说却行不通,而且从全球范围来看是不可接受的。
因此,该命令的输出旨在供机器和人类使用。前者是因为它生成的 CSS 类显然是机器使用的。后者是因为人类可能希望通过修改生成的 CSS 类的 CSS 属性来调整其 HTML 文档的呈现。
理想情况下,所有 CSS 设置都可以使用通过lettrine
映射的选项来完成lettrine.4ht
,但我们还没有做到这一点。
答案1
如果已知 Unicode 值,则存在从字形名称到 Unicode 的映射glyphlist.txt
可以很容易地解析(使用#
注释字符)以获取 Unicode 值的十六进制字符串。但是这种方法非常有限,因为此列表中有很多 Unicode 字符没有正确的字形名称。
如果名称无关紧要,则可以直接使用 Unicode 十六进制值。因为您还想支持 LICR(`A
),所以这有点棘手。当将任意 TeX 字符串转换为 PDF 字符串时,包必须执行类似的工作。因此,主要工作由以下示例hyperref
完成:\pdfstringdef
\documentclass{article}
\usepackage{ifluatex}
\usepackage{ifxetex}
\ifluatex
\else
\ifxetex
\else
\usepackage[utf8]{inputenc}
\fi
\fi
\usepackage[pdfencoding=auto]{hyperref}
\usepackage{pdfescape}
\newcommand*{\namethatchar}[2][]{%
\begingroup
\hypersetup{unicode}%
\pdfstringdef\gcharname{#2}%
\endgroup
\EdefUnescapeString\charname{\gcharname}%
\EdefEscapeHex\charname{\charname}%
\edef\charname{%
\expandafter\stripBOM\charname\@empty\@empty\@empty\@empty
}%
\ifx\relax#1\relax
\expandafter\charname
\else
\let#1\charname
\fi
}
\newcommand*{\stripBOM}[4]{%
\ifnum"0#1#2#3#4="FEFF %
\else
#1#2#3#4%
\fi
}
\begin{document}
\namethatchar{A}
\namethatchar{À}
\namethatchar{a}
\namethatchar{\`A}
\namethatchar{\texteuro}
\namethatchar{\textpertenthousand}
\end{document}
如果指定了可选参数,则结果将存储在宏中而不是打印结果。
\namethatchar[\result]{\`A}
\stripBOM
删除这里不需要的字节顺序标记。结果实际上是 UTF-16BE,这意味着代理用于不适合第一个平面(基本多语言平面)的更高 Unicode 值。
因为
hyperref
's\pdfstringdef
支持 XeTeX 和 LuaTeX 的大字符,所以该解决方案适用于 XeTeX 和 LuaTeX。然后应该删除行 `\usepackage[utf8]{inputenc}'。
带有字形名称的扩展解决方案
glyphlist.txt
此解决方案还会在和中查找字形名称glyphtounicode.tex
。需要注意使映射唯一。因此,我留下了很多\typeout
和\@latex@warning
行来显示分配和删除的映射。应用程序提供自己独特的映射文件是有意义的,这样可以更快地加载并更好地控制映射。
\documentclass{article}
\usepackage{ifluatex}
\usepackage{ifxetex}
\ifluatex
\else
\ifxetex
\else
\usepackage[utf8]{inputenc}
\fi
\fi
\usepackage[T1]{fontenc}
\usepackage[pdfencoding=auto]{hyperref}
\usepackage{pdfescape}
\usepackage{ltxcmds}
\makeatletter
\def\GlyphlistLine#1;#2;#3\@nil{%
\ifx\\#2\\%
\else
\ltx@ifundefined{glyphlist@#2}{%
\ltx@ifundefined{listglyph@#1}{%
\typeout{Defining #2 -> #1}%
\expandafter\gdef\csname glyphlist@#2\endcsname{#1}%
\expandafter\gdef\csname listglyph@#1\endcsname{#2}%
}{%
\@latex@warning{%
#2 -> #1 ignored, because of\MessageBreak
\@nameuse{listglyph@#1} -> #1%
}%
}%
}{%
\edef\ua{\@nameuse{glyphlist@#2}}%
\edef\ub{#1}%
\ifx\ua\ub
\else
\@latex@warning{%
#2 -> #1 ignored, because\MessageBreak
#2 -> \ua\space exists
}%
\fi
}%
\fi
}%
\IfFileExists{glyphlist.txt}\@firstoftwo\@secondoftwo{%
\typeout{* Glyph mapping: glyphlist.txt}%
\begingroup
\catcode`\#=14 % comment
\catcode`\ =9 % ignore spaces
\endlinechar=-1 % ignore line ends
% misusing \@inputcheck to save a read register
\openin\@inputcheck=glyphlist.txt\relax
\loop
\read\@inputcheck to\mapline
\ifeof\@inputcheck
\else
\expandafter\GlyphlistLine\mapline;;\@nil
\repeat
\immediate\closein\@inputcheck
\endgroup
}{%
\@latex@warning@no@line{Missing `glyphlist.txt'}%
}
\IfFileExists{glyphtounicode}\@firstoftwo\@secondoftwo{%
\typeout{* Glyph mapping: glyphtounicode.tex}%
\begingroup
\def\pdfglyphtounicode#1#2{%
\GlyphlistLine#1;#2;\@nil
}%
\endlinechar=-1 %
\catcode`\ =9 %
\input{glyphtounicode.tex}%
\endgroup
}{%
\@latex@warning@no@line{Missing `glyphtounicode.tex'}%
}
\newcommand*{\namethatchar}[2][]{%
\begingroup
\hypersetup{unicode}%
\pdfstringdef\gcharname{#2}%
\endgroup
\EdefUnescapeString\charname{\gcharname}%
\EdefEscapeHex\charname{\charname}%
\edef\charname{%
\expandafter\stripBOM\charname\@empty\@empty\@empty\@empty
}%
\ltx@IfUndefined{glyphlist@\charname}{%
}{%
\expandafter\let\expandafter\charname
\csname glyphlist@\charname\endcsname
}%
\ifx\relax#1\relax
\expandafter\charname
\else
\let#1\charname
\fi
}
\newcommand*{\stripBOM}[4]{%
\ifnum"0#1#2#3#4="FEFF %
\else
#1#2#3#4%
\fi
}
\makeatother
\begin{document}
\newcommand*{\test}[2][]{%
\texttt{\ifx\\#1\\\detokenize{#2}\else#1\fi}
& \texttt{\namethatchar{#2}}\\
}
\begin{tabular}{ll}
\test{A}
\test[Ã@]{Ã@}
\test{a}
\test{\`A}
\test{\texteuro}
\test{\textpertenthousand}
\test{\textsucceqq}% needs hyperref 2012/08/18 or later
\test{\textBicycle}% needs hyperref 2012/08/18 or later
\test{\textcopyleft}% needs hyperref 2012/08/18 or later
\end{tabular}
\end{document}
答案2
不确定你是否想将其排版或记录在日志中,此版本使用\typeout
并生成
A is A
À is A grave
a is a
\`A is A grave
\documentclass{article}
\usepackage[utf8]{inputenc}
\makeatletter
\def\namethatchar#1{{%
\let\IeC\@firstofone
\def\'##1{##1 acute}%
\def\`##1{##1 grave}%
\protected@edef\zzz{#1}%
\typeout{\unexpanded{#1} is \zzz}}}
\makeatother
\namethatchar{A}
\namethatchar{À}
\namethatchar{a}
\namethatchar{\`A}
\stop