Command to format any number of equations
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:
eqsRefequ: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.~(refequ:name_one, refequ:name_two, refequ: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
add a comment |
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:
eqsRefequ: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.~(refequ:name_one, refequ:name_two, refequ: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
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
add a comment |
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:
eqsRefequ: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.~(refequ:name_one, refequ:name_two, refequ: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
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:
eqsRefequ: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.~(refequ:name_one, refequ:name_two, refequ: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
macros cross-referencing comma-separated-list
edited Nov 13 '18 at 20:44
Werner
441k679701662
441k679701662
asked Nov 13 '18 at 20:28
Joan Solà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
add a comment |
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
add a comment |
4 Answers
4
active
oldest
votes
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.
documentclassarticle
usepackageetoolbox,amsmath
newcountereqncount
% eqsRef<csv of labels to equations>
newcommandeqsRef[1]%
setcountereqncount0% Restart equation counter
renewcommand*do[1]stepcountereqncount% Step equation reference counter
docsvlist#1% Count number of equation references
Eq%
ifnumvalueeqncount>1
s% Plural
fi
.nobreakspace
% https://tex.stackexchange.com/a/89187/5764
defeqnrefdelimdefeqnrefdelim, %
renewcommanddoeqnrefdelimref%
textup(%
docsvlist#1%
textup)%
begindocument
beginalign
f(x) labeleqn:first \
s(x) labeleqn:second \
t(x) labeleqn:third \
l(x) labeleqn:last
endalign
eqsRefeqn:first, eqn:second, eqn:last
eqsRefeqn:third
enddocument
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.
add a comment |
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
eqrefsequ:name_one, equ:name_two, equ:name_three
eqrefsequ:name_one,equ:name_two,equ:name_three
eqrefs equ:name_one , equ:name_two, equ:name_three
are equivalent.
documentclassarticle
usepackageamsmath
usepackagexparse
ExplSyntaxOn
NewDocumentCommandeqrefsm
% #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
begindocument
beginalign
a&=b labelequ:name_one \
c&=d labelequ:name_two \
e&=f labelequ:name_three
endalign
eqrefsequ:name_one, equ:name_two, equ:name_three
eqrefsequ:name_one, equ:name_three
eqrefsequ:name_one
enddocument
add a comment |
An approach using package xinttools
, part of the xint
libraries.
documentclassarticle
usepackageamsmath
usepackagexinttools
% eqsRef<csv of labels to equations>
newcommandeqsRef[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)
oodefeqsRefinputxintCSVtoList#1%
% count how many items and typeset either Eq. or Eqs.
EqifnumxintNthElt0eqsRefinput>1
s% Plural
fi
.nobreakspace
textup(%
% Do now an xintFor* loop to act upon each item
xintFor* ##1 in eqsRefinput:
xintifForFirstxintifForLast and , ref##1%
textup)%
%
begindocument
beginalign
f(x) labeleqn:first \
s(x) labeleqn:second \
t(x) labeleqn:third \
u(x) labeleqn:fourth \
l(x) labeleqn:last
endalign
eqsRefeqn:first, eqn:third, eqn:last
eqsRefeqn:third
enddocument
add a comment |
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. ;-) )
documentclassarticle
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@secondoftwostringexpandafter
UD@secondoftwoexpandafterexpandafterstring#1expandafter
UD@secondoftwostringexpandafterUD@firstoftwoexpandafterexpandafter
UD@secondoftwostringexpandafterexpandafterUD@firstoftwo %
UD@secondoftwoexpandafterexpandafterUD@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@CheckWhetherNullexpandafterUD@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@secondoftwostringUD@CheckWhetherLeadingSpaceB.#1 %
%
newcommandUD@CheckWhetherLeadingSpaceB%
longdefUD@CheckWhetherLeadingSpaceB#1 %
expandafterUD@CheckWhetherNullexpandafterUD@secondoftwo#1%
UD@ExchangeUD@firstoftwoUD@ExchangeUD@secondoftwo%
UD@Exchange expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafterexpandafterexpandafter
expandafterexpandafterUD@secondoftwoexpandafterstring%
%
%%==============================================================================
%% 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
expandafterUD@removespace#1#2%
%
#2#1%
%
newcommandUD@removespaceUD@firstoftwodefUD@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
expandafterUD@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
expandafterUD@RemoveTokensTillNextSpace#1%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter%
expandafterexpandafterexpandafter%
expandafterUD@gobbledotUD@BraceStripRemoveNextSpace#1%
%
expandafterUD@ObtainFirstSpaceDelimitedTokenSetLoop
expandafterUD@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
expandafterUD@removespace#1UD@firstoftwoUD@secondoftwo%
UD@secondoftwo%
UD@TrimTrailSpaceLoop#3#2#4%
%
UD@ObtainFirstSpaceDelimitedTokenSetLoop.#1UD@SeLDom%
expandafterUD@CheckWhetherLastSpaceDelimitedItem
expandafterUD@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@TrimAllLeadSpaceUD@TrimAllTrailSpace0 #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@gobbletocommalongdefUD@gobbletocomma#1,%
newcommandUD@removecommalongdefUD@removecomma#1,#1%
newcommandUD@removebracesNrmstop[2]%
UD@CheckWhetherNull#2%
0 %
%
expandafterUD@Exchange
expandafter%
expandafterUD@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@CheckWhetherNullexpandafterUD@gobbletocomma#1%
%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter%
expandafterexpandafterexpandafter%
expandafterUD@gobbledotUD@removecomma#1%
UD@TrimAllSurroundSpace%
UD@removebracesNrmstop#2%
%
%
%
expandafterUD@ExtractFirstCommaArgLoop
expandafterUD@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#10 %
expandafterUD@CheckWhetherNull
expandafterUD@gobbletocomma#1,0 Eq0 Eqs.~(#1)%
%
%
expandafterUD@Exchangeexpandafter%
expandafterUD@gobbletocomma#2%
%
expandafterUD@eqsRefiteratorexpandafter%
romannumeral0%
expandafterexpandafterexpandafterUD@CheckWhetherNull
expandafterexpandafterexpandafter%
UD@ExtractFirstCommaArgref#2%
#1%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter%
UD@ExtractFirstCommaArgref#2%
%
UD@CheckWhetherNull#1 #1, %
%
%
%
%
%
%
%%
%% EOF SECTION EXPANDABLE ITERATION ON LIST OF LABELS
%%//////////////////////////////////////////////////////////////////////////////
makeatother
newcommandTestGobbleToGT%
longdefTestGobbleToGT#1>%
newcommandTest[1]%
expandafterexpandafterexpandafterdef
expandafterexpandafterexpandaftertest
expandafterexpandafterexpandafter%
#1%
%
textttexpandafterTestGobbleToGTmeaningtest%
parnoindenthrulefill
%
begindocument
section*testing textttstringUD@ExtractFirstCommaArg
makeatletter
noindentverb|UD@ExtractFirstCommaArg<Action>,A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>,A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> ,A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> ,A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>,A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>,A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>AB,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>AB,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>AB ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> A, B ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> A, B ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB ,C,D,E%
makeatother
newpage
section*testing textttstringeqsRef
noindentverb|eqsRef A ,B, C,D ,,,E, F| yields:\
TesteqsRef 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:\
TesteqsRef A ,B,C,%
noindentverb|eqsRef C| yields:\
TesteqsRef C%
noindentverb|eqsRef , | yields:\
TesteqsRef , %
noindentverb|eqsRef | yields:\
TesteqsRef %
noindentverb|eqsRef| yields:\
TesteqsRef%
enddocument
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
documentclassarticle
usepackageetoolbox,amsmath
newcountereqncount
% eqsRef<csv of labels to equations>
newcommandeqsRef[1]%
setcountereqncount0% Restart equation counter
renewcommand*do[1]stepcountereqncount% Step equation reference counter
docsvlist#1% Count number of equation references
Eq%
ifnumvalueeqncount>1
s% Plural
fi
.nobreakspace
% https://tex.stackexchange.com/a/89187/5764
defeqnrefdelimdefeqnrefdelim, %
renewcommanddoeqnrefdelimref%
textup(%
docsvlist#1%
textup)%
begindocument
beginalign
f(x) labeleqn:first \
s(x) labeleqn:second \
t(x) labeleqn:third \
l(x) labeleqn:last
endalign
eqsRefeqn:first, eqn:second, eqn:last
eqsRefeqn:third
enddocument
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.
add a comment |
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.
documentclassarticle
usepackageetoolbox,amsmath
newcountereqncount
% eqsRef<csv of labels to equations>
newcommandeqsRef[1]%
setcountereqncount0% Restart equation counter
renewcommand*do[1]stepcountereqncount% Step equation reference counter
docsvlist#1% Count number of equation references
Eq%
ifnumvalueeqncount>1
s% Plural
fi
.nobreakspace
% https://tex.stackexchange.com/a/89187/5764
defeqnrefdelimdefeqnrefdelim, %
renewcommanddoeqnrefdelimref%
textup(%
docsvlist#1%
textup)%
begindocument
beginalign
f(x) labeleqn:first \
s(x) labeleqn:second \
t(x) labeleqn:third \
l(x) labeleqn:last
endalign
eqsRefeqn:first, eqn:second, eqn:last
eqsRefeqn:third
enddocument
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.
add a comment |
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.
documentclassarticle
usepackageetoolbox,amsmath
newcountereqncount
% eqsRef<csv of labels to equations>
newcommandeqsRef[1]%
setcountereqncount0% Restart equation counter
renewcommand*do[1]stepcountereqncount% Step equation reference counter
docsvlist#1% Count number of equation references
Eq%
ifnumvalueeqncount>1
s% Plural
fi
.nobreakspace
% https://tex.stackexchange.com/a/89187/5764
defeqnrefdelimdefeqnrefdelim, %
renewcommanddoeqnrefdelimref%
textup(%
docsvlist#1%
textup)%
begindocument
beginalign
f(x) labeleqn:first \
s(x) labeleqn:second \
t(x) labeleqn:third \
l(x) labeleqn:last
endalign
eqsRefeqn:first, eqn:second, eqn:last
eqsRefeqn:third
enddocument
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.
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.
documentclassarticle
usepackageetoolbox,amsmath
newcountereqncount
% eqsRef<csv of labels to equations>
newcommandeqsRef[1]%
setcountereqncount0% Restart equation counter
renewcommand*do[1]stepcountereqncount% Step equation reference counter
docsvlist#1% Count number of equation references
Eq%
ifnumvalueeqncount>1
s% Plural
fi
.nobreakspace
% https://tex.stackexchange.com/a/89187/5764
defeqnrefdelimdefeqnrefdelim, %
renewcommanddoeqnrefdelimref%
textup(%
docsvlist#1%
textup)%
begindocument
beginalign
f(x) labeleqn:first \
s(x) labeleqn:second \
t(x) labeleqn:third \
l(x) labeleqn:last
endalign
eqsRefeqn:first, eqn:second, eqn:last
eqsRefeqn:third
enddocument
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.
answered Nov 13 '18 at 20:43
WernerWerner
441k679701662
441k679701662
add a comment |
add a comment |
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
eqrefsequ:name_one, equ:name_two, equ:name_three
eqrefsequ:name_one,equ:name_two,equ:name_three
eqrefs equ:name_one , equ:name_two, equ:name_three
are equivalent.
documentclassarticle
usepackageamsmath
usepackagexparse
ExplSyntaxOn
NewDocumentCommandeqrefsm
% #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
begindocument
beginalign
a&=b labelequ:name_one \
c&=d labelequ:name_two \
e&=f labelequ:name_three
endalign
eqrefsequ:name_one, equ:name_two, equ:name_three
eqrefsequ:name_one, equ:name_three
eqrefsequ:name_one
enddocument
add a comment |
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
eqrefsequ:name_one, equ:name_two, equ:name_three
eqrefsequ:name_one,equ:name_two,equ:name_three
eqrefs equ:name_one , equ:name_two, equ:name_three
are equivalent.
documentclassarticle
usepackageamsmath
usepackagexparse
ExplSyntaxOn
NewDocumentCommandeqrefsm
% #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
begindocument
beginalign
a&=b labelequ:name_one \
c&=d labelequ:name_two \
e&=f labelequ:name_three
endalign
eqrefsequ:name_one, equ:name_two, equ:name_three
eqrefsequ:name_one, equ:name_three
eqrefsequ:name_one
enddocument
add a comment |
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
eqrefsequ:name_one, equ:name_two, equ:name_three
eqrefsequ:name_one,equ:name_two,equ:name_three
eqrefs equ:name_one , equ:name_two, equ:name_three
are equivalent.
documentclassarticle
usepackageamsmath
usepackagexparse
ExplSyntaxOn
NewDocumentCommandeqrefsm
% #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
begindocument
beginalign
a&=b labelequ:name_one \
c&=d labelequ:name_two \
e&=f labelequ:name_three
endalign
eqrefsequ:name_one, equ:name_two, equ:name_three
eqrefsequ:name_one, equ:name_three
eqrefsequ:name_one
enddocument
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
eqrefsequ:name_one, equ:name_two, equ:name_three
eqrefsequ:name_one,equ:name_two,equ:name_three
eqrefs equ:name_one , equ:name_two, equ:name_three
are equivalent.
documentclassarticle
usepackageamsmath
usepackagexparse
ExplSyntaxOn
NewDocumentCommandeqrefsm
% #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
begindocument
beginalign
a&=b labelequ:name_one \
c&=d labelequ:name_two \
e&=f labelequ:name_three
endalign
eqrefsequ:name_one, equ:name_two, equ:name_three
eqrefsequ:name_one, equ:name_three
eqrefsequ:name_one
enddocument
answered Nov 13 '18 at 23:29
egregegreg
714k8618983184
714k8618983184
add a comment |
add a comment |
An approach using package xinttools
, part of the xint
libraries.
documentclassarticle
usepackageamsmath
usepackagexinttools
% eqsRef<csv of labels to equations>
newcommandeqsRef[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)
oodefeqsRefinputxintCSVtoList#1%
% count how many items and typeset either Eq. or Eqs.
EqifnumxintNthElt0eqsRefinput>1
s% Plural
fi
.nobreakspace
textup(%
% Do now an xintFor* loop to act upon each item
xintFor* ##1 in eqsRefinput:
xintifForFirstxintifForLast and , ref##1%
textup)%
%
begindocument
beginalign
f(x) labeleqn:first \
s(x) labeleqn:second \
t(x) labeleqn:third \
u(x) labeleqn:fourth \
l(x) labeleqn:last
endalign
eqsRefeqn:first, eqn:third, eqn:last
eqsRefeqn:third
enddocument
add a comment |
An approach using package xinttools
, part of the xint
libraries.
documentclassarticle
usepackageamsmath
usepackagexinttools
% eqsRef<csv of labels to equations>
newcommandeqsRef[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)
oodefeqsRefinputxintCSVtoList#1%
% count how many items and typeset either Eq. or Eqs.
EqifnumxintNthElt0eqsRefinput>1
s% Plural
fi
.nobreakspace
textup(%
% Do now an xintFor* loop to act upon each item
xintFor* ##1 in eqsRefinput:
xintifForFirstxintifForLast and , ref##1%
textup)%
%
begindocument
beginalign
f(x) labeleqn:first \
s(x) labeleqn:second \
t(x) labeleqn:third \
u(x) labeleqn:fourth \
l(x) labeleqn:last
endalign
eqsRefeqn:first, eqn:third, eqn:last
eqsRefeqn:third
enddocument
add a comment |
An approach using package xinttools
, part of the xint
libraries.
documentclassarticle
usepackageamsmath
usepackagexinttools
% eqsRef<csv of labels to equations>
newcommandeqsRef[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)
oodefeqsRefinputxintCSVtoList#1%
% count how many items and typeset either Eq. or Eqs.
EqifnumxintNthElt0eqsRefinput>1
s% Plural
fi
.nobreakspace
textup(%
% Do now an xintFor* loop to act upon each item
xintFor* ##1 in eqsRefinput:
xintifForFirstxintifForLast and , ref##1%
textup)%
%
begindocument
beginalign
f(x) labeleqn:first \
s(x) labeleqn:second \
t(x) labeleqn:third \
u(x) labeleqn:fourth \
l(x) labeleqn:last
endalign
eqsRefeqn:first, eqn:third, eqn:last
eqsRefeqn:third
enddocument
An approach using package xinttools
, part of the xint
libraries.
documentclassarticle
usepackageamsmath
usepackagexinttools
% eqsRef<csv of labels to equations>
newcommandeqsRef[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)
oodefeqsRefinputxintCSVtoList#1%
% count how many items and typeset either Eq. or Eqs.
EqifnumxintNthElt0eqsRefinput>1
s% Plural
fi
.nobreakspace
textup(%
% Do now an xintFor* loop to act upon each item
xintFor* ##1 in eqsRefinput:
xintifForFirstxintifForLast and , ref##1%
textup)%
%
begindocument
beginalign
f(x) labeleqn:first \
s(x) labeleqn:second \
t(x) labeleqn:third \
u(x) labeleqn:fourth \
l(x) labeleqn:last
endalign
eqsRefeqn:first, eqn:third, eqn:last
eqsRefeqn:third
enddocument
answered Nov 14 '18 at 13:34
jfbujfbu
47k66149
47k66149
add a comment |
add a comment |
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. ;-) )
documentclassarticle
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@secondoftwostringexpandafter
UD@secondoftwoexpandafterexpandafterstring#1expandafter
UD@secondoftwostringexpandafterUD@firstoftwoexpandafterexpandafter
UD@secondoftwostringexpandafterexpandafterUD@firstoftwo %
UD@secondoftwoexpandafterexpandafterUD@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@CheckWhetherNullexpandafterUD@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@secondoftwostringUD@CheckWhetherLeadingSpaceB.#1 %
%
newcommandUD@CheckWhetherLeadingSpaceB%
longdefUD@CheckWhetherLeadingSpaceB#1 %
expandafterUD@CheckWhetherNullexpandafterUD@secondoftwo#1%
UD@ExchangeUD@firstoftwoUD@ExchangeUD@secondoftwo%
UD@Exchange expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafterexpandafterexpandafter
expandafterexpandafterUD@secondoftwoexpandafterstring%
%
%%==============================================================================
%% 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
expandafterUD@removespace#1#2%
%
#2#1%
%
newcommandUD@removespaceUD@firstoftwodefUD@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
expandafterUD@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
expandafterUD@RemoveTokensTillNextSpace#1%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter%
expandafterexpandafterexpandafter%
expandafterUD@gobbledotUD@BraceStripRemoveNextSpace#1%
%
expandafterUD@ObtainFirstSpaceDelimitedTokenSetLoop
expandafterUD@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
expandafterUD@removespace#1UD@firstoftwoUD@secondoftwo%
UD@secondoftwo%
UD@TrimTrailSpaceLoop#3#2#4%
%
UD@ObtainFirstSpaceDelimitedTokenSetLoop.#1UD@SeLDom%
expandafterUD@CheckWhetherLastSpaceDelimitedItem
expandafterUD@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@TrimAllLeadSpaceUD@TrimAllTrailSpace0 #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@gobbletocommalongdefUD@gobbletocomma#1,%
newcommandUD@removecommalongdefUD@removecomma#1,#1%
newcommandUD@removebracesNrmstop[2]%
UD@CheckWhetherNull#2%
0 %
%
expandafterUD@Exchange
expandafter%
expandafterUD@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@CheckWhetherNullexpandafterUD@gobbletocomma#1%
%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter%
expandafterexpandafterexpandafter%
expandafterUD@gobbledotUD@removecomma#1%
UD@TrimAllSurroundSpace%
UD@removebracesNrmstop#2%
%
%
%
expandafterUD@ExtractFirstCommaArgLoop
expandafterUD@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#10 %
expandafterUD@CheckWhetherNull
expandafterUD@gobbletocomma#1,0 Eq0 Eqs.~(#1)%
%
%
expandafterUD@Exchangeexpandafter%
expandafterUD@gobbletocomma#2%
%
expandafterUD@eqsRefiteratorexpandafter%
romannumeral0%
expandafterexpandafterexpandafterUD@CheckWhetherNull
expandafterexpandafterexpandafter%
UD@ExtractFirstCommaArgref#2%
#1%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter%
UD@ExtractFirstCommaArgref#2%
%
UD@CheckWhetherNull#1 #1, %
%
%
%
%
%
%
%%
%% EOF SECTION EXPANDABLE ITERATION ON LIST OF LABELS
%%//////////////////////////////////////////////////////////////////////////////
makeatother
newcommandTestGobbleToGT%
longdefTestGobbleToGT#1>%
newcommandTest[1]%
expandafterexpandafterexpandafterdef
expandafterexpandafterexpandaftertest
expandafterexpandafterexpandafter%
#1%
%
textttexpandafterTestGobbleToGTmeaningtest%
parnoindenthrulefill
%
begindocument
section*testing textttstringUD@ExtractFirstCommaArg
makeatletter
noindentverb|UD@ExtractFirstCommaArg<Action>,A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>,A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> ,A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> ,A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>,A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>,A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>AB,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>AB,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>AB ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> A, B ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> A, B ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB ,C,D,E%
makeatother
newpage
section*testing textttstringeqsRef
noindentverb|eqsRef A ,B, C,D ,,,E, F| yields:\
TesteqsRef 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:\
TesteqsRef A ,B,C,%
noindentverb|eqsRef C| yields:\
TesteqsRef C%
noindentverb|eqsRef , | yields:\
TesteqsRef , %
noindentverb|eqsRef | yields:\
TesteqsRef %
noindentverb|eqsRef| yields:\
TesteqsRef%
enddocument
add a comment |
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. ;-) )
documentclassarticle
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@secondoftwostringexpandafter
UD@secondoftwoexpandafterexpandafterstring#1expandafter
UD@secondoftwostringexpandafterUD@firstoftwoexpandafterexpandafter
UD@secondoftwostringexpandafterexpandafterUD@firstoftwo %
UD@secondoftwoexpandafterexpandafterUD@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@CheckWhetherNullexpandafterUD@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@secondoftwostringUD@CheckWhetherLeadingSpaceB.#1 %
%
newcommandUD@CheckWhetherLeadingSpaceB%
longdefUD@CheckWhetherLeadingSpaceB#1 %
expandafterUD@CheckWhetherNullexpandafterUD@secondoftwo#1%
UD@ExchangeUD@firstoftwoUD@ExchangeUD@secondoftwo%
UD@Exchange expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafterexpandafterexpandafter
expandafterexpandafterUD@secondoftwoexpandafterstring%
%
%%==============================================================================
%% 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
expandafterUD@removespace#1#2%
%
#2#1%
%
newcommandUD@removespaceUD@firstoftwodefUD@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
expandafterUD@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
expandafterUD@RemoveTokensTillNextSpace#1%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter%
expandafterexpandafterexpandafter%
expandafterUD@gobbledotUD@BraceStripRemoveNextSpace#1%
%
expandafterUD@ObtainFirstSpaceDelimitedTokenSetLoop
expandafterUD@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
expandafterUD@removespace#1UD@firstoftwoUD@secondoftwo%
UD@secondoftwo%
UD@TrimTrailSpaceLoop#3#2#4%
%
UD@ObtainFirstSpaceDelimitedTokenSetLoop.#1UD@SeLDom%
expandafterUD@CheckWhetherLastSpaceDelimitedItem
expandafterUD@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@TrimAllLeadSpaceUD@TrimAllTrailSpace0 #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@gobbletocommalongdefUD@gobbletocomma#1,%
newcommandUD@removecommalongdefUD@removecomma#1,#1%
newcommandUD@removebracesNrmstop[2]%
UD@CheckWhetherNull#2%
0 %
%
expandafterUD@Exchange
expandafter%
expandafterUD@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@CheckWhetherNullexpandafterUD@gobbletocomma#1%
%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter%
expandafterexpandafterexpandafter%
expandafterUD@gobbledotUD@removecomma#1%
UD@TrimAllSurroundSpace%
UD@removebracesNrmstop#2%
%
%
%
expandafterUD@ExtractFirstCommaArgLoop
expandafterUD@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#10 %
expandafterUD@CheckWhetherNull
expandafterUD@gobbletocomma#1,0 Eq0 Eqs.~(#1)%
%
%
expandafterUD@Exchangeexpandafter%
expandafterUD@gobbletocomma#2%
%
expandafterUD@eqsRefiteratorexpandafter%
romannumeral0%
expandafterexpandafterexpandafterUD@CheckWhetherNull
expandafterexpandafterexpandafter%
UD@ExtractFirstCommaArgref#2%
#1%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter%
UD@ExtractFirstCommaArgref#2%
%
UD@CheckWhetherNull#1 #1, %
%
%
%
%
%
%
%%
%% EOF SECTION EXPANDABLE ITERATION ON LIST OF LABELS
%%//////////////////////////////////////////////////////////////////////////////
makeatother
newcommandTestGobbleToGT%
longdefTestGobbleToGT#1>%
newcommandTest[1]%
expandafterexpandafterexpandafterdef
expandafterexpandafterexpandaftertest
expandafterexpandafterexpandafter%
#1%
%
textttexpandafterTestGobbleToGTmeaningtest%
parnoindenthrulefill
%
begindocument
section*testing textttstringUD@ExtractFirstCommaArg
makeatletter
noindentverb|UD@ExtractFirstCommaArg<Action>,A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>,A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> ,A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> ,A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>,A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>,A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>AB,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>AB,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>AB ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> A, B ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> A, B ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB ,C,D,E%
makeatother
newpage
section*testing textttstringeqsRef
noindentverb|eqsRef A ,B, C,D ,,,E, F| yields:\
TesteqsRef 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:\
TesteqsRef A ,B,C,%
noindentverb|eqsRef C| yields:\
TesteqsRef C%
noindentverb|eqsRef , | yields:\
TesteqsRef , %
noindentverb|eqsRef | yields:\
TesteqsRef %
noindentverb|eqsRef| yields:\
TesteqsRef%
enddocument
add a comment |
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. ;-) )
documentclassarticle
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@secondoftwostringexpandafter
UD@secondoftwoexpandafterexpandafterstring#1expandafter
UD@secondoftwostringexpandafterUD@firstoftwoexpandafterexpandafter
UD@secondoftwostringexpandafterexpandafterUD@firstoftwo %
UD@secondoftwoexpandafterexpandafterUD@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@CheckWhetherNullexpandafterUD@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@secondoftwostringUD@CheckWhetherLeadingSpaceB.#1 %
%
newcommandUD@CheckWhetherLeadingSpaceB%
longdefUD@CheckWhetherLeadingSpaceB#1 %
expandafterUD@CheckWhetherNullexpandafterUD@secondoftwo#1%
UD@ExchangeUD@firstoftwoUD@ExchangeUD@secondoftwo%
UD@Exchange expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafterexpandafterexpandafter
expandafterexpandafterUD@secondoftwoexpandafterstring%
%
%%==============================================================================
%% 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
expandafterUD@removespace#1#2%
%
#2#1%
%
newcommandUD@removespaceUD@firstoftwodefUD@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
expandafterUD@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
expandafterUD@RemoveTokensTillNextSpace#1%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter%
expandafterexpandafterexpandafter%
expandafterUD@gobbledotUD@BraceStripRemoveNextSpace#1%
%
expandafterUD@ObtainFirstSpaceDelimitedTokenSetLoop
expandafterUD@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
expandafterUD@removespace#1UD@firstoftwoUD@secondoftwo%
UD@secondoftwo%
UD@TrimTrailSpaceLoop#3#2#4%
%
UD@ObtainFirstSpaceDelimitedTokenSetLoop.#1UD@SeLDom%
expandafterUD@CheckWhetherLastSpaceDelimitedItem
expandafterUD@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@TrimAllLeadSpaceUD@TrimAllTrailSpace0 #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@gobbletocommalongdefUD@gobbletocomma#1,%
newcommandUD@removecommalongdefUD@removecomma#1,#1%
newcommandUD@removebracesNrmstop[2]%
UD@CheckWhetherNull#2%
0 %
%
expandafterUD@Exchange
expandafter%
expandafterUD@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@CheckWhetherNullexpandafterUD@gobbletocomma#1%
%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter%
expandafterexpandafterexpandafter%
expandafterUD@gobbledotUD@removecomma#1%
UD@TrimAllSurroundSpace%
UD@removebracesNrmstop#2%
%
%
%
expandafterUD@ExtractFirstCommaArgLoop
expandafterUD@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#10 %
expandafterUD@CheckWhetherNull
expandafterUD@gobbletocomma#1,0 Eq0 Eqs.~(#1)%
%
%
expandafterUD@Exchangeexpandafter%
expandafterUD@gobbletocomma#2%
%
expandafterUD@eqsRefiteratorexpandafter%
romannumeral0%
expandafterexpandafterexpandafterUD@CheckWhetherNull
expandafterexpandafterexpandafter%
UD@ExtractFirstCommaArgref#2%
#1%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter%
UD@ExtractFirstCommaArgref#2%
%
UD@CheckWhetherNull#1 #1, %
%
%
%
%
%
%
%%
%% EOF SECTION EXPANDABLE ITERATION ON LIST OF LABELS
%%//////////////////////////////////////////////////////////////////////////////
makeatother
newcommandTestGobbleToGT%
longdefTestGobbleToGT#1>%
newcommandTest[1]%
expandafterexpandafterexpandafterdef
expandafterexpandafterexpandaftertest
expandafterexpandafterexpandafter%
#1%
%
textttexpandafterTestGobbleToGTmeaningtest%
parnoindenthrulefill
%
begindocument
section*testing textttstringUD@ExtractFirstCommaArg
makeatletter
noindentverb|UD@ExtractFirstCommaArg<Action>,A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>,A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> ,A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> ,A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>,A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>,A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>AB,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>AB,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>AB ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> A, B ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> A, B ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB ,C,D,E%
makeatother
newpage
section*testing textttstringeqsRef
noindentverb|eqsRef A ,B, C,D ,,,E, F| yields:\
TesteqsRef 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:\
TesteqsRef A ,B,C,%
noindentverb|eqsRef C| yields:\
TesteqsRef C%
noindentverb|eqsRef , | yields:\
TesteqsRef , %
noindentverb|eqsRef | yields:\
TesteqsRef %
noindentverb|eqsRef| yields:\
TesteqsRef%
enddocument
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. ;-) )
documentclassarticle
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@secondoftwostringexpandafter
UD@secondoftwoexpandafterexpandafterstring#1expandafter
UD@secondoftwostringexpandafterUD@firstoftwoexpandafterexpandafter
UD@secondoftwostringexpandafterexpandafterUD@firstoftwo %
UD@secondoftwoexpandafterexpandafterUD@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@CheckWhetherNullexpandafterUD@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@secondoftwostringUD@CheckWhetherLeadingSpaceB.#1 %
%
newcommandUD@CheckWhetherLeadingSpaceB%
longdefUD@CheckWhetherLeadingSpaceB#1 %
expandafterUD@CheckWhetherNullexpandafterUD@secondoftwo#1%
UD@ExchangeUD@firstoftwoUD@ExchangeUD@secondoftwo%
UD@Exchange expandafterexpandafterexpandafterexpandafter
expandafterexpandafterexpandafterexpandafterexpandafter
expandafterexpandafterUD@secondoftwoexpandafterstring%
%
%%==============================================================================
%% 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
expandafterUD@removespace#1#2%
%
#2#1%
%
newcommandUD@removespaceUD@firstoftwodefUD@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
expandafterUD@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
expandafterUD@RemoveTokensTillNextSpace#1%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter%
expandafterexpandafterexpandafter%
expandafterUD@gobbledotUD@BraceStripRemoveNextSpace#1%
%
expandafterUD@ObtainFirstSpaceDelimitedTokenSetLoop
expandafterUD@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
expandafterUD@removespace#1UD@firstoftwoUD@secondoftwo%
UD@secondoftwo%
UD@TrimTrailSpaceLoop#3#2#4%
%
UD@ObtainFirstSpaceDelimitedTokenSetLoop.#1UD@SeLDom%
expandafterUD@CheckWhetherLastSpaceDelimitedItem
expandafterUD@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@TrimAllLeadSpaceUD@TrimAllTrailSpace0 #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@gobbletocommalongdefUD@gobbletocomma#1,%
newcommandUD@removecommalongdefUD@removecomma#1,#1%
newcommandUD@removebracesNrmstop[2]%
UD@CheckWhetherNull#2%
0 %
%
expandafterUD@Exchange
expandafter%
expandafterUD@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@CheckWhetherNullexpandafterUD@gobbletocomma#1%
%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter%
expandafterexpandafterexpandafter%
expandafterUD@gobbledotUD@removecomma#1%
UD@TrimAllSurroundSpace%
UD@removebracesNrmstop#2%
%
%
%
expandafterUD@ExtractFirstCommaArgLoop
expandafterUD@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#10 %
expandafterUD@CheckWhetherNull
expandafterUD@gobbletocomma#1,0 Eq0 Eqs.~(#1)%
%
%
expandafterUD@Exchangeexpandafter%
expandafterUD@gobbletocomma#2%
%
expandafterUD@eqsRefiteratorexpandafter%
romannumeral0%
expandafterexpandafterexpandafterUD@CheckWhetherNull
expandafterexpandafterexpandafter%
UD@ExtractFirstCommaArgref#2%
#1%
expandafterexpandafterexpandafterUD@Exchange
expandafterexpandafterexpandafter%
UD@ExtractFirstCommaArgref#2%
%
UD@CheckWhetherNull#1 #1, %
%
%
%
%
%
%
%%
%% EOF SECTION EXPANDABLE ITERATION ON LIST OF LABELS
%%//////////////////////////////////////////////////////////////////////////////
makeatother
newcommandTestGobbleToGT%
longdefTestGobbleToGT#1>%
newcommandTest[1]%
expandafterexpandafterexpandafterdef
expandafterexpandafterexpandaftertest
expandafterexpandafterexpandafter%
#1%
%
textttexpandafterTestGobbleToGTmeaningtest%
parnoindenthrulefill
%
begindocument
section*testing textttstringUD@ExtractFirstCommaArg
makeatletter
noindentverb|UD@ExtractFirstCommaArg<Action>,A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>,A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> ,A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> ,A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>,A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>,A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>A,B,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>A,B,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>AB,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>AB,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action>AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action>AB ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> A, B ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> A, B ,C,D,E%
noindentverb|UD@ExtractFirstCommaArg<Action> AB ,C,D,E| yields:\
TestUD@ExtractFirstCommaArg<Action> AB ,C,D,E%
makeatother
newpage
section*testing textttstringeqsRef
noindentverb|eqsRef A ,B, C,D ,,,E, F| yields:\
TesteqsRef 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:\
TesteqsRef A ,B,C,%
noindentverb|eqsRef C| yields:\
TesteqsRef C%
noindentverb|eqsRef , | yields:\
TesteqsRef , %
noindentverb|eqsRef | yields:\
TesteqsRef %
noindentverb|eqsRef| yields:\
TesteqsRef%
enddocument
edited Nov 14 '18 at 13:57
answered Nov 14 '18 at 11:30
Ulrich DiezUlrich Diez
4,295615
4,295615
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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