I'd like to define a command, with xparse's \NewDocumentCommand, which receives a comma separated list as argument, but to be able to somehow signal that some items on that list should be treated specially.
My first thought for this was to use bracing. And I came up with something like:
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand \mylist { > { \SplitList { , } } m }
{
\tl_map_inline:nn {#1}
{
\tl_if_head_is_group:nTF {##1}
{ Hi,~I'm~special~##1! \par }
{ ##1 \par }
}
}
\ExplSyntaxOff
\begin{document}
\mylist{item1,item2,{{item3}},item4,{{item5}},item6}
\end{document}
Which prints, as expected:
And, in case I cannot rely on the extra braces being just expanded away in typesetting, as with the example above, I could go with something like:
\cs_new:Npn \__my_tl_set_unbraced:Nn #1#2
{
\tl_if_head_is_group:nTF {#2}
{ \tl_set:Nn #1 #2 }
{ \tl_set:Nn #1 {#2} }
}
after I've retrieved the "signal", and can then pass a variable set with this function as an argument for this to work as any other "non special" item on the list.
While this all works, and feels OK at first sight, I find it a little too "creative", to the point of getting weary, and got wondering if there are alternatives. Hence this question.
What I'd like to know is: is this a reasonable procedure? (from both the TeXnical and the user interface sides). Do you see any blatant caveats in it? Are there any good alternatives to it?



\tl_if_head_is_group:nTFfor this case is that both{item3}and{i}tem3will be true. Other than that, your code looks correct, but you have to be sure what syntax you want to impose on your users (assuming it's not just for personal use). I'd find using{{item}}a bit cumbersome. – Phelype Oleinik Aug 20 '21 at 02:23{i}tem3, indeed. I don't expect it to be a problem in the case, since I don't expect to get this kind of input. But well pointed. And, agreed,{{item}}is cumbersome. In a way it is the fact that I don't really like it that triggered me to ask... Do you know any good alternatives? – gusbrs Aug 20 '21 at 02:28*item(since*is already ubiquitously used to mean “treat this differently”), but then you'd need extra gymnastics to actually add an item with a*in its name because it would be confused with the marker: you'll have this problem with any marker you choose. That's why it depends quite a bit on what the list contains. A safer bet is to writeitem1,\special{item2}for a good choice on the name of the macro\special(but then that's a lot to type, so not really good either). – Phelype Oleinik Aug 20 '21 at 02:35\specialmay be safer, but I think it is more cumbersome than the double bracing, to the user, and to handle in the implementation side (as far as I can tell). – gusbrs Aug 20 '21 at 02:40\str_if_eq:eeTF { \tl_head:n {##1} } { * } { Hi,~I'm~special~\use_none:n ##1! \par } { ##1 \par }– Phelype Oleinik Aug 20 '21 at 02:46cleverefuses an "empty item" following the signaled one for the purpose, it is also good, but not ideal. Regarding*, you said it is "ubiquitously used to mean “treat this differently”". You mean here starred commands, or in this context? I personally don't recall seeing it used for this particular purpose. – gusbrs Aug 20 '21 at 02:57*(see\newcommand), and some behave in a completely different way (for example thetabularandtabular*environments), so a*seems fitting. – Phelype Oleinik Aug 20 '21 at 03:03|special item|(the|is not used in normal typesetting). – egreg Aug 20 '21 at 08:16|...|looks good indeed! – Phelype Oleinik Aug 20 '21 at 11:36{you can check if gobbling the first undelimited argument yields emptiness. If so, the entire argument is nested in braces. – Ulrich Diez Aug 20 '21 at 12:50