% \iffalse meta-comment % !TEX program = XeLaTeX %<*internal> \iffalse % %<*readme> Introduction ------------ xpinyin is a LaTeX package written to simplify the input of Hanyu Pinyin. The package provides macros to automatically add pinyin to Chinese characters. It can only be used in conjunction with xeCJK or CJK/CJKutf8 package. Given that the implementation of pinyin package of CJK bundle is not very well, it seems that xpinyin is a good replacement of it. You can read the package manual (in Chinese) for more detailed explanations. It may be distributed and/or modified under the conditions of the LaTeX Project Public License (LPPL), either version 1.3c of this license or (at your option) any later version. The latest version of this license is in http://www.latex-project.org/lppl.txt and version 1.3 or later is part of all distributions of LaTeX version 2005/12/01 or later. This work has the LPPL maintenance status "maintained". The Current Maintainer of this work is Qing Lee. This package consists of the file xpinyin.dtx, and the derived files xpinyin.sty, xpinyin.pdf, xpinyin.ins, xpinyin.lua, xpinyin.db, xpinyin-database.def and README (this file). Author ------ Qing Lee Email: sobenlee@gmail.com If you are interested in the process of development you may observe http://code.google.com/p/ctex-kit/ Installation ------------ The package is supplied in dtx format and as a pre-extracted zip file, xpinyin.tds.zip. The later is most convenient for most users: simply unzip this in your local texmf directory and run texhash to update the database of file locations. If you want to unpack the dtx yourself, running "luatex xpinyin.dtx" will extract the package whereas "xelatex xpinyin.dtx" will typeset the documentation. The package requires LaTeX3 support as provided in the l3kernel and l3packages bundles. Both of these are available on CTAN as ready-to-install zip files. Suitable versions are available in the latest version of MiKTeX and TeX Live (updating the relevant packages online may be necessary). To compile the documentation without error, you will need the xeCJK package and some specific Chinese Simplified fonts (TrueType or OpenType). % %<*internal> \fi \begingroup \def\temp{LaTeX2e} \expandafter\endgroup\ifx\temp\fmtname\else \csname fi\endcsname % %<*install> \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname directlua\endcsname\relax \begingroup \newlinechar=10 % \errmessage{^^J ********************************************^^J * LuaTeX is required to unpack this package.^^J ********************************************^^J } \endgroup \csname @@end\expandafter\endcsname\expandafter\end \fi \input l3docstrip.tex \keepsilent \askforoverwritefalse \let\MetaPrefix\relax \preamble Copyright (C) 2012-2014 by Qing Lee -------------------------------------------------------------------------- This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3 of this license or (at your option) any later version. The latest version of this license is in http://www.latex-project.org/lppl.txt and version 1.3 or later is part of all distributions of LaTeX version 2005/12/01 or later. This work has the LPPL maintenance status "maintained". The Current Maintainer of this work is Qing Lee. \endpreamble \postamble This package consists of the file xpinyin.dtx, and the derived files xpinyin.sty, xpinyin.pdf, xpinyin.ins, xpinyin.lua, xpinyin.db, xpinyin-database.def and README. \endpostamble \declarepostamble\emptypostamble \endpostamble \def\MetaPrefix{-- } \generate { \usedir{source/latex/xpinyin} \usepostamble\emptypostamble \file{xpinyin.lua} {\from{\jobname.dtx}{lua}} } \directlua{dofile("xpinyin.lua")} \let\MetaPrefix\DoubleperCent \generate { \usedir{source/latex/xpinyin} \file{xpinyin.ins} {\from{\jobname.dtx}{install}} \usedir{tex/latex/xpinyin} \file{xpinyin.sty} {\from{\jobname.dtx}{package}} \usepostamble\emptypostamble \file{xpinyin-database.def} { \from{\jobname.dtx} {database} \from{xpinyin.db} {} } \nopreamble\nopostamble \usedir{doc/latex/xpinyin} \file{README.txt} {\from{\jobname.dtx}{readme}} } \endbatchfile % %<*internal> \fi % % %<*driver|package> \NeedsTeXFormat{LaTeX2e} \RequirePackage{expl3} \GetIdInfo$Id: xpinyin.dtx 749 2014-12-24 15:05:15Z sobenlee@gmail.com $ {Automatically add pinyin to Chinese characters} %<*driver> \ProvidesExplFile{\ExplFileName.\ExplFileExtension} % %\ProvidesExplPackage{\ExplFileName} {\ExplFileDate}{2.1}{\ExplFileDescription} %<*driver> \ExplSyntaxOff % % %\ProvidesFile{xpinyin-database.def}% % [2014/12/24 v2.1 xpinyin database] % %<*driver> \documentclass[full,a4paper]{l3doc} \usepackage{xeCJK} \usepackage{indentfirst} \usepackage{xpinyin} \usepackage{fvrb-ex} \usepackage{geometry} \hypersetup{pdfstartview=FitH} \geometry{includemp,hmargin={0mm,15mm},vmargin=15mm,footskip=7mm} \BeforeBeginEnvironment{SideBySideExample}{\vskip1ex\relax} \fvset{formatcom=\xeCJKVerbAddon} \linespread{1.1} \setmainfont{TeX Gyre Pagella} \setsansfont{CMU Sans Serif} \setmonofont[ UprightFont=* Light, BoldFont=* Bold, SlantedFont=* Light Oblique]{CMU Typewriter Text} \setCJKmainfont[BoldFont=Adobe Heiti Std,ItalicFont=Adobe Kaiti Std]{Adobe Song Std} \setCJKmonofont{Adobe Kaiti Std} \xeCJKsetup{PunctStyle=kaiming} \newfontfamily\PinYinFont{TeX Gyre Adventor} \xpinyinsetup{font=\PinYinFont,multiple=\color{red}} \def\MacroFont{\linespread{1}\small\normalfont\ttfamily} \makeatletter \ExplSyntaxOn \DeclareDocumentCommand \package { o m } { \exp_args:Nx \tex_lowercase:D { \exp_not:N \href { http \token_to_str:N : //www.ctan.org/pkg/ \IfNoValueTF {#1} {#2} {#1} } } { \pkg {#2} } } \cs_set_protected:Npn \__codedoc_special_index_aux:nnnnn #1#2#3#4#5 { \__codedoc_special_index_set:Nn \l__codedoc_index_escaped_macro_tl {#2} \str_if_eq:onTF { \@currenvir } { macrocode } { \codeline@wrindex } { \HD@target \index } { \tl_if_empty:nF { #3 #4 } { #3 \actualchar #4 \levelchar } #1 \actualchar { \token_to_str:N \verbatim@font \c_space_tl \l__codedoc_index_escaped_macro_tl } \encapchar hdclindex{\the\c@HD@hypercount}{#5} } } \DeclareDocumentCommand \cs { O{} m } { \__codedoc_cmd_aux:no {#1} { \c__codedoc_backslash_tl #2 } } \DeclareDocumentCommand \tn { O{} m } { \__codedoc_cmd_aux:no { index = TeX , replace = false , #1 } { \c__codedoc_backslash_tl #2 } } \DeclareDocumentCommand \meta { +m } { \__codedoc_meta_aux:n {#1} } \DeclareExpandableDocumentCommand \bookmarkcstn { O{} m } { \tl_to_str:n {#2} } \cs_new:Npn \bookmarkmeta #1 { < \tl_to_str:n {#1} > } \cs_generate_variant:Nn \__codedoc_cmd_aux:nn { no } \ExplSyntaxOff \pdfstringdefDisableCommands{% \let\cs\bookmarkcstn \let\tn\bookmarkcstn \let\meta\bookmarkmeta \let\path\@firstofone \let\pkg\@firstofone} \def\LaTeX{\hologo{LaTeX}} \def\pdfLaTeX{\hologo{pdfLaTeX}} \def\XeLaTeX{\hologo{XeLaTeX}} \def\TF{true\orval{}false} \def\TTF{\defaultval{true}\orval{}false} \def\TFF{true\orval\defaultval{false}} \def\orval{\textup{\textbar}} \def\defaultval#1{\textbf{\textup{#1}}} \makeatother \def\indexname{代码索引} \IndexPrologue{% \section*{\indexname} \markboth{\indexname}{\indexname} 斜体的数字表示对应项说明所在的页码,下划线的数字表示定义所在的代码行号,而直立体的 数字表示对应项使用时所在的行号。} \begin{document} \DocInput{\jobname.dtx} \newgeometry{margin=15mm,footskip=7mm} \PrintIndex \end{document} % % \fi % % \CheckSum{707} % \GetFileInfo{\jobname.dtx} % % \title{\bfseries\pkg{xpinyin} 宏包} % \author{李清\\ \path{sobenlee@gmail.com}} % \date{\filedate\qquad\fileversion} % \maketitle % % \begin{documentation} % % \section{简介} % % \pkg{xpinyin} 是一个 \LaTeX 宏包,提供了为汉字自动注音的功能。 % % \section{基本用法} % % \pkg{xpinyin} 支持采用 \texttt{GBK} 和 \texttt{UTF-8} 编码的 \TeX 源文件,建议 % 总是使用 \texttt{UTF-8}。如果使用 \LaTeX 或 \pdfLaTeX\ 的编译方式,则根据编码的 % 情况,\pkg{xpinyin} 依赖 \package{CJK} 或者 \package[cjk]{CJKutf8} 宏包。 % 如果使用 \XeLaTeX,则依赖 \package{xeCJK} 宏包。如果它们没有在 \pkg{xpinyin} % 之前被载入,\pkg{xpinyin} 将根据编译方式自动选择,\LaTeX 或 \pdfLaTeX\ 将使用 % \pkg{CJKutf8}。 % % \pkg{xpinyin} 还依赖 \package{l3kernel} 和 \package{l3packages},使用 (pdf)\LaTeX % 下的 \texttt{GBK} 编码时,还将依赖 \package{xCJK2uni}。 % % 需要注意的是,\pkg{xpinyin} 缺省将拼音的字体设置为与文档的主字体(\tn{normalfont})相同, % 所以为了保证声调字母的正确输出,应该选用合适的西文主字体。也可以通过将在下一节介绍的 % \meta{font} 选项来单独设置拼音的字体。 % % \begin{minipage}[t]{\dimexpr(\linewidth-\parindent-2em)/2\relax} % \XeLaTeX 下的简单示例: % \begin{verbatim}[frame=single,gobble=3] % \documentclass{article} % \usepackage{xeCJK} % \usepackage{xpinyin} % \setmainfont{CMU Serif} % \setCJKmainfont{SimSun} % % \begin{document} % \xpinyin*{汉语拼音示例} % \end{document} % \end{verbatim} % \end{minipage}\qquad % \begin{minipage}[t]{\dimexpr(\linewidth-\parindent-2em)/2\relax} % (pdf)\LaTeX 下的简单示例: % \begin{verbatim}[frame=single,gobble=3] % \documentclass{article} % \usepackage{CJKutf8} % \usepackage{xpinyin} % \usepackage[T1]{fontenc} % \usepackage{lmodern} % % \begin{document} % \begin{CJK}{UTF8}{gbsn} % \xpinyin*{汉语拼音示例} % \end{CJK} % \end{document} % \end{verbatim} % \hrule height \dp\strutbox width 0pt \relax % \end{minipage} % % 运行上述示例要求系统安装了设置的字体,源文件用 |UTF-8| 编码保存,使用相应的编译方式。 % % \pkg{xpinyin} 可以与 \package{ctex} 宏包或文档类共同使用,使用方式与上面类似。 % % \section{用户手册} % % \begin{function}{pinyinscope} % \begin{syntax} % \tn{begin}\{pinyinscope\}\oarg{options} % ..... % \tn{end}\{pinyinscope\} % \end{syntax} % 为 \env{pinyinscope} 环境中的汉字自动注音。例如 % \begin{Example}[frame=single,numbers=left,gobble=5] % \begin{pinyinscope} % 列位看官:你道此书从何而来?说起根由,虽近荒唐,细按则深有趣味。 % 待在下将此来历注明,方使阅者\xpinyin{了}{liao3}然不惑。 % \end{pinyinscope} % \end{Example} % \end{function} % % 可选项 \meta{options} 用于局部设置拼音的格式,将在下面说明。 % % \begin{function}{\xpinyin} % \begin{syntax} % \tn{xpinyin} \oarg{options} \Arg{单个汉字} \Arg{拼音} % \tn{xpinyin*} \oarg{options} \Arg{文字} % \end{syntax} % 对于多音字,可以使用 \tn{xpinyin} 为其设置拼音;而 \tn{xpinyin*} 相当于 % \env{pinyinscope} 环境的命令形式。\tn{xpinyin} 可以在 \env{pinyinscope} 环境和 % \tn{xpinyin*} 中使用。例如, % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.5\linewidth,gobble=5] % \xpinyin{长}{chang2}\\ % \xpinyin*{甄士隐梦幻识通灵}\\ % \xpinyin*{\xpinyin{重}{zhong4}要} % \end{SideBySideExample} % \end{function} % % \begin{function}{\pinyin} % \begin{syntax} % \tn{pinyin} \oarg{options} \Arg{拼音} % \end{syntax} % 用于输出拼音,为了输入的方便 \texttt{\"u} 可以用 |v| 代替。例如, % \begin{SideBySideExample}[frame=single,numbers=left,xrightmargin=.5\linewidth,gobble=5] % \pinyin{lv2zi}\\ % \pinyin{nv3hai2zi} % \end{SideBySideExample} % \end{function} % % \begin{function}{\setpinyin} % \begin{syntax} % \tn{setpinyin} \Arg{汉字} \Arg{拼音} % \end{syntax} % \pkg{xpinyin} 宏包的拼音数据(\file{xpinyin-database.def})来源于 \texttt{Unicode} % 的 \texttt{Unihan} 数据库\footnotemark 中的 \file{Unihan_Readings.txt} 文件。对于多 % 音字,一般来说这个文件选用的是常用读音。可以使用 \tn{setpinyin} 来设置多音字的首选读音。 % \end{function} % % \footnotetext{\url{http://www.unicode.org/Public/UNIDATA/Unihan.zip}} % % \begin{function}{\xpinyinsetup} % \begin{syntax} % \tn{xpinyinsetup} \{ \meta{key_1}=\meta{val_1}, \meta{key_2}=\meta{val_2}, ... \} % \end{syntax} % 用于在导言区或文档中,设置拼音的格式。目前可以设置的 \meta{key} 如下介绍。 % \end{function} % % \begin{function}{ratio} % \begin{syntax} % ratio = \Arg{number} % \end{syntax} % 设置拼音字体大小与当前正文字体大小的比例,缺省值是 |0.4|。 % \end{function} % % \begin{function}{vsep} % \begin{syntax} % vsep = \Arg{dimen} % \end{syntax} % 设置拼音的基线与汉字基线的间距,缺省值是 |1 em|。 % \end{function} % % \begin{function}{hsep} % \begin{syntax} % hsep = \Arg{skip} % \end{syntax} % 设置注音汉字之间的间距,缺省值与 \tn{CJKglue} 的值相同。为了断行时行末的对齐,设置 % 的 \meta{skip} 最后有一定的弹性。例如 % \begin{Example}[frame=single,numbers=left,gobble=5] % \xpinyin*[ratio={.7},hsep={.5em plus .1em},vsep={1.1em}]{贾雨村风尘怀闺秀} % \end{Example} % \end{function} % % \begin{function}{pysep} % \begin{syntax} % pysep = \Arg{glue} % \end{syntax} % 设置 \tn{pinyin} 输出的相邻两个汉语拼音的空白,缺省值是一个空格。 % \end{function} % % \begin{function}{font} % \begin{syntax} % font = \Arg{font} % \end{syntax} % 设置拼音的字体,缺省值是 \tn{normalfont},即以正文西文字体相同。为了保证拼音能正确 % 输出,最好选用收字量较大的西文字体。 % \end{function} % % \begin{function}{format} % \begin{syntax} % format = \Arg{format} % \end{syntax} % 设置拼音的其它格式,例如颜色等,缺省值为空。 % \end{function} % % \begin{function}{multiple} % \begin{syntax} % multiple = \Arg{format} % \end{syntax} % 设置多音字拼音的其它格式,缺省值为空。可以通过这个选项来提醒校正多音字的拼音。例如 % 本文档设置多音字拼音的颜色是红色(需要载入 \pkg{color} 宏包): % \begin{verbatim}[frame=single,gobble=5] % \xpinyinsetup{multiple={\color{red}}} % \end{verbatim} % \end{function} % % \begin{function}[added=2014/01/12]{footnote} % \begin{syntax} % footnote = \meta{\TFF} % \end{syntax} % 是否对拼音环境中的脚注(\tn{footnote})汉字加上拼音。缺省值为 \texttt{false}。 % 更一般的情况,请使用 \tn{disablepinyin}。 % \end{function} % % \begin{function}[added=2014/01/12]{\disablepinyin,\enablepinyin} % \tn{disablepinyin} 用于在拼音环境(\env{pinyinscope})中临时取消对汉字的注音,而 % \tn{enablepinyin} 用于其后的恢复。 % \end{function} % % \end{documentation} % % \StopEventually{} % % \begin{implementation} % % \section{代码实现} % % \begin{macrocode} %<*package> %<@@=xpinyin> % \end{macrocode} % % \begin{macrocode} \msg_new:nnn { xpinyin } { no-LuaTeX } { The~xpinyin~package~is~not~supported~in~LuaTeX.\\\\ You~must~change~your~typesetting~engine~to\\ "xelatex"~or~"pdflatex"~or~"latex"~instead~of~"lualatex". } \luatex_if_engine:T { \msg_critical:nn { xpinyin } { no-LuaTeX } } % \end{macrocode} % % \begin{macrocode} \RequirePackage { xparse } \RequirePackage { l3keys2e } % \end{macrocode} % % \begin{macro}[internal]{\c_@@_tone_prop} % 重音标记 |\`|、|\'| 和 |\=| 在 \env{tabbing} 环境中被移作他用,为避免错误, % 我们使用内部命令 \tn{@tabacckludge} 或 \tn{a} 来定义。 % \begin{macrocode} \prop_new:N \c_@@_tone_prop \clist_map_inline:nn { { ā }{ \@tabacckludge= a } , { á }{ \@tabacckludge' a } , { ǎ }{ \v a } , { à }{ \@tabacckludge` a } , { ō }{ \@tabacckludge= o } , { ó }{ \@tabacckludge' o } , { ǒ }{ \v o } , { ò }{ \@tabacckludge` o } , { ē }{ \@tabacckludge= e } , { é }{ \@tabacckludge' e } , { ě }{ \v e } , { è }{ \@tabacckludge` e } , { ū }{ \@tabacckludge= u } , { ú }{ \@tabacckludge' u } , { ǔ }{ \v u } , { ù }{ \@tabacckludge` u } , { ḿ }{ \@tabacckludge' m } , { ń }{ \@tabacckludge' n } , { ň }{ \v n } , { ǹ }{ \@tabacckludge` n } , { ī }{ \@tabacckludge= { \i } } , { í }{ \@tabacckludge' { \i } } , { ǐ }{ \v { \i } } , { ì }{ \@tabacckludge` { \i } } , { ü }{ \" u } , { ǖ }{ \@tabacckludge= { \" u } } , { ǘ }{ \@tabacckludge' { \" u } } , { ǚ }{ \v { \" u } } , { ǜ }{ \@tabacckludge` { \" u } } } { \prop_gput:Nnn \c_@@_tone_prop #1 } % \end{macrocode} % \end{macro} % % % \begin{macro}[internal]{\@@_UTF_char:nn} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_UTF_char:nn #1#2 { \cs_if_exist:cF { u8:#1 } { \tl_const:cn { u8:#1 } {#2} } } % \end{macrocode} % \end{macro} % % % \begin{macro}[internal]{\@@_GBK_char:nn} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_GBK_char:nn #1#2 { \@@_UTF_char:nn {#1} {#2} \exp_args:Nx \@@_GBK_char_aux:nn { \tl_head:n {#1} } {#1} } \cs_new_protected_nopar:Npn \@@_GBK_char_aux:nn #1#2 { \exp_args:Nf \@@_GBK_char_aux:nnn { \int_eval:n { `#1 } } {#1} {#2} } \cs_new_protected_nopar:Npn \@@_GBK_char_aux:nnn #1#2#3 { \cs_if_exist:cF { @@_UTF_ #1 :w } { \exp_args:Nf \@@_GBK_char_def:nnn { \int_case:nn { \tl_count:n {#3} } { { \c_two } { ##1 } { \c_three } { ##1##2 } { \c_four } { ##1##2##3 } } } {#1} {#2} \exp_args:Nc \@@_save_UTF_cs:Nn { @@_UTF_ #1 :w } {#1} \tl_gput_right:Nx \c_@@_reset_UTF_catcode_tl { \char_set_catcode:nn {#1} { \char_value_catcode:n {#1} } } \char_set_catcode_active:n {#1} } } \cs_new_protected_nopar:Npn \@@_GBK_char_def:nnn #1#2#3 { \cs_new_protected_nopar:cpn { @@_UTF_ #2 :w } #1 { \use:c { u8: \tl_to_str:n { #3#1 } } } } \tl_new:N \c_@@_reset_UTF_catcode_tl % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_save_UTF_cs:Nn} % \begin{macrocode} \group_begin: \char_set_catcode_active:n { 126 } \cs_new_protected_nopar:Npn \@@_save_UTF_cs:Nn #1#2 { \group_begin: \char_set_lccode:nn { 126 } {#2} \tex_lowercase:D { \group_end: \tl_gput_right:Nn \c_@@_reset_UTF_cs_tl { \cs_set_eq:NN ~ #1 } } } \group_end: \tl_new:N \c_@@_reset_UTF_cs_tl % \end{macrocode} % \end{macro} % % \begin{macrocode} \bool_new:N \g_@@_GBK_bool \@ifpackageloaded { xeCJK } { \AtEndOfPackage { \@@_adjust_xeCJK_hook: } } { \@ifpackageloaded { CJKutf8 } { \prop_map_function:NN \c_@@_tone_prop \@@_UTF_char:nn \AtEndOfPackage { \@@_adjust_CJK_hook: } } { \@ifpackageloaded { CJK } { \RequirePackage { xCJK2uni } \prop_map_function:NN \c_@@_tone_prop \@@_GBK_char:nn \AtEndOfPackage { \tl_put_right:Nn \l_@@_pinyin_box_hook_tl { \c_@@_reset_UTF_cs_tl } \@@_adjust_CJK_hook: \tl_use:N \c_@@_reset_UTF_catcode_tl } \bool_gset_true:N \g_@@_GBK_bool } { \xetex_if_engine:TF { \RequirePackage { xeCJK } \AtEndOfPackage { \@@_adjust_xeCJK_hook: } } { \RequirePackage { CJKutf8 } \prop_map_function:NN \c_@@_tone_prop \@@_UTF_char:nn \AtEndOfPackage { \@@_adjust_CJK_hook: } } } } } % \end{macrocode} % % \begin{macro}[internal,var]{\l_@@_tmpa_box,\l_@@_tmpb_box} % \begin{macrocode} \box_new:N \l_@@_tmpa_box \box_new:N \l_@@_tmpb_box % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_width:Nn} % \begin{macrocode} \cs_new_protected:Npn \@@_width:Nn #1#2 { \hbox_set:Nn \l_@@_tmpa_box {#2} #1 = \box_wd:N \l_@@_tmpa_box } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_leave_vmode:} % \begin{macrocode} \cs_if_exist:NTF \quitvmode { \cs_new_eq:NN \@@_quit_vmode: \quitvmode } { \cs_new_protected_nopar:Npn \@@_quit_vmode: { \if_mode_vertical: \exp_after:wN \tex_indent:D \fi: } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_make_pinyin_box:nnn} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_make_pinyin_box:nnn #1#2#3 { \@@_leavevmode: \hbox_overlap_right:n { \hbox_set:Nn \l_@@_tmpa_box { \@@_CJKsymbol_hook: \@@_save_CJKsymbol:n {#2} } \hbox_set:Nn \l_@@_tmpb_box { \color_group_begin: \color_ensure_current: \l_@@_pinyin_box_hook_tl \@@_select_font: \clist_if_exist:cTF { c_@@_multiple_ #1 _clist } { \l_@@_multiple_tl \l_@@_format_tl } { \l_@@_format_tl } {#3} \color_group_end: } \dim_compare:nNnT { \box_wd:N \l_@@_tmpb_box } > { \box_wd:N \l_@@_tmpa_box + \l_@@_CJKglue_dim } { \box_resize:Nnn \l_@@_tmpb_box { \box_wd:N \l_@@_tmpa_box + \l_@@_CJKglue_dim } { \box_ht:N \l_@@_tmpb_box + \box_dp:N \l_@@_tmpb_box } } \box_move_up:nn { \l_@@_vsep_tl } { \hbox_to_wd:nn { \box_wd:N \l_@@_tmpa_box } { \tex_hss:D \box_use_clear:N \l_@@_tmpb_box \tex_hss:D } } } } \tl_new:N \l_@@_pinyin_box_hook_tl \pdftex_if_engine:T { \tl_put_right:Nn \l_@@_pinyin_box_hook_tl { \cs_set_eq:NN \CJK@plane \tex_undefined:D } } \cs_generate_variant:Nn \@@_make_pinyin_box:nnn { x } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_CJKsymbol:n} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_CJKsymbol:n #1 { \@@_CJKsymbol:xn { \@@_to_unicode:n {#1} } {#1} } \cs_new_protected_nopar:Npn \@@_CJKsymbol:nn #1#2 { \@@_make_pinyin_box:nnn {#1} {#2} { \use:c { c_@@_ #1 _tl } } \@@_save_CJKsymbol:n {#2} } \cs_generate_variant:Nn \@@_CJKsymbol:nn { x } % \end{macrocode} % \end{macro} % % \begin{macro}{pinyinscope} % \begin{macrocode} \NewDocumentEnvironment { pinyinscope } { O { } } { \keys_set:nn { xpinyin } {#1} \enablepinyin } { } % \end{macrocode} % \end{macro} % % \begin{macro}{\xpinyin} % \begin{macrocode} \NewDocumentCommand \xpinyin { s O { } m } { \IfBooleanTF {#1} { \group_begin: \keys_set:nn { xpinyin } {#2} \enablepinyin #3 \group_end: } { \group_begin: \keys_set:nn { xpinyin } {#2} \bool_if:NF \l_@@_enable_bool { \@@_width:Nn \l_@@_CJKglue_dim { \CJKglue } } \@@_quit_vmode: \@@_single_aux:nn {#3} } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\l_@@_enable_bool} % \begin{macrocode} \bool_new:N \l_@@_enable_bool % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_CJKglue:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_CJKglue: { \skip_horizontal:n { \l_@@_hsep_tl } } % \end{macrocode} % \end{macro} % % \begin{macro}{\enablepinyin} % \begin{macrocode} \NewDocumentCommand \enablepinyin { } { \bool_if:NF \l_@@_enable_bool { \tl_if_empty:NF \l_@@_hsep_tl { \cs_set_eq:NN \@@_save_CJKglue: \CJKglue \cs_set_eq:NN \CJKglue \@@_CJKglue: } \@@_width:Nn \l_@@_CJKglue_dim { \CJKglue } \@@_replace_CJKsymbol: \@@_restore_footnote: \bool_set_true:N \l_@@_enable_bool } } % \end{macrocode} % \end{macro} % % \begin{macro}{\disablepinyin} % \begin{macrocode} \NewDocumentCommand \disablepinyin { } { \bool_if:NT \l_@@_enable_bool { \cs_if_eq:NNT \CJKglue \@@_CJKglue: { \cs_set_eq:NN \CJKglue \@@_save_CJKglue: } \@@_restore_CJKsymbol: \bool_set_false:N \l_@@_enable_bool } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_restore_footnote:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_restore_footnote: { \bool_if:NF \l_@@_footnote_bool { \tl_put_left:Nn \@parboxrestore { \l_@@_restore_footnote_tl } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\l_@@_restore_footnote_tl} % \begin{macrocode} \tl_new:N \l_@@_restore_footnote_tl \tl_set:Nn \l_@@_restore_footnote_tl { \int_compare:nNnT \etex_currentgrouptype:D = \c_eleven { \disablepinyin } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal,var]{\l_@@_CJKglue_dim} % \begin{macrocode} \dim_new:N \l_@@_CJKglue_dim % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_single_aux:nn} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_single_aux:nn #1#2 { \@@_replace_CJKsymbol_single:n {#2} #1 \group_end: } \cs_new_protected_nopar:Npn \@@_replace_CJKsymbol_single_aux:n #1 { \bool_if:NF \l_@@_enable_bool { \@@_replace_CJKsymbol: } \cs_set_protected_nopar:Npn \CJKsymbol ##1 { \@@_single_CJKsymbol:nn {##1} {#1} } } \cs_new_protected_nopar:Npn \@@_single_CJKsymbol:nn #1#2 { \@@_make_pinyin_box:xnn { \@@_to_unicode:n {#1} } {#1} { \@@_pinyin:n {#2} } \@@_save_CJKsymbol:n {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_replace_CJKsymbol_aux:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_replace_CJKsymbol_aux: { \cs_set_eq:NN \@@_save_CJKsymbol:n \CJKsymbol \cs_set_eq:NN \CJKsymbol \@@_CJKsymbol:n } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_restore_CJKsymbol_aux:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_restore_CJKsymbol_aux: { \cs_set_eq:NN \CJKsymbol \@@_save_CJKsymbol:n } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_select_font_xetex:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_select_font_xetex: { \cs_if_exist_use:cF { \l_@@_coor_tl } { \tl_set:Nx \l_@@_current_coor_tl { \l_@@_coor_tl } \@@_select_font_aux: \int_compare:nNnF { \XeTeXfonttype \tex_font:D } = \c_zero { \exp_last_unbraced:NNV \cs_gset_eq:cN \l_@@_current_coor_tl \tex_font:D } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_select_font_aux:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_select_font_aux: { \fontsize { \l_@@_ratio_tl \etex_dimexpr:D \f@size pt \scan_stop: } { \f@baselineskip } \normalfont \l_@@_font_tl \selectfont } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_to_unicode_xetex:n} % \begin{macrocode} \cs_new_nopar:Npn \@@_to_unicode_xetex:n #1 { \int_to_arabic:n { `#1 } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_UTF_to_unicode:n,\@@_UTFchar_to_unicode:n} % \begin{macrocode} \cs_new_nopar:Npn \@@_UTF_to_unicode:n #1 { \int_to_arabic:n { \exp_args:No \int_from_hex:n { \CJK@plane } * "100 + #1 } } \cs_new_nopar:Npn \@@_UTFchar_to_unicode:n #1 { \int_to_arabic:n { \@@_UTF_viii_to_unicode:NNNw #1 \q_stop } } \cs_new_nopar:Npn \@@_UTF_viii_to_unicode:NNNw #1#2#3#4 \q_stop { \tl_if_empty:nTF {#4} { ( `#1 - "E0 ) * "1000 + ( `#2 - "80 ) * "40 + ( `#3 - "80 ) } { ( `#1 - "F0 ) * "4000 + ( `#2 - "80 ) * "1000 + ( `#3 - "80 ) * "40 + ( `#4 - "80 ) } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_GBK_to_unicode:n,\@@_GBKchar_to_unicode:n} % \begin{macrocode} \cs_new_nopar:Npn \@@_GBK_to_unicode:n #1 { \int_to_arabic:n { " \CJKtu_sfd_map:nn { \CJK@plane } {#1} } } \cs_new_nopar:Npn \@@_GBKchar_to_unicode:n #1 { \int_to_arabic:n { " \CJKchartouni {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_adjust_xeCJK_hook:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_adjust_xeCJK_hook: { \cs_new_eq:NN \@@_select_font: \@@_select_font_xetex: \cs_new_eq:NN \@@_to_unicode:n \@@_to_unicode_xetex:n \cs_new_eq:NN \@@_char_to_unicode:n \@@_to_unicode:n \cs_new_eq:NN \@@_restore_CJKsymbol: \@@_restore_CJKsymbol_aux: \cs_new_eq:NN \@@_replace_CJKsymbol: \@@_replace_CJKsymbol_aux: \cs_new_eq:NN \@@_replace_CJKsymbol_single:n \@@_replace_CJKsymbol_single_aux:n \tl_if_exist:NTF \l_xeCJK_current_font_tl { \tl_set:Nn \l_@@_coor_tl { ( \tl_to_str:N \l_@@_font_tl ) / \l_xeCJK_current_font_tl/\l_@@_ratio_tl } } { \tl_set:Nn \l_@@_coor_tl { ( \tl_to_str:N \l_@@_font_tl ) / \xeCJK@family/\f@series/\f@shape/\f@size/\l_@@_ratio_tl } } \cs_new_eq:NN \@@_leavevmode: \prg_do_nothing: \cs_new_protected_nopar:Npx \@@_CJKsymbol_hook: { \exp_not:N \makexeCJKinactive \cs_if_exist_use:NF \xeCJK_select_font: { \exp_not:N \xeCJK@setfont } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_adjust_CJK_hook:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_adjust_CJK_hook: { \bool_if:NTF \g_@@_GBK_bool { \cs_new_eq:NN \@@_to_unicode:n \@@_GBK_to_unicode:n \cs_new_eq:NN \@@_char_to_unicode:n \@@_GBKchar_to_unicode:n } { \cs_new_eq:NN \@@_to_unicode:n \@@_UTF_to_unicode:n \cs_new_eq:NN \@@_char_to_unicode:n \@@_UTFchar_to_unicode:n } \cs_new_eq:NN \@@_select_font: \@@_select_font_aux: \cs_new_eq:NN \@@_leavevmode: \@@_quit_vmode: \cs_new_eq:NN \@@_CJKsymbol_hook: \prg_do_nothing: \@ifpackageloaded { CJKpunct } { \@@_adjust_CJKpunct_hook: } { \cs_new_eq:NN \@@_restore_CJKsymbol: \@@_restore_CJKsymbol_aux: \cs_new_eq:NN \@@_replace_CJKsymbol: \@@_replace_CJKsymbol_aux: \cs_new_eq:NN \@@_replace_CJKsymbol_single:n \@@_replace_CJKsymbol_single_aux:n \AtBeginDocument { \@ifpackageloaded { CJKpunct } { \cs_undefine:N \@@_restore_CJKsymbol: \cs_undefine:N \@@_replace_CJKsymbol: \cs_undefine:N \@@_replace_CJKsymbol_single:n \@@_adjust_CJKpunct_hook: } { } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_adjust_CJKpunct_hook:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_adjust_CJKpunct_hook: { \cs_new_protected_nopar:Npn \@@_restore_CJKsymbol: { \int_compare:nNnTF { \CJKpunct@punctstyle } = { \CJKpunct@ps@plain } { \@@_restore_CJKsymbol_aux: } { \cs_set_eq:NN \CJKosymbol \@@_save_CJKsymbol:n } } \cs_new_protected_nopar:Npn \@@_replace_CJKsymbol: { \int_compare:nNnTF { \CJKpunct@punctstyle } = { \CJKpunct@ps@plain } { \@@_replace_CJKsymbol_aux: } { \cs_set_eq:NN \@@_save_CJKsymbol:n \CJKosymbol \cs_set_eq:NN \CJKosymbol \@@_CJKsymbol:n } } \cs_new_protected_nopar:Npn \@@_replace_CJKsymbol_single:n ##1 { \int_compare:nNnTF { \CJKpunct@punctstyle } = { \CJKpunct@ps@plain } { \@@_replace_CJKsymbol_single_aux:n { ##1 } } { \bool_if:NF \l_@@_enable_bool { \cs_set_eq:NN \@@_save_CJKsymbol:n \CJKosymbol } \cs_set_protected_nopar:Npn \CJKosymbol ####1 { \@@_single_CJKsymbol:nn { ####1 } { ##1 } } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\pinyin} % \begin{macrocode} \NewDocumentCommand \pinyin { O { } m } { \group_begin: \keys_set:nn { xpinyin } {#1} \l_@@_font_tl \l_@@_format_tl { } \selectfont \c_@@_reset_UTF_cs_tl \@@_pinyin:n {#2} \group_end: } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_pinyin:n} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_pinyin:n #1 { \@@_pinyin_init: \bool_set_true:N \l_@@_first_bool \tl_set:Nn \l_@@_save_tl {#1} \@@_pinyin_aux:n #1 \q_recursion_tail \q_recursion_stop } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_pinyin_aux:n} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_pinyin_aux:n #1 { \quark_if_recursion_tail_stop_do:nn {#1} { \bool_if:NTF \l_@@_first_bool { \l_@@_save_tl } { \tl_if_empty:NF \l_@@_item_tl { \l_@@_pysep_tl \l_@@_item_tl } } } \@@_if_number:nTF {#1} { \bool_if:NTF \l_@@_first_bool { \bool_set_false:N \l_@@_first_bool } { \l_@@_pysep_tl } \l_@@_pre_tl \@@_tone:Vn \l_@@_tone_tl {#1} \l_@@_post_tl \@@_pinyin_init: } { \int_compare:nNnTF { 0 \cs_if_exist_use:c { c_@@_ \tl_to_str:N \l_@@_tone_tl _tl } } > { 0 \cs_if_exist_use:c { c_@@_ \tl_to_str:n {#1} _tl } } { \tl_put_right:Nn \l_@@_post_tl {#1} } { \tl_set:Nn \l_@@_tone_tl {#1} \tl_set_eq:NN \l_@@_pre_tl \l_@@_item_tl \tl_clear:N \l_@@_post_tl } \tl_put_right:Nx \l_@@_item_tl { \@@_replace_v:n {#1} } } \@@_pinyin_aux:n } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_tone:Nn} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_tone:Nn #1#2 { \use:c { @@_num_to_tone_ #1 :Nn } {#1} {#2} } \cs_generate_variant:Nn \@@_tone:Nn { V } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_replace_v:n} % \begin{macrocode} \cs_new_nopar:Npn \@@_replace_v:n #1 { \str_if_eq:nnTF {#1} { v } { \str_case:onTF { \l_@@_item_tl } { { l } { } { n } { } { L } { } { N } { } } { \exp_not:n { ü } } { u } } { \exp_not:n {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_pinyin_init:} % \begin{macrocode} \cs_new_nopar:Npn \@@_pinyin_init: { \tl_clear:N \l_@@_pre_tl \tl_clear:N \l_@@_post_tl \tl_clear:N \l_@@_item_tl \tl_clear:N \l_@@_tone_tl } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_if_number:nTF} % \begin{macrocode} \prg_new_conditional:Npnn \@@_if_number:n #1 { TF } { \if_int_compare:w \c_one < 1 \tl_to_str:n {#1} \exp_stop_f: \prg_return_true: \else: \prg_return_false: \fi: } % \end{macrocode} % \end{macro} % % \begin{macro}[internal,var]{\l_@@_first_bool} % \begin{macrocode} \bool_new:N \l_@@_first_bool % \end{macrocode} % \end{macro} % % \begin{macro}[internal,var] % {\c_@@_a_tl,\c_@@_o_tl,\c_@@_e_tl,\c_@@_i_tl,\c_@@_u_tl,\c_@@_v_tl} % \begin{macrocode} \tl_const:Nn \c_@@_a_tl { 3 } \tl_const:Nn \c_@@_o_tl { 2 } \tl_const:Nn \c_@@_e_tl { 2 } \tl_const:Nn \c_@@_i_tl { 1 } \tl_const:Nn \c_@@_u_tl { 1 } \tl_const:Nn \c_@@_v_tl { 1 } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\@@_num_to_tone:Nn} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_num_to_tone:Nn #1#2 { \if_case:w \int_eval:n { #2 - \c_one } \exp_stop_f: \= {#1} \or: \'{#1} \or: \v {#1} \or: \` {#1} \else: #1 \fi: } \tl_map_inline:nn { a o e u } { \cs_new_eq:cN { @@_num_to_tone_ #1 :Nn } \@@_num_to_tone:Nn } \cs_new_nopar:Npn \@@_num_to_tone_i:Nn #1#2 { \if_case:w \int_eval:n { #2 - \c_one } \exp_stop_f: ī \or: í \or: ǐ \or: ì \else: i \fi: } \cs_new_protected_nopar:Npn \@@_num_to_tone_v:Nn #1#2 { \str_case:onTF { \l_@@_pre_tl } { { l } { } { n } { } { L } { } { N } { } } { \if_case:w \int_eval:n { #2 - \c_one } \exp_stop_f: ǖ \or: ǘ \or: ǚ \or: ǜ \else: ü \fi: } { \@@_num_to_tone:Nn u {#2} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\xpinyinsetup} % \begin{macrocode} \NewDocumentCommand \xpinyinsetup { m } { \keys_set:nn { xpinyin } {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}{ratio,vsep,hsep,pysep,font,format,multiple,footnote} % \begin{macrocode} \clist_map_inline:nn { ratio , vsep , hsep , pysep , font , format , multiple } { \keys_define:nn { xpinyin } { #1 .tl_set:c = { l_@@_ #1 _tl } } } \keys_define:nn { xpinyin } { footnote .bool_set:N = \l_@@_footnote_bool } \keys_set:nn { xpinyin } { ratio = .4 , vsep = 1 em , pysep = \c_space_tl , font = \normalfont , } % \end{macrocode} % \end{macro} % % \begin{macro}[internal]{\xpinyin_customary:nnn,\xpinyin_multiple:nnn} % \begin{macrocode} \cs_new_protected_nopar:Npn \xpinyin_customary:nnn #1#2#3 { \cs_gset_nopar:cpn { c_@@_ #2 _tl } {#3} } \cs_new_protected_nopar:Npn \xpinyin_multiple:nnn #1#2#3 { \cs_gset_nopar:cpn { c_@@_multiple_ #2 _clist } {#3} } % \end{macrocode} % \end{macro} % % \begin{macrocode} \group_begin: \cs_set_eq:NN \XPYU \xpinyin_customary:nnn \cs_set_eq:NN \XPYUM \xpinyin_multiple:nnn \file_input:n { xpinyin-database.def } \group_end: % \end{macrocode} % % \begin{macro}{\setpinyin} % \begin{macrocode} \NewDocumentCommand \setpinyin { m m } { \tl_set:cn { c_@@_ \@@_char_to_unicode:n {#1} _tl } { \@@_pinyin:n {#2} } } % \end{macrocode} % \end{macro} % % \begin{macrocode} \ProcessKeysOptions { xpinyin } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \section{\pkg{xpinyin.lua}} % % \begin{macrocode} %<*lua> % \end{macrocode} % % \begin{macrocode} xpinyin = xpinyin or { } local xpinyin = xpinyin % \end{macrocode} % % 计算时区\footnote{\url{http://lua-users.org/wiki/TimeZone}}。 % \begin{macrocode} xpinyin.tzoffset = "+0000" do -- Compute the difference in seconds between local time and UTC. local function get_timezone() local now = os.time() return os.difftime(now, os.time(os.date("!*t", now))) end -- Return a timezone string in ISO 8601:2000 standard form (+hhmm or -hhmm) local function get_tzoffset(timezone) local h, m = math.modf(timezone / 3600) return string.format("%+.4d", 100 * h + 60 * m) end xpinyin.tzoffset = get_tzoffset(get_timezone()) end % \end{macrocode} % % \begin{macrocode} xpinyin = { svnid = "$Id: xpinyin.dtx 749 2014-12-24 15:05:15Z sobenlee@gmail.com $", uchar = unicode.utf8.char, readings = { }, fixreadings = { % \end{macrocode} % 为汉字“〇”增加拼音。 % \begin{macrocode} {"U+3007", "Mandarin", "líng"} }, % \end{macrocode} % % \begin{macrocode} database = { source = "http://www.unicode.org/Public/UNIDATA/Unihan.zip", file = "Unihan_Readings.txt", date = "Date: 2014-05-09 18:17:02 GMT [JHJ]", version = "Unicode version: 7.0.0", dbfile = "xpinyin.db" }, % \end{macrocode} % \pkg{DocStrip} 会将一行开头的 |%%| 替换成 \tn{MetaPrefix},因此我们在行首加了 % 空格,需要把它去掉。 % \begin{macrocode} preamble = string.gsub([[ %% %% Do not edit this file! %% Created from Unihan database: %% %% $file %% $date %% $version %% %% by "texlua xpinyin.lua" on ]] .. os.date("%Y-%m-%d %X ") .. xpinyin.tzoffset .. "\n%%", "[ ]+(%%%%)", "%1") } % \end{macrocode} % % 将 \file{Unihan_Readings.txt}^^A % \footnote{\url{http://http://www.unicode.org/reports/tr38/}。} 保存到一张表里面。 % \begin{macrocode} function xpinyin.maketable (txt) local f = io.open(txt or xpinyin.database.file, "r") if not f then local source = xpinyin.database.source local zfilename = source:match("[^/]+$") local zfile = zip.open(zfilename) if not zfile then xpinyin.download(source, zfilename) zfile = assert(zip.open(zfilename)) end f = assert(zfile:open(xpinyin.database.file)) zfile:close() end local s, prop for line in f:lines() do s = line:explode("\t") if #s == 3 then prop = s[2]:sub(2) if prop == "Mandarin" or prop == "HanyuPinyin" or prop == "XHC1983" or prop == "HanyuPinlu" then xpinyin.insert(s[1], prop, s[3]) end elseif line:find("Date") then xpinyin.database.date = line:match("^[#%s]*(.*)") elseif line:find("Unicode version:") then xpinyin.database.version = line:match("^[#%s]*(.*)") end end f:close() if xpinyin.fixreadings then for _, s in pairs(xpinyin.fixreadings) do xpinyin.insert(s[1], s[2], s[3]) end end end % \end{macrocode} % % 下载 \file{Unihan.zip}。 % \begin{macrocode} function xpinyin.download (source, zip) print("\nRetrieving Unihan Database from\n", source) local unihan_data = assert(socket.http.request(source), "download failed") local f = assert(io.open(zip, "wb"), "Unihan file (" .. zip .. ") not writable") f:write(unihan_data) f:close() end % \end{macrocode} % % 往拼音表中加入项目。 % \begin{macrocode} function xpinyin.insert (unicode, prop, value) local index = tonumber(unicode:match("%x+$"), 16) if not xpinyin.readings[index] then xpinyin.readings[index] = { } end xpinyin.readings[index][prop] = value end % \end{macrocode} % % 输出需要的格式文件。 % \begin{macrocode} function xpinyin.output (db) local f = assert(io.open(db or xpinyin.database.dbfile, "w")) local preamble = xpinyin.preamble:gsub("%$(%w+)", xpinyin.database) f:write(preamble, "\n") local hanzi, pinyin local mt = { } for index, pyt in xpinyin.pairsByKeys(xpinyin.readings) do pinyin = assert(xpinyin.grep(pyt)) hanzi = xpinyin.uchar(index) f:write("\\XPYU{", hanzi, "}{", index, "}{", pinyin, "}\n") pinyin = xpinyin.multiple(pyt) if pinyin then mt[#mt + 1] = "\\XPYUM{" .. hanzi .. "}{" .. index .. "}{" .. pinyin .."}" end end f:write(table.concat(mt, "\n"), "\n") f:close() end % \end{macrocode} % % 将表按照索引排序,代码来源于 % \href{http://www.lua.org/pil/19.3.html}{\textit{Programming in Lua}}。 % \begin{macrocode} function xpinyin.pairsByKeys (t, f) local a = { } for n in pairs(t) do a[#a + 1] = n end table.sort(a, f) local i = 0 -- iterator variable return function () -- iterator function i = i + 1 return a[i], t[a[i]] end end % \end{macrocode} % % 按照 \texttt{Mandarin}、\texttt{XHC1983}、\texttt{HanyuPinyin} % 的顺序选择最常用的拼音。\texttt{HanyuPinlu} 的质量较差,不采用。 % \begin{macrocode} function xpinyin.grep (pyt) if pyt.Mandarin then return pyt.Mandarin:match("%S+"), "Mandarin" elseif pyt.XHC1983 then return pyt.XHC1983:match(":(%S+)"), "XHC1983" elseif pyt.HanyuPinyin then return pyt.HanyuPinyin:match(":([^,%s]+)"), "HanyuPinyin" end end % \end{macrocode} % % 根据 \texttt{XHC1983} 和 \texttt{HanyuPinyin} 选出多音字。 % \begin{macrocode} function xpinyin.multiple (pyt) if pyt.XHC1983 then local s = pyt.XHC1983:explode() if s[2] then local t = { } for i, v in ipairs(s) do t[#t + 1] = v:explode(":")[2] end return xpinyin.unique(t), "XHC1983" end elseif pyt.HanyuPinyin and pyt.HanyuPinyin:find("%D,") then local t = { } for _, v in ipairs(pyt.HanyuPinyin:explode()) do for _, py in ipairs(v:explode(":")[2]:explode(",")) do t[#t + 1] = py end end return xpinyin.unique(t), "HanyuPinyin" end end % \end{macrocode} % % 删除掉数组中的重复元素。 % \begin{macrocode} function xpinyin.unique (t) local rt = xpinyin.remove_duplicate(t) if #rt > 1 then return table.concat(rt, ",") end end function xpinyin.remove_duplicate (t) local ht = { } local nt = { } for i, v in ipairs(t) do if not ht[v] then nt[#nt + 1] = v ht[v] = true end end return nt end % \end{macrocode} % % \begin{macrocode} xpinyin.maketable() % \end{macrocode} % % \begin{macrocode} xpinyin.output() % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \Finale % \endinput