# Compare macro names instead of meaning

I want to replace unicode character pairs in XeTeX similar to Country flags unicode char. I don't want to specify every option (every country code) and want to be flexible for other emoji (skin color variations, other non-country-code flags etc.). The problem with the code in the mentioned answer is, that it doesn't allow single pairable characters (even if I modify the False-statement accordingly). I already tried tackling this problem (but failed in part): Peek ahead and process characters

I now have another possible solution, which is flawed as well:

\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}


If I enter "➁➀" the result should be "➁+➀"/"b+a". As you can see the code works for the intended purpose, but it works for an unintended purpose, too: other protected macros (like the \cyrillic:n macro).

I know, that I can't directly compare the meanings, as they are different, even if they call the same macro (the one is \protected macro:->\dual_uni:n {b}and the other \protected macro:->\dual_uni:n {c}).

Is there a way to compare the macro names (the meaning without the parameters so to speak) like the following (pseudo-) code snippet?

% 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 { + }


With the help of a solution by Manuel, I was able to implement the following solution which is based on comparing the peeked "first token inside the definition of a macro" to the expected string:

\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}


In combination with the hex-replacement, as mentioned in the other linked question, the code in the header would look like this:

\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 ➂}

• From this I would create a function that would take care about everything about obtaining the first token inside, so the code would be clearer, and apart from that, may be the naming conventions (\l_jfs_peek_token). Oct 23, 2017 at 18:08
• @Manuel Thank you for your feedback. I edited it accordingly. Oct 24, 2017 at 6:08
• Sorry, I wrote it bad \l_jfs_peek_str should be correct. In any case, you could create your own conditional that does everything \fjs_tokeninside_case:NnTF \l_peek_token { { \fjs_uni:N } { } { \fjs_uni:NN } { } } { <true> \fjs_uni:NN #1 } { <false> \fjs_uni:N #1 } so that your code is clearer, and you separate each function and their definition. Oct 24, 2017 at 7:21
• @Manuel Thanks for your good advice. I implemented your suggestions… I hope I did the new conditional correctly :D Oct 24, 2017 at 13:15

I'm not 100% sure if this is what you're after but I think \peek_charcode:NTF can help you achieve it. Does this help?

\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}

• Thank you for your idea. Sadly, this does not work for [➁➀]. I have updated my answer, to clarify what I want. Oct 22, 2017 at 8:00
• @genericFJS — well, yes :) I can see the problem now; you don't want to have 100s of case statements inside the code! Looking for a common "head" inside the token makes sense. Your solution below gives me an idea for something similar that's been bugging me for years in unicode-math. Oct 22, 2017 at 23:22
• I wish you the best with that :-) I still feel like I cheated by comparing some strings ;-) Oct 23, 2017 at 11:31
• @WillRobertson You mean the idea of making a few macros with \macro:n {asdf} and make each of them see the next one if they have \macro:n at the beginning inside? I mean, that's not new hehehe \DOTSB and family from amsmath. Although in this case I opted to expand the macro rather than get the info from \meaning which seems to be quite difficult in the original code. Oct 23, 2017 at 18:13
• @Manuel — nothing new under the sun, of course :) I think with my own code I'll need to insert a common marker that is gobbled (or maybe \relax`) under normal conditions. I'd been ignoring this for years since the current code works, it's just a bit inelegant. So thanks for sparking the idea! Oct 25, 2017 at 0:59