比较宏名称而不是含义

比较宏名称而不是含义

我想替换 XeTeX 中的 unicode 字符对,类似于国家国旗 unicode 字符。我不想指定每个选项(每个国家代码),并且希望灵活处理其他表情符号(肤色变化、其他非国家代码标志等)。上述答案中的代码的问题在于,它不允许单个可配对字符(即使我相应地修改了 False 语句)。我已经尝试解决这个问题(但部分失败了):预览并处理角色

我现在有另一个可能的解决方案,但也有缺陷:

\documentclass[varwidth,border=10pt]{standalone}
\usepackage{expl3}
\usepackage{newunicodechar}
\ExplSyntaxOn

\cs_new_protected:Npn \single_uni:n #1 { #1 }

\cs_new_protected:Nn \dual_uni:n {
    \peek_catcode:NF ## {
        #1\token_if_protected_macro:NTF \l_peek_token {+} {}
    }
}

\cs_new_protected:Nn \cyrillic:n {
    #1
}

\newunicodechar{➀}{\single_uni:n{a}}
\newunicodechar{➁}{\dual_uni:n{b}}
\newunicodechar{➂}{\dual_uni:n{c}}
\newunicodechar{И}{\cyrillic:n{x}}
% ... hundreds more single/dual_uni characters !
\begin{document}
➀\par   % a
➁\par   % b
➀➁\par  % ab
➁➀\par  % b+a
➂➀\par  % c+a
➂➁➀\par % c+b+a
➀{➁}\par    % ab
$➁$\par % b
➁И\par  % bx, NOT b+x
\end{document}

如果我输入“➁➀”,结果应该是“➁+➀”/“b+a”。如您所见,代码可以用于预期目的,但它也可以用于非预期目的:其他受保护的宏(如宏\cyrillic:n)。

我知道,我无法直接比较它们的含义,因为它们是不同的,即使它们调用相同的宏(一个是,\protected macro:->\dual_uni:n {b}另一个是\protected macro:->\dual_uni:n {c})。

有没有办法比较宏名称(所谓的没有参数的含义)像下面的(伪)代码片段?

% wishfull thinking code (instead of \token_if_protected_macro:NTF):
\token_if_eq_macro_name:NNT \l_peek_token \dual_uni:n { + }
\token_if_eq_macro_name:NNT \l_peek_token \single_uni:n { + }

答案1

Manuel 的解决方案,我能够实现以下解决方案,该解决方案基于将偷看的“宏定义中的第一个标记”与预期字符串进行比较:

\documentclass[varwidth,border=10pt]{standalone}
\usepackage{expl3}
\usepackage{newunicodechar}
\ExplSyntaxOn

\cs_new:Npn \fjs_string_first_delimit_q_nil:Nw #1 #2 \q_nil { \token_to_str:N #1 }

\cs_new:Npn \fjs_obtain_first_token:N #1 {
    \exp_after:wN \fjs_string_first_delimit_q_nil:Nw #1 xxxxxxxxx \q_nil
    \space
}

\prg_new_conditional:Npnn \fjs_tokeninside_case:Nn #1 #2 { TF, T, F } {
    \str_set:Nx \l_fjs_first_token_str {\fjs_obtain_first_token:N #1}
    \str_case_x:nnTF {\l_fjs_first_token_str} {
        #2
    } {
        \prg_return_true:
    }{
        \prg_return_false:
    }
}

\cs_new_protected:Npn \fjs_uni:N #1 { #1 }

\cs_new_protected:Nn \fjs_checkdual:N {
    \peek_catcode:NF ## {
        #1
        \token_if_macro:NT \l_peek_token {
            \fjs_tokeninside_case:NnT \l_peek_token {
                 { \fjs_uni:N } { } 
                 { \fjs_checkdual:N } { } 
            } {
                +
            }
        }
    }
}

\cs_new_protected:Nn \fjs_cyrillic:n { #1 }

\newunicodechar{➀}{\fjs_uni:N a}
\newunicodechar{➁}{\fjs_checkdual:N b}
\newunicodechar{➂}{\fjs_checkdual:N c}
\newunicodechar{И}{\fjs_cyrillic:n{x}}
% ... hundreds more single/dual_uni characters !
\begin{document}
➀\par   % a
➁\par   % b
➀➁\par  % ab
➁➀\par  % b+a
➂➀\par  % c+a
➂➁➀\par % c+b+a
➀{➁}\par    % ab
$➁$\par % b
➁И\par  % bx, NOT b+x
\end{document}

结合十六进制替换,如另一个链接问题中提到的,标题中的代码将如下所示:

\cs_new_protected:Npn \fjs_uni:N #1 { [\int_to_Hex:n { `#1 }] }
\cs_new_protected:Npn \fjs_uni:NN #1 #2 { [\int_to_Hex:n{`#1};\int_to_Hex:n{`#2}] }

\cs_new_protected:Nn \fjs_dualuni:N {
    \peek_catcode:NF ## {
        \token_if_macro:NTF \l_peek_token {
            \fjs_tokeninside_case:NnTF \l_peek_token {
                 { \fjs_uni:N } { } 
                 { \fjs_uni:NN } { } 
                 { \fjs_dualuni:N } { } 
            } {
                \fjs_uni:NN #1 
            } {
                \fjs_uni:N #1 
            }
        }{
            \fjs_uni:N #1
        }
    }
}

\cs_new_protected:Nn \fjs_cyrillic:n { #1 }

\newunicodechar{➀}{\fjs_uni:N ➀}
\newunicodechar{➁}{\fjs_dualuni:N ➁}
\newunicodechar{➂}{\fjs_dualuni:N ➂}

答案2

我不能 100% 确定这是否是您想要的,但我认为\peek_charcode:NTF可以帮助您实现它。这有帮助吗?

\documentclass{article}
\usepackage{newunicodechar,expl3}
\ExplSyntaxOn
\newunicodechar{➀}{\some_macro:n{a}}
\newunicodechar{➁}{\some_macro:n{b}}
\cs_set:Npn \some_macro_alone:n #1 {=#1=}
\cs_set:Npn \some_macro:n #1
  {
    \some_macro_alone:n {#1}
    \peek_charcode:NT ➁ { + }
  }
\ExplSyntaxOff
\begin{document}
[➀]\par
[➀{➁}]\par
[➁]\par
[➀➁]\par
\end{document}

相关内容