Command to format any number of equations












5














I am reading many entries here on comma-separated list of arguments in new commands. I cannot get them to adapt to my needs, so here I come with my question.



I'd like a command like so:



eqsRef{equ:name_one, equ:name_two, equ:name_three} % with any number of arguments


where the 'equ:foo_bar' things are equation labels, always including the colon and often with the underscore character, which produces something equivalent to this:



Eqs.~(ref{equ:name_one}, ref{equ:name_two}, ref{equ:name_three})


but with any number of arguments. That is, which prints e.g.



Eqs. (3, 45, 62)



if the provided equation labels happen to be those equation numbers.



Bonus (not really needed but...): if only one argument is provided, then write 'Eq.~' instead of 'Eqs.~'.



I will happily accept solutions using or not using extra packages.










share|improve this question
























  • You might also look at the xstring package.
    – John Kormylo
    Nov 13 '18 at 21:01






  • 1




    Have you seen the cleveref package?
    – TeXnician
    Nov 14 '18 at 6:41
















5














I am reading many entries here on comma-separated list of arguments in new commands. I cannot get them to adapt to my needs, so here I come with my question.



I'd like a command like so:



eqsRef{equ:name_one, equ:name_two, equ:name_three} % with any number of arguments


where the 'equ:foo_bar' things are equation labels, always including the colon and often with the underscore character, which produces something equivalent to this:



Eqs.~(ref{equ:name_one}, ref{equ:name_two}, ref{equ:name_three})


but with any number of arguments. That is, which prints e.g.



Eqs. (3, 45, 62)



if the provided equation labels happen to be those equation numbers.



Bonus (not really needed but...): if only one argument is provided, then write 'Eq.~' instead of 'Eqs.~'.



I will happily accept solutions using or not using extra packages.










share|improve this question
























  • You might also look at the xstring package.
    – John Kormylo
    Nov 13 '18 at 21:01






  • 1




    Have you seen the cleveref package?
    – TeXnician
    Nov 14 '18 at 6:41














5












5








5







I am reading many entries here on comma-separated list of arguments in new commands. I cannot get them to adapt to my needs, so here I come with my question.



I'd like a command like so:



eqsRef{equ:name_one, equ:name_two, equ:name_three} % with any number of arguments


where the 'equ:foo_bar' things are equation labels, always including the colon and often with the underscore character, which produces something equivalent to this:



Eqs.~(ref{equ:name_one}, ref{equ:name_two}, ref{equ:name_three})


but with any number of arguments. That is, which prints e.g.



Eqs. (3, 45, 62)



if the provided equation labels happen to be those equation numbers.



Bonus (not really needed but...): if only one argument is provided, then write 'Eq.~' instead of 'Eqs.~'.



I will happily accept solutions using or not using extra packages.










share|improve this question















I am reading many entries here on comma-separated list of arguments in new commands. I cannot get them to adapt to my needs, so here I come with my question.



I'd like a command like so:



eqsRef{equ:name_one, equ:name_two, equ:name_three} % with any number of arguments


where the 'equ:foo_bar' things are equation labels, always including the colon and often with the underscore character, which produces something equivalent to this:



Eqs.~(ref{equ:name_one}, ref{equ:name_two}, ref{equ:name_three})


but with any number of arguments. That is, which prints e.g.



Eqs. (3, 45, 62)



if the provided equation labels happen to be those equation numbers.



Bonus (not really needed but...): if only one argument is provided, then write 'Eq.~' instead of 'Eqs.~'.



I will happily accept solutions using or not using extra packages.







macros cross-referencing comma-separated-list






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 '18 at 20:44









Werner

437k649591649




437k649591649










asked Nov 13 '18 at 20:28









Joan Solà

284




284












  • You might also look at the xstring package.
    – John Kormylo
    Nov 13 '18 at 21:01






  • 1




    Have you seen the cleveref package?
    – TeXnician
    Nov 14 '18 at 6:41


















  • You might also look at the xstring package.
    – John Kormylo
    Nov 13 '18 at 21:01






  • 1




    Have you seen the cleveref package?
    – TeXnician
    Nov 14 '18 at 6:41
















You might also look at the xstring package.
– John Kormylo
Nov 13 '18 at 21:01




You might also look at the xstring package.
– John Kormylo
Nov 13 '18 at 21:01




1




1




Have you seen the cleveref package?
– TeXnician
Nov 14 '18 at 6:41




Have you seen the cleveref package?
– TeXnician
Nov 14 '18 at 6:41










4 Answers
4






active

oldest

votes


















3














The following example defines eqsRef to take a list of <label>s and processes this list using etoolbox's docsvlist. Accommodation for pluralization is made by counting the number of <label>s used.



enter image description here



documentclass{article}

usepackage{etoolbox,amsmath}

newcounter{eqncount}

