如何得到xpinyin拼音宏包得到的拼音文本?

发布于 2021-09-28 15:00:11

最近在完善基于xpinyin拼音宏包的汉字读写练习宏包hanzibox,想通过对xpinyin宏包得到的拼音字符串分解后参考工作室的基于xpinyin宏包获取汉字的声母,韵母,声调分离拼音声母和韵母。同时,参考stone-zeng在xpinyin:包功能的模块化中给出的示例,用LaTeX3编写了如下代码:

\documentclass{ctexart}

\usepackage{xpinyin}

\ExplSyntaxOn
\NewDocumentCommand{\splitautopy}{}
  {
    \group_begin:
      \tl_gset_eq:Nc \l_pinyin_tl
        {
           c__xpinyin_ \int_to_arabic:n { `好 } _tl
        } 
      \__split_pinyin:V \l_pinyin_tl         
    \group_end:
  }
  
\NewDocumentCommand{\splitmanulpy}{}
  {
    \group_begin:
      \tl_gset:Nx \l_pinyin_tl
        {
           \pinyin{hao3}
        } 
      \__split_pinyin:V \l_pinyin_tl
    \group_end:
  }  

\tl_new:N \l_pinyin_tl
\tl_new:N \l_test_pinyin_tl
\str_new:N \l_pinyin_str

\cs_new_protected:Npn \__split_pinyin:n #1
  {
    \str_clear:N \l_pinyin_str
    \tl_clear:N  \l_test_pinyin_tl
    \tl_set:Nn \l_test_pinyin_tl {#1}

    \tl_map_inline:Nn \l_test_pinyin_tl
      {
        \str_put_right:Nn \l_pinyin_str {##1}
      }
    \str_use:N \l_pinyin_str
  }
\cs_generate_variant:Nn  \__split_pinyin:n { V }
\cs_generate_variant:Nn  \__split_pinyin:n { x }
\ExplSyntaxOff

% 正文区(有且只能有一个)
\begin{document}

\section{测试自动获取拼音}

\subsection{自动拼音}% 可以得到拼音
xpinyin宏包:\xpinyin*{好},
拼音提取:\splitautopy

\subsection{拼音调整}% 无法正确等到拼音
\setpinyin{好}{hao4}
xpinyin宏包:\xpinyin*{好},
拼音提取:\splitautopy

\section{测试手动获取拼音}% 无法得到正确的拼音
xpinyin宏包:\pinyin{hao3},
拼音提取:\splitmanulpy

\end{document}

该代码能够自动处理汉字得到的拼音,但对于使用类似\setpinyin{好}{hao4}设置的拼音及\pinyin{hao3}命令得到的拼音却无法正确解析(结果如图),不知哪位大神能帮我解决一下这个问题?

2021-09-28_14-59.png

查看更多

关注者
0
被浏览
1.6k
雾月
雾月 2021-09-29
这家伙很懒,什么也没写!

xpinpin\setpinyin{#1}{#2} 定义是

\NewDocumentCommand \setpinyin { m m }
  { 
    \tl_set:cn
      { c__xpinyin_ \__xpinyin_char_to_unicode:n {#1} _tl }
      { \__xpinyin_pinyin:n {#2} }
  }

实际上就是把 #1 的拼音定义为了 \__xpinyin_pinyin:n {#2}
因此如果用户自行设置了拼音,我们只要得到 \__xpinyin_pinyin:n {#2} 中的 #2
如果没有自行设置,我们直接使用 \tl_use:c { c__xpinyin_ \__xpinyin_char_to_unicode:n {#1} _tl } 即可。

\documentclass{ctexart}
\usepackage{xpinyin}

\begin{document}

\ExplSyntaxOn

\tl_new:N \l_pinyin_tl

\cs_new:Npn \my_get_pinyin:n #1
  {
    \tl_set_eq:Nc \l_tmpa_tl { c__xpinyin_ \__xpinyin_char_to_unicode:n {#1} _tl }
    \exp_args:No \tl_if_head_eq_meaning:nNTF { \l_tmpa_tl } \__xpinyin_pinyin:n
      { 
        \tl_set:Nf \l_pinyin_tl { \exp_after:wN \use_ii:nn \l_tmpa_tl }
        % 不使用 \tl_tail:N 是为了去掉括号
        % \tl_set:Nf \l_pinyin_tl { \tl_tail:N \l_tmpa_tl } % \l_tmpa_tl = {...}
      }
      { \tl_set_eq:NN \l_pinyin_tl \l_tmpa_tl }
  }

\my_get_pinyin:n {好}
\tl_show:N \l_pinyin_tl % = hǎo

\setpinyin{好}{hao4}

\my_get_pinyin:n {好}
\tl_show:N \l_pinyin_tl % = hao4

\ExplSyntaxOff

\end{document}

代码的含义应该是十分明显的。

xpinyin 的拼音的转化、排版是由 \__xpinyin_pinyin:n 完成的,如果其参数包含数字,就将它替换为对应的声调,如果不包含数字,直接输出(当然还包括一些其它的处理)。同时它也是不可扩展的。详细可见其源码。

\pinyin 是由 \NewDocumentCommand 定义的,由它定义的命令是不可扩展的,你这里用 \tl_set:Nx 当然只能得到原本的 \pinyin{...}。它的转化、排版也是由 \__xpinyin_pinyin:n完成的。

不过我不懂为什么要定义 \splitmanulpy 这个命令。

如果要自动获取 \xpinyin 使用的拼音,可以定义一个新命令:

\NewDocumentCommand \myxpinyin { O{} m m } % `*' 是不必要的
  {
    \tl_set:Nn \l_my_curr_char_tl {#2}
    \tl_set:Nn \l_pinyin_tl {#3}
    \xpinyin [#1] {#2} {#3}
  }

更新:

为了从 hao4 得到 hào,只要再将其转化一次,这个功能由 \my_get_pinyin_tone:n 完成。见代码

\documentclass{ctexart}
\usepackage{xpinyin}

\begin{document}

\ExplSyntaxOn

\tl_new:N \l__my_save_tl
\tl_new:N \l_pinyin_tl
\tl_new:N \l__my_pinyin_tl
\clist_const:Nn \c__my_tone_a_clist { a,ā,á,ǎ,à }
\clist_const:Nn \c__my_tone_o_clist { o,ō,ó,ǒ,ò }
\clist_const:Nn \c__my_tone_e_clist { e,ē,é,ě,è }
\clist_const:Nn \c__my_tone_u_clist { u,ū,ú,ǔ,ù }
\clist_const:Nn \c__my_tone_i_clist { i,ī,í,ǐ,ì }
\clist_const:Nn \c__my_tone_v_clist { ü,ǖ,ǘ,ǚ,ǜ }
\cs_new_protected:Npn \__my_pinyin_aux:n #1
  {
    \quark_if_recursion_tail_stop_do:nn {#1}
      {
        \bool_if:NT \l__xpinyin_first_bool
          { \tl_set:NV \l__my_pinyin_tl \l__xpinyin_item_tl } 
      }
    \__xpinyin_if_number:nTF {#1}
      {
        \bool_if:NT \l__xpinyin_first_bool
          { \bool_set_false:N \l__xpinyin_first_bool }
        \tl_put_right:NV \l__my_pinyin_tl \l__xpinyin_pre_tl
        \tl_put_right:Nx \l__my_pinyin_tl 
          { \clist_item:cn { c__my_tone_ \l__xpinyin_tone_tl _clist } {#1+1} }
        \tl_put_right:NV \l__my_pinyin_tl \l__xpinyin_post_tl
        \__xpinyin_pinyin_init:
      }
      {
        \int_compare:nNnTF
          { 0 \cs_if_exist_use:c { c__xpinyin_ \tl_to_str:N \l__xpinyin_tone_tl _tl } } >
          { 0 \cs_if_exist_use:c { c__xpinyin_ \tl_to_str:n {#1} _tl } }
          { \tl_put_right:Nn \l__xpinyin_post_tl {#1} }
          {
            \tl_set:Nn \l__xpinyin_tone_tl {#1}
            \tl_set_eq:NN \l__xpinyin_pre_tl \l__xpinyin_item_tl
            \tl_clear:N \l__xpinyin_post_tl
          }
        \tl_put_right:Nx \l__xpinyin_item_tl { \__xpinyin_replace_v:n {#1} }
      }
    \__my_pinyin_aux:n
  }
\cs_new:Npn \my_get_pinyin_tone:n #1
  {
    \tl_clear:N \l__my_pinyin_tl
    \__xpinyin_pinyin_init:
    \tl_set:Nn \l__my_save_tl {#1}
    \bool_set_true:N \l__xpinyin_first_bool
    \__my_pinyin_aux:n #1 \q_recursion_tail \q_recursion_stop
  }
\cs_new:Npn \my_get_char_pinyin:n #1
  {
    \tl_set_eq:Nc \l_tmpa_tl { c__xpinyin_ \__xpinyin_char_to_unicode:n {#1} _tl }
    \exp_args:No \tl_if_head_eq_meaning:nNTF { \l_tmpa_tl } \__xpinyin_pinyin:n
      { 
        % 不使用 \tl_tail:N 是为了去掉括号
        % \tl_set:Nf \l_pinyin_tl { \tl_tail:N \l_tmpa_tl } % \l_tmpa_tl = {...}
        % 为了得到声调, 只要再调用 \my_get_pinyin_tone:n
        \exp_args:Nf \my_get_pinyin_tone:n { \exp_after:wN \use_ii:nn \l_tmpa_tl }
        \tl_set_eq:NN \l_pinyin_tl \l__my_pinyin_tl
      }
      { \tl_set_eq:NN \l_pinyin_tl \l_tmpa_tl }
  }

\my_get_char_pinyin:n {好}
好: \l_pinyin_tl % = hǎo

\setpinyin{好}{hao4}

\my_get_char_pinyin:n {好}
好: \l_pinyin_tl % = hào

\setpinyin{男}{lan}
\my_get_char_pinyin:n {男}
男: \l_pinyin_tl % = lan

\setpinyin{女}{Lv3}
\my_get_char_pinyin:n {女}
女: \l_pinyin_tl % = Lǚ

\par
\my_get_pinyin_tone:n {hao3}
\l__my_pinyin_tl % = hǎo
\my_get_pinyin_tone:n {hào}
\l__my_pinyin_tl % = hào
\my_get_pinyin_tone:n {mei2shi4}
\l__my_pinyin_tl % = méishì
\ExplSyntaxOff

\end{document}

主要修改了 \__xpinyin_pinyin_aux:n\__xpinyin_pinyin:n 命令,使得它们将标点符号保存到 \l__my_pinyin_tl 中,而不是直接输出。

\c__..._clist 用于保存对应的声调,这样,使用 \clist_item:cn 就能从标声调的字母和数字得到带有声调的字母:a,声调3 --> ǎ。(查 表 法)

声调字母的判断使用了 \__xpinyin_pinyin_aux:n 中的判断方法。

使用 \my_get_char_pinyin:n 可以得到单个字符的拼音,它保存在 \l_pinyin_tl 中。使用 \my_get_pinyin_tone:n 可以得到带声调的拼音,它保存在 \l__my_pinyin_tl 中。因为这两个都是不可扩展的,所以必须使用一个宏来保存。

因为这个定义使用了 ǚǎ 等符号,可能无法在其它编码环境下使用,但是 XeTeX + UTF8 是可以的。

1 个回答

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览