我想替换 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}