% eqsRef{<csv of labels to equations>}
newcommand{eqsRef}[1]{%
setcounter{eqncount}{0}% Restart equation counter
renewcommand*{do}[1]{stepcounter{eqncount}}% Step equation reference counter
docsvlist{#1}% Count number of equation references
Eq%
ifnumvalue{eqncount}>1
s% Plural
fi
.nobreakspace
% https://tex.stackexchange.com/a/89187/5764
defeqnrefdelim{defeqnrefdelim{, }}%
renewcommand{do}{eqnrefdelimref}%
textup{(}%
docsvlist{#1}%
textup{)}%
}

begin{document}

begin{align}
f(x) label{eqn:first} \
s(x) label{eqn:second} \
t(x) label{eqn:third} \
l(x) label{eqn:last}
end{align}

eqsRef{eqn:first, eqn:second, eqn:last}

eqsRef{eqn:third}

end{document}


The references are set inside a textup{(}...textup{)} series, meaning the parentheses will always be upright. Other formatting considerations can also be introduced, as needed.






share|improve this answer





























    5














    The input is split at commas, then a new sequence is made with each item fed as argument to ref.



    Finally the list is printed; if there is just one item, it is preceded by Eq. otherwise the list is preceded by Eqs..



    Leading or trailing spaces around items are ignored. Thus



    eqrefs{equ:name_one, equ:name_two, equ:name_three}
    eqrefs{equ:name_one,equ:name_two,equ:name_three}
    eqrefs{ equ:name_one , equ:name_two, equ:name_three }


    are equivalent.



    documentclass{article}
    usepackage{amsmath}
    usepackage{xparse}

    ExplSyntaxOn
    NewDocumentCommand{eqrefs}{m}
    {% #1 = list of labels
    joansola_eqrefs:n { #1 }
    }

    seq_new:N l__joansola_eqrefs_in_seq
    seq_new:N l__joansola_eqrefs_out_seq

    cs_new_protected:Nn joansola_eqrefs:n
    {
    seq_set_split:Nnn l__joansola_eqrefs_in_seq { , } { #1 }
    seq_set_map:NNn l__joansola_eqrefs_out_seq l__joansola_eqrefs_in_seq
    {
    exp_not:n { ref{##1} }
    }
    int_compare:nTF { seq_count:N l__joansola_eqrefs_out_seq < 2 }
    { Eq.nobreakspace }
    { Eqs.nobreakspace }
    textup{(seq_use:Nn l__joansola_eqrefs_out_seq {,~})}
    }
    ExplSyntaxOff

    begin{document}

    begin{align}
    a&=b label{equ:name_one} \
    c&=d label{equ:name_two} \
    e&=f label{equ:name_three}
    end{align}

    eqrefs{equ:name_one, equ:name_two, equ:name_three}

    eqrefs{equ:name_one, equ:name_three}

    eqrefs{equ:name_one}

    end{document}


    enter image description here






    share|improve this answer





























      3














      An approach using package xinttools, part of the xint libraries.



      documentclass{article}

      usepackage{amsmath}

      usepackage{xinttools}

      % eqsRef{<csv of labels to equations>}
      newcommand{eqsRef}[1]{%
      % First we trim from the input items leading and trailing spaces
      % The argument #1 is allowed to be a macro, say, mylist, holding
      % the values, because xintCSVtoList applies expansion to it
      % (this means the first item will also be submitted to some expansion)
      oodefeqsRefinput{xintCSVtoList{#1}}%
      % count how many items and typeset either Eq. or Eqs.
      EqifnumxintNthElt{0}{eqsRefinput}>1
      s% Plural
      fi
      .nobreakspace
      textup{(}%
      % Do now an xintFor* loop to act upon each item
      xintFor* ##1 in eqsRefinput:
      {xintifForFirst{}{xintifForLast{ and }{, }}ref{##1}}%
      textup{)}%
      }%

      begin{document}

      begin{align}
      f(x) label{eqn:first} \
      s(x) label{eqn:second} \
      t(x) label{eqn:third} \
      u(x) label{eqn:fourth} \
      l(x) label{eqn:last}
      end{align}

      eqsRef{eqn:first, eqn:third, eqn:last}

      eqsRef{eqn:third}

      end{document}


      enter image description here






      share|improve this answer





























        1














        You wish comma-list-parsing.



        Yeah!! Comma-list-parsing in (La)TeX is fun as




        • you need to take care of spaces surrounding the single items.


        • you need to take care of one pair of braces surrounding an entire single item for providing a means of masking commas and spaces that are parts of names of labels. Also be aware that you can have a "nameless" referencing-label by simply doing label{} … ref{}.


        • it always provides an opportunity of reinventing the wheel. ;-)



        I took the challenge of doing everything expandably (i.e. none of the loops etc does define temporary macros), without forbidden tokens, without if…-switches, without extensions like eTeX,
        without extra packages.



        I give no warranties.



        If you see the need of editing this post for correcting bugs/errors not related to spelling/not related to the English language but to the code, please drop me a hint. ;-)



        (Well, eh, if you see the need of editing this post for correcting bugs/errors related to spelling/related to the English language, you, of course, can drop me a hint, too. ;-) )



        documentclass{article}

        makeatletter
        %%//////////////////////////////////////////////////////////////////////////////
        %% SECTION LICENCE AND COPYRIGHT
        %%
        %% Copyright (C) 2018 by Ulrich W. Diez (ud.usenetcorrespondence@web.de)
        %%..............................................................................
        %% This work may be distributed and/or modified under the conditions of the
        %% LaTeX Project Public Licence (LPPL), either version 1.3 of this license or
        %% (at your option) any later version.
        %% (The latest version of this license is in:
        %% http://www.latex-project.org/lppl.txt
        %% and version 1.3 or later is part of all distributions of
        %% LaTeX version 1999/12/01 or later.)
        %% The author of this work is Ulrich Diez.
        %% This work has the LPPL maintenance status ‘not maintained’.
        %% Usage of any/every component of this work is at your own risk.
        %% There is no warranty — neither for probably included documentation nor for
        %% any other part/component of this work.
        %% If something breaks, you usually may keep the pieces.
        %%
        %% EOF SECTION LICENCE AND COPYRIGHT
        %%//////////////////////////////////////////////////////////////////////////////
        %%
        %%
        %%//////////////////////////////////////////////////////////////////////////////
        %% SECTION PARAPHERNALIA:
        %%
        %% UD@firstoftwo, UD@secondoftwo, UD@Exchange, UD@CheckWhetherNull,
        %% UD@CheckWhetherBlank
        %%==============================================================================
        newcommandUD@firstoftwo[2]{#1}%
        newcommandUD@secondoftwo[2]{#2}%
        newcommandUD@Exchange[2]{#2#1}%
        %%------------------------------------------------------------------------------
        %% Check whether argument is empty:
        %%..............................................................................
        %% UD@CheckWhetherNull{<Argument which is to be checked>}%
        %% {<Tokens to be delivered in case that argument
        %% which is to be checked is empty>}%
        %% {<Tokens to be delivered in case that argument
        %% which is to be checked is not empty>}%
        %%
        %% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
        %% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
        %%
        newcommandUD@CheckWhetherNull[1]{%
        romannumeral0expandafterUD@secondoftwostring{expandafter
        UD@secondoftwoexpandafter{expandafter{string#1}expandafter
        UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
        UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
        UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
        }%
        %%------------------------------------------------------------------------------
        %% Check whether argument is blank (empty or only spaces):
        %%..............................................................................
        %% -- Take advantage of the fact that TeX discards space tokens when
        %% "fetching" _un_delimited arguments: --
        %% UD@CheckWhetherBlank{<Argument which is to be checked>}%
        %% {<Tokens to be delivered in case that
        %% argument which is to be checked is blank>}%
        %% {<Tokens to be delivered in case that argument
        %% which is to be checked is not blank}%
        newcommandUD@CheckWhetherBlank[1]{%
        romannumeralexpandafterexpandafterexpandafterUD@secondoftwo
        expandafterUD@CheckWhetherNullexpandafter{UD@firstoftwo#1{}.}%
        }%
        %%
        %% EOF SECTION PARAPHERNALIA
        %%//////////////////////////////////////////////////////////////////////////////
        %%
        %%
        %%//////////////////////////////////////////////////////////////////////////////
        %% SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
        %%
        %% - REQUIRES SECTION PARAPHERNALIA.
        %%
        %% The obscure case of removing several leading/trailing spaces was taken
        %% into consideration.
        %%
        %% Removal of spaces was implemented in a way where no brace-stripping from
        %% the arguments takes place.
        %% Explicit-catcode-1/2-character-token-pairs remain untouched.
        %%
        %% Spaces interspersing the argument or hidden within braces will be left in
        %% place.
        %%
        %% The arguments themselves do not get expanded.
        %%
        %% (For some obscure reason I don't remember any more I needed this in the
        %% past.)
        %%
        %%==============================================================================
        %% Check whether brace-balanced argument starts with a space-token
        %%..............................................................................
        %% UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
        %% {<Tokens to be delivered in case <argument
        %% which is to be checked>'s 1st token is a
        %% space-token>}%
        %% {<Tokens to be delivered in case <argument
        %% which is to be checked>'s 1st token is not
        %% a space-token>}%
        newcommandUD@CheckWhetherLeadingSpace[1]{%
        romannumeral0UD@CheckWhetherNull{#1}%
        {expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
        {expandafterUD@secondoftwostring{UD@CheckWhetherLeadingSpaceB.#1 }{}}%
        }%
        newcommandUD@CheckWhetherLeadingSpaceB{}%
        longdefUD@CheckWhetherLeadingSpaceB#1 {%
        expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
        {UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
        {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
        expandafterexpandafterexpandafter}expandafterexpandafter
        expandafter}expandafterUD@secondoftwoexpandafter{string}%
        }%
        %%==============================================================================
        %% UD@TrimAllLeadSpace{<action>}{<argument>}
        %%..............................................................................
        %% expandably removes all leading spaces from <argument> in case at least
        %% one leading space is present.
        %% Then
        %% <action>{<argument without leading spaces>}
        %% is performed.
        %%==============================================================================
        newcommandUD@TrimAllLeadSpace[2]{%
        romannumeral0UD@TrimAllLeadSpaceLoop{#2}{#1}%
        }%
        newcommandUD@TrimAllLeadSpaceLoop[2]{%
        UD@CheckWhetherLeadingSpace{#1}%
        {%
        expandafterUD@TrimAllLeadSpaceLoop
        expandafter{UD@removespace#1}{#2}%
        }%
        { #2{#1}}%
        }%
        newcommandUD@removespace{}UD@firstoftwo{defUD@removespace}{} {}%
        %%==============================================================================
        %% UD@TrimAllTrailSpace{<action>}{<argument>}
        %%..............................................................................
        %% expandably removes all trailing spaces from <argument> in case at least
        %% one trailing space is present.
        %% Then
        %% <action>{<argument without trailing spaces>}
        %% is performed.
        %%==============================================================================
        newcommandUD@TrimAllTrailSpace[2]{%
        romannumeral0UD@TrimTrailSpaceLoop{#2}{#1}%
        }%
        %%------------------------------------------------------------------------------
        %% UD@TrimTrailSpaceLoop{<list of space-delimited arguments>}{<action>}
        %%..............................................................................
        %% both extracts the first space-delimited argument from the <list of space-
        %% delimited arguments> as {<current argument with one trailing space
        %% removed>} and removes it from the <list of space-delimited arguments> for
        %% obtaining the <remaining list of space delimited arguments> and passes
        %% these two things and an empty list of <arguments preceding the current
        %% argument gathered so far> and the <action> to perform at the end of the
        %% iteration to UD@CheckWhetherLastSpaceDelimitedItem.
        %%
        %% UD@CheckWhetherLastSpaceDelimitedItem in turn does choose the next
        %% action.
        newcommandUD@TrimTrailSpaceLoop[2]{%
        UD@ObtainFirstSpaceDelimitedTokenSetLoop{.#1 UD@SeLDom}{%
        expandafterUD@CheckWhetherLastSpaceDelimitedItem
        expandafter{UD@RemoveTokensTillNextSpace.#1 }%
        }{}{#2}%
        }%
        %%------------------------------------------------------------------------------
        %% Macros for UD@ObtainFirstSpaceDelimitedTokenSetLoop.
        %%
        newcommand*UD@RemoveTokensTillNextSpace{}%
        longdefUD@RemoveTokensTillNextSpace#1 {}%
        newcommand*UD@BraceStripRemoveNextSpace{}%
        longdefUD@BraceStripRemoveNextSpace#1 {#1}%
        newcommand*UD@GetFirstSpaceDelimitedTokenSet{}%
        longdefUD@GetFirstSpaceDelimitedTokenSet#1 #2UD@SeLDom{#1 }%
        newcommandUD@gobbledot{}%
        defUD@gobbledot.{}%
        %%------------------------------------------------------------------------------
        %% UD@ObtainFirstSpaceDelimitedTokenSetLoop%
        %% {<list of space delimited arguments>}%
        %% {<action>}%
        %%
        %% -> <action>{<first element of list of space delimited arguments>}%
        %%...............................................................................
        %% UD@ObtainFirstSpaceDelimitedTokenSetLoop does--without unwanted brace-re-
        %% moval--append the first space delimited argument from a
        %% <list of space delimited arguments> as brace-delimited argument behind
        %% a set of tokens given as <action>.
        newcommandUD@ObtainFirstSpaceDelimitedTokenSetLoop[1]{%
        expandafterUD@CheckWhetherNull
        expandafter{UD@RemoveTokensTillNextSpace#1}{%
        expandafterexpandafterexpandafterUD@Exchange
        expandafterexpandafterexpandafter{%
        expandafterexpandafterexpandafter{%
        expandafterUD@gobbledotUD@BraceStripRemoveNextSpace#1}}%
        }{%
        expandafterUD@ObtainFirstSpaceDelimitedTokenSetLoop
        expandafter{UD@GetFirstSpaceDelimitedTokenSet#1}%
        }%
        }%
        %%------------------------------------------------------------------------------
        %% UD@CheckWhetherLastSpaceDelimitedItem
        %% {<remaining list of space delimited arguments>}%
        %% {<current argument with one trailing space removed>}%
        %% {<arguments preceding the current argument gathered
        %% so far>}%
        %% {<action>}%
        %%..............................................................................
        %% Case 1: <remaining list of space delimited arguments> is
        %% empty.
        %% We are done: Thus:
        %% <space>% for terminating romannumeral-expansion, and
        %% <action>{<arguments preceding the current argument gathered so
        %% far><current argument with one trailing space removed>}
        %% Case 2: <remaining list of space delimited arguments> consists of a single
        %% space.
        %% A trailing space was removed. There may be more. Thus:
        %% UD@TrimTrailSpaceLoop{%
        %% <arguments preceding the current argument gathered so
        %% far><current argument with one trailing space removed>%
        %% }{<action>}%
        %% Neither case 1 nor case 2:
        %% The <current argument with one trailing space removed> is not the
        %% last argument of the list, thus:
        %% For the next iteration
        %% - attach it and a trailing space to the <arguments preceding the
        %% current argument gathered so far>,
        %% - get the first space delimited argument of the <remaining list of
        %% space delimited arguments> as <current argument with one trailing
        %% space removed>
        %% - remove that first space delimited argument from the <remaining list
        %% of space delimited arguments>
        newcommandUD@CheckWhetherLastSpaceDelimitedItem[4]{%
        UD@CheckWhetherNull{#1}{ #4{#3#2}}{%
        UD@CheckWhetherLeadingSpace{#1}{%
        expandafterUD@CheckWhetherNull
        expandafter{UD@removespace#1}{UD@firstoftwo}{UD@secondoftwo}%
        }{UD@secondoftwo}%
        {UD@TrimTrailSpaceLoop{#3#2}{#4}}%
        {%
        UD@ObtainFirstSpaceDelimitedTokenSetLoop{.#1UD@SeLDom}{%
        expandafterUD@CheckWhetherLastSpaceDelimitedItem
        expandafter{UD@RemoveTokensTillNextSpace.#1}%
        }{#3#2 }{#4}%
        }%
        }%
        }%
        %%==============================================================================
        %% UD@TrimAllSurroundSpace{<action>}{<argument>}
        %%..............................................................................
        %% expandably removes all leading and trailing spaces from <argument> in
        %% case at least one leading space is present.
        %% Then
        %% <action>{<argument without leading and trailing spaces>}
        %% is performed.
        %%==============================================================================
        newcommandUD@TrimAllSurroundSpace[2]{%
        romannumeralUD@TrimAllLeadSpace{UD@TrimAllTrailSpace{0 #1}}{#2}%
        }%
        %%
        %% EOF SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
        %%//////////////////////////////////////////////////////////////////////////////
        %%
        %%
        %%//////////////////////////////////////////////////////////////////////////////
        %% SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
        %%
        %% - REQUIRES SECTION PARAPHERNALIA.
        %% - REQUIRES SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
        %%
        %%-----------------------------------------------------------------------------
        %% Extract first inner comma-delimited argument:
        %%
        %% UD@ExtractFirstCommaArg{<action>}{<comma list>}
        %%
        %% yields:
        %%
        %% <action>{<first item/first comma-delimited argument from comma
        %% list with surrounding spaces and one level of surroundinng
        %% braces removed if present>}
        %%
        %% <comma-list> is considered a sequence of comma-delimited arguments.
        %%
        %% The <first item/first comma-delimited argument from comma list>
        %% will be extracted. The remainder of the <comma list> will be discarded.
        %%
        %% Then space tokens surrounding the <first item/first comma-delimited
        %% argument from comma list> will be removed.
        %%
        %% If removal of surrounding spaces yields emptiness, no tokens will be
        %% delivered.
        %%
        %% If removal of surrounding spaces does not yield emptiness,
        %% - one pair of braces surrounding the entire result of space-removal
        %% will be removed if present!!!!!
        %%
        %% - Then the result thereof, no matter if empty or not, will be wrapped
        %% in braces and passed on to <action>.
        %%
        %% This implies you can have <comma-delimited arguments> contain
        %% emptiness or commas and spaces by nesting them into braces.
        %%
        %% Examples:
        %%
        %% UD@ExtractFirstCommaArg{<action>}{,A,B,C,D,E} yields no token at all
        %%
        %% UD@ExtractFirstCommaArg{<action>}{{},A,B,C,D,E} yields <action>{}
        %%
        %% UD@ExtractFirstCommaArg{<action>}{A,B,C,D,E} yields <action>{A}
        %%
        %% UD@ExtractFirstCommaArg{<action>}{{AB},C,D,E} yields <action>{AB}
        %%
        %% UD@ExtractFirstCommaArg{<action>}{ AB ,C,D,E} yields <action>{AB}
        %%
        %% UD@ExtractFirstCommaArg{<action>}{ {AB} ,C,D,E} yields <action>{AB}
        %%
        %% UD@ExtractFirstCommaArg{<action>}{ { A, B } ,C,D,E} yields <action>{ A, B }
        %%
        %% UD@ExtractFirstCommaArg{<action>}{ { {AB} } ,C,D,E} yields <action>{ {AB} }
        %%
        %% Due to romannumeral0-expansion, the result will be delivered after
        %% two expansion-steps/after having UD@ExtractFirstCommaArg "hit" via
        %% two expandafter(-chains).
        %%.............................................................................
        newcommandUD@gobbletocomma{}longdefUD@gobbletocomma#1,{}%
        newcommandUD@removecomma{}longdefUD@removecomma#1,{#1}%
        newcommandUD@removebracesNrmstop[2]{%
        UD@CheckWhetherNull{#2}{%
        0 %
        }{%
        expandafterUD@Exchange
        expandafter{%
        expandafter{UD@removecomma#2,}%
        }{0 #1}%
        }%
        }%
        newcommandUD@RemoveFromCommaTillUD@SelDOm{}%
        longdefUD@RemoveFromCommaTillUD@SelDOm#1,#2UD@SelDOm{#1,}%
        newcommandUD@ExtractFirstCommaArg[2]{%
        romannumeral%
        UD@ExtractFirstCommaArgLoop{.#2,UD@SelDOm}{#1}%
        }%
        newcommandUD@ExtractFirstCommaArgLoop[2]{%
        expandafterUD@CheckWhetherNullexpandafter{UD@gobbletocomma#1}%
        {%
        expandafterexpandafterexpandafterUD@Exchange
        expandafterexpandafterexpandafter{%
        expandafterexpandafterexpandafter{%
        expandafterUD@gobbledotUD@removecomma#1}}%
        {UD@TrimAllSurroundSpace{%
        UD@removebracesNrmstop{#2}%
        }}%
        }%
        {%
        expandafterUD@ExtractFirstCommaArgLoop
        expandafter{UD@RemoveFromCommaTillUD@SelDOm#1}{#2}%
        }%
        }%
        %%
        %% EOF SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
        %%//////////////////////////////////////////////////////////////////////////////
        %%
        %%
        %%//////////////////////////////////////////////////////////////////////////////
        %% SECTION EXPANDABLE ITERATION ON LIST OF LABELS
        %%
        %% - REQUIRES SECTION PARAPHERNALIA.
        %% - REQUIRES SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
        %% - REQUIRES SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
        %%
        %% eqsRef{<comma-list>}%
        %%
        %% If <comma-list> contains only commas and/or space tokens, or is empty:
        %% yields nothing.
        %% !!! Be aware that there is no @bsphack..@esphack for this case.
        %% This implies that you will get two spaces in this case if
        %% the call to EQsref has both a leading and a trailing space,
        %% i.e., is, e.g., <space>EQsref{, ,}<space> !!!
        %%
        %% If <comma-list> contains one item:
        %% yields: Eq~(ref{<item of comma-list>})
        %%
        %% If <comma-list> contains k items; k > 1:
        %% yields:
        %% Eq~(ref{<item 1 of comma-list>}%
        %% , ref{<item 2 of comma-list>}%
        %% [...]%
        %% , ref{<item k of comma-list>})%
        %%
        %% Due to romannumeral0-expansion, the result will be delivered after two
        %% expansion-steps/after having eqsRef "hit" via two expandafter(-chains).
        %%
        newcommandeqsRef[1]{%
        romannumeralUD@eqsRefiterator{}{#1,}%
        }%
        %% UD@eqsRefiterator: #1 -- ref-calls constructed so far
        %% #2 -- (remaining) comma-list of labels
        %%
        newcommandUD@eqsRefiterator[2]{%
        UD@CheckWhetherNull{#2}{%
        UD@CheckWhetherBlank{#1}{0 }{%
        expandafterUD@CheckWhetherNull
        expandafter{UD@gobbletocomma#1,}{0 Eq}{0 Eqs}.~(#1)%
        }%
        }{%
        expandafterUD@Exchangeexpandafter{%
        expandafter{UD@gobbletocomma#2}%
        }{%
        expandafterUD@eqsRefiteratorexpandafter{%
        romannumeral0%
        expandafterexpandafterexpandafterUD@CheckWhetherNull
        expandafterexpandafterexpandafter{%
        UD@ExtractFirstCommaArg{ref}{#2}%
        }{ #1}{%
        expandafterexpandafterexpandafterUD@Exchange
        expandafterexpandafterexpandafter{%
        UD@ExtractFirstCommaArg{ref}{#2}%
        }{%
        UD@CheckWhetherNull{#1}{ }{ #1, }%
        }%
        }%
        }%
        }%
        }%
        }%
        %%
        %% EOF SECTION EXPANDABLE ITERATION ON LIST OF LABELS
        %%//////////////////////////////////////////////////////////////////////////////
        makeatother


        newcommandTestGobbleToGT{}%
        longdefTestGobbleToGT#1>{}%
        newcommandTest[1]{%
        expandafterexpandafterexpandafterdef
        expandafterexpandafterexpandaftertest
        expandafterexpandafterexpandafter{%
        #1%
        }%
        texttt{expandafterTestGobbleToGTmeaningtest}%
        parnoindenthrulefill
        }%

        begin{document}

        section*{testing texttt{stringUD@ExtractFirstCommaArg}}

        makeatletter

        noindentverb|UD@ExtractFirstCommaArg{<Action>}{,A,B,C,D,E}| yields:\
        Test{UD@ExtractFirstCommaArg{<Action>}{,A,B,C,D,E}}%

        noindentverb|UD@ExtractFirstCommaArg{<Action>}{ {} ,A,B,C,D,E}| yields:\
        Test{UD@ExtractFirstCommaArg{<Action>}{ {} ,A,B,C,D,E}}%

        noindentverb|UD@ExtractFirstCommaArg{<Action>}{{},A,B,C,D,E}| yields:\
        Test{UD@ExtractFirstCommaArg{<Action>}{{},A,B,C,D,E}}%

        noindentverb|UD@ExtractFirstCommaArg{<Action>}{A,B,C,D,E}| yields:\
        Test{UD@ExtractFirstCommaArg{<Action>}{A,B,C,D,E}}%

        noindentverb|UD@ExtractFirstCommaArg{<Action>}{{AB},C,D,E}| yields:\
        Test{UD@ExtractFirstCommaArg{<Action>}{{AB},C,D,E}}%

        noindentverb|UD@ExtractFirstCommaArg{<Action>}{ {AB} ,C,D,E}| yields:\
        Test{UD@ExtractFirstCommaArg{<Action>}{ {AB} ,C,D,E}}%

        noindentverb|UD@ExtractFirstCommaArg{<Action>}{ AB ,C,D,E}| yields:\
        Test{UD@ExtractFirstCommaArg{<Action>}{ AB ,C,D,E}}%

        noindentverb|UD@ExtractFirstCommaArg{<Action>}{ {AB},C,D,E}| yields:\
        Test{UD@ExtractFirstCommaArg{<Action>}{ {AB},C,D,E}}%

        noindentverb|UD@ExtractFirstCommaArg{<Action>}{{AB} ,C,D,E}| yields:\
        Test{UD@ExtractFirstCommaArg{<Action>}{{AB} ,C,D,E}}%

        noindentverb|UD@ExtractFirstCommaArg{<Action>}{ { A, B } ,C,D,E}| yields:\
        Test{UD@ExtractFirstCommaArg{<Action>}{ { A, B } ,C,D,E}}%

        noindentverb|UD@ExtractFirstCommaArg{<Action>}{ { {AB} } ,C,D,E}| yields:\
        Test{UD@ExtractFirstCommaArg{<Action>}{ { {AB} } ,C,D,E}}%

        makeatother

        newpage
        section*{testing texttt{stringeqsRef}}

        noindentverb|eqsRef{ A ,B, C,D ,,,E, F}| yields:\
        Test{eqsRef{ A ,B, C,D ,,,E, F}}%

        noindent
        Be aware that it is possible to have one nameless referencing-label, \
        i.e. verb|label{}| ..verb|ref{}|.\
        Here the last thing denotes the nameless label:\
        verb|eqsRef{ { A } ,B,C,{}}| yields:\
        Test{eqsRef{ { A } ,B,C,{}}}%

        noindentverb|eqsRef{ C}| yields:\
        Test{eqsRef{ C}}%

        noindentverb|eqsRef{ , }| yields:\
        Test{eqsRef{ , }}%

        noindentverb|eqsRef{ }| yields:\
        Test{eqsRef{ }}%

        noindentverb|eqsRef{}| yields:\
        Test{eqsRef{}}%

        end{document}


        enter image description hereenter image description here






        share|improve this answer























          Your Answer








          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "85"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f459841%2fcommand-to-format-any-number-of-equations%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          4 Answers
          4






          active

          oldest

          votes








          4 Answers
          4






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          3














          The following example defines eqsRef to take a list of <label>s and processes this list using etoolbox's docsvlist. Accommodation for pluralization is made by counting the number of <label>s used.



          enter image description here



          documentclass{article}

          usepackage{etoolbox,amsmath}

          newcounter{eqncount}

          % eqsRef{<csv of labels to equations>}
          newcommand{eqsRef}[1]{%
          setcounter{eqncount}{0}% Restart equation counter
          renewcommand*{do}[1]{stepcounter{eqncount}}% Step equation reference counter
          docsvlist{#1}% Count number of equation references
          Eq%
          ifnumvalue{eqncount}>1
          s% Plural
          fi
          .nobreakspace
          % https://tex.stackexchange.com/a/89187/5764
          defeqnrefdelim{defeqnrefdelim{, }}%
          renewcommand{do}{eqnrefdelimref}%
          textup{(}%
          docsvlist{#1}%
          textup{)}%
          }

          begin{document}

          begin{align}
          f(x) label{eqn:first} \
          s(x) label{eqn:second} \
          t(x) label{eqn:third} \
          l(x) label{eqn:last}
          end{align}

          eqsRef{eqn:first, eqn:second, eqn:last}

          eqsRef{eqn:third}

          end{document}


          The references are set inside a textup{(}...textup{)} series, meaning the parentheses will always be upright. Other formatting considerations can also be introduced, as needed.






          share|improve this answer


























            3














            The following example defines eqsRef to take a list of <label>s and processes this list using etoolbox's docsvlist. Accommodation for pluralization is made by counting the number of <label>s used.



            enter image description here



            documentclass{article}

            usepackage{etoolbox,amsmath}

            newcounter{eqncount}

            % eqsRef{<csv of labels to equations>}
            newcommand{eqsRef}[1]{%
            setcounter{eqncount}{0}% Restart equation counter
            renewcommand*{do}[1]{stepcounter{eqncount}}% Step equation reference counter
            docsvlist{#1}% Count number of equation references
            Eq%
            ifnumvalue{eqncount}>1
            s% Plural
            fi
            .nobreakspace
            % https://tex.stackexchange.com/a/89187/5764
            defeqnrefdelim{defeqnrefdelim{, }}%
            renewcommand{do}{eqnrefdelimref}%
            textup{(}%
            docsvlist{#1}%
            textup{)}%
            }

            begin{document}

            begin{align}
            f(x) label{eqn:first} \
            s(x) label{eqn:second} \
            t(x) label{eqn:third} \
            l(x) label{eqn:last}
            end{align}

            eqsRef{eqn:first, eqn:second, eqn:last}

            eqsRef{eqn:third}

            end{document}


            The references are set inside a textup{(}...textup{)} series, meaning the parentheses will always be upright. Other formatting considerations can also be introduced, as needed.






            share|improve this answer
























              3












              3








              3






              The following example defines eqsRef to take a list of <label>s and processes this list using etoolbox's docsvlist. Accommodation for pluralization is made by counting the number of <label>s used.



              enter image description here



              documentclass{article}

              usepackage{etoolbox,amsmath}

              newcounter{eqncount}

              % eqsRef{<csv of labels to equations>}
              newcommand{eqsRef}[1]{%
              setcounter{eqncount}{0}% Restart equation counter
              renewcommand*{do}[1]{stepcounter{eqncount}}% Step equation reference counter
              docsvlist{#1}% Count number of equation references
              Eq%
              ifnumvalue{eqncount}>1
              s% Plural
              fi
              .nobreakspace
              % https://tex.stackexchange.com/a/89187/5764
              defeqnrefdelim{defeqnrefdelim{, }}%
              renewcommand{do}{eqnrefdelimref}%
              textup{(}%
              docsvlist{#1}%
              textup{)}%
              }

              begin{document}

              begin{align}
              f(x) label{eqn:first} \
              s(x) label{eqn:second} \
              t(x) label{eqn:third} \
              l(x) label{eqn:last}
              end{align}

              eqsRef{eqn:first, eqn:second, eqn:last}

              eqsRef{eqn:third}

              end{document}


              The references are set inside a textup{(}...textup{)} series, meaning the parentheses will always be upright. Other formatting considerations can also be introduced, as needed.






              share|improve this answer












              The following example defines eqsRef to take a list of <label>s and processes this list using etoolbox's docsvlist. Accommodation for pluralization is made by counting the number of <label>s used.



              enter image description here



              documentclass{article}

              usepackage{etoolbox,amsmath}

              newcounter{eqncount}

              % eqsRef{<csv of labels to equations>}
              newcommand{eqsRef}[1]{%
              setcounter{eqncount}{0}% Restart equation counter
              renewcommand*{do}[1]{stepcounter{eqncount}}% Step equation reference counter
              docsvlist{#1}% Count number of equation references
              Eq%
              ifnumvalue{eqncount}>1
              s% Plural
              fi
              .nobreakspace
              % https://tex.stackexchange.com/a/89187/5764
              defeqnrefdelim{defeqnrefdelim{, }}%
              renewcommand{do}{eqnrefdelimref}%
              textup{(}%
              docsvlist{#1}%
              textup{)}%
              }

              begin{document}

              begin{align}
              f(x) label{eqn:first} \
              s(x) label{eqn:second} \
              t(x) label{eqn:third} \
              l(x) label{eqn:last}
              end{align}

              eqsRef{eqn:first, eqn:second, eqn:last}

              eqsRef{eqn:third}

              end{document}


              The references are set inside a textup{(}...textup{)} series, meaning the parentheses will always be upright. Other formatting considerations can also be introduced, as needed.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Nov 13 '18 at 20:43









              Werner

              437k649591649




              437k649591649























                  5














                  The input is split at commas, then a new sequence is made with each item fed as argument to ref.



                  Finally the list is printed; if there is just one item, it is preceded by Eq. otherwise the list is preceded by Eqs..



                  Leading or trailing spaces around items are ignored. Thus



                  eqrefs{equ:name_one, equ:name_two, equ:name_three}
                  eqrefs{equ:name_one,equ:name_two,equ:name_three}
                  eqrefs{ equ:name_one , equ:name_two, equ:name_three }


                  are equivalent.



                  documentclass{article}
                  usepackage{amsmath}
                  usepackage{xparse}

                  ExplSyntaxOn
                  NewDocumentCommand{eqrefs}{m}
                  {% #1 = list of labels
                  joansola_eqrefs:n { #1 }
                  }

                  seq_new:N l__joansola_eqrefs_in_seq
                  seq_new:N l__joansola_eqrefs_out_seq

                  cs_new_protected:Nn joansola_eqrefs:n
                  {
                  seq_set_split:Nnn l__joansola_eqrefs_in_seq { , } { #1 }
                  seq_set_map:NNn l__joansola_eqrefs_out_seq l__joansola_eqrefs_in_seq
                  {
                  exp_not:n { ref{##1} }
                  }
                  int_compare:nTF { seq_count:N l__joansola_eqrefs_out_seq < 2 }
                  { Eq.nobreakspace }
                  { Eqs.nobreakspace }
                  textup{(seq_use:Nn l__joansola_eqrefs_out_seq {,~})}
                  }
                  ExplSyntaxOff

                  begin{document}

                  begin{align}
                  a&=b label{equ:name_one} \
                  c&=d label{equ:name_two} \
                  e&=f label{equ:name_three}
                  end{align}

                  eqrefs{equ:name_one, equ:name_two, equ:name_three}

                  eqrefs{equ:name_one, equ:name_three}

                  eqrefs{equ:name_one}

                  end{document}


                  enter image description here






                  share|improve this answer


























                    5














                    The input is split at commas, then a new sequence is made with each item fed as argument to ref.



                    Finally the list is printed; if there is just one item, it is preceded by Eq. otherwise the list is preceded by Eqs..



                    Leading or trailing spaces around items are ignored. Thus



                    eqrefs{equ:name_one, equ:name_two, equ:name_three}
                    eqrefs{equ:name_one,equ:name_two,equ:name_three}
                    eqrefs{ equ:name_one , equ:name_two, equ:name_three }


                    are equivalent.



                    documentclass{article}
                    usepackage{amsmath}
                    usepackage{xparse}

                    ExplSyntaxOn
                    NewDocumentCommand{eqrefs}{m}
                    {% #1 = list of labels
                    joansola_eqrefs:n { #1 }
                    }

                    seq_new:N l__joansola_eqrefs_in_seq
                    seq_new:N l__joansola_eqrefs_out_seq

                    cs_new_protected:Nn joansola_eqrefs:n
                    {
                    seq_set_split:Nnn l__joansola_eqrefs_in_seq { , } { #1 }
                    seq_set_map:NNn l__joansola_eqrefs_out_seq l__joansola_eqrefs_in_seq
                    {
                    exp_not:n { ref{##1} }
                    }
                    int_compare:nTF { seq_count:N l__joansola_eqrefs_out_seq < 2 }
                    { Eq.nobreakspace }
                    { Eqs.nobreakspace }
                    textup{(seq_use:Nn l__joansola_eqrefs_out_seq {,~})}
                    }
                    ExplSyntaxOff

                    begin{document}

                    begin{align}
                    a&=b label{equ:name_one} \
                    c&=d label{equ:name_two} \
                    e&=f label{equ:name_three}
                    end{align}

                    eqrefs{equ:name_one, equ:name_two, equ:name_three}

                    eqrefs{equ:name_one, equ:name_three}

                    eqrefs{equ:name_one}

                    end{document}


                    enter image description here






                    share|improve this answer
























                      5












                      5








                      5






                      The input is split at commas, then a new sequence is made with each item fed as argument to ref.



                      Finally the list is printed; if there is just one item, it is preceded by Eq. otherwise the list is preceded by Eqs..



                      Leading or trailing spaces around items are ignored. Thus



                      eqrefs{equ:name_one, equ:name_two, equ:name_three}
                      eqrefs{equ:name_one,equ:name_two,equ:name_three}
                      eqrefs{ equ:name_one , equ:name_two, equ:name_three }


                      are equivalent.



                      documentclass{article}
                      usepackage{amsmath}
                      usepackage{xparse}

                      ExplSyntaxOn
                      NewDocumentCommand{eqrefs}{m}
                      {% #1 = list of labels
                      joansola_eqrefs:n { #1 }
                      }

                      seq_new:N l__joansola_eqrefs_in_seq
                      seq_new:N l__joansola_eqrefs_out_seq

                      cs_new_protected:Nn joansola_eqrefs:n
                      {
                      seq_set_split:Nnn l__joansola_eqrefs_in_seq { , } { #1 }
                      seq_set_map:NNn l__joansola_eqrefs_out_seq l__joansola_eqrefs_in_seq
                      {
                      exp_not:n { ref{##1} }
                      }
                      int_compare:nTF { seq_count:N l__joansola_eqrefs_out_seq < 2 }
                      { Eq.nobreakspace }
                      { Eqs.nobreakspace }
                      textup{(seq_use:Nn l__joansola_eqrefs_out_seq {,~})}
                      }
                      ExplSyntaxOff

                      begin{document}

                      begin{align}
                      a&=b label{equ:name_one} \
                      c&=d label{equ:name_two} \
                      e&=f label{equ:name_three}
                      end{align}

                      eqrefs{equ:name_one, equ:name_two, equ:name_three}

                      eqrefs{equ:name_one, equ:name_three}

                      eqrefs{equ:name_one}

                      end{document}


                      enter image description here






                      share|improve this answer












                      The input is split at commas, then a new sequence is made with each item fed as argument to ref.



                      Finally the list is printed; if there is just one item, it is preceded by Eq. otherwise the list is preceded by Eqs..



                      Leading or trailing spaces around items are ignored. Thus



                      eqrefs{equ:name_one, equ:name_two, equ:name_three}
                      eqrefs{equ:name_one,equ:name_two,equ:name_three}
                      eqrefs{ equ:name_one , equ:name_two, equ:name_three }


                      are equivalent.



                      documentclass{article}
                      usepackage{amsmath}
                      usepackage{xparse}

                      ExplSyntaxOn
                      NewDocumentCommand{eqrefs}{m}
                      {% #1 = list of labels
                      joansola_eqrefs:n { #1 }
                      }

                      seq_new:N l__joansola_eqrefs_in_seq
                      seq_new:N l__joansola_eqrefs_out_seq

                      cs_new_protected:Nn joansola_eqrefs:n
                      {
                      seq_set_split:Nnn l__joansola_eqrefs_in_seq { , } { #1 }
                      seq_set_map:NNn l__joansola_eqrefs_out_seq l__joansola_eqrefs_in_seq
                      {
                      exp_not:n { ref{##1} }
                      }
                      int_compare:nTF { seq_count:N l__joansola_eqrefs_out_seq < 2 }
                      { Eq.nobreakspace }
                      { Eqs.nobreakspace }
                      textup{(seq_use:Nn l__joansola_eqrefs_out_seq {,~})}
                      }
                      ExplSyntaxOff

                      begin{document}

                      begin{align}
                      a&=b label{equ:name_one} \
                      c&=d label{equ:name_two} \
                      e&=f label{equ:name_three}
                      end{align}

                      eqrefs{equ:name_one, equ:name_two, equ:name_three}

                      eqrefs{equ:name_one, equ:name_three}

                      eqrefs{equ:name_one}

                      end{document}


                      enter image description here







                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Nov 13 '18 at 23:29









                      egreg

                      709k8618823165




                      709k8618823165























                          3














                          An approach using package xinttools, part of the xint libraries.



                          documentclass{article}

                          usepackage{amsmath}

                          usepackage{xinttools}

                          % eqsRef{<csv of labels to equations>}
                          newcommand{eqsRef}[1]{%
                          % First we trim from the input items leading and trailing spaces
                          % The argument #1 is allowed to be a macro, say, mylist, holding
                          % the values, because xintCSVtoList applies expansion to it
                          % (this means the first item will also be submitted to some expansion)
                          oodefeqsRefinput{xintCSVtoList{#1}}%
                          % count how many items and typeset either Eq. or Eqs.
                          EqifnumxintNthElt{0}{eqsRefinput}>1
                          s% Plural
                          fi
                          .nobreakspace
                          textup{(}%
                          % Do now an xintFor* loop to act upon each item
                          xintFor* ##1 in eqsRefinput:
                          {xintifForFirst{}{xintifForLast{ and }{, }}ref{##1}}%
                          textup{)}%
                          }%

                          begin{document}

                          begin{align}
                          f(x) label{eqn:first} \
                          s(x) label{eqn:second} \
                          t(x) label{eqn:third} \
                          u(x) label{eqn:fourth} \
                          l(x) label{eqn:last}
                          end{align}

                          eqsRef{eqn:first, eqn:third, eqn:last}

                          eqsRef{eqn:third}

                          end{document}


                          enter image description here






                          share|improve this answer


























                            3














                            An approach using package xinttools, part of the xint libraries.



                            documentclass{article}

                            usepackage{amsmath}

                            usepackage{xinttools}

                            % eqsRef{<csv of labels to equations>}
                            newcommand{eqsRef}[1]{%
                            % First we trim from the input items leading and trailing spaces
                            % The argument #1 is allowed to be a macro, say, mylist, holding
                            % the values, because xintCSVtoList applies expansion to it
                            % (this means the first item will also be submitted to some expansion)
                            oodefeqsRefinput{xintCSVtoList{#1}}%
                            % count how many items and typeset either Eq. or Eqs.
                            EqifnumxintNthElt{0}{eqsRefinput}>1
                            s% Plural
                            fi
                            .nobreakspace
                            textup{(}%
                            % Do now an xintFor* loop to act upon each item
                            xintFor* ##1 in eqsRefinput:
                            {xintifForFirst{}{xintifForLast{ and }{, }}ref{##1}}%
                            textup{)}%
                            }%

                            begin{document}

                            begin{align}
                            f(x) label{eqn:first} \
                            s(x) label{eqn:second} \
                            t(x) label{eqn:third} \
                            u(x) label{eqn:fourth} \
                            l(x) label{eqn:last}
                            end{align}

                            eqsRef{eqn:first, eqn:third, eqn:last}

                            eqsRef{eqn:third}

                            end{document}


                            enter image description here






                            share|improve this answer
























                              3












                              3








                              3






                              An approach using package xinttools, part of the xint libraries.



                              documentclass{article}

                              usepackage{amsmath}

                              usepackage{xinttools}

                              % eqsRef{<csv of labels to equations>}
                              newcommand{eqsRef}[1]{%
                              % First we trim from the input items leading and trailing spaces
                              % The argument #1 is allowed to be a macro, say, mylist, holding
                              % the values, because xintCSVtoList applies expansion to it
                              % (this means the first item will also be submitted to some expansion)
                              oodefeqsRefinput{xintCSVtoList{#1}}%
                              % count how many items and typeset either Eq. or Eqs.
                              EqifnumxintNthElt{0}{eqsRefinput}>1
                              s% Plural
                              fi
                              .nobreakspace
                              textup{(}%
                              % Do now an xintFor* loop to act upon each item
                              xintFor* ##1 in eqsRefinput:
                              {xintifForFirst{}{xintifForLast{ and }{, }}ref{##1}}%
                              textup{)}%
                              }%

                              begin{document}

                              begin{align}
                              f(x) label{eqn:first} \
                              s(x) label{eqn:second} \
                              t(x) label{eqn:third} \
                              u(x) label{eqn:fourth} \
                              l(x) label{eqn:last}
                              end{align}

                              eqsRef{eqn:first, eqn:third, eqn:last}

                              eqsRef{eqn:third}

                              end{document}


                              enter image description here






                              share|improve this answer












                              An approach using package xinttools, part of the xint libraries.



                              documentclass{article}

                              usepackage{amsmath}

                              usepackage{xinttools}

                              % eqsRef{<csv of labels to equations>}
                              newcommand{eqsRef}[1]{%
                              % First we trim from the input items leading and trailing spaces
                              % The argument #1 is allowed to be a macro, say, mylist, holding
                              % the values, because xintCSVtoList applies expansion to it
                              % (this means the first item will also be submitted to some expansion)
                              oodefeqsRefinput{xintCSVtoList{#1}}%
                              % count how many items and typeset either Eq. or Eqs.
                              EqifnumxintNthElt{0}{eqsRefinput}>1
                              s% Plural
                              fi
                              .nobreakspace
                              textup{(}%
                              % Do now an xintFor* loop to act upon each item
                              xintFor* ##1 in eqsRefinput:
                              {xintifForFirst{}{xintifForLast{ and }{, }}ref{##1}}%
                              textup{)}%
                              }%

                              begin{document}

                              begin{align}
                              f(x) label{eqn:first} \
                              s(x) label{eqn:second} \
                              t(x) label{eqn:third} \
                              u(x) label{eqn:fourth} \
                              l(x) label{eqn:last}
                              end{align}

                              eqsRef{eqn:first, eqn:third, eqn:last}

                              eqsRef{eqn:third}

                              end{document}


                              enter image description here







                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered Nov 14 '18 at 13:34









                              jfbu

                              46k66148




                              46k66148























                                  1














                                  You wish comma-list-parsing.



                                  Yeah!! Comma-list-parsing in (La)TeX is fun as




                                  • you need to take care of spaces surrounding the single items.


                                  • you need to take care of one pair of braces surrounding an entire single item for providing a means of masking commas and spaces that are parts of names of labels. Also be aware that you can have a "nameless" referencing-label by simply doing label{} … ref{}.


                                  • it always provides an opportunity of reinventing the wheel. ;-)



                                  I took the challenge of doing everything expandably (i.e. none of the loops etc does define temporary macros), without forbidden tokens, without if…-switches, without extensions like eTeX,
                                  without extra packages.



                                  I give no warranties.



                                  If you see the need of editing this post for correcting bugs/errors not related to spelling/not related to the English language but to the code, please drop me a hint. ;-)



                                  (Well, eh, if you see the need of editing this post for correcting bugs/errors related to spelling/related to the English language, you, of course, can drop me a hint, too. ;-) )



                                  documentclass{article}

                                  makeatletter
                                  %%//////////////////////////////////////////////////////////////////////////////
                                  %% SECTION LICENCE AND COPYRIGHT
                                  %%
                                  %% Copyright (C) 2018 by Ulrich W. Diez (ud.usenetcorrespondence@web.de)
                                  %%..............................................................................
                                  %% This work may be distributed and/or modified under the conditions of the
                                  %% LaTeX Project Public Licence (LPPL), either version 1.3 of this license or
                                  %% (at your option) any later version.
                                  %% (The latest version of this license is in:
                                  %% http://www.latex-project.org/lppl.txt
                                  %% and version 1.3 or later is part of all distributions of
                                  %% LaTeX version 1999/12/01 or later.)
                                  %% The author of this work is Ulrich Diez.
                                  %% This work has the LPPL maintenance status ‘not maintained’.
                                  %% Usage of any/every component of this work is at your own risk.
                                  %% There is no warranty — neither for probably included documentation nor for
                                  %% any other part/component of this work.
                                  %% If something breaks, you usually may keep the pieces.
                                  %%
                                  %% EOF SECTION LICENCE AND COPYRIGHT
                                  %%//////////////////////////////////////////////////////////////////////////////
                                  %%
                                  %%
                                  %%//////////////////////////////////////////////////////////////////////////////
                                  %% SECTION PARAPHERNALIA:
                                  %%
                                  %% UD@firstoftwo, UD@secondoftwo, UD@Exchange, UD@CheckWhetherNull,
                                  %% UD@CheckWhetherBlank
                                  %%==============================================================================
                                  newcommandUD@firstoftwo[2]{#1}%
                                  newcommandUD@secondoftwo[2]{#2}%
                                  newcommandUD@Exchange[2]{#2#1}%
                                  %%------------------------------------------------------------------------------
                                  %% Check whether argument is empty:
                                  %%..............................................................................
                                  %% UD@CheckWhetherNull{<Argument which is to be checked>}%
                                  %% {<Tokens to be delivered in case that argument
                                  %% which is to be checked is empty>}%
                                  %% {<Tokens to be delivered in case that argument
                                  %% which is to be checked is not empty>}%
                                  %%
                                  %% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
                                  %% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
                                  %%
                                  newcommandUD@CheckWhetherNull[1]{%
                                  romannumeral0expandafterUD@secondoftwostring{expandafter
                                  UD@secondoftwoexpandafter{expandafter{string#1}expandafter
                                  UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
                                  UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
                                  UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
                                  }%
                                  %%------------------------------------------------------------------------------
                                  %% Check whether argument is blank (empty or only spaces):
                                  %%..............................................................................
                                  %% -- Take advantage of the fact that TeX discards space tokens when
                                  %% "fetching" _un_delimited arguments: --
                                  %% UD@CheckWhetherBlank{<Argument which is to be checked>}%
                                  %% {<Tokens to be delivered in case that
                                  %% argument which is to be checked is blank>}%
                                  %% {<Tokens to be delivered in case that argument
                                  %% which is to be checked is not blank}%
                                  newcommandUD@CheckWhetherBlank[1]{%
                                  romannumeralexpandafterexpandafterexpandafterUD@secondoftwo
                                  expandafterUD@CheckWhetherNullexpandafter{UD@firstoftwo#1{}.}%
                                  }%
                                  %%
                                  %% EOF SECTION PARAPHERNALIA
                                  %%//////////////////////////////////////////////////////////////////////////////
                                  %%
                                  %%
                                  %%//////////////////////////////////////////////////////////////////////////////
                                  %% SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                  %%
                                  %% - REQUIRES SECTION PARAPHERNALIA.
                                  %%
                                  %% The obscure case of removing several leading/trailing spaces was taken
                                  %% into consideration.
                                  %%
                                  %% Removal of spaces was implemented in a way where no brace-stripping from
                                  %% the arguments takes place.
                                  %% Explicit-catcode-1/2-character-token-pairs remain untouched.
                                  %%
                                  %% Spaces interspersing the argument or hidden within braces will be left in
                                  %% place.
                                  %%
                                  %% The arguments themselves do not get expanded.
                                  %%
                                  %% (For some obscure reason I don't remember any more I needed this in the
                                  %% past.)
                                  %%
                                  %%==============================================================================
                                  %% Check whether brace-balanced argument starts with a space-token
                                  %%..............................................................................
                                  %% UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
                                  %% {<Tokens to be delivered in case <argument
                                  %% which is to be checked>'s 1st token is a
                                  %% space-token>}%
                                  %% {<Tokens to be delivered in case <argument
                                  %% which is to be checked>'s 1st token is not
                                  %% a space-token>}%
                                  newcommandUD@CheckWhetherLeadingSpace[1]{%
                                  romannumeral0UD@CheckWhetherNull{#1}%
                                  {expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
                                  {expandafterUD@secondoftwostring{UD@CheckWhetherLeadingSpaceB.#1 }{}}%
                                  }%
                                  newcommandUD@CheckWhetherLeadingSpaceB{}%
                                  longdefUD@CheckWhetherLeadingSpaceB#1 {%
                                  expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
                                  {UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
                                  {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
                                  expandafterexpandafterexpandafter}expandafterexpandafter
                                  expandafter}expandafterUD@secondoftwoexpandafter{string}%
                                  }%
                                  %%==============================================================================
                                  %% UD@TrimAllLeadSpace{<action>}{<argument>}
                                  %%..............................................................................
                                  %% expandably removes all leading spaces from <argument> in case at least
                                  %% one leading space is present.
                                  %% Then
                                  %% <action>{<argument without leading spaces>}
                                  %% is performed.
                                  %%==============================================================================
                                  newcommandUD@TrimAllLeadSpace[2]{%
                                  romannumeral0UD@TrimAllLeadSpaceLoop{#2}{#1}%
                                  }%
                                  newcommandUD@TrimAllLeadSpaceLoop[2]{%
                                  UD@CheckWhetherLeadingSpace{#1}%
                                  {%
                                  expandafterUD@TrimAllLeadSpaceLoop
                                  expandafter{UD@removespace#1}{#2}%
                                  }%
                                  { #2{#1}}%
                                  }%
                                  newcommandUD@removespace{}UD@firstoftwo{defUD@removespace}{} {}%
                                  %%==============================================================================
                                  %% UD@TrimAllTrailSpace{<action>}{<argument>}
                                  %%..............................................................................
                                  %% expandably removes all trailing spaces from <argument> in case at least
                                  %% one trailing space is present.
                                  %% Then
                                  %% <action>{<argument without trailing spaces>}
                                  %% is performed.
                                  %%==============================================================================
                                  newcommandUD@TrimAllTrailSpace[2]{%
                                  romannumeral0UD@TrimTrailSpaceLoop{#2}{#1}%
                                  }%
                                  %%------------------------------------------------------------------------------
                                  %% UD@TrimTrailSpaceLoop{<list of space-delimited arguments>}{<action>}
                                  %%..............................................................................
                                  %% both extracts the first space-delimited argument from the <list of space-
                                  %% delimited arguments> as {<current argument with one trailing space
                                  %% removed>} and removes it from the <list of space-delimited arguments> for
                                  %% obtaining the <remaining list of space delimited arguments> and passes
                                  %% these two things and an empty list of <arguments preceding the current
                                  %% argument gathered so far> and the <action> to perform at the end of the
                                  %% iteration to UD@CheckWhetherLastSpaceDelimitedItem.
                                  %%
                                  %% UD@CheckWhetherLastSpaceDelimitedItem in turn does choose the next
                                  %% action.
                                  newcommandUD@TrimTrailSpaceLoop[2]{%
                                  UD@ObtainFirstSpaceDelimitedTokenSetLoop{.#1 UD@SeLDom}{%
                                  expandafterUD@CheckWhetherLastSpaceDelimitedItem
                                  expandafter{UD@RemoveTokensTillNextSpace.#1 }%
                                  }{}{#2}%
                                  }%
                                  %%------------------------------------------------------------------------------
                                  %% Macros for UD@ObtainFirstSpaceDelimitedTokenSetLoop.
                                  %%
                                  newcommand*UD@RemoveTokensTillNextSpace{}%
                                  longdefUD@RemoveTokensTillNextSpace#1 {}%
                                  newcommand*UD@BraceStripRemoveNextSpace{}%
                                  longdefUD@BraceStripRemoveNextSpace#1 {#1}%
                                  newcommand*UD@GetFirstSpaceDelimitedTokenSet{}%
                                  longdefUD@GetFirstSpaceDelimitedTokenSet#1 #2UD@SeLDom{#1 }%
                                  newcommandUD@gobbledot{}%
                                  defUD@gobbledot.{}%
                                  %%------------------------------------------------------------------------------
                                  %% UD@ObtainFirstSpaceDelimitedTokenSetLoop%
                                  %% {<list of space delimited arguments>}%
                                  %% {<action>}%
                                  %%
                                  %% -> <action>{<first element of list of space delimited arguments>}%
                                  %%...............................................................................
                                  %% UD@ObtainFirstSpaceDelimitedTokenSetLoop does--without unwanted brace-re-
                                  %% moval--append the first space delimited argument from a
                                  %% <list of space delimited arguments> as brace-delimited argument behind
                                  %% a set of tokens given as <action>.
                                  newcommandUD@ObtainFirstSpaceDelimitedTokenSetLoop[1]{%
                                  expandafterUD@CheckWhetherNull
                                  expandafter{UD@RemoveTokensTillNextSpace#1}{%
                                  expandafterexpandafterexpandafterUD@Exchange
                                  expandafterexpandafterexpandafter{%
                                  expandafterexpandafterexpandafter{%
                                  expandafterUD@gobbledotUD@BraceStripRemoveNextSpace#1}}%
                                  }{%
                                  expandafterUD@ObtainFirstSpaceDelimitedTokenSetLoop
                                  expandafter{UD@GetFirstSpaceDelimitedTokenSet#1}%
                                  }%
                                  }%
                                  %%------------------------------------------------------------------------------
                                  %% UD@CheckWhetherLastSpaceDelimitedItem
                                  %% {<remaining list of space delimited arguments>}%
                                  %% {<current argument with one trailing space removed>}%
                                  %% {<arguments preceding the current argument gathered
                                  %% so far>}%
                                  %% {<action>}%
                                  %%..............................................................................
                                  %% Case 1: <remaining list of space delimited arguments> is
                                  %% empty.
                                  %% We are done: Thus:
                                  %% <space>% for terminating romannumeral-expansion, and
                                  %% <action>{<arguments preceding the current argument gathered so
                                  %% far><current argument with one trailing space removed>}
                                  %% Case 2: <remaining list of space delimited arguments> consists of a single
                                  %% space.
                                  %% A trailing space was removed. There may be more. Thus:
                                  %% UD@TrimTrailSpaceLoop{%
                                  %% <arguments preceding the current argument gathered so
                                  %% far><current argument with one trailing space removed>%
                                  %% }{<action>}%
                                  %% Neither case 1 nor case 2:
                                  %% The <current argument with one trailing space removed> is not the
                                  %% last argument of the list, thus:
                                  %% For the next iteration
                                  %% - attach it and a trailing space to the <arguments preceding the
                                  %% current argument gathered so far>,
                                  %% - get the first space delimited argument of the <remaining list of
                                  %% space delimited arguments> as <current argument with one trailing
                                  %% space removed>
                                  %% - remove that first space delimited argument from the <remaining list
                                  %% of space delimited arguments>
                                  newcommandUD@CheckWhetherLastSpaceDelimitedItem[4]{%
                                  UD@CheckWhetherNull{#1}{ #4{#3#2}}{%
                                  UD@CheckWhetherLeadingSpace{#1}{%
                                  expandafterUD@CheckWhetherNull
                                  expandafter{UD@removespace#1}{UD@firstoftwo}{UD@secondoftwo}%
                                  }{UD@secondoftwo}%
                                  {UD@TrimTrailSpaceLoop{#3#2}{#4}}%
                                  {%
                                  UD@ObtainFirstSpaceDelimitedTokenSetLoop{.#1UD@SeLDom}{%
                                  expandafterUD@CheckWhetherLastSpaceDelimitedItem
                                  expandafter{UD@RemoveTokensTillNextSpace.#1}%
                                  }{#3#2 }{#4}%
                                  }%
                                  }%
                                  }%
                                  %%==============================================================================
                                  %% UD@TrimAllSurroundSpace{<action>}{<argument>}
                                  %%..............................................................................
                                  %% expandably removes all leading and trailing spaces from <argument> in
                                  %% case at least one leading space is present.
                                  %% Then
                                  %% <action>{<argument without leading and trailing spaces>}
                                  %% is performed.
                                  %%==============================================================================
                                  newcommandUD@TrimAllSurroundSpace[2]{%
                                  romannumeralUD@TrimAllLeadSpace{UD@TrimAllTrailSpace{0 #1}}{#2}%
                                  }%
                                  %%
                                  %% EOF SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                  %%//////////////////////////////////////////////////////////////////////////////
                                  %%
                                  %%
                                  %%//////////////////////////////////////////////////////////////////////////////
                                  %% SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
                                  %%
                                  %% - REQUIRES SECTION PARAPHERNALIA.
                                  %% - REQUIRES SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                  %%
                                  %%-----------------------------------------------------------------------------
                                  %% Extract first inner comma-delimited argument:
                                  %%
                                  %% UD@ExtractFirstCommaArg{<action>}{<comma list>}
                                  %%
                                  %% yields:
                                  %%
                                  %% <action>{<first item/first comma-delimited argument from comma
                                  %% list with surrounding spaces and one level of surroundinng
                                  %% braces removed if present>}
                                  %%
                                  %% <comma-list> is considered a sequence of comma-delimited arguments.
                                  %%
                                  %% The <first item/first comma-delimited argument from comma list>
                                  %% will be extracted. The remainder of the <comma list> will be discarded.
                                  %%
                                  %% Then space tokens surrounding the <first item/first comma-delimited
                                  %% argument from comma list> will be removed.
                                  %%
                                  %% If removal of surrounding spaces yields emptiness, no tokens will be
                                  %% delivered.
                                  %%
                                  %% If removal of surrounding spaces does not yield emptiness,
                                  %% - one pair of braces surrounding the entire result of space-removal
                                  %% will be removed if present!!!!!
                                  %%
                                  %% - Then the result thereof, no matter if empty or not, will be wrapped
                                  %% in braces and passed on to <action>.
                                  %%
                                  %% This implies you can have <comma-delimited arguments> contain
                                  %% emptiness or commas and spaces by nesting them into braces.
                                  %%
                                  %% Examples:
                                  %%
                                  %% UD@ExtractFirstCommaArg{<action>}{,A,B,C,D,E} yields no token at all
                                  %%
                                  %% UD@ExtractFirstCommaArg{<action>}{{},A,B,C,D,E} yields <action>{}
                                  %%
                                  %% UD@ExtractFirstCommaArg{<action>}{A,B,C,D,E} yields <action>{A}
                                  %%
                                  %% UD@ExtractFirstCommaArg{<action>}{{AB},C,D,E} yields <action>{AB}
                                  %%
                                  %% UD@ExtractFirstCommaArg{<action>}{ AB ,C,D,E} yields <action>{AB}
                                  %%
                                  %% UD@ExtractFirstCommaArg{<action>}{ {AB} ,C,D,E} yields <action>{AB}
                                  %%
                                  %% UD@ExtractFirstCommaArg{<action>}{ { A, B } ,C,D,E} yields <action>{ A, B }
                                  %%
                                  %% UD@ExtractFirstCommaArg{<action>}{ { {AB} } ,C,D,E} yields <action>{ {AB} }
                                  %%
                                  %% Due to romannumeral0-expansion, the result will be delivered after
                                  %% two expansion-steps/after having UD@ExtractFirstCommaArg "hit" via
                                  %% two expandafter(-chains).
                                  %%.............................................................................
                                  newcommandUD@gobbletocomma{}longdefUD@gobbletocomma#1,{}%
                                  newcommandUD@removecomma{}longdefUD@removecomma#1,{#1}%
                                  newcommandUD@removebracesNrmstop[2]{%
                                  UD@CheckWhetherNull{#2}{%
                                  0 %
                                  }{%
                                  expandafterUD@Exchange
                                  expandafter{%
                                  expandafter{UD@removecomma#2,}%
                                  }{0 #1}%
                                  }%
                                  }%
                                  newcommandUD@RemoveFromCommaTillUD@SelDOm{}%
                                  longdefUD@RemoveFromCommaTillUD@SelDOm#1,#2UD@SelDOm{#1,}%
                                  newcommandUD@ExtractFirstCommaArg[2]{%
                                  romannumeral%
                                  UD@ExtractFirstCommaArgLoop{.#2,UD@SelDOm}{#1}%
                                  }%
                                  newcommandUD@ExtractFirstCommaArgLoop[2]{%
                                  expandafterUD@CheckWhetherNullexpandafter{UD@gobbletocomma#1}%
                                  {%
                                  expandafterexpandafterexpandafterUD@Exchange
                                  expandafterexpandafterexpandafter{%
                                  expandafterexpandafterexpandafter{%
                                  expandafterUD@gobbledotUD@removecomma#1}}%
                                  {UD@TrimAllSurroundSpace{%
                                  UD@removebracesNrmstop{#2}%
                                  }}%
                                  }%
                                  {%
                                  expandafterUD@ExtractFirstCommaArgLoop
                                  expandafter{UD@RemoveFromCommaTillUD@SelDOm#1}{#2}%
                                  }%
                                  }%
                                  %%
                                  %% EOF SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
                                  %%//////////////////////////////////////////////////////////////////////////////
                                  %%
                                  %%
                                  %%//////////////////////////////////////////////////////////////////////////////
                                  %% SECTION EXPANDABLE ITERATION ON LIST OF LABELS
                                  %%
                                  %% - REQUIRES SECTION PARAPHERNALIA.
                                  %% - REQUIRES SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                  %% - REQUIRES SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
                                  %%
                                  %% eqsRef{<comma-list>}%
                                  %%
                                  %% If <comma-list> contains only commas and/or space tokens, or is empty:
                                  %% yields nothing.
                                  %% !!! Be aware that there is no @bsphack..@esphack for this case.
                                  %% This implies that you will get two spaces in this case if
                                  %% the call to EQsref has both a leading and a trailing space,
                                  %% i.e., is, e.g., <space>EQsref{, ,}<space> !!!
                                  %%
                                  %% If <comma-list> contains one item:
                                  %% yields: Eq~(ref{<item of comma-list>})
                                  %%
                                  %% If <comma-list> contains k items; k > 1:
                                  %% yields:
                                  %% Eq~(ref{<item 1 of comma-list>}%
                                  %% , ref{<item 2 of comma-list>}%
                                  %% [...]%
                                  %% , ref{<item k of comma-list>})%
                                  %%
                                  %% Due to romannumeral0-expansion, the result will be delivered after two
                                  %% expansion-steps/after having eqsRef "hit" via two expandafter(-chains).
                                  %%
                                  newcommandeqsRef[1]{%
                                  romannumeralUD@eqsRefiterator{}{#1,}%
                                  }%
                                  %% UD@eqsRefiterator: #1 -- ref-calls constructed so far
                                  %% #2 -- (remaining) comma-list of labels
                                  %%
                                  newcommandUD@eqsRefiterator[2]{%
                                  UD@CheckWhetherNull{#2}{%
                                  UD@CheckWhetherBlank{#1}{0 }{%
                                  expandafterUD@CheckWhetherNull
                                  expandafter{UD@gobbletocomma#1,}{0 Eq}{0 Eqs}.~(#1)%
                                  }%
                                  }{%
                                  expandafterUD@Exchangeexpandafter{%
                                  expandafter{UD@gobbletocomma#2}%
                                  }{%
                                  expandafterUD@eqsRefiteratorexpandafter{%
                                  romannumeral0%
                                  expandafterexpandafterexpandafterUD@CheckWhetherNull
                                  expandafterexpandafterexpandafter{%
                                  UD@ExtractFirstCommaArg{ref}{#2}%
                                  }{ #1}{%
                                  expandafterexpandafterexpandafterUD@Exchange
                                  expandafterexpandafterexpandafter{%
                                  UD@ExtractFirstCommaArg{ref}{#2}%
                                  }{%
                                  UD@CheckWhetherNull{#1}{ }{ #1, }%
                                  }%
                                  }%
                                  }%
                                  }%
                                  }%
                                  }%
                                  %%
                                  %% EOF SECTION EXPANDABLE ITERATION ON LIST OF LABELS
                                  %%//////////////////////////////////////////////////////////////////////////////
                                  makeatother


                                  newcommandTestGobbleToGT{}%
                                  longdefTestGobbleToGT#1>{}%
                                  newcommandTest[1]{%
                                  expandafterexpandafterexpandafterdef
                                  expandafterexpandafterexpandaftertest
                                  expandafterexpandafterexpandafter{%
                                  #1%
                                  }%
                                  texttt{expandafterTestGobbleToGTmeaningtest}%
                                  parnoindenthrulefill
                                  }%

                                  begin{document}

                                  section*{testing texttt{stringUD@ExtractFirstCommaArg}}

                                  makeatletter

                                  noindentverb|UD@ExtractFirstCommaArg{<Action>}{,A,B,C,D,E}| yields:\
                                  Test{UD@ExtractFirstCommaArg{<Action>}{,A,B,C,D,E}}%

                                  noindentverb|UD@ExtractFirstCommaArg{<Action>}{ {} ,A,B,C,D,E}| yields:\
                                  Test{UD@ExtractFirstCommaArg{<Action>}{ {} ,A,B,C,D,E}}%

                                  noindentverb|UD@ExtractFirstCommaArg{<Action>}{{},A,B,C,D,E}| yields:\
                                  Test{UD@ExtractFirstCommaArg{<Action>}{{},A,B,C,D,E}}%

                                  noindentverb|UD@ExtractFirstCommaArg{<Action>}{A,B,C,D,E}| yields:\
                                  Test{UD@ExtractFirstCommaArg{<Action>}{A,B,C,D,E}}%

                                  noindentverb|UD@ExtractFirstCommaArg{<Action>}{{AB},C,D,E}| yields:\
                                  Test{UD@ExtractFirstCommaArg{<Action>}{{AB},C,D,E}}%

                                  noindentverb|UD@ExtractFirstCommaArg{<Action>}{ {AB} ,C,D,E}| yields:\
                                  Test{UD@ExtractFirstCommaArg{<Action>}{ {AB} ,C,D,E}}%

                                  noindentverb|UD@ExtractFirstCommaArg{<Action>}{ AB ,C,D,E}| yields:\
                                  Test{UD@ExtractFirstCommaArg{<Action>}{ AB ,C,D,E}}%

                                  noindentverb|UD@ExtractFirstCommaArg{<Action>}{ {AB},C,D,E}| yields:\
                                  Test{UD@ExtractFirstCommaArg{<Action>}{ {AB},C,D,E}}%

                                  noindentverb|UD@ExtractFirstCommaArg{<Action>}{{AB} ,C,D,E}| yields:\
                                  Test{UD@ExtractFirstCommaArg{<Action>}{{AB} ,C,D,E}}%

                                  noindentverb|UD@ExtractFirstCommaArg{<Action>}{ { A, B } ,C,D,E}| yields:\
                                  Test{UD@ExtractFirstCommaArg{<Action>}{ { A, B } ,C,D,E}}%

                                  noindentverb|UD@ExtractFirstCommaArg{<Action>}{ { {AB} } ,C,D,E}| yields:\
                                  Test{UD@ExtractFirstCommaArg{<Action>}{ { {AB} } ,C,D,E}}%

                                  makeatother

                                  newpage
                                  section*{testing texttt{stringeqsRef}}

                                  noindentverb|eqsRef{ A ,B, C,D ,,,E, F}| yields:\
                                  Test{eqsRef{ A ,B, C,D ,,,E, F}}%

                                  noindent
                                  Be aware that it is possible to have one nameless referencing-label, \
                                  i.e. verb|label{}| ..verb|ref{}|.\
                                  Here the last thing denotes the nameless label:\
                                  verb|eqsRef{ { A } ,B,C,{}}| yields:\
                                  Test{eqsRef{ { A } ,B,C,{}}}%

                                  noindentverb|eqsRef{ C}| yields:\
                                  Test{eqsRef{ C}}%

                                  noindentverb|eqsRef{ , }| yields:\
                                  Test{eqsRef{ , }}%

                                  noindentverb|eqsRef{ }| yields:\
                                  Test{eqsRef{ }}%

                                  noindentverb|eqsRef{}| yields:\
                                  Test{eqsRef{}}%

                                  end{document}


                                  enter image description hereenter image description here






                                  share|improve this answer




























                                    1














                                    You wish comma-list-parsing.



                                    Yeah!! Comma-list-parsing in (La)TeX is fun as




                                    • you need to take care of spaces surrounding the single items.


                                    • you need to take care of one pair of braces surrounding an entire single item for providing a means of masking commas and spaces that are parts of names of labels. Also be aware that you can have a "nameless" referencing-label by simply doing label{} … ref{}.


                                    • it always provides an opportunity of reinventing the wheel. ;-)



                                    I took the challenge of doing everything expandably (i.e. none of the loops etc does define temporary macros), without forbidden tokens, without if…-switches, without extensions like eTeX,
                                    without extra packages.



                                    I give no warranties.



                                    If you see the need of editing this post for correcting bugs/errors not related to spelling/not related to the English language but to the code, please drop me a hint. ;-)



                                    (Well, eh, if you see the need of editing this post for correcting bugs/errors related to spelling/related to the English language, you, of course, can drop me a hint, too. ;-) )



                                    documentclass{article}

                                    makeatletter
                                    %%//////////////////////////////////////////////////////////////////////////////
                                    %% SECTION LICENCE AND COPYRIGHT
                                    %%
                                    %% Copyright (C) 2018 by Ulrich W. Diez (ud.usenetcorrespondence@web.de)
                                    %%..............................................................................
                                    %% This work may be distributed and/or modified under the conditions of the
                                    %% LaTeX Project Public Licence (LPPL), either version 1.3 of this license or
                                    %% (at your option) any later version.
                                    %% (The latest version of this license is in:
                                    %% http://www.latex-project.org/lppl.txt
                                    %% and version 1.3 or later is part of all distributions of
                                    %% LaTeX version 1999/12/01 or later.)
                                    %% The author of this work is Ulrich Diez.
                                    %% This work has the LPPL maintenance status ‘not maintained’.
                                    %% Usage of any/every component of this work is at your own risk.
                                    %% There is no warranty — neither for probably included documentation nor for
                                    %% any other part/component of this work.
                                    %% If something breaks, you usually may keep the pieces.
                                    %%
                                    %% EOF SECTION LICENCE AND COPYRIGHT
                                    %%//////////////////////////////////////////////////////////////////////////////
                                    %%
                                    %%
                                    %%//////////////////////////////////////////////////////////////////////////////
                                    %% SECTION PARAPHERNALIA:
                                    %%
                                    %% UD@firstoftwo, UD@secondoftwo, UD@Exchange, UD@CheckWhetherNull,
                                    %% UD@CheckWhetherBlank
                                    %%==============================================================================
                                    newcommandUD@firstoftwo[2]{#1}%
                                    newcommandUD@secondoftwo[2]{#2}%
                                    newcommandUD@Exchange[2]{#2#1}%
                                    %%------------------------------------------------------------------------------
                                    %% Check whether argument is empty:
                                    %%..............................................................................
                                    %% UD@CheckWhetherNull{<Argument which is to be checked>}%
                                    %% {<Tokens to be delivered in case that argument
                                    %% which is to be checked is empty>}%
                                    %% {<Tokens to be delivered in case that argument
                                    %% which is to be checked is not empty>}%
                                    %%
                                    %% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
                                    %% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
                                    %%
                                    newcommandUD@CheckWhetherNull[1]{%
                                    romannumeral0expandafterUD@secondoftwostring{expandafter
                                    UD@secondoftwoexpandafter{expandafter{string#1}expandafter
                                    UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
                                    UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
                                    UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
                                    }%
                                    %%------------------------------------------------------------------------------
                                    %% Check whether argument is blank (empty or only spaces):
                                    %%..............................................................................
                                    %% -- Take advantage of the fact that TeX discards space tokens when
                                    %% "fetching" _un_delimited arguments: --
                                    %% UD@CheckWhetherBlank{<Argument which is to be checked>}%
                                    %% {<Tokens to be delivered in case that
                                    %% argument which is to be checked is blank>}%
                                    %% {<Tokens to be delivered in case that argument
                                    %% which is to be checked is not blank}%
                                    newcommandUD@CheckWhetherBlank[1]{%
                                    romannumeralexpandafterexpandafterexpandafterUD@secondoftwo
                                    expandafterUD@CheckWhetherNullexpandafter{UD@firstoftwo#1{}.}%
                                    }%
                                    %%
                                    %% EOF SECTION PARAPHERNALIA
                                    %%//////////////////////////////////////////////////////////////////////////////
                                    %%
                                    %%
                                    %%//////////////////////////////////////////////////////////////////////////////
                                    %% SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                    %%
                                    %% - REQUIRES SECTION PARAPHERNALIA.
                                    %%
                                    %% The obscure case of removing several leading/trailing spaces was taken
                                    %% into consideration.
                                    %%
                                    %% Removal of spaces was implemented in a way where no brace-stripping from
                                    %% the arguments takes place.
                                    %% Explicit-catcode-1/2-character-token-pairs remain untouched.
                                    %%
                                    %% Spaces interspersing the argument or hidden within braces will be left in
                                    %% place.
                                    %%
                                    %% The arguments themselves do not get expanded.
                                    %%
                                    %% (For some obscure reason I don't remember any more I needed this in the
                                    %% past.)
                                    %%
                                    %%==============================================================================
                                    %% Check whether brace-balanced argument starts with a space-token
                                    %%..............................................................................
                                    %% UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
                                    %% {<Tokens to be delivered in case <argument
                                    %% which is to be checked>'s 1st token is a
                                    %% space-token>}%
                                    %% {<Tokens to be delivered in case <argument
                                    %% which is to be checked>'s 1st token is not
                                    %% a space-token>}%
                                    newcommandUD@CheckWhetherLeadingSpace[1]{%
                                    romannumeral0UD@CheckWhetherNull{#1}%
                                    {expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
                                    {expandafterUD@secondoftwostring{UD@CheckWhetherLeadingSpaceB.#1 }{}}%
                                    }%
                                    newcommandUD@CheckWhetherLeadingSpaceB{}%
                                    longdefUD@CheckWhetherLeadingSpaceB#1 {%
                                    expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
                                    {UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
                                    {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
                                    expandafterexpandafterexpandafter}expandafterexpandafter
                                    expandafter}expandafterUD@secondoftwoexpandafter{string}%
                                    }%
                                    %%==============================================================================
                                    %% UD@TrimAllLeadSpace{<action>}{<argument>}
                                    %%..............................................................................
                                    %% expandably removes all leading spaces from <argument> in case at least
                                    %% one leading space is present.
                                    %% Then
                                    %% <action>{<argument without leading spaces>}
                                    %% is performed.
                                    %%==============================================================================
                                    newcommandUD@TrimAllLeadSpace[2]{%
                                    romannumeral0UD@TrimAllLeadSpaceLoop{#2}{#1}%
                                    }%
                                    newcommandUD@TrimAllLeadSpaceLoop[2]{%
                                    UD@CheckWhetherLeadingSpace{#1}%
                                    {%
                                    expandafterUD@TrimAllLeadSpaceLoop
                                    expandafter{UD@removespace#1}{#2}%
                                    }%
                                    { #2{#1}}%
                                    }%
                                    newcommandUD@removespace{}UD@firstoftwo{defUD@removespace}{} {}%
                                    %%==============================================================================
                                    %% UD@TrimAllTrailSpace{<action>}{<argument>}
                                    %%..............................................................................
                                    %% expandably removes all trailing spaces from <argument> in case at least
                                    %% one trailing space is present.
                                    %% Then
                                    %% <action>{<argument without trailing spaces>}
                                    %% is performed.
                                    %%==============================================================================
                                    newcommandUD@TrimAllTrailSpace[2]{%
                                    romannumeral0UD@TrimTrailSpaceLoop{#2}{#1}%
                                    }%
                                    %%------------------------------------------------------------------------------
                                    %% UD@TrimTrailSpaceLoop{<list of space-delimited arguments>}{<action>}
                                    %%..............................................................................
                                    %% both extracts the first space-delimited argument from the <list of space-
                                    %% delimited arguments> as {<current argument with one trailing space
                                    %% removed>} and removes it from the <list of space-delimited arguments> for
                                    %% obtaining the <remaining list of space delimited arguments> and passes
                                    %% these two things and an empty list of <arguments preceding the current
                                    %% argument gathered so far> and the <action> to perform at the end of the
                                    %% iteration to UD@CheckWhetherLastSpaceDelimitedItem.
                                    %%
                                    %% UD@CheckWhetherLastSpaceDelimitedItem in turn does choose the next
                                    %% action.
                                    newcommandUD@TrimTrailSpaceLoop[2]{%
                                    UD@ObtainFirstSpaceDelimitedTokenSetLoop{.#1 UD@SeLDom}{%
                                    expandafterUD@CheckWhetherLastSpaceDelimitedItem
                                    expandafter{UD@RemoveTokensTillNextSpace.#1 }%
                                    }{}{#2}%
                                    }%
                                    %%------------------------------------------------------------------------------
                                    %% Macros for UD@ObtainFirstSpaceDelimitedTokenSetLoop.
                                    %%
                                    newcommand*UD@RemoveTokensTillNextSpace{}%
                                    longdefUD@RemoveTokensTillNextSpace#1 {}%
                                    newcommand*UD@BraceStripRemoveNextSpace{}%
                                    longdefUD@BraceStripRemoveNextSpace#1 {#1}%
                                    newcommand*UD@GetFirstSpaceDelimitedTokenSet{}%
                                    longdefUD@GetFirstSpaceDelimitedTokenSet#1 #2UD@SeLDom{#1 }%
                                    newcommandUD@gobbledot{}%
                                    defUD@gobbledot.{}%
                                    %%------------------------------------------------------------------------------
                                    %% UD@ObtainFirstSpaceDelimitedTokenSetLoop%
                                    %% {<list of space delimited arguments>}%
                                    %% {<action>}%
                                    %%
                                    %% -> <action>{<first element of list of space delimited arguments>}%
                                    %%...............................................................................
                                    %% UD@ObtainFirstSpaceDelimitedTokenSetLoop does--without unwanted brace-re-
                                    %% moval--append the first space delimited argument from a
                                    %% <list of space delimited arguments> as brace-delimited argument behind
                                    %% a set of tokens given as <action>.
                                    newcommandUD@ObtainFirstSpaceDelimitedTokenSetLoop[1]{%
                                    expandafterUD@CheckWhetherNull
                                    expandafter{UD@RemoveTokensTillNextSpace#1}{%
                                    expandafterexpandafterexpandafterUD@Exchange
                                    expandafterexpandafterexpandafter{%
                                    expandafterexpandafterexpandafter{%
                                    expandafterUD@gobbledotUD@BraceStripRemoveNextSpace#1}}%
                                    }{%
                                    expandafterUD@ObtainFirstSpaceDelimitedTokenSetLoop
                                    expandafter{UD@GetFirstSpaceDelimitedTokenSet#1}%
                                    }%
                                    }%
                                    %%------------------------------------------------------------------------------
                                    %% UD@CheckWhetherLastSpaceDelimitedItem
                                    %% {<remaining list of space delimited arguments>}%
                                    %% {<current argument with one trailing space removed>}%
                                    %% {<arguments preceding the current argument gathered
                                    %% so far>}%
                                    %% {<action>}%
                                    %%..............................................................................
                                    %% Case 1: <remaining list of space delimited arguments> is
                                    %% empty.
                                    %% We are done: Thus:
                                    %% <space>% for terminating romannumeral-expansion, and
                                    %% <action>{<arguments preceding the current argument gathered so
                                    %% far><current argument with one trailing space removed>}
                                    %% Case 2: <remaining list of space delimited arguments> consists of a single
                                    %% space.
                                    %% A trailing space was removed. There may be more. Thus:
                                    %% UD@TrimTrailSpaceLoop{%
                                    %% <arguments preceding the current argument gathered so
                                    %% far><current argument with one trailing space removed>%
                                    %% }{<action>}%
                                    %% Neither case 1 nor case 2:
                                    %% The <current argument with one trailing space removed> is not the
                                    %% last argument of the list, thus:
                                    %% For the next iteration
                                    %% - attach it and a trailing space to the <arguments preceding the
                                    %% current argument gathered so far>,
                                    %% - get the first space delimited argument of the <remaining list of
                                    %% space delimited arguments> as <current argument with one trailing
                                    %% space removed>
                                    %% - remove that first space delimited argument from the <remaining list
                                    %% of space delimited arguments>
                                    newcommandUD@CheckWhetherLastSpaceDelimitedItem[4]{%
                                    UD@CheckWhetherNull{#1}{ #4{#3#2}}{%
                                    UD@CheckWhetherLeadingSpace{#1}{%
                                    expandafterUD@CheckWhetherNull
                                    expandafter{UD@removespace#1}{UD@firstoftwo}{UD@secondoftwo}%
                                    }{UD@secondoftwo}%
                                    {UD@TrimTrailSpaceLoop{#3#2}{#4}}%
                                    {%
                                    UD@ObtainFirstSpaceDelimitedTokenSetLoop{.#1UD@SeLDom}{%
                                    expandafterUD@CheckWhetherLastSpaceDelimitedItem
                                    expandafter{UD@RemoveTokensTillNextSpace.#1}%
                                    }{#3#2 }{#4}%
                                    }%
                                    }%
                                    }%
                                    %%==============================================================================
                                    %% UD@TrimAllSurroundSpace{<action>}{<argument>}
                                    %%..............................................................................
                                    %% expandably removes all leading and trailing spaces from <argument> in
                                    %% case at least one leading space is present.
                                    %% Then
                                    %% <action>{<argument without leading and trailing spaces>}
                                    %% is performed.
                                    %%==============================================================================
                                    newcommandUD@TrimAllSurroundSpace[2]{%
                                    romannumeralUD@TrimAllLeadSpace{UD@TrimAllTrailSpace{0 #1}}{#2}%
                                    }%
                                    %%
                                    %% EOF SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                    %%//////////////////////////////////////////////////////////////////////////////
                                    %%
                                    %%
                                    %%//////////////////////////////////////////////////////////////////////////////
                                    %% SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
                                    %%
                                    %% - REQUIRES SECTION PARAPHERNALIA.
                                    %% - REQUIRES SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                    %%
                                    %%-----------------------------------------------------------------------------
                                    %% Extract first inner comma-delimited argument:
                                    %%
                                    %% UD@ExtractFirstCommaArg{<action>}{<comma list>}
                                    %%
                                    %% yields:
                                    %%
                                    %% <action>{<first item/first comma-delimited argument from comma
                                    %% list with surrounding spaces and one level of surroundinng
                                    %% braces removed if present>}
                                    %%
                                    %% <comma-list> is considered a sequence of comma-delimited arguments.
                                    %%
                                    %% The <first item/first comma-delimited argument from comma list>
                                    %% will be extracted. The remainder of the <comma list> will be discarded.
                                    %%
                                    %% Then space tokens surrounding the <first item/first comma-delimited
                                    %% argument from comma list> will be removed.
                                    %%
                                    %% If removal of surrounding spaces yields emptiness, no tokens will be
                                    %% delivered.
                                    %%
                                    %% If removal of surrounding spaces does not yield emptiness,
                                    %% - one pair of braces surrounding the entire result of space-removal
                                    %% will be removed if present!!!!!
                                    %%
                                    %% - Then the result thereof, no matter if empty or not, will be wrapped
                                    %% in braces and passed on to <action>.
                                    %%
                                    %% This implies you can have <comma-delimited arguments> contain
                                    %% emptiness or commas and spaces by nesting them into braces.
                                    %%
                                    %% Examples:
                                    %%
                                    %% UD@ExtractFirstCommaArg{<action>}{,A,B,C,D,E} yields no token at all
                                    %%
                                    %% UD@ExtractFirstCommaArg{<action>}{{},A,B,C,D,E} yields <action>{}
                                    %%
                                    %% UD@ExtractFirstCommaArg{<action>}{A,B,C,D,E} yields <action>{A}
                                    %%
                                    %% UD@ExtractFirstCommaArg{<action>}{{AB},C,D,E} yields <action>{AB}
                                    %%
                                    %% UD@ExtractFirstCommaArg{<action>}{ AB ,C,D,E} yields <action>{AB}
                                    %%
                                    %% UD@ExtractFirstCommaArg{<action>}{ {AB} ,C,D,E} yields <action>{AB}
                                    %%
                                    %% UD@ExtractFirstCommaArg{<action>}{ { A, B } ,C,D,E} yields <action>{ A, B }
                                    %%
                                    %% UD@ExtractFirstCommaArg{<action>}{ { {AB} } ,C,D,E} yields <action>{ {AB} }
                                    %%
                                    %% Due to romannumeral0-expansion, the result will be delivered after
                                    %% two expansion-steps/after having UD@ExtractFirstCommaArg "hit" via
                                    %% two expandafter(-chains).
                                    %%.............................................................................
                                    newcommandUD@gobbletocomma{}longdefUD@gobbletocomma#1,{}%
                                    newcommandUD@removecomma{}longdefUD@removecomma#1,{#1}%
                                    newcommandUD@removebracesNrmstop[2]{%
                                    UD@CheckWhetherNull{#2}{%
                                    0 %
                                    }{%
                                    expandafterUD@Exchange
                                    expandafter{%
                                    expandafter{UD@removecomma#2,}%
                                    }{0 #1}%
                                    }%
                                    }%
                                    newcommandUD@RemoveFromCommaTillUD@SelDOm{}%
                                    longdefUD@RemoveFromCommaTillUD@SelDOm#1,#2UD@SelDOm{#1,}%
                                    newcommandUD@ExtractFirstCommaArg[2]{%
                                    romannumeral%
                                    UD@ExtractFirstCommaArgLoop{.#2,UD@SelDOm}{#1}%
                                    }%
                                    newcommandUD@ExtractFirstCommaArgLoop[2]{%
                                    expandafterUD@CheckWhetherNullexpandafter{UD@gobbletocomma#1}%
                                    {%
                                    expandafterexpandafterexpandafterUD@Exchange
                                    expandafterexpandafterexpandafter{%
                                    expandafterexpandafterexpandafter{%
                                    expandafterUD@gobbledotUD@removecomma#1}}%
                                    {UD@TrimAllSurroundSpace{%
                                    UD@removebracesNrmstop{#2}%
                                    }}%
                                    }%
                                    {%
                                    expandafterUD@ExtractFirstCommaArgLoop
                                    expandafter{UD@RemoveFromCommaTillUD@SelDOm#1}{#2}%
                                    }%
                                    }%
                                    %%
                                    %% EOF SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
                                    %%//////////////////////////////////////////////////////////////////////////////
                                    %%
                                    %%
                                    %%//////////////////////////////////////////////////////////////////////////////
                                    %% SECTION EXPANDABLE ITERATION ON LIST OF LABELS
                                    %%
                                    %% - REQUIRES SECTION PARAPHERNALIA.
                                    %% - REQUIRES SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                    %% - REQUIRES SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
                                    %%
                                    %% eqsRef{<comma-list>}%
                                    %%
                                    %% If <comma-list> contains only commas and/or space tokens, or is empty:
                                    %% yields nothing.
                                    %% !!! Be aware that there is no @bsphack..@esphack for this case.
                                    %% This implies that you will get two spaces in this case if
                                    %% the call to EQsref has both a leading and a trailing space,
                                    %% i.e., is, e.g., <space>EQsref{, ,}<space> !!!
                                    %%
                                    %% If <comma-list> contains one item:
                                    %% yields: Eq~(ref{<item of comma-list>})
                                    %%
                                    %% If <comma-list> contains k items; k > 1:
                                    %% yields:
                                    %% Eq~(ref{<item 1 of comma-list>}%
                                    %% , ref{<item 2 of comma-list>}%
                                    %% [...]%
                                    %% , ref{<item k of comma-list>})%
                                    %%
                                    %% Due to romannumeral0-expansion, the result will be delivered after two
                                    %% expansion-steps/after having eqsRef "hit" via two expandafter(-chains).
                                    %%
                                    newcommandeqsRef[1]{%
                                    romannumeralUD@eqsRefiterator{}{#1,}%
                                    }%
                                    %% UD@eqsRefiterator: #1 -- ref-calls constructed so far
                                    %% #2 -- (remaining) comma-list of labels
                                    %%
                                    newcommandUD@eqsRefiterator[2]{%
                                    UD@CheckWhetherNull{#2}{%
                                    UD@CheckWhetherBlank{#1}{0 }{%
                                    expandafterUD@CheckWhetherNull
                                    expandafter{UD@gobbletocomma#1,}{0 Eq}{0 Eqs}.~(#1)%
                                    }%
                                    }{%
                                    expandafterUD@Exchangeexpandafter{%
                                    expandafter{UD@gobbletocomma#2}%
                                    }{%
                                    expandafterUD@eqsRefiteratorexpandafter{%
                                    romannumeral0%
                                    expandafterexpandafterexpandafterUD@CheckWhetherNull
                                    expandafterexpandafterexpandafter{%
                                    UD@ExtractFirstCommaArg{ref}{#2}%
                                    }{ #1}{%
                                    expandafterexpandafterexpandafterUD@Exchange
                                    expandafterexpandafterexpandafter{%
                                    UD@ExtractFirstCommaArg{ref}{#2}%
                                    }{%
                                    UD@CheckWhetherNull{#1}{ }{ #1, }%
                                    }%
                                    }%
                                    }%
                                    }%
                                    }%
                                    }%
                                    %%
                                    %% EOF SECTION EXPANDABLE ITERATION ON LIST OF LABELS
                                    %%//////////////////////////////////////////////////////////////////////////////
                                    makeatother


                                    newcommandTestGobbleToGT{}%
                                    longdefTestGobbleToGT#1>{}%
                                    newcommandTest[1]{%
                                    expandafterexpandafterexpandafterdef
                                    expandafterexpandafterexpandaftertest
                                    expandafterexpandafterexpandafter{%
                                    #1%
                                    }%
                                    texttt{expandafterTestGobbleToGTmeaningtest}%
                                    parnoindenthrulefill
                                    }%

                                    begin{document}

                                    section*{testing texttt{stringUD@ExtractFirstCommaArg}}

                                    makeatletter

                                    noindentverb|UD@ExtractFirstCommaArg{<Action>}{,A,B,C,D,E}| yields:\
                                    Test{UD@ExtractFirstCommaArg{<Action>}{,A,B,C,D,E}}%

                                    noindentverb|UD@ExtractFirstCommaArg{<Action>}{ {} ,A,B,C,D,E}| yields:\
                                    Test{UD@ExtractFirstCommaArg{<Action>}{ {} ,A,B,C,D,E}}%

                                    noindentverb|UD@ExtractFirstCommaArg{<Action>}{{},A,B,C,D,E}| yields:\
                                    Test{UD@ExtractFirstCommaArg{<Action>}{{},A,B,C,D,E}}%

                                    noindentverb|UD@ExtractFirstCommaArg{<Action>}{A,B,C,D,E}| yields:\
                                    Test{UD@ExtractFirstCommaArg{<Action>}{A,B,C,D,E}}%

                                    noindentverb|UD@ExtractFirstCommaArg{<Action>}{{AB},C,D,E}| yields:\
                                    Test{UD@ExtractFirstCommaArg{<Action>}{{AB},C,D,E}}%

                                    noindentverb|UD@ExtractFirstCommaArg{<Action>}{ {AB} ,C,D,E}| yields:\
                                    Test{UD@ExtractFirstCommaArg{<Action>}{ {AB} ,C,D,E}}%

                                    noindentverb|UD@ExtractFirstCommaArg{<Action>}{ AB ,C,D,E}| yields:\
                                    Test{UD@ExtractFirstCommaArg{<Action>}{ AB ,C,D,E}}%

                                    noindentverb|UD@ExtractFirstCommaArg{<Action>}{ {AB},C,D,E}| yields:\
                                    Test{UD@ExtractFirstCommaArg{<Action>}{ {AB},C,D,E}}%

                                    noindentverb|UD@ExtractFirstCommaArg{<Action>}{{AB} ,C,D,E}| yields:\
                                    Test{UD@ExtractFirstCommaArg{<Action>}{{AB} ,C,D,E}}%

                                    noindentverb|UD@ExtractFirstCommaArg{<Action>}{ { A, B } ,C,D,E}| yields:\
                                    Test{UD@ExtractFirstCommaArg{<Action>}{ { A, B } ,C,D,E}}%

                                    noindentverb|UD@ExtractFirstCommaArg{<Action>}{ { {AB} } ,C,D,E}| yields:\
                                    Test{UD@ExtractFirstCommaArg{<Action>}{ { {AB} } ,C,D,E}}%

                                    makeatother

                                    newpage
                                    section*{testing texttt{stringeqsRef}}

                                    noindentverb|eqsRef{ A ,B, C,D ,,,E, F}| yields:\
                                    Test{eqsRef{ A ,B, C,D ,,,E, F}}%

                                    noindent
                                    Be aware that it is possible to have one nameless referencing-label, \
                                    i.e. verb|label{}| ..verb|ref{}|.\
                                    Here the last thing denotes the nameless label:\
                                    verb|eqsRef{ { A } ,B,C,{}}| yields:\
                                    Test{eqsRef{ { A } ,B,C,{}}}%

                                    noindentverb|eqsRef{ C}| yields:\
                                    Test{eqsRef{ C}}%

                                    noindentverb|eqsRef{ , }| yields:\
                                    Test{eqsRef{ , }}%

                                    noindentverb|eqsRef{ }| yields:\
                                    Test{eqsRef{ }}%

                                    noindentverb|eqsRef{}| yields:\
                                    Test{eqsRef{}}%

                                    end{document}


                                    enter image description hereenter image description here






                                    share|improve this answer


























                                      1












                                      1








                                      1






                                      You wish comma-list-parsing.



                                      Yeah!! Comma-list-parsing in (La)TeX is fun as




                                      • you need to take care of spaces surrounding the single items.


                                      • you need to take care of one pair of braces surrounding an entire single item for providing a means of masking commas and spaces that are parts of names of labels. Also be aware that you can have a "nameless" referencing-label by simply doing label{} … ref{}.


                                      • it always provides an opportunity of reinventing the wheel. ;-)



                                      I took the challenge of doing everything expandably (i.e. none of the loops etc does define temporary macros), without forbidden tokens, without if…-switches, without extensions like eTeX,
                                      without extra packages.



                                      I give no warranties.



                                      If you see the need of editing this post for correcting bugs/errors not related to spelling/not related to the English language but to the code, please drop me a hint. ;-)



                                      (Well, eh, if you see the need of editing this post for correcting bugs/errors related to spelling/related to the English language, you, of course, can drop me a hint, too. ;-) )



                                      documentclass{article}

                                      makeatletter
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %% SECTION LICENCE AND COPYRIGHT
                                      %%
                                      %% Copyright (C) 2018 by Ulrich W. Diez (ud.usenetcorrespondence@web.de)
                                      %%..............................................................................
                                      %% This work may be distributed and/or modified under the conditions of the
                                      %% LaTeX Project Public Licence (LPPL), either version 1.3 of this license or
                                      %% (at your option) any later version.
                                      %% (The latest version of this license is in:
                                      %% http://www.latex-project.org/lppl.txt
                                      %% and version 1.3 or later is part of all distributions of
                                      %% LaTeX version 1999/12/01 or later.)
                                      %% The author of this work is Ulrich Diez.
                                      %% This work has the LPPL maintenance status ‘not maintained’.
                                      %% Usage of any/every component of this work is at your own risk.
                                      %% There is no warranty — neither for probably included documentation nor for
                                      %% any other part/component of this work.
                                      %% If something breaks, you usually may keep the pieces.
                                      %%
                                      %% EOF SECTION LICENCE AND COPYRIGHT
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %%
                                      %%
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %% SECTION PARAPHERNALIA:
                                      %%
                                      %% UD@firstoftwo, UD@secondoftwo, UD@Exchange, UD@CheckWhetherNull,
                                      %% UD@CheckWhetherBlank
                                      %%==============================================================================
                                      newcommandUD@firstoftwo[2]{#1}%
                                      newcommandUD@secondoftwo[2]{#2}%
                                      newcommandUD@Exchange[2]{#2#1}%
                                      %%------------------------------------------------------------------------------
                                      %% Check whether argument is empty:
                                      %%..............................................................................
                                      %% UD@CheckWhetherNull{<Argument which is to be checked>}%
                                      %% {<Tokens to be delivered in case that argument
                                      %% which is to be checked is empty>}%
                                      %% {<Tokens to be delivered in case that argument
                                      %% which is to be checked is not empty>}%
                                      %%
                                      %% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
                                      %% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
                                      %%
                                      newcommandUD@CheckWhetherNull[1]{%
                                      romannumeral0expandafterUD@secondoftwostring{expandafter
                                      UD@secondoftwoexpandafter{expandafter{string#1}expandafter
                                      UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
                                      UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
                                      UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
                                      }%
                                      %%------------------------------------------------------------------------------
                                      %% Check whether argument is blank (empty or only spaces):
                                      %%..............................................................................
                                      %% -- Take advantage of the fact that TeX discards space tokens when
                                      %% "fetching" _un_delimited arguments: --
                                      %% UD@CheckWhetherBlank{<Argument which is to be checked>}%
                                      %% {<Tokens to be delivered in case that
                                      %% argument which is to be checked is blank>}%
                                      %% {<Tokens to be delivered in case that argument
                                      %% which is to be checked is not blank}%
                                      newcommandUD@CheckWhetherBlank[1]{%
                                      romannumeralexpandafterexpandafterexpandafterUD@secondoftwo
                                      expandafterUD@CheckWhetherNullexpandafter{UD@firstoftwo#1{}.}%
                                      }%
                                      %%
                                      %% EOF SECTION PARAPHERNALIA
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %%
                                      %%
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %% SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                      %%
                                      %% - REQUIRES SECTION PARAPHERNALIA.
                                      %%
                                      %% The obscure case of removing several leading/trailing spaces was taken
                                      %% into consideration.
                                      %%
                                      %% Removal of spaces was implemented in a way where no brace-stripping from
                                      %% the arguments takes place.
                                      %% Explicit-catcode-1/2-character-token-pairs remain untouched.
                                      %%
                                      %% Spaces interspersing the argument or hidden within braces will be left in
                                      %% place.
                                      %%
                                      %% The arguments themselves do not get expanded.
                                      %%
                                      %% (For some obscure reason I don't remember any more I needed this in the
                                      %% past.)
                                      %%
                                      %%==============================================================================
                                      %% Check whether brace-balanced argument starts with a space-token
                                      %%..............................................................................
                                      %% UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
                                      %% {<Tokens to be delivered in case <argument
                                      %% which is to be checked>'s 1st token is a
                                      %% space-token>}%
                                      %% {<Tokens to be delivered in case <argument
                                      %% which is to be checked>'s 1st token is not
                                      %% a space-token>}%
                                      newcommandUD@CheckWhetherLeadingSpace[1]{%
                                      romannumeral0UD@CheckWhetherNull{#1}%
                                      {expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
                                      {expandafterUD@secondoftwostring{UD@CheckWhetherLeadingSpaceB.#1 }{}}%
                                      }%
                                      newcommandUD@CheckWhetherLeadingSpaceB{}%
                                      longdefUD@CheckWhetherLeadingSpaceB#1 {%
                                      expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
                                      {UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
                                      {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
                                      expandafterexpandafterexpandafter}expandafterexpandafter
                                      expandafter}expandafterUD@secondoftwoexpandafter{string}%
                                      }%
                                      %%==============================================================================
                                      %% UD@TrimAllLeadSpace{<action>}{<argument>}
                                      %%..............................................................................
                                      %% expandably removes all leading spaces from <argument> in case at least
                                      %% one leading space is present.
                                      %% Then
                                      %% <action>{<argument without leading spaces>}
                                      %% is performed.
                                      %%==============================================================================
                                      newcommandUD@TrimAllLeadSpace[2]{%
                                      romannumeral0UD@TrimAllLeadSpaceLoop{#2}{#1}%
                                      }%
                                      newcommandUD@TrimAllLeadSpaceLoop[2]{%
                                      UD@CheckWhetherLeadingSpace{#1}%
                                      {%
                                      expandafterUD@TrimAllLeadSpaceLoop
                                      expandafter{UD@removespace#1}{#2}%
                                      }%
                                      { #2{#1}}%
                                      }%
                                      newcommandUD@removespace{}UD@firstoftwo{defUD@removespace}{} {}%
                                      %%==============================================================================
                                      %% UD@TrimAllTrailSpace{<action>}{<argument>}
                                      %%..............................................................................
                                      %% expandably removes all trailing spaces from <argument> in case at least
                                      %% one trailing space is present.
                                      %% Then
                                      %% <action>{<argument without trailing spaces>}
                                      %% is performed.
                                      %%==============================================================================
                                      newcommandUD@TrimAllTrailSpace[2]{%
                                      romannumeral0UD@TrimTrailSpaceLoop{#2}{#1}%
                                      }%
                                      %%------------------------------------------------------------------------------
                                      %% UD@TrimTrailSpaceLoop{<list of space-delimited arguments>}{<action>}
                                      %%..............................................................................
                                      %% both extracts the first space-delimited argument from the <list of space-
                                      %% delimited arguments> as {<current argument with one trailing space
                                      %% removed>} and removes it from the <list of space-delimited arguments> for
                                      %% obtaining the <remaining list of space delimited arguments> and passes
                                      %% these two things and an empty list of <arguments preceding the current
                                      %% argument gathered so far> and the <action> to perform at the end of the
                                      %% iteration to UD@CheckWhetherLastSpaceDelimitedItem.
                                      %%
                                      %% UD@CheckWhetherLastSpaceDelimitedItem in turn does choose the next
                                      %% action.
                                      newcommandUD@TrimTrailSpaceLoop[2]{%
                                      UD@ObtainFirstSpaceDelimitedTokenSetLoop{.#1 UD@SeLDom}{%
                                      expandafterUD@CheckWhetherLastSpaceDelimitedItem
                                      expandafter{UD@RemoveTokensTillNextSpace.#1 }%
                                      }{}{#2}%
                                      }%
                                      %%------------------------------------------------------------------------------
                                      %% Macros for UD@ObtainFirstSpaceDelimitedTokenSetLoop.
                                      %%
                                      newcommand*UD@RemoveTokensTillNextSpace{}%
                                      longdefUD@RemoveTokensTillNextSpace#1 {}%
                                      newcommand*UD@BraceStripRemoveNextSpace{}%
                                      longdefUD@BraceStripRemoveNextSpace#1 {#1}%
                                      newcommand*UD@GetFirstSpaceDelimitedTokenSet{}%
                                      longdefUD@GetFirstSpaceDelimitedTokenSet#1 #2UD@SeLDom{#1 }%
                                      newcommandUD@gobbledot{}%
                                      defUD@gobbledot.{}%
                                      %%------------------------------------------------------------------------------
                                      %% UD@ObtainFirstSpaceDelimitedTokenSetLoop%
                                      %% {<list of space delimited arguments>}%
                                      %% {<action>}%
                                      %%
                                      %% -> <action>{<first element of list of space delimited arguments>}%
                                      %%...............................................................................
                                      %% UD@ObtainFirstSpaceDelimitedTokenSetLoop does--without unwanted brace-re-
                                      %% moval--append the first space delimited argument from a
                                      %% <list of space delimited arguments> as brace-delimited argument behind
                                      %% a set of tokens given as <action>.
                                      newcommandUD@ObtainFirstSpaceDelimitedTokenSetLoop[1]{%
                                      expandafterUD@CheckWhetherNull
                                      expandafter{UD@RemoveTokensTillNextSpace#1}{%
                                      expandafterexpandafterexpandafterUD@Exchange
                                      expandafterexpandafterexpandafter{%
                                      expandafterexpandafterexpandafter{%
                                      expandafterUD@gobbledotUD@BraceStripRemoveNextSpace#1}}%
                                      }{%
                                      expandafterUD@ObtainFirstSpaceDelimitedTokenSetLoop
                                      expandafter{UD@GetFirstSpaceDelimitedTokenSet#1}%
                                      }%
                                      }%
                                      %%------------------------------------------------------------------------------
                                      %% UD@CheckWhetherLastSpaceDelimitedItem
                                      %% {<remaining list of space delimited arguments>}%
                                      %% {<current argument with one trailing space removed>}%
                                      %% {<arguments preceding the current argument gathered
                                      %% so far>}%
                                      %% {<action>}%
                                      %%..............................................................................
                                      %% Case 1: <remaining list of space delimited arguments> is
                                      %% empty.
                                      %% We are done: Thus:
                                      %% <space>% for terminating romannumeral-expansion, and
                                      %% <action>{<arguments preceding the current argument gathered so
                                      %% far><current argument with one trailing space removed>}
                                      %% Case 2: <remaining list of space delimited arguments> consists of a single
                                      %% space.
                                      %% A trailing space was removed. There may be more. Thus:
                                      %% UD@TrimTrailSpaceLoop{%
                                      %% <arguments preceding the current argument gathered so
                                      %% far><current argument with one trailing space removed>%
                                      %% }{<action>}%
                                      %% Neither case 1 nor case 2:
                                      %% The <current argument with one trailing space removed> is not the
                                      %% last argument of the list, thus:
                                      %% For the next iteration
                                      %% - attach it and a trailing space to the <arguments preceding the
                                      %% current argument gathered so far>,
                                      %% - get the first space delimited argument of the <remaining list of
                                      %% space delimited arguments> as <current argument with one trailing
                                      %% space removed>
                                      %% - remove that first space delimited argument from the <remaining list
                                      %% of space delimited arguments>
                                      newcommandUD@CheckWhetherLastSpaceDelimitedItem[4]{%
                                      UD@CheckWhetherNull{#1}{ #4{#3#2}}{%
                                      UD@CheckWhetherLeadingSpace{#1}{%
                                      expandafterUD@CheckWhetherNull
                                      expandafter{UD@removespace#1}{UD@firstoftwo}{UD@secondoftwo}%
                                      }{UD@secondoftwo}%
                                      {UD@TrimTrailSpaceLoop{#3#2}{#4}}%
                                      {%
                                      UD@ObtainFirstSpaceDelimitedTokenSetLoop{.#1UD@SeLDom}{%
                                      expandafterUD@CheckWhetherLastSpaceDelimitedItem
                                      expandafter{UD@RemoveTokensTillNextSpace.#1}%
                                      }{#3#2 }{#4}%
                                      }%
                                      }%
                                      }%
                                      %%==============================================================================
                                      %% UD@TrimAllSurroundSpace{<action>}{<argument>}
                                      %%..............................................................................
                                      %% expandably removes all leading and trailing spaces from <argument> in
                                      %% case at least one leading space is present.
                                      %% Then
                                      %% <action>{<argument without leading and trailing spaces>}
                                      %% is performed.
                                      %%==============================================================================
                                      newcommandUD@TrimAllSurroundSpace[2]{%
                                      romannumeralUD@TrimAllLeadSpace{UD@TrimAllTrailSpace{0 #1}}{#2}%
                                      }%
                                      %%
                                      %% EOF SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %%
                                      %%
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %% SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
                                      %%
                                      %% - REQUIRES SECTION PARAPHERNALIA.
                                      %% - REQUIRES SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                      %%
                                      %%-----------------------------------------------------------------------------
                                      %% Extract first inner comma-delimited argument:
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{<comma list>}
                                      %%
                                      %% yields:
                                      %%
                                      %% <action>{<first item/first comma-delimited argument from comma
                                      %% list with surrounding spaces and one level of surroundinng
                                      %% braces removed if present>}
                                      %%
                                      %% <comma-list> is considered a sequence of comma-delimited arguments.
                                      %%
                                      %% The <first item/first comma-delimited argument from comma list>
                                      %% will be extracted. The remainder of the <comma list> will be discarded.
                                      %%
                                      %% Then space tokens surrounding the <first item/first comma-delimited
                                      %% argument from comma list> will be removed.
                                      %%
                                      %% If removal of surrounding spaces yields emptiness, no tokens will be
                                      %% delivered.
                                      %%
                                      %% If removal of surrounding spaces does not yield emptiness,
                                      %% - one pair of braces surrounding the entire result of space-removal
                                      %% will be removed if present!!!!!
                                      %%
                                      %% - Then the result thereof, no matter if empty or not, will be wrapped
                                      %% in braces and passed on to <action>.
                                      %%
                                      %% This implies you can have <comma-delimited arguments> contain
                                      %% emptiness or commas and spaces by nesting them into braces.
                                      %%
                                      %% Examples:
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{,A,B,C,D,E} yields no token at all
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{{},A,B,C,D,E} yields <action>{}
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{A,B,C,D,E} yields <action>{A}
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{{AB},C,D,E} yields <action>{AB}
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{ AB ,C,D,E} yields <action>{AB}
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{ {AB} ,C,D,E} yields <action>{AB}
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{ { A, B } ,C,D,E} yields <action>{ A, B }
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{ { {AB} } ,C,D,E} yields <action>{ {AB} }
                                      %%
                                      %% Due to romannumeral0-expansion, the result will be delivered after
                                      %% two expansion-steps/after having UD@ExtractFirstCommaArg "hit" via
                                      %% two expandafter(-chains).
                                      %%.............................................................................
                                      newcommandUD@gobbletocomma{}longdefUD@gobbletocomma#1,{}%
                                      newcommandUD@removecomma{}longdefUD@removecomma#1,{#1}%
                                      newcommandUD@removebracesNrmstop[2]{%
                                      UD@CheckWhetherNull{#2}{%
                                      0 %
                                      }{%
                                      expandafterUD@Exchange
                                      expandafter{%
                                      expandafter{UD@removecomma#2,}%
                                      }{0 #1}%
                                      }%
                                      }%
                                      newcommandUD@RemoveFromCommaTillUD@SelDOm{}%
                                      longdefUD@RemoveFromCommaTillUD@SelDOm#1,#2UD@SelDOm{#1,}%
                                      newcommandUD@ExtractFirstCommaArg[2]{%
                                      romannumeral%
                                      UD@ExtractFirstCommaArgLoop{.#2,UD@SelDOm}{#1}%
                                      }%
                                      newcommandUD@ExtractFirstCommaArgLoop[2]{%
                                      expandafterUD@CheckWhetherNullexpandafter{UD@gobbletocomma#1}%
                                      {%
                                      expandafterexpandafterexpandafterUD@Exchange
                                      expandafterexpandafterexpandafter{%
                                      expandafterexpandafterexpandafter{%
                                      expandafterUD@gobbledotUD@removecomma#1}}%
                                      {UD@TrimAllSurroundSpace{%
                                      UD@removebracesNrmstop{#2}%
                                      }}%
                                      }%
                                      {%
                                      expandafterUD@ExtractFirstCommaArgLoop
                                      expandafter{UD@RemoveFromCommaTillUD@SelDOm#1}{#2}%
                                      }%
                                      }%
                                      %%
                                      %% EOF SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %%
                                      %%
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %% SECTION EXPANDABLE ITERATION ON LIST OF LABELS
                                      %%
                                      %% - REQUIRES SECTION PARAPHERNALIA.
                                      %% - REQUIRES SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                      %% - REQUIRES SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
                                      %%
                                      %% eqsRef{<comma-list>}%
                                      %%
                                      %% If <comma-list> contains only commas and/or space tokens, or is empty:
                                      %% yields nothing.
                                      %% !!! Be aware that there is no @bsphack..@esphack for this case.
                                      %% This implies that you will get two spaces in this case if
                                      %% the call to EQsref has both a leading and a trailing space,
                                      %% i.e., is, e.g., <space>EQsref{, ,}<space> !!!
                                      %%
                                      %% If <comma-list> contains one item:
                                      %% yields: Eq~(ref{<item of comma-list>})
                                      %%
                                      %% If <comma-list> contains k items; k > 1:
                                      %% yields:
                                      %% Eq~(ref{<item 1 of comma-list>}%
                                      %% , ref{<item 2 of comma-list>}%
                                      %% [...]%
                                      %% , ref{<item k of comma-list>})%
                                      %%
                                      %% Due to romannumeral0-expansion, the result will be delivered after two
                                      %% expansion-steps/after having eqsRef "hit" via two expandafter(-chains).
                                      %%
                                      newcommandeqsRef[1]{%
                                      romannumeralUD@eqsRefiterator{}{#1,}%
                                      }%
                                      %% UD@eqsRefiterator: #1 -- ref-calls constructed so far
                                      %% #2 -- (remaining) comma-list of labels
                                      %%
                                      newcommandUD@eqsRefiterator[2]{%
                                      UD@CheckWhetherNull{#2}{%
                                      UD@CheckWhetherBlank{#1}{0 }{%
                                      expandafterUD@CheckWhetherNull
                                      expandafter{UD@gobbletocomma#1,}{0 Eq}{0 Eqs}.~(#1)%
                                      }%
                                      }{%
                                      expandafterUD@Exchangeexpandafter{%
                                      expandafter{UD@gobbletocomma#2}%
                                      }{%
                                      expandafterUD@eqsRefiteratorexpandafter{%
                                      romannumeral0%
                                      expandafterexpandafterexpandafterUD@CheckWhetherNull
                                      expandafterexpandafterexpandafter{%
                                      UD@ExtractFirstCommaArg{ref}{#2}%
                                      }{ #1}{%
                                      expandafterexpandafterexpandafterUD@Exchange
                                      expandafterexpandafterexpandafter{%
                                      UD@ExtractFirstCommaArg{ref}{#2}%
                                      }{%
                                      UD@CheckWhetherNull{#1}{ }{ #1, }%
                                      }%
                                      }%
                                      }%
                                      }%
                                      }%
                                      }%
                                      %%
                                      %% EOF SECTION EXPANDABLE ITERATION ON LIST OF LABELS
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      makeatother


                                      newcommandTestGobbleToGT{}%
                                      longdefTestGobbleToGT#1>{}%
                                      newcommandTest[1]{%
                                      expandafterexpandafterexpandafterdef
                                      expandafterexpandafterexpandaftertest
                                      expandafterexpandafterexpandafter{%
                                      #1%
                                      }%
                                      texttt{expandafterTestGobbleToGTmeaningtest}%
                                      parnoindenthrulefill
                                      }%

                                      begin{document}

                                      section*{testing texttt{stringUD@ExtractFirstCommaArg}}

                                      makeatletter

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{,A,B,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{,A,B,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{ {} ,A,B,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{ {} ,A,B,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{{},A,B,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{{},A,B,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{A,B,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{A,B,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{{AB},C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{{AB},C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{ {AB} ,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{ {AB} ,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{ AB ,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{ AB ,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{ {AB},C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{ {AB},C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{{AB} ,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{{AB} ,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{ { A, B } ,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{ { A, B } ,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{ { {AB} } ,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{ { {AB} } ,C,D,E}}%

                                      makeatother

                                      newpage
                                      section*{testing texttt{stringeqsRef}}

                                      noindentverb|eqsRef{ A ,B, C,D ,,,E, F}| yields:\
                                      Test{eqsRef{ A ,B, C,D ,,,E, F}}%

                                      noindent
                                      Be aware that it is possible to have one nameless referencing-label, \
                                      i.e. verb|label{}| ..verb|ref{}|.\
                                      Here the last thing denotes the nameless label:\
                                      verb|eqsRef{ { A } ,B,C,{}}| yields:\
                                      Test{eqsRef{ { A } ,B,C,{}}}%

                                      noindentverb|eqsRef{ C}| yields:\
                                      Test{eqsRef{ C}}%

                                      noindentverb|eqsRef{ , }| yields:\
                                      Test{eqsRef{ , }}%

                                      noindentverb|eqsRef{ }| yields:\
                                      Test{eqsRef{ }}%

                                      noindentverb|eqsRef{}| yields:\
                                      Test{eqsRef{}}%

                                      end{document}


                                      enter image description hereenter image description here






                                      share|improve this answer














                                      You wish comma-list-parsing.



                                      Yeah!! Comma-list-parsing in (La)TeX is fun as




                                      • you need to take care of spaces surrounding the single items.


                                      • you need to take care of one pair of braces surrounding an entire single item for providing a means of masking commas and spaces that are parts of names of labels. Also be aware that you can have a "nameless" referencing-label by simply doing label{} … ref{}.


                                      • it always provides an opportunity of reinventing the wheel. ;-)



                                      I took the challenge of doing everything expandably (i.e. none of the loops etc does define temporary macros), without forbidden tokens, without if…-switches, without extensions like eTeX,
                                      without extra packages.



                                      I give no warranties.



                                      If you see the need of editing this post for correcting bugs/errors not related to spelling/not related to the English language but to the code, please drop me a hint. ;-)



                                      (Well, eh, if you see the need of editing this post for correcting bugs/errors related to spelling/related to the English language, you, of course, can drop me a hint, too. ;-) )



                                      documentclass{article}

                                      makeatletter
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %% SECTION LICENCE AND COPYRIGHT
                                      %%
                                      %% Copyright (C) 2018 by Ulrich W. Diez (ud.usenetcorrespondence@web.de)
                                      %%..............................................................................
                                      %% This work may be distributed and/or modified under the conditions of the
                                      %% LaTeX Project Public Licence (LPPL), either version 1.3 of this license or
                                      %% (at your option) any later version.
                                      %% (The latest version of this license is in:
                                      %% http://www.latex-project.org/lppl.txt
                                      %% and version 1.3 or later is part of all distributions of
                                      %% LaTeX version 1999/12/01 or later.)
                                      %% The author of this work is Ulrich Diez.
                                      %% This work has the LPPL maintenance status ‘not maintained’.
                                      %% Usage of any/every component of this work is at your own risk.
                                      %% There is no warranty — neither for probably included documentation nor for
                                      %% any other part/component of this work.
                                      %% If something breaks, you usually may keep the pieces.
                                      %%
                                      %% EOF SECTION LICENCE AND COPYRIGHT
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %%
                                      %%
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %% SECTION PARAPHERNALIA:
                                      %%
                                      %% UD@firstoftwo, UD@secondoftwo, UD@Exchange, UD@CheckWhetherNull,
                                      %% UD@CheckWhetherBlank
                                      %%==============================================================================
                                      newcommandUD@firstoftwo[2]{#1}%
                                      newcommandUD@secondoftwo[2]{#2}%
                                      newcommandUD@Exchange[2]{#2#1}%
                                      %%------------------------------------------------------------------------------
                                      %% Check whether argument is empty:
                                      %%..............................................................................
                                      %% UD@CheckWhetherNull{<Argument which is to be checked>}%
                                      %% {<Tokens to be delivered in case that argument
                                      %% which is to be checked is empty>}%
                                      %% {<Tokens to be delivered in case that argument
                                      %% which is to be checked is not empty>}%
                                      %%
                                      %% The gist of this macro comes from Robert R. Schneck's ifempty-macro:
                                      %% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
                                      %%
                                      newcommandUD@CheckWhetherNull[1]{%
                                      romannumeral0expandafterUD@secondoftwostring{expandafter
                                      UD@secondoftwoexpandafter{expandafter{string#1}expandafter
                                      UD@secondoftwostring}expandafterUD@firstoftwoexpandafter{expandafter
                                      UD@secondoftwostring}expandafterexpandafterUD@firstoftwo{ }{}%
                                      UD@secondoftwo}{expandafterexpandafterUD@firstoftwo{ }{}UD@firstoftwo}%
                                      }%
                                      %%------------------------------------------------------------------------------
                                      %% Check whether argument is blank (empty or only spaces):
                                      %%..............................................................................
                                      %% -- Take advantage of the fact that TeX discards space tokens when
                                      %% "fetching" _un_delimited arguments: --
                                      %% UD@CheckWhetherBlank{<Argument which is to be checked>}%
                                      %% {<Tokens to be delivered in case that
                                      %% argument which is to be checked is blank>}%
                                      %% {<Tokens to be delivered in case that argument
                                      %% which is to be checked is not blank}%
                                      newcommandUD@CheckWhetherBlank[1]{%
                                      romannumeralexpandafterexpandafterexpandafterUD@secondoftwo
                                      expandafterUD@CheckWhetherNullexpandafter{UD@firstoftwo#1{}.}%
                                      }%
                                      %%
                                      %% EOF SECTION PARAPHERNALIA
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %%
                                      %%
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %% SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                      %%
                                      %% - REQUIRES SECTION PARAPHERNALIA.
                                      %%
                                      %% The obscure case of removing several leading/trailing spaces was taken
                                      %% into consideration.
                                      %%
                                      %% Removal of spaces was implemented in a way where no brace-stripping from
                                      %% the arguments takes place.
                                      %% Explicit-catcode-1/2-character-token-pairs remain untouched.
                                      %%
                                      %% Spaces interspersing the argument or hidden within braces will be left in
                                      %% place.
                                      %%
                                      %% The arguments themselves do not get expanded.
                                      %%
                                      %% (For some obscure reason I don't remember any more I needed this in the
                                      %% past.)
                                      %%
                                      %%==============================================================================
                                      %% Check whether brace-balanced argument starts with a space-token
                                      %%..............................................................................
                                      %% UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
                                      %% {<Tokens to be delivered in case <argument
                                      %% which is to be checked>'s 1st token is a
                                      %% space-token>}%
                                      %% {<Tokens to be delivered in case <argument
                                      %% which is to be checked>'s 1st token is not
                                      %% a space-token>}%
                                      newcommandUD@CheckWhetherLeadingSpace[1]{%
                                      romannumeral0UD@CheckWhetherNull{#1}%
                                      {expandafterexpandafterUD@firstoftwo{ }{}UD@secondoftwo}%
                                      {expandafterUD@secondoftwostring{UD@CheckWhetherLeadingSpaceB.#1 }{}}%
                                      }%
                                      newcommandUD@CheckWhetherLeadingSpaceB{}%
                                      longdefUD@CheckWhetherLeadingSpaceB#1 {%
                                      expandafterUD@CheckWhetherNullexpandafter{UD@secondoftwo#1{}}%
                                      {UD@Exchange{UD@firstoftwo}}{UD@Exchange{UD@secondoftwo}}%
                                      {UD@Exchange{ }{expandafterexpandafterexpandafterexpandafter
                                      expandafterexpandafterexpandafter}expandafterexpandafter
                                      expandafter}expandafterUD@secondoftwoexpandafter{string}%
                                      }%
                                      %%==============================================================================
                                      %% UD@TrimAllLeadSpace{<action>}{<argument>}
                                      %%..............................................................................
                                      %% expandably removes all leading spaces from <argument> in case at least
                                      %% one leading space is present.
                                      %% Then
                                      %% <action>{<argument without leading spaces>}
                                      %% is performed.
                                      %%==============================================================================
                                      newcommandUD@TrimAllLeadSpace[2]{%
                                      romannumeral0UD@TrimAllLeadSpaceLoop{#2}{#1}%
                                      }%
                                      newcommandUD@TrimAllLeadSpaceLoop[2]{%
                                      UD@CheckWhetherLeadingSpace{#1}%
                                      {%
                                      expandafterUD@TrimAllLeadSpaceLoop
                                      expandafter{UD@removespace#1}{#2}%
                                      }%
                                      { #2{#1}}%
                                      }%
                                      newcommandUD@removespace{}UD@firstoftwo{defUD@removespace}{} {}%
                                      %%==============================================================================
                                      %% UD@TrimAllTrailSpace{<action>}{<argument>}
                                      %%..............................................................................
                                      %% expandably removes all trailing spaces from <argument> in case at least
                                      %% one trailing space is present.
                                      %% Then
                                      %% <action>{<argument without trailing spaces>}
                                      %% is performed.
                                      %%==============================================================================
                                      newcommandUD@TrimAllTrailSpace[2]{%
                                      romannumeral0UD@TrimTrailSpaceLoop{#2}{#1}%
                                      }%
                                      %%------------------------------------------------------------------------------
                                      %% UD@TrimTrailSpaceLoop{<list of space-delimited arguments>}{<action>}
                                      %%..............................................................................
                                      %% both extracts the first space-delimited argument from the <list of space-
                                      %% delimited arguments> as {<current argument with one trailing space
                                      %% removed>} and removes it from the <list of space-delimited arguments> for
                                      %% obtaining the <remaining list of space delimited arguments> and passes
                                      %% these two things and an empty list of <arguments preceding the current
                                      %% argument gathered so far> and the <action> to perform at the end of the
                                      %% iteration to UD@CheckWhetherLastSpaceDelimitedItem.
                                      %%
                                      %% UD@CheckWhetherLastSpaceDelimitedItem in turn does choose the next
                                      %% action.
                                      newcommandUD@TrimTrailSpaceLoop[2]{%
                                      UD@ObtainFirstSpaceDelimitedTokenSetLoop{.#1 UD@SeLDom}{%
                                      expandafterUD@CheckWhetherLastSpaceDelimitedItem
                                      expandafter{UD@RemoveTokensTillNextSpace.#1 }%
                                      }{}{#2}%
                                      }%
                                      %%------------------------------------------------------------------------------
                                      %% Macros for UD@ObtainFirstSpaceDelimitedTokenSetLoop.
                                      %%
                                      newcommand*UD@RemoveTokensTillNextSpace{}%
                                      longdefUD@RemoveTokensTillNextSpace#1 {}%
                                      newcommand*UD@BraceStripRemoveNextSpace{}%
                                      longdefUD@BraceStripRemoveNextSpace#1 {#1}%
                                      newcommand*UD@GetFirstSpaceDelimitedTokenSet{}%
                                      longdefUD@GetFirstSpaceDelimitedTokenSet#1 #2UD@SeLDom{#1 }%
                                      newcommandUD@gobbledot{}%
                                      defUD@gobbledot.{}%
                                      %%------------------------------------------------------------------------------
                                      %% UD@ObtainFirstSpaceDelimitedTokenSetLoop%
                                      %% {<list of space delimited arguments>}%
                                      %% {<action>}%
                                      %%
                                      %% -> <action>{<first element of list of space delimited arguments>}%
                                      %%...............................................................................
                                      %% UD@ObtainFirstSpaceDelimitedTokenSetLoop does--without unwanted brace-re-
                                      %% moval--append the first space delimited argument from a
                                      %% <list of space delimited arguments> as brace-delimited argument behind
                                      %% a set of tokens given as <action>.
                                      newcommandUD@ObtainFirstSpaceDelimitedTokenSetLoop[1]{%
                                      expandafterUD@CheckWhetherNull
                                      expandafter{UD@RemoveTokensTillNextSpace#1}{%
                                      expandafterexpandafterexpandafterUD@Exchange
                                      expandafterexpandafterexpandafter{%
                                      expandafterexpandafterexpandafter{%
                                      expandafterUD@gobbledotUD@BraceStripRemoveNextSpace#1}}%
                                      }{%
                                      expandafterUD@ObtainFirstSpaceDelimitedTokenSetLoop
                                      expandafter{UD@GetFirstSpaceDelimitedTokenSet#1}%
                                      }%
                                      }%
                                      %%------------------------------------------------------------------------------
                                      %% UD@CheckWhetherLastSpaceDelimitedItem
                                      %% {<remaining list of space delimited arguments>}%
                                      %% {<current argument with one trailing space removed>}%
                                      %% {<arguments preceding the current argument gathered
                                      %% so far>}%
                                      %% {<action>}%
                                      %%..............................................................................
                                      %% Case 1: <remaining list of space delimited arguments> is
                                      %% empty.
                                      %% We are done: Thus:
                                      %% <space>% for terminating romannumeral-expansion, and
                                      %% <action>{<arguments preceding the current argument gathered so
                                      %% far><current argument with one trailing space removed>}
                                      %% Case 2: <remaining list of space delimited arguments> consists of a single
                                      %% space.
                                      %% A trailing space was removed. There may be more. Thus:
                                      %% UD@TrimTrailSpaceLoop{%
                                      %% <arguments preceding the current argument gathered so
                                      %% far><current argument with one trailing space removed>%
                                      %% }{<action>}%
                                      %% Neither case 1 nor case 2:
                                      %% The <current argument with one trailing space removed> is not the
                                      %% last argument of the list, thus:
                                      %% For the next iteration
                                      %% - attach it and a trailing space to the <arguments preceding the
                                      %% current argument gathered so far>,
                                      %% - get the first space delimited argument of the <remaining list of
                                      %% space delimited arguments> as <current argument with one trailing
                                      %% space removed>
                                      %% - remove that first space delimited argument from the <remaining list
                                      %% of space delimited arguments>
                                      newcommandUD@CheckWhetherLastSpaceDelimitedItem[4]{%
                                      UD@CheckWhetherNull{#1}{ #4{#3#2}}{%
                                      UD@CheckWhetherLeadingSpace{#1}{%
                                      expandafterUD@CheckWhetherNull
                                      expandafter{UD@removespace#1}{UD@firstoftwo}{UD@secondoftwo}%
                                      }{UD@secondoftwo}%
                                      {UD@TrimTrailSpaceLoop{#3#2}{#4}}%
                                      {%
                                      UD@ObtainFirstSpaceDelimitedTokenSetLoop{.#1UD@SeLDom}{%
                                      expandafterUD@CheckWhetherLastSpaceDelimitedItem
                                      expandafter{UD@RemoveTokensTillNextSpace.#1}%
                                      }{#3#2 }{#4}%
                                      }%
                                      }%
                                      }%
                                      %%==============================================================================
                                      %% UD@TrimAllSurroundSpace{<action>}{<argument>}
                                      %%..............................................................................
                                      %% expandably removes all leading and trailing spaces from <argument> in
                                      %% case at least one leading space is present.
                                      %% Then
                                      %% <action>{<argument without leading and trailing spaces>}
                                      %% is performed.
                                      %%==============================================================================
                                      newcommandUD@TrimAllSurroundSpace[2]{%
                                      romannumeralUD@TrimAllLeadSpace{UD@TrimAllTrailSpace{0 #1}}{#2}%
                                      }%
                                      %%
                                      %% EOF SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %%
                                      %%
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %% SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
                                      %%
                                      %% - REQUIRES SECTION PARAPHERNALIA.
                                      %% - REQUIRES SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                      %%
                                      %%-----------------------------------------------------------------------------
                                      %% Extract first inner comma-delimited argument:
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{<comma list>}
                                      %%
                                      %% yields:
                                      %%
                                      %% <action>{<first item/first comma-delimited argument from comma
                                      %% list with surrounding spaces and one level of surroundinng
                                      %% braces removed if present>}
                                      %%
                                      %% <comma-list> is considered a sequence of comma-delimited arguments.
                                      %%
                                      %% The <first item/first comma-delimited argument from comma list>
                                      %% will be extracted. The remainder of the <comma list> will be discarded.
                                      %%
                                      %% Then space tokens surrounding the <first item/first comma-delimited
                                      %% argument from comma list> will be removed.
                                      %%
                                      %% If removal of surrounding spaces yields emptiness, no tokens will be
                                      %% delivered.
                                      %%
                                      %% If removal of surrounding spaces does not yield emptiness,
                                      %% - one pair of braces surrounding the entire result of space-removal
                                      %% will be removed if present!!!!!
                                      %%
                                      %% - Then the result thereof, no matter if empty or not, will be wrapped
                                      %% in braces and passed on to <action>.
                                      %%
                                      %% This implies you can have <comma-delimited arguments> contain
                                      %% emptiness or commas and spaces by nesting them into braces.
                                      %%
                                      %% Examples:
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{,A,B,C,D,E} yields no token at all
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{{},A,B,C,D,E} yields <action>{}
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{A,B,C,D,E} yields <action>{A}
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{{AB},C,D,E} yields <action>{AB}
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{ AB ,C,D,E} yields <action>{AB}
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{ {AB} ,C,D,E} yields <action>{AB}
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{ { A, B } ,C,D,E} yields <action>{ A, B }
                                      %%
                                      %% UD@ExtractFirstCommaArg{<action>}{ { {AB} } ,C,D,E} yields <action>{ {AB} }
                                      %%
                                      %% Due to romannumeral0-expansion, the result will be delivered after
                                      %% two expansion-steps/after having UD@ExtractFirstCommaArg "hit" via
                                      %% two expandafter(-chains).
                                      %%.............................................................................
                                      newcommandUD@gobbletocomma{}longdefUD@gobbletocomma#1,{}%
                                      newcommandUD@removecomma{}longdefUD@removecomma#1,{#1}%
                                      newcommandUD@removebracesNrmstop[2]{%
                                      UD@CheckWhetherNull{#2}{%
                                      0 %
                                      }{%
                                      expandafterUD@Exchange
                                      expandafter{%
                                      expandafter{UD@removecomma#2,}%
                                      }{0 #1}%
                                      }%
                                      }%
                                      newcommandUD@RemoveFromCommaTillUD@SelDOm{}%
                                      longdefUD@RemoveFromCommaTillUD@SelDOm#1,#2UD@SelDOm{#1,}%
                                      newcommandUD@ExtractFirstCommaArg[2]{%
                                      romannumeral%
                                      UD@ExtractFirstCommaArgLoop{.#2,UD@SelDOm}{#1}%
                                      }%
                                      newcommandUD@ExtractFirstCommaArgLoop[2]{%
                                      expandafterUD@CheckWhetherNullexpandafter{UD@gobbletocomma#1}%
                                      {%
                                      expandafterexpandafterexpandafterUD@Exchange
                                      expandafterexpandafterexpandafter{%
                                      expandafterexpandafterexpandafter{%
                                      expandafterUD@gobbledotUD@removecomma#1}}%
                                      {UD@TrimAllSurroundSpace{%
                                      UD@removebracesNrmstop{#2}%
                                      }}%
                                      }%
                                      {%
                                      expandafterUD@ExtractFirstCommaArgLoop
                                      expandafter{UD@RemoveFromCommaTillUD@SelDOm#1}{#2}%
                                      }%
                                      }%
                                      %%
                                      %% EOF SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %%
                                      %%
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      %% SECTION EXPANDABLE ITERATION ON LIST OF LABELS
                                      %%
                                      %% - REQUIRES SECTION PARAPHERNALIA.
                                      %% - REQUIRES SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
                                      %% - REQUIRES SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
                                      %%
                                      %% eqsRef{<comma-list>}%
                                      %%
                                      %% If <comma-list> contains only commas and/or space tokens, or is empty:
                                      %% yields nothing.
                                      %% !!! Be aware that there is no @bsphack..@esphack for this case.
                                      %% This implies that you will get two spaces in this case if
                                      %% the call to EQsref has both a leading and a trailing space,
                                      %% i.e., is, e.g., <space>EQsref{, ,}<space> !!!
                                      %%
                                      %% If <comma-list> contains one item:
                                      %% yields: Eq~(ref{<item of comma-list>})
                                      %%
                                      %% If <comma-list> contains k items; k > 1:
                                      %% yields:
                                      %% Eq~(ref{<item 1 of comma-list>}%
                                      %% , ref{<item 2 of comma-list>}%
                                      %% [...]%
                                      %% , ref{<item k of comma-list>})%
                                      %%
                                      %% Due to romannumeral0-expansion, the result will be delivered after two
                                      %% expansion-steps/after having eqsRef "hit" via two expandafter(-chains).
                                      %%
                                      newcommandeqsRef[1]{%
                                      romannumeralUD@eqsRefiterator{}{#1,}%
                                      }%
                                      %% UD@eqsRefiterator: #1 -- ref-calls constructed so far
                                      %% #2 -- (remaining) comma-list of labels
                                      %%
                                      newcommandUD@eqsRefiterator[2]{%
                                      UD@CheckWhetherNull{#2}{%
                                      UD@CheckWhetherBlank{#1}{0 }{%
                                      expandafterUD@CheckWhetherNull
                                      expandafter{UD@gobbletocomma#1,}{0 Eq}{0 Eqs}.~(#1)%
                                      }%
                                      }{%
                                      expandafterUD@Exchangeexpandafter{%
                                      expandafter{UD@gobbletocomma#2}%
                                      }{%
                                      expandafterUD@eqsRefiteratorexpandafter{%
                                      romannumeral0%
                                      expandafterexpandafterexpandafterUD@CheckWhetherNull
                                      expandafterexpandafterexpandafter{%
                                      UD@ExtractFirstCommaArg{ref}{#2}%
                                      }{ #1}{%
                                      expandafterexpandafterexpandafterUD@Exchange
                                      expandafterexpandafterexpandafter{%
                                      UD@ExtractFirstCommaArg{ref}{#2}%
                                      }{%
                                      UD@CheckWhetherNull{#1}{ }{ #1, }%
                                      }%
                                      }%
                                      }%
                                      }%
                                      }%
                                      }%
                                      %%
                                      %% EOF SECTION EXPANDABLE ITERATION ON LIST OF LABELS
                                      %%//////////////////////////////////////////////////////////////////////////////
                                      makeatother


                                      newcommandTestGobbleToGT{}%
                                      longdefTestGobbleToGT#1>{}%
                                      newcommandTest[1]{%
                                      expandafterexpandafterexpandafterdef
                                      expandafterexpandafterexpandaftertest
                                      expandafterexpandafterexpandafter{%
                                      #1%
                                      }%
                                      texttt{expandafterTestGobbleToGTmeaningtest}%
                                      parnoindenthrulefill
                                      }%

                                      begin{document}

                                      section*{testing texttt{stringUD@ExtractFirstCommaArg}}

                                      makeatletter

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{,A,B,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{,A,B,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{ {} ,A,B,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{ {} ,A,B,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{{},A,B,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{{},A,B,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{A,B,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{A,B,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{{AB},C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{{AB},C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{ {AB} ,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{ {AB} ,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{ AB ,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{ AB ,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{ {AB},C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{ {AB},C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{{AB} ,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{{AB} ,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{ { A, B } ,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{ { A, B } ,C,D,E}}%

                                      noindentverb|UD@ExtractFirstCommaArg{<Action>}{ { {AB} } ,C,D,E}| yields:\
                                      Test{UD@ExtractFirstCommaArg{<Action>}{ { {AB} } ,C,D,E}}%

                                      makeatother

                                      newpage
                                      section*{testing texttt{stringeqsRef}}

                                      noindentverb|eqsRef{ A ,B, C,D ,,,E, F}| yields:\
                                      Test{eqsRef{ A ,B, C,D ,,,E, F}}%

                                      noindent
                                      Be aware that it is possible to have one nameless referencing-label, \
                                      i.e. verb|label{}| ..verb|ref{}|.\
                                      Here the last thing denotes the nameless label:\
                                      verb|eqsRef{ { A } ,B,C,{}}| yields:\
                                      Test{eqsRef{ { A } ,B,C,{}}}%

                                      noindentverb|eqsRef{ C}| yields:\
                                      Test{eqsRef{ C}}%

                                      noindentverb|eqsRef{ , }| yields:\
                                      Test{eqsRef{ , }}%

                                      noindentverb|eqsRef{ }| yields:\
                                      Test{eqsRef{ }}%

                                      noindentverb|eqsRef{}| yields:\
                                      Test{eqsRef{}}%

                                      end{document}


                                      enter image description hereenter image description here







                                      share|improve this answer














                                      share|improve this answer



                                      share|improve this answer








                                      edited Nov 14 '18 at 13:57

























                                      answered Nov 14 '18 at 11:30









                                      Ulrich Diez

                                      4,145615




                                      4,145615






























                                          draft saved

                                          draft discarded




















































                                          Thanks for contributing an answer to TeX - LaTeX Stack Exchange!


                                          • Please be sure to answer the question. Provide details and share your research!

                                          But avoid



                                          • Asking for help, clarification, or responding to other answers.

                                          • Making statements based on opinion; back them up with references or personal experience.


                                          To learn more, see our tips on writing great answers.





                                          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                          Please pay close attention to the following guidance:


                                          • Please be sure to answer the question. Provide details and share your research!

                                          But avoid



                                          • Asking for help, clarification, or responding to other answers.

                                          • Making statements based on opinion; back them up with references or personal experience.


                                          To learn more, see our tips on writing great answers.




                                          draft saved


                                          draft discarded














                                          StackExchange.ready(
                                          function () {
                                          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f459841%2fcommand-to-format-any-number-of-equations%23new-answer', 'question_page');
                                          }
                                          );

                                          Post as a guest















                                          Required, but never shown





















































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown

































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown







                                          Popular posts from this blog

                                          Guess what letter conforming each word

                                          Port of Spain

                                          Run scheduled task as local user group (not BUILTIN)