2

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

2 Answers 2

2

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 ➂}
4
  • 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).
    – Manuel
    Oct 23, 2017 at 18:08
  • @Manuel Thank you for your feedback. I edited it accordingly.
    – genericFJS
    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.
    – Manuel
    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
    – genericFJS
    Oct 24, 2017 at 13:15
1

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}
5
  • Thank you for your idea. Sadly, this does not work for [➁➀]. I have updated my answer, to clarify what I want.
    – genericFJS
    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 ;-)
    – genericFJS
    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.
    – Manuel
    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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.