“Namethatchar”宏

“Namethatchar”宏

我正在寻找一个可以提供角色名称的宏/包。以下是一些可能行为的示例:

\namethatchar{A} → A
\namethatchar{À} → Agrave
\namethatchar{a} → a
\namethatchar{\`A} → Agrave

这些名称不必特别指定,只需使用 ASCII 字符即可。是否有一个基本的宏或包可以做到这一点?

编辑:

需要澄清的是,这种需求来自lettrine.4htTeX4HT 的设置。目前,在排版首字下沉时,它会创建一个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

相关内容