A command with a variable number of arguments: comma versus andCommands that may take a variable number of argumentsrelative hspace in newcommandIterating through comma-separated argumentsCommand with variable number of arguments to format menu sequencesProcessing “List” of “List”Aliasing a variable argument command into tabular environmentDynamic length variable with argument? (like “setlengthfoo[1]0.5+#1*0.5”)Variable number of arguments in a commandOptional arguments in “families”… When and how?Command to format any number of equationsAn ellipsis with N dots

How does one intimidate enemies without having the capacity for violence?

Is it possible to make sharp wind that can cut stuff from afar?

How do you conduct xenoanthropology after first contact?

How can the DM most effectively choose 1 out of an odd number of players to be targeted by an attack or effect?

What would the Romans have called "sorcery"?

Japan - Plan around max visa duration

DOS, create pipe for stdin/stdout of command.com(or 4dos.com) in C or Batch?

"which" command doesn't work / path of Safari?

Is there really no realistic way for a skeleton monster to move around without magic?

Why doesn't Newton's third law mean a person bounces back to where they started when they hit the ground?

Why Is Death Allowed In the Matrix?

Banach space and Hilbert space topology

Why can't I see bouncing of a switch on an oscilloscope?

How to calculate implied correlation via observed market price (Margrabe option)

What is the white spray-pattern residue inside these Falcon Heavy nozzles?

How do I create uniquely male characters?

Can Medicine checks be used, with decent rolls, to completely mitigate the risk of death from ongoing damage?

Extreme, but not acceptable situation and I can't start the work tomorrow morning

What Brexit solution does the DUP want?

What makes Graph invariants so useful/important?

Could a US political party gain complete control over the government by removing checks & balances?

Why is an old chain unsafe?

TGV timetables / schedules?

Copenhagen passport control - US citizen



A command with a variable number of arguments: comma versus and


Commands that may take a variable number of argumentsrelative hspace in newcommandIterating through comma-separated argumentsCommand with variable number of arguments to format menu sequencesProcessing “List” of “List”Aliasing a variable argument command into tabular environmentDynamic length variable with argument? (like “setlengthfoo[1]0.5+#1*0.5”)Variable number of arguments in a commandOptional arguments in “families”… When and how?Command to format any number of equationsAn ellipsis with N dots













2















I have the following command: newcommandtriangles[2]triangles $triangle #1$ and $triangle #2, such that trianglesABCDEF produces triangles $triangle ABC$ and $triangle DEF$. I would like to expand that command such that it can take any number of arguments and such that trianglesABCDEFGHIJKL produces triangles $triangle ABC$, $triangle DEF$, $triangle GHI$ and $triangle DEF$. I have seen a solution somewhere for a shoppinglist that makes use of makeatletter and some TeX command, but this is more difficult, I think, because before you add the current argument, you need to know whether it is the last argument (if not: put a comma, if yes: put "and").










share|improve this question
























  • For the sake of unambiguity regarding the question which brace groups belong to triangles and which do not, I strongly recommend a syntax like trianglesABCDEFGHI. Or a syntax without brace-groups at all, as suggested by egreg, trianglesABC,DEF,GHI.

    – Ulrich Diez
    Mar 27 at 19:25















2















I have the following command: newcommandtriangles[2]triangles $triangle #1$ and $triangle #2, such that trianglesABCDEF produces triangles $triangle ABC$ and $triangle DEF$. I would like to expand that command such that it can take any number of arguments and such that trianglesABCDEFGHIJKL produces triangles $triangle ABC$, $triangle DEF$, $triangle GHI$ and $triangle DEF$. I have seen a solution somewhere for a shoppinglist that makes use of makeatletter and some TeX command, but this is more difficult, I think, because before you add the current argument, you need to know whether it is the last argument (if not: put a comma, if yes: put "and").










share|improve this question
























  • For the sake of unambiguity regarding the question which brace groups belong to triangles and which do not, I strongly recommend a syntax like trianglesABCDEFGHI. Or a syntax without brace-groups at all, as suggested by egreg, trianglesABC,DEF,GHI.

    – Ulrich Diez
    Mar 27 at 19:25













2












2








2








I have the following command: newcommandtriangles[2]triangles $triangle #1$ and $triangle #2, such that trianglesABCDEF produces triangles $triangle ABC$ and $triangle DEF$. I would like to expand that command such that it can take any number of arguments and such that trianglesABCDEFGHIJKL produces triangles $triangle ABC$, $triangle DEF$, $triangle GHI$ and $triangle DEF$. I have seen a solution somewhere for a shoppinglist that makes use of makeatletter and some TeX command, but this is more difficult, I think, because before you add the current argument, you need to know whether it is the last argument (if not: put a comma, if yes: put "and").










share|improve this question
















I have the following command: newcommandtriangles[2]triangles $triangle #1$ and $triangle #2, such that trianglesABCDEF produces triangles $triangle ABC$ and $triangle DEF$. I would like to expand that command such that it can take any number of arguments and such that trianglesABCDEFGHIJKL produces triangles $triangle ABC$, $triangle DEF$, $triangle GHI$ and $triangle DEF$. I have seen a solution somewhere for a shoppinglist that makes use of makeatletter and some TeX command, but this is more difficult, I think, because before you add the current argument, you need to know whether it is the last argument (if not: put a comma, if yes: put "and").







macros






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 27 at 14:13









egreg

732k8919303253




732k8919303253










asked Mar 27 at 13:59









BartBart

111




111












  • For the sake of unambiguity regarding the question which brace groups belong to triangles and which do not, I strongly recommend a syntax like trianglesABCDEFGHI. Or a syntax without brace-groups at all, as suggested by egreg, trianglesABC,DEF,GHI.

    – Ulrich Diez
    Mar 27 at 19:25

















  • For the sake of unambiguity regarding the question which brace groups belong to triangles and which do not, I strongly recommend a syntax like trianglesABCDEFGHI. Or a syntax without brace-groups at all, as suggested by egreg, trianglesABC,DEF,GHI.

    – Ulrich Diez
    Mar 27 at 19:25
















For the sake of unambiguity regarding the question which brace groups belong to triangles and which do not, I strongly recommend a syntax like trianglesABCDEFGHI. Or a syntax without brace-groups at all, as suggested by egreg, trianglesABC,DEF,GHI.

– Ulrich Diez
Mar 27 at 19:25





For the sake of unambiguity regarding the question which brace groups belong to triangles and which do not, I strongly recommend a syntax like trianglesABCDEFGHI. Or a syntax without brace-groups at all, as suggested by egreg, trianglesABC,DEF,GHI.

– Ulrich Diez
Mar 27 at 19:25










4 Answers
4






active

oldest

votes


















4














The shoppinglist you're talking about is at Writing a LaTeX macro that takes a variable number of arguments.



You can adapt it quickly to work with any number of triangles. The case with one triangle is also handled in order to only display "Triangle" instead of "Triangles".



documentclass[11pt]article

makeatletter
newcommandtriangles[1]%
checknextarg#1
newcommandchecknextarg[1]%
@ifnextcharbgroupTriangles $triangle #1$gobblenextargTriangle $triangle #1$
newcommandgobblenextarg[1]%
@ifnextcharbgroup, $triangle #1$gobblenextarg and $triangle #1$
makeatother

begindocument

trianglesABC

trianglesABCDEF

trianglesABCDEFGHI

trianglesABCDEFGHIJKL

enddocument


This is the result obtained:



Triangles



EDIT



Following the comment by Ulrich Diez, an improved version of this command would be:



documentclass[11pt]article

usepackageltxcmds

makeatletter
newcommandtriangles[1]%
checknextarg#1
newcommandchecknextarg[1]%
ltx@ifnextchar@nospacebgroupTriangles $triangle #1$gobblenextargTriangle $triangle #1$
newcommandgobblenextarg[1]%
ltx@ifnextchar@nospacebgroup, $triangle #1$gobblenextarg and $triangle #1$
makeatother

begindocument

trianglesABC

trianglesABCDEF

trianglesABCDEFGHI

trianglesABCDEFGHIJKL

trianglesABCDEFGHIJKL Large This shall not be part of the command

enddocument


where ltx@ifnextchar@nospace does not skip space and prevent the text after the command to be interpreted as an "argument" of the command triangles.



However, as stated in egreg's answer, this way of doing things should be avoided.






share|improve this answer




















  • 1





    What about trianglesABCDEFGHIJKL large This shall not be part of the triangle-command ?

    – Ulrich Diez
    Mar 27 at 19:29


















3














Macros with a variable number of arguments are not the best thing to do with LaTeX; in your case it's simpler to use a comma separated list of triangles.



documentclassarticle
usepackagexparse

ExplSyntaxOn

NewDocumentCommandtrianglesm

bart_triangles:n #1


seq_new:N l__bart_triangles_seq
tl_new:N l__bart_triangles_item_tl

cs_new_protected:Nn bart_triangles:n

seq_clear:N l__bart_triangles_seq
clist_map_variable:nNn #1 l__bart_triangles_item_tl

__bart_triangles_add:V l__bart_triangles_item_tl

triangle
int_compare:nF seq_count:N l__bart_triangles_seq < 2 s
nobreakspace
seq_use:Nnnn l__bart_triangles_seq ~and~ ,~ ~and~


cs_new_protected:Nn __bart_triangles_add:n

seq_put_right:Nn l__bart_triangles_seq $triangle #1$

cs_generate_variant:Nn __bart_triangles_add:n V

ExplSyntaxOff

begindocument

trianglesABC

trianglesABC,DEF

trianglesABC,DEF,GHI

enddocument


The comma separated list is mapped and each item is added to a sequence in the form $triangle<vertices>$. Then the sequence is used, with the specified separators (between two, between more than two, between last two).



The “s” is added only if the list contains at least two items.



enter image description here






share|improve this answer






























    1














    A listofitems approach. Note: I was taught that for a list of more than 2 items, a comma precedes the "and".



    documentclassarticle
    usepackagelistofitems
    newcommandtriangles[1]%
    setsepchar,%
    readlisttrilist#1%
    foreachitemxintrilist[]%
    $trianglex$%
    ifnumnumexprxcnt+1<listlentrilist[]relax%
    , %
    else%
    ifnumnumexprxcnt+1=listlentrilist[]relax%
    ifnumlistlentrilist[]>2relax,fi
    and %
    fi
    fi%
    %

    begindocument
    Given trianglesABC.par
    Given trianglesABC, DEF.par
    Given trianglesABC, DEF,GHI.par
    Given trianglesABC, DEF,GHI, JKL.par
    enddocument


    enter image description here






    share|improve this answer






























      1














      What about
      trianglesABCDEFGHIJKL large This shall not be part of the triangle-command ?



      For the sake of unambiguity regarding the question which brace groups belong to triangles and which do not, I strongly recommend a syntax like trianglesABCDEFGHI.



      Or a syntax without brace-groups at all, as suggested by egreg, trianglesABC,DEF,GHI



      The following example exhibits a romannumeral-expansion-based way of implementing the trianglesABCDEFGHI-syntax:



      documentclassarticle

      makeatletter
      %%----------------------------------------------------------------------
      newcommandUD@gobble[1]%
      newcommandUD@firstoftwo[2]#1%
      newcommandUD@secondoftwo[2]#2%
      newcommandUD@exchange[2]#2#1%
      newcommandUD@PassFirstToSecond[2]#2#1%
      %%-----------------------------------------------------------------------------
      %% Extract first inner undelimited argument:
      %%.............................................................................
      %% UD@ExtractFirstArgABCDE yields A
      %%
      %% UD@ExtractFirstArgABCDE yields AB
      %%
      %% !!! The argument of UD@ExtractFirstArg must not be empty. !!!
      %% You can check for emptiness via UD@CheckWhetherNull before applying
      %% UD@ExtractFirstArg.
      %% The argument of UD@ExtractFirstArg may contain the token UD@SelDOm.
      %%
      %%.............................................................................
      newcommandUD@RemoveTillUD@SelDOm%
      longdefUD@RemoveTillUD@SelDOm#1#2UD@SelDOm#1%
      newcommandUD@ExtractFirstArg[1]%
      romannumeral0%
      UD@ExtractFirstArgLoop#1UD@SelDOm%
      %
      newcommandUD@ExtractFirstArgLoop[1]%
      expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
      UD@exchange#1 %
      expandafterUD@ExtractFirstArgLoopexpandafterUD@RemoveTillUD@SelDOm#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.%
      %
      %%------------------------------------------------------------------------------
      %% The triangles-list:
      %%..............................................................................
      newcommandtriangles[1]%
      romannumeral0UD@CheckWhetherBlank#1 no triangletriangleloop#1%
      %
      newcommandtriangleloop[2]%
      UD@CheckWhetherBlank#1 #2%
      expandafterUD@PassFirstToSecondexpandafter%
      romannumeral0expandafterUD@exchangeexpandafter
      %
      romannumeral0expandafterexpandafterexpandafterUD@exchange
      expandafterexpandafterexpandafterUD@ExtractFirstArg#1$ $triangle%
      %
      expandafterUD@CheckWhetherBlankexpandafterUD@gobble#1%
      UD@CheckWhetherBlank#2 triangle triangles #2 and %
      %
      UD@CheckWhetherBlank#2 #2, %
      %
      %
      %
      expandaftertriangleloopexpandafterUD@gobble#1%
      %
      %
      %
      makeatother


      begindocument

      trianglespar
      trianglesABCpar
      trianglesABC DEF GHIpar
      trianglesABC DEFpar
      trianglesABC DEF GHI JKLpar

      expandafterexpandafterexpandafterdef
      expandafterexpandafterexpandafterThisTrianglelist
      expandafterexpandafterexpandafter%
      trianglesABC DEF GHI JKL%
      %

      textttfrenchspacing

      enddocument


      enter image description here




      In case you wish a comma before the "and" when the list has more than two items:



      documentclassarticle

      makeatletter
      %%----------------------------------------------------------------------
      newcommandUD@gobble[1]%
      newcommandUD@firstoftwo[2]#1%
      newcommandUD@secondoftwo[2]#2%
      newcommandUD@exchange[2]#2#1%
      newcommandUD@PassFirstToSecond[2]#2#1%
      %%-----------------------------------------------------------------------------
      %% Extract first inner undelimited argument:
      %%.............................................................................
      %% UD@ExtractFirstArgABCDE yields A
      %%
      %% UD@ExtractFirstArgABCDE yields AB
      %%
      %% !!! The argument of UD@ExtractFirstArg must not be empty. !!!
      %% You can check for emptiness via UD@CheckWhetherNull before applying
      %% UD@ExtractFirstArg.
      %% The argument of UD@ExtractFirstArg may contain the token UD@SelDOm.
      %%
      %%.............................................................................
      newcommandUD@RemoveTillUD@SelDOm%
      longdefUD@RemoveTillUD@SelDOm#1#2UD@SelDOm#1%
      newcommandUD@ExtractFirstArg[1]%
      romannumeral0%
      UD@ExtractFirstArgLoop#1UD@SelDOm%
      %
      newcommandUD@ExtractFirstArgLoop[1]%
      expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
      UD@exchange#1 %
      expandafterUD@ExtractFirstArgLoopexpandafterUD@RemoveTillUD@SelDOm#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.%
      %
      %%------------------------------------------------------------------------------
      %% The triangles-list:
      %%..............................................................................
      newcommandtriangles[1]%
      romannumeral0UD@CheckWhetherBlank#1 no triangletriangleloop#1%
      %
      newcommandtriangleloop[3]%
      UD@CheckWhetherBlank#1 #2%
      expandafterUD@exchangeexpandafter%
      romannumeral0UD@exchange expandafterexpandafterexpandafter
      expandafterexpandafterexpandafterexpandafter%
      expandafterUD@exchangeexpandafter%
      romannumeral0%
      expandafterUD@CheckWhetherBlankexpandafterUD@gobble#1 %
      UD@CheckWhetherBlank#2 ,%
      %
      expandafter%
      romannumeral0expandafterUD@exchangeexpandafter
      %
      romannumeral0expandafterexpandafterexpandafterUD@exchange
      expandafterexpandafterexpandafterUD@ExtractFirstArg#1$ $triangle%
      %
      expandafterUD@CheckWhetherBlankexpandafterUD@gobble#1%
      UD@CheckWhetherBlank#2 triangle triangles #2#3 and %
      %
      UD@CheckWhetherBlank#2 #2, %
      %
      %
      %
      %
      expandaftertriangleloopexpandafterUD@gobble#1%
      %
      %
      %
      makeatother


      begindocument

      trianglespar
      trianglesABCpar
      trianglesABC DEFpar
      trianglesABC DEF GHIpar
      trianglesABC DEF GHI JKLpar

      expandafterexpandafterexpandafterdef
      expandafterexpandafterexpandafterThisTrianglelist
      expandafterexpandafterexpandafter%
      trianglesABC DEF GHI JKL%
      %

      textttfrenchspacing

      enddocument


      enter image description here






      share|improve this answer

























        Your Answer








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

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

        else
        createEditor();

        );

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



        );













        draft saved

        draft discarded


















        StackExchange.ready(
        function ()
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f481707%2fa-command-with-a-variable-number-of-arguments-comma-versus-and%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









        4














        The shoppinglist you're talking about is at Writing a LaTeX macro that takes a variable number of arguments.



        You can adapt it quickly to work with any number of triangles. The case with one triangle is also handled in order to only display "Triangle" instead of "Triangles".



        documentclass[11pt]article

        makeatletter
        newcommandtriangles[1]%
        checknextarg#1
        newcommandchecknextarg[1]%
        @ifnextcharbgroupTriangles $triangle #1$gobblenextargTriangle $triangle #1$
        newcommandgobblenextarg[1]%
        @ifnextcharbgroup, $triangle #1$gobblenextarg and $triangle #1$
        makeatother

        begindocument

        trianglesABC

        trianglesABCDEF

        trianglesABCDEFGHI

        trianglesABCDEFGHIJKL

        enddocument


        This is the result obtained:



        Triangles



        EDIT



        Following the comment by Ulrich Diez, an improved version of this command would be:



        documentclass[11pt]article

        usepackageltxcmds

        makeatletter
        newcommandtriangles[1]%
        checknextarg#1
        newcommandchecknextarg[1]%
        ltx@ifnextchar@nospacebgroupTriangles $triangle #1$gobblenextargTriangle $triangle #1$
        newcommandgobblenextarg[1]%
        ltx@ifnextchar@nospacebgroup, $triangle #1$gobblenextarg and $triangle #1$
        makeatother

        begindocument

        trianglesABC

        trianglesABCDEF

        trianglesABCDEFGHI

        trianglesABCDEFGHIJKL

        trianglesABCDEFGHIJKL Large This shall not be part of the command

        enddocument


        where ltx@ifnextchar@nospace does not skip space and prevent the text after the command to be interpreted as an "argument" of the command triangles.



        However, as stated in egreg's answer, this way of doing things should be avoided.






        share|improve this answer




















        • 1





          What about trianglesABCDEFGHIJKL large This shall not be part of the triangle-command ?

          – Ulrich Diez
          Mar 27 at 19:29















        4














        The shoppinglist you're talking about is at Writing a LaTeX macro that takes a variable number of arguments.



        You can adapt it quickly to work with any number of triangles. The case with one triangle is also handled in order to only display "Triangle" instead of "Triangles".



        documentclass[11pt]article

        makeatletter
        newcommandtriangles[1]%
        checknextarg#1
        newcommandchecknextarg[1]%
        @ifnextcharbgroupTriangles $triangle #1$gobblenextargTriangle $triangle #1$
        newcommandgobblenextarg[1]%
        @ifnextcharbgroup, $triangle #1$gobblenextarg and $triangle #1$
        makeatother

        begindocument

        trianglesABC

        trianglesABCDEF

        trianglesABCDEFGHI

        trianglesABCDEFGHIJKL

        enddocument


        This is the result obtained:



        Triangles



        EDIT



        Following the comment by Ulrich Diez, an improved version of this command would be:



        documentclass[11pt]article

        usepackageltxcmds

        makeatletter
        newcommandtriangles[1]%
        checknextarg#1
        newcommandchecknextarg[1]%
        ltx@ifnextchar@nospacebgroupTriangles $triangle #1$gobblenextargTriangle $triangle #1$
        newcommandgobblenextarg[1]%
        ltx@ifnextchar@nospacebgroup, $triangle #1$gobblenextarg and $triangle #1$
        makeatother

        begindocument

        trianglesABC

        trianglesABCDEF

        trianglesABCDEFGHI

        trianglesABCDEFGHIJKL

        trianglesABCDEFGHIJKL Large This shall not be part of the command

        enddocument


        where ltx@ifnextchar@nospace does not skip space and prevent the text after the command to be interpreted as an "argument" of the command triangles.



        However, as stated in egreg's answer, this way of doing things should be avoided.






        share|improve this answer




















        • 1





          What about trianglesABCDEFGHIJKL large This shall not be part of the triangle-command ?

          – Ulrich Diez
          Mar 27 at 19:29













        4












        4








        4







        The shoppinglist you're talking about is at Writing a LaTeX macro that takes a variable number of arguments.



        You can adapt it quickly to work with any number of triangles. The case with one triangle is also handled in order to only display "Triangle" instead of "Triangles".



        documentclass[11pt]article

        makeatletter
        newcommandtriangles[1]%
        checknextarg#1
        newcommandchecknextarg[1]%
        @ifnextcharbgroupTriangles $triangle #1$gobblenextargTriangle $triangle #1$
        newcommandgobblenextarg[1]%
        @ifnextcharbgroup, $triangle #1$gobblenextarg and $triangle #1$
        makeatother

        begindocument

        trianglesABC

        trianglesABCDEF

        trianglesABCDEFGHI

        trianglesABCDEFGHIJKL

        enddocument


        This is the result obtained:



        Triangles



        EDIT



        Following the comment by Ulrich Diez, an improved version of this command would be:



        documentclass[11pt]article

        usepackageltxcmds

        makeatletter
        newcommandtriangles[1]%
        checknextarg#1
        newcommandchecknextarg[1]%
        ltx@ifnextchar@nospacebgroupTriangles $triangle #1$gobblenextargTriangle $triangle #1$
        newcommandgobblenextarg[1]%
        ltx@ifnextchar@nospacebgroup, $triangle #1$gobblenextarg and $triangle #1$
        makeatother

        begindocument

        trianglesABC

        trianglesABCDEF

        trianglesABCDEFGHI

        trianglesABCDEFGHIJKL

        trianglesABCDEFGHIJKL Large This shall not be part of the command

        enddocument


        where ltx@ifnextchar@nospace does not skip space and prevent the text after the command to be interpreted as an "argument" of the command triangles.



        However, as stated in egreg's answer, this way of doing things should be avoided.






        share|improve this answer















        The shoppinglist you're talking about is at Writing a LaTeX macro that takes a variable number of arguments.



        You can adapt it quickly to work with any number of triangles. The case with one triangle is also handled in order to only display "Triangle" instead of "Triangles".



        documentclass[11pt]article

        makeatletter
        newcommandtriangles[1]%
        checknextarg#1
        newcommandchecknextarg[1]%
        @ifnextcharbgroupTriangles $triangle #1$gobblenextargTriangle $triangle #1$
        newcommandgobblenextarg[1]%
        @ifnextcharbgroup, $triangle #1$gobblenextarg and $triangle #1$
        makeatother

        begindocument

        trianglesABC

        trianglesABCDEF

        trianglesABCDEFGHI

        trianglesABCDEFGHIJKL

        enddocument


        This is the result obtained:



        Triangles



        EDIT



        Following the comment by Ulrich Diez, an improved version of this command would be:



        documentclass[11pt]article

        usepackageltxcmds

        makeatletter
        newcommandtriangles[1]%
        checknextarg#1
        newcommandchecknextarg[1]%
        ltx@ifnextchar@nospacebgroupTriangles $triangle #1$gobblenextargTriangle $triangle #1$
        newcommandgobblenextarg[1]%
        ltx@ifnextchar@nospacebgroup, $triangle #1$gobblenextarg and $triangle #1$
        makeatother

        begindocument

        trianglesABC

        trianglesABCDEF

        trianglesABCDEFGHI

        trianglesABCDEFGHIJKL

        trianglesABCDEFGHIJKL Large This shall not be part of the command

        enddocument


        where ltx@ifnextchar@nospace does not skip space and prevent the text after the command to be interpreted as an "argument" of the command triangles.



        However, as stated in egreg's answer, this way of doing things should be avoided.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Mar 27 at 20:37

























        answered Mar 27 at 14:16









        KersouManKersouMan

        1485




        1485







        • 1





          What about trianglesABCDEFGHIJKL large This shall not be part of the triangle-command ?

          – Ulrich Diez
          Mar 27 at 19:29












        • 1





          What about trianglesABCDEFGHIJKL large This shall not be part of the triangle-command ?

          – Ulrich Diez
          Mar 27 at 19:29







        1




        1





        What about trianglesABCDEFGHIJKL large This shall not be part of the triangle-command ?

        – Ulrich Diez
        Mar 27 at 19:29





        What about trianglesABCDEFGHIJKL large This shall not be part of the triangle-command ?

        – Ulrich Diez
        Mar 27 at 19:29











        3














        Macros with a variable number of arguments are not the best thing to do with LaTeX; in your case it's simpler to use a comma separated list of triangles.



        documentclassarticle
        usepackagexparse

        ExplSyntaxOn

        NewDocumentCommandtrianglesm

        bart_triangles:n #1


        seq_new:N l__bart_triangles_seq
        tl_new:N l__bart_triangles_item_tl

        cs_new_protected:Nn bart_triangles:n

        seq_clear:N l__bart_triangles_seq
        clist_map_variable:nNn #1 l__bart_triangles_item_tl

        __bart_triangles_add:V l__bart_triangles_item_tl

        triangle
        int_compare:nF seq_count:N l__bart_triangles_seq < 2 s
        nobreakspace
        seq_use:Nnnn l__bart_triangles_seq ~and~ ,~ ~and~


        cs_new_protected:Nn __bart_triangles_add:n

        seq_put_right:Nn l__bart_triangles_seq $triangle #1$

        cs_generate_variant:Nn __bart_triangles_add:n V

        ExplSyntaxOff

        begindocument

        trianglesABC

        trianglesABC,DEF

        trianglesABC,DEF,GHI

        enddocument


        The comma separated list is mapped and each item is added to a sequence in the form $triangle<vertices>$. Then the sequence is used, with the specified separators (between two, between more than two, between last two).



        The “s” is added only if the list contains at least two items.



        enter image description here






        share|improve this answer



























          3














          Macros with a variable number of arguments are not the best thing to do with LaTeX; in your case it's simpler to use a comma separated list of triangles.



          documentclassarticle
          usepackagexparse

          ExplSyntaxOn

          NewDocumentCommandtrianglesm

          bart_triangles:n #1


          seq_new:N l__bart_triangles_seq
          tl_new:N l__bart_triangles_item_tl

          cs_new_protected:Nn bart_triangles:n

          seq_clear:N l__bart_triangles_seq
          clist_map_variable:nNn #1 l__bart_triangles_item_tl

          __bart_triangles_add:V l__bart_triangles_item_tl

          triangle
          int_compare:nF seq_count:N l__bart_triangles_seq < 2 s
          nobreakspace
          seq_use:Nnnn l__bart_triangles_seq ~and~ ,~ ~and~


          cs_new_protected:Nn __bart_triangles_add:n

          seq_put_right:Nn l__bart_triangles_seq $triangle #1$

          cs_generate_variant:Nn __bart_triangles_add:n V

          ExplSyntaxOff

          begindocument

          trianglesABC

          trianglesABC,DEF

          trianglesABC,DEF,GHI

          enddocument


          The comma separated list is mapped and each item is added to a sequence in the form $triangle<vertices>$. Then the sequence is used, with the specified separators (between two, between more than two, between last two).



          The “s” is added only if the list contains at least two items.



          enter image description here






          share|improve this answer

























            3












            3








            3







            Macros with a variable number of arguments are not the best thing to do with LaTeX; in your case it's simpler to use a comma separated list of triangles.



            documentclassarticle
            usepackagexparse

            ExplSyntaxOn

            NewDocumentCommandtrianglesm

            bart_triangles:n #1


            seq_new:N l__bart_triangles_seq
            tl_new:N l__bart_triangles_item_tl

            cs_new_protected:Nn bart_triangles:n

            seq_clear:N l__bart_triangles_seq
            clist_map_variable:nNn #1 l__bart_triangles_item_tl

            __bart_triangles_add:V l__bart_triangles_item_tl

            triangle
            int_compare:nF seq_count:N l__bart_triangles_seq < 2 s
            nobreakspace
            seq_use:Nnnn l__bart_triangles_seq ~and~ ,~ ~and~


            cs_new_protected:Nn __bart_triangles_add:n

            seq_put_right:Nn l__bart_triangles_seq $triangle #1$

            cs_generate_variant:Nn __bart_triangles_add:n V

            ExplSyntaxOff

            begindocument

            trianglesABC

            trianglesABC,DEF

            trianglesABC,DEF,GHI

            enddocument


            The comma separated list is mapped and each item is added to a sequence in the form $triangle<vertices>$. Then the sequence is used, with the specified separators (between two, between more than two, between last two).



            The “s” is added only if the list contains at least two items.



            enter image description here






            share|improve this answer













            Macros with a variable number of arguments are not the best thing to do with LaTeX; in your case it's simpler to use a comma separated list of triangles.



            documentclassarticle
            usepackagexparse

            ExplSyntaxOn

            NewDocumentCommandtrianglesm

            bart_triangles:n #1


            seq_new:N l__bart_triangles_seq
            tl_new:N l__bart_triangles_item_tl

            cs_new_protected:Nn bart_triangles:n

            seq_clear:N l__bart_triangles_seq
            clist_map_variable:nNn #1 l__bart_triangles_item_tl

            __bart_triangles_add:V l__bart_triangles_item_tl

            triangle
            int_compare:nF seq_count:N l__bart_triangles_seq < 2 s
            nobreakspace
            seq_use:Nnnn l__bart_triangles_seq ~and~ ,~ ~and~


            cs_new_protected:Nn __bart_triangles_add:n

            seq_put_right:Nn l__bart_triangles_seq $triangle #1$

            cs_generate_variant:Nn __bart_triangles_add:n V

            ExplSyntaxOff

            begindocument

            trianglesABC

            trianglesABC,DEF

            trianglesABC,DEF,GHI

            enddocument


            The comma separated list is mapped and each item is added to a sequence in the form $triangle<vertices>$. Then the sequence is used, with the specified separators (between two, between more than two, between last two).



            The “s” is added only if the list contains at least two items.



            enter image description here







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Mar 27 at 14:26









            egregegreg

            732k8919303253




            732k8919303253





















                1














                A listofitems approach. Note: I was taught that for a list of more than 2 items, a comma precedes the "and".



                documentclassarticle
                usepackagelistofitems
                newcommandtriangles[1]%
                setsepchar,%
                readlisttrilist#1%
                foreachitemxintrilist[]%
                $trianglex$%
                ifnumnumexprxcnt+1<listlentrilist[]relax%
                , %
                else%
                ifnumnumexprxcnt+1=listlentrilist[]relax%
                ifnumlistlentrilist[]>2relax,fi
                and %
                fi
                fi%
                %

                begindocument
                Given trianglesABC.par
                Given trianglesABC, DEF.par
                Given trianglesABC, DEF,GHI.par
                Given trianglesABC, DEF,GHI, JKL.par
                enddocument


                enter image description here






                share|improve this answer



























                  1














                  A listofitems approach. Note: I was taught that for a list of more than 2 items, a comma precedes the "and".



                  documentclassarticle
                  usepackagelistofitems
                  newcommandtriangles[1]%
                  setsepchar,%
                  readlisttrilist#1%
                  foreachitemxintrilist[]%
                  $trianglex$%
                  ifnumnumexprxcnt+1<listlentrilist[]relax%
                  , %
                  else%
                  ifnumnumexprxcnt+1=listlentrilist[]relax%
                  ifnumlistlentrilist[]>2relax,fi
                  and %
                  fi
                  fi%
                  %

                  begindocument
                  Given trianglesABC.par
                  Given trianglesABC, DEF.par
                  Given trianglesABC, DEF,GHI.par
                  Given trianglesABC, DEF,GHI, JKL.par
                  enddocument


                  enter image description here






                  share|improve this answer

























                    1












                    1








                    1







                    A listofitems approach. Note: I was taught that for a list of more than 2 items, a comma precedes the "and".



                    documentclassarticle
                    usepackagelistofitems
                    newcommandtriangles[1]%
                    setsepchar,%
                    readlisttrilist#1%
                    foreachitemxintrilist[]%
                    $trianglex$%
                    ifnumnumexprxcnt+1<listlentrilist[]relax%
                    , %
                    else%
                    ifnumnumexprxcnt+1=listlentrilist[]relax%
                    ifnumlistlentrilist[]>2relax,fi
                    and %
                    fi
                    fi%
                    %

                    begindocument
                    Given trianglesABC.par
                    Given trianglesABC, DEF.par
                    Given trianglesABC, DEF,GHI.par
                    Given trianglesABC, DEF,GHI, JKL.par
                    enddocument


                    enter image description here






                    share|improve this answer













                    A listofitems approach. Note: I was taught that for a list of more than 2 items, a comma precedes the "and".



                    documentclassarticle
                    usepackagelistofitems
                    newcommandtriangles[1]%
                    setsepchar,%
                    readlisttrilist#1%
                    foreachitemxintrilist[]%
                    $trianglex$%
                    ifnumnumexprxcnt+1<listlentrilist[]relax%
                    , %
                    else%
                    ifnumnumexprxcnt+1=listlentrilist[]relax%
                    ifnumlistlentrilist[]>2relax,fi
                    and %
                    fi
                    fi%
                    %

                    begindocument
                    Given trianglesABC.par
                    Given trianglesABC, DEF.par
                    Given trianglesABC, DEF,GHI.par
                    Given trianglesABC, DEF,GHI, JKL.par
                    enddocument


                    enter image description here







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Mar 28 at 2:41









                    Steven B. SegletesSteven B. Segletes

                    161k9205416




                    161k9205416





















                        1














                        What about
                        trianglesABCDEFGHIJKL large This shall not be part of the triangle-command ?



                        For the sake of unambiguity regarding the question which brace groups belong to triangles and which do not, I strongly recommend a syntax like trianglesABCDEFGHI.



                        Or a syntax without brace-groups at all, as suggested by egreg, trianglesABC,DEF,GHI



                        The following example exhibits a romannumeral-expansion-based way of implementing the trianglesABCDEFGHI-syntax:



                        documentclassarticle

                        makeatletter
                        %%----------------------------------------------------------------------
                        newcommandUD@gobble[1]%
                        newcommandUD@firstoftwo[2]#1%
                        newcommandUD@secondoftwo[2]#2%
                        newcommandUD@exchange[2]#2#1%
                        newcommandUD@PassFirstToSecond[2]#2#1%
                        %%-----------------------------------------------------------------------------
                        %% Extract first inner undelimited argument:
                        %%.............................................................................
                        %% UD@ExtractFirstArgABCDE yields A
                        %%
                        %% UD@ExtractFirstArgABCDE yields AB
                        %%
                        %% !!! The argument of UD@ExtractFirstArg must not be empty. !!!
                        %% You can check for emptiness via UD@CheckWhetherNull before applying
                        %% UD@ExtractFirstArg.
                        %% The argument of UD@ExtractFirstArg may contain the token UD@SelDOm.
                        %%
                        %%.............................................................................
                        newcommandUD@RemoveTillUD@SelDOm%
                        longdefUD@RemoveTillUD@SelDOm#1#2UD@SelDOm#1%
                        newcommandUD@ExtractFirstArg[1]%
                        romannumeral0%
                        UD@ExtractFirstArgLoop#1UD@SelDOm%
                        %
                        newcommandUD@ExtractFirstArgLoop[1]%
                        expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
                        UD@exchange#1 %
                        expandafterUD@ExtractFirstArgLoopexpandafterUD@RemoveTillUD@SelDOm#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.%
                        %
                        %%------------------------------------------------------------------------------
                        %% The triangles-list:
                        %%..............................................................................
                        newcommandtriangles[1]%
                        romannumeral0UD@CheckWhetherBlank#1 no triangletriangleloop#1%
                        %
                        newcommandtriangleloop[2]%
                        UD@CheckWhetherBlank#1 #2%
                        expandafterUD@PassFirstToSecondexpandafter%
                        romannumeral0expandafterUD@exchangeexpandafter
                        %
                        romannumeral0expandafterexpandafterexpandafterUD@exchange
                        expandafterexpandafterexpandafterUD@ExtractFirstArg#1$ $triangle%
                        %
                        expandafterUD@CheckWhetherBlankexpandafterUD@gobble#1%
                        UD@CheckWhetherBlank#2 triangle triangles #2 and %
                        %
                        UD@CheckWhetherBlank#2 #2, %
                        %
                        %
                        %
                        expandaftertriangleloopexpandafterUD@gobble#1%
                        %
                        %
                        %
                        makeatother


                        begindocument

                        trianglespar
                        trianglesABCpar
                        trianglesABC DEF GHIpar
                        trianglesABC DEFpar
                        trianglesABC DEF GHI JKLpar

                        expandafterexpandafterexpandafterdef
                        expandafterexpandafterexpandafterThisTrianglelist
                        expandafterexpandafterexpandafter%
                        trianglesABC DEF GHI JKL%
                        %

                        textttfrenchspacing

                        enddocument


                        enter image description here




                        In case you wish a comma before the "and" when the list has more than two items:



                        documentclassarticle

                        makeatletter
                        %%----------------------------------------------------------------------
                        newcommandUD@gobble[1]%
                        newcommandUD@firstoftwo[2]#1%
                        newcommandUD@secondoftwo[2]#2%
                        newcommandUD@exchange[2]#2#1%
                        newcommandUD@PassFirstToSecond[2]#2#1%
                        %%-----------------------------------------------------------------------------
                        %% Extract first inner undelimited argument:
                        %%.............................................................................
                        %% UD@ExtractFirstArgABCDE yields A
                        %%
                        %% UD@ExtractFirstArgABCDE yields AB
                        %%
                        %% !!! The argument of UD@ExtractFirstArg must not be empty. !!!
                        %% You can check for emptiness via UD@CheckWhetherNull before applying
                        %% UD@ExtractFirstArg.
                        %% The argument of UD@ExtractFirstArg may contain the token UD@SelDOm.
                        %%
                        %%.............................................................................
                        newcommandUD@RemoveTillUD@SelDOm%
                        longdefUD@RemoveTillUD@SelDOm#1#2UD@SelDOm#1%
                        newcommandUD@ExtractFirstArg[1]%
                        romannumeral0%
                        UD@ExtractFirstArgLoop#1UD@SelDOm%
                        %
                        newcommandUD@ExtractFirstArgLoop[1]%
                        expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
                        UD@exchange#1 %
                        expandafterUD@ExtractFirstArgLoopexpandafterUD@RemoveTillUD@SelDOm#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.%
                        %
                        %%------------------------------------------------------------------------------
                        %% The triangles-list:
                        %%..............................................................................
                        newcommandtriangles[1]%
                        romannumeral0UD@CheckWhetherBlank#1 no triangletriangleloop#1%
                        %
                        newcommandtriangleloop[3]%
                        UD@CheckWhetherBlank#1 #2%
                        expandafterUD@exchangeexpandafter%
                        romannumeral0UD@exchange expandafterexpandafterexpandafter
                        expandafterexpandafterexpandafterexpandafter%
                        expandafterUD@exchangeexpandafter%
                        romannumeral0%
                        expandafterUD@CheckWhetherBlankexpandafterUD@gobble#1 %
                        UD@CheckWhetherBlank#2 ,%
                        %
                        expandafter%
                        romannumeral0expandafterUD@exchangeexpandafter
                        %
                        romannumeral0expandafterexpandafterexpandafterUD@exchange
                        expandafterexpandafterexpandafterUD@ExtractFirstArg#1$ $triangle%
                        %
                        expandafterUD@CheckWhetherBlankexpandafterUD@gobble#1%
                        UD@CheckWhetherBlank#2 triangle triangles #2#3 and %
                        %
                        UD@CheckWhetherBlank#2 #2, %
                        %
                        %
                        %
                        %
                        expandaftertriangleloopexpandafterUD@gobble#1%
                        %
                        %
                        %
                        makeatother


                        begindocument

                        trianglespar
                        trianglesABCpar
                        trianglesABC DEFpar
                        trianglesABC DEF GHIpar
                        trianglesABC DEF GHI JKLpar

                        expandafterexpandafterexpandafterdef
                        expandafterexpandafterexpandafterThisTrianglelist
                        expandafterexpandafterexpandafter%
                        trianglesABC DEF GHI JKL%
                        %

                        textttfrenchspacing

                        enddocument


                        enter image description here






                        share|improve this answer





























                          1














                          What about
                          trianglesABCDEFGHIJKL large This shall not be part of the triangle-command ?



                          For the sake of unambiguity regarding the question which brace groups belong to triangles and which do not, I strongly recommend a syntax like trianglesABCDEFGHI.



                          Or a syntax without brace-groups at all, as suggested by egreg, trianglesABC,DEF,GHI



                          The following example exhibits a romannumeral-expansion-based way of implementing the trianglesABCDEFGHI-syntax:



                          documentclassarticle

                          makeatletter
                          %%----------------------------------------------------------------------
                          newcommandUD@gobble[1]%
                          newcommandUD@firstoftwo[2]#1%
                          newcommandUD@secondoftwo[2]#2%
                          newcommandUD@exchange[2]#2#1%
                          newcommandUD@PassFirstToSecond[2]#2#1%
                          %%-----------------------------------------------------------------------------
                          %% Extract first inner undelimited argument:
                          %%.............................................................................
                          %% UD@ExtractFirstArgABCDE yields A
                          %%
                          %% UD@ExtractFirstArgABCDE yields AB
                          %%
                          %% !!! The argument of UD@ExtractFirstArg must not be empty. !!!
                          %% You can check for emptiness via UD@CheckWhetherNull before applying
                          %% UD@ExtractFirstArg.
                          %% The argument of UD@ExtractFirstArg may contain the token UD@SelDOm.
                          %%
                          %%.............................................................................
                          newcommandUD@RemoveTillUD@SelDOm%
                          longdefUD@RemoveTillUD@SelDOm#1#2UD@SelDOm#1%
                          newcommandUD@ExtractFirstArg[1]%
                          romannumeral0%
                          UD@ExtractFirstArgLoop#1UD@SelDOm%
                          %
                          newcommandUD@ExtractFirstArgLoop[1]%
                          expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
                          UD@exchange#1 %
                          expandafterUD@ExtractFirstArgLoopexpandafterUD@RemoveTillUD@SelDOm#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.%
                          %
                          %%------------------------------------------------------------------------------
                          %% The triangles-list:
                          %%..............................................................................
                          newcommandtriangles[1]%
                          romannumeral0UD@CheckWhetherBlank#1 no triangletriangleloop#1%
                          %
                          newcommandtriangleloop[2]%
                          UD@CheckWhetherBlank#1 #2%
                          expandafterUD@PassFirstToSecondexpandafter%
                          romannumeral0expandafterUD@exchangeexpandafter
                          %
                          romannumeral0expandafterexpandafterexpandafterUD@exchange
                          expandafterexpandafterexpandafterUD@ExtractFirstArg#1$ $triangle%
                          %
                          expandafterUD@CheckWhetherBlankexpandafterUD@gobble#1%
                          UD@CheckWhetherBlank#2 triangle triangles #2 and %
                          %
                          UD@CheckWhetherBlank#2 #2, %
                          %
                          %
                          %
                          expandaftertriangleloopexpandafterUD@gobble#1%
                          %
                          %
                          %
                          makeatother


                          begindocument

                          trianglespar
                          trianglesABCpar
                          trianglesABC DEF GHIpar
                          trianglesABC DEFpar
                          trianglesABC DEF GHI JKLpar

                          expandafterexpandafterexpandafterdef
                          expandafterexpandafterexpandafterThisTrianglelist
                          expandafterexpandafterexpandafter%
                          trianglesABC DEF GHI JKL%
                          %

                          textttfrenchspacing

                          enddocument


                          enter image description here




                          In case you wish a comma before the "and" when the list has more than two items:



                          documentclassarticle

                          makeatletter
                          %%----------------------------------------------------------------------
                          newcommandUD@gobble[1]%
                          newcommandUD@firstoftwo[2]#1%
                          newcommandUD@secondoftwo[2]#2%
                          newcommandUD@exchange[2]#2#1%
                          newcommandUD@PassFirstToSecond[2]#2#1%
                          %%-----------------------------------------------------------------------------
                          %% Extract first inner undelimited argument:
                          %%.............................................................................
                          %% UD@ExtractFirstArgABCDE yields A
                          %%
                          %% UD@ExtractFirstArgABCDE yields AB
                          %%
                          %% !!! The argument of UD@ExtractFirstArg must not be empty. !!!
                          %% You can check for emptiness via UD@CheckWhetherNull before applying
                          %% UD@ExtractFirstArg.
                          %% The argument of UD@ExtractFirstArg may contain the token UD@SelDOm.
                          %%
                          %%.............................................................................
                          newcommandUD@RemoveTillUD@SelDOm%
                          longdefUD@RemoveTillUD@SelDOm#1#2UD@SelDOm#1%
                          newcommandUD@ExtractFirstArg[1]%
                          romannumeral0%
                          UD@ExtractFirstArgLoop#1UD@SelDOm%
                          %
                          newcommandUD@ExtractFirstArgLoop[1]%
                          expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
                          UD@exchange#1 %
                          expandafterUD@ExtractFirstArgLoopexpandafterUD@RemoveTillUD@SelDOm#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.%
                          %
                          %%------------------------------------------------------------------------------
                          %% The triangles-list:
                          %%..............................................................................
                          newcommandtriangles[1]%
                          romannumeral0UD@CheckWhetherBlank#1 no triangletriangleloop#1%
                          %
                          newcommandtriangleloop[3]%
                          UD@CheckWhetherBlank#1 #2%
                          expandafterUD@exchangeexpandafter%
                          romannumeral0UD@exchange expandafterexpandafterexpandafter
                          expandafterexpandafterexpandafterexpandafter%
                          expandafterUD@exchangeexpandafter%
                          romannumeral0%
                          expandafterUD@CheckWhetherBlankexpandafterUD@gobble#1 %
                          UD@CheckWhetherBlank#2 ,%
                          %
                          expandafter%
                          romannumeral0expandafterUD@exchangeexpandafter
                          %
                          romannumeral0expandafterexpandafterexpandafterUD@exchange
                          expandafterexpandafterexpandafterUD@ExtractFirstArg#1$ $triangle%
                          %
                          expandafterUD@CheckWhetherBlankexpandafterUD@gobble#1%
                          UD@CheckWhetherBlank#2 triangle triangles #2#3 and %
                          %
                          UD@CheckWhetherBlank#2 #2, %
                          %
                          %
                          %
                          %
                          expandaftertriangleloopexpandafterUD@gobble#1%
                          %
                          %
                          %
                          makeatother


                          begindocument

                          trianglespar
                          trianglesABCpar
                          trianglesABC DEFpar
                          trianglesABC DEF GHIpar
                          trianglesABC DEF GHI JKLpar

                          expandafterexpandafterexpandafterdef
                          expandafterexpandafterexpandafterThisTrianglelist
                          expandafterexpandafterexpandafter%
                          trianglesABC DEF GHI JKL%
                          %

                          textttfrenchspacing

                          enddocument


                          enter image description here






                          share|improve this answer



























                            1












                            1








                            1







                            What about
                            trianglesABCDEFGHIJKL large This shall not be part of the triangle-command ?



                            For the sake of unambiguity regarding the question which brace groups belong to triangles and which do not, I strongly recommend a syntax like trianglesABCDEFGHI.



                            Or a syntax without brace-groups at all, as suggested by egreg, trianglesABC,DEF,GHI



                            The following example exhibits a romannumeral-expansion-based way of implementing the trianglesABCDEFGHI-syntax:



                            documentclassarticle

                            makeatletter
                            %%----------------------------------------------------------------------
                            newcommandUD@gobble[1]%
                            newcommandUD@firstoftwo[2]#1%
                            newcommandUD@secondoftwo[2]#2%
                            newcommandUD@exchange[2]#2#1%
                            newcommandUD@PassFirstToSecond[2]#2#1%
                            %%-----------------------------------------------------------------------------
                            %% Extract first inner undelimited argument:
                            %%.............................................................................
                            %% UD@ExtractFirstArgABCDE yields A
                            %%
                            %% UD@ExtractFirstArgABCDE yields AB
                            %%
                            %% !!! The argument of UD@ExtractFirstArg must not be empty. !!!
                            %% You can check for emptiness via UD@CheckWhetherNull before applying
                            %% UD@ExtractFirstArg.
                            %% The argument of UD@ExtractFirstArg may contain the token UD@SelDOm.
                            %%
                            %%.............................................................................
                            newcommandUD@RemoveTillUD@SelDOm%
                            longdefUD@RemoveTillUD@SelDOm#1#2UD@SelDOm#1%
                            newcommandUD@ExtractFirstArg[1]%
                            romannumeral0%
                            UD@ExtractFirstArgLoop#1UD@SelDOm%
                            %
                            newcommandUD@ExtractFirstArgLoop[1]%
                            expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
                            UD@exchange#1 %
                            expandafterUD@ExtractFirstArgLoopexpandafterUD@RemoveTillUD@SelDOm#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.%
                            %
                            %%------------------------------------------------------------------------------
                            %% The triangles-list:
                            %%..............................................................................
                            newcommandtriangles[1]%
                            romannumeral0UD@CheckWhetherBlank#1 no triangletriangleloop#1%
                            %
                            newcommandtriangleloop[2]%
                            UD@CheckWhetherBlank#1 #2%
                            expandafterUD@PassFirstToSecondexpandafter%
                            romannumeral0expandafterUD@exchangeexpandafter
                            %
                            romannumeral0expandafterexpandafterexpandafterUD@exchange
                            expandafterexpandafterexpandafterUD@ExtractFirstArg#1$ $triangle%
                            %
                            expandafterUD@CheckWhetherBlankexpandafterUD@gobble#1%
                            UD@CheckWhetherBlank#2 triangle triangles #2 and %
                            %
                            UD@CheckWhetherBlank#2 #2, %
                            %
                            %
                            %
                            expandaftertriangleloopexpandafterUD@gobble#1%
                            %
                            %
                            %
                            makeatother


                            begindocument

                            trianglespar
                            trianglesABCpar
                            trianglesABC DEF GHIpar
                            trianglesABC DEFpar
                            trianglesABC DEF GHI JKLpar

                            expandafterexpandafterexpandafterdef
                            expandafterexpandafterexpandafterThisTrianglelist
                            expandafterexpandafterexpandafter%
                            trianglesABC DEF GHI JKL%
                            %

                            textttfrenchspacing

                            enddocument


                            enter image description here




                            In case you wish a comma before the "and" when the list has more than two items:



                            documentclassarticle

                            makeatletter
                            %%----------------------------------------------------------------------
                            newcommandUD@gobble[1]%
                            newcommandUD@firstoftwo[2]#1%
                            newcommandUD@secondoftwo[2]#2%
                            newcommandUD@exchange[2]#2#1%
                            newcommandUD@PassFirstToSecond[2]#2#1%
                            %%-----------------------------------------------------------------------------
                            %% Extract first inner undelimited argument:
                            %%.............................................................................
                            %% UD@ExtractFirstArgABCDE yields A
                            %%
                            %% UD@ExtractFirstArgABCDE yields AB
                            %%
                            %% !!! The argument of UD@ExtractFirstArg must not be empty. !!!
                            %% You can check for emptiness via UD@CheckWhetherNull before applying
                            %% UD@ExtractFirstArg.
                            %% The argument of UD@ExtractFirstArg may contain the token UD@SelDOm.
                            %%
                            %%.............................................................................
                            newcommandUD@RemoveTillUD@SelDOm%
                            longdefUD@RemoveTillUD@SelDOm#1#2UD@SelDOm#1%
                            newcommandUD@ExtractFirstArg[1]%
                            romannumeral0%
                            UD@ExtractFirstArgLoop#1UD@SelDOm%
                            %
                            newcommandUD@ExtractFirstArgLoop[1]%
                            expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
                            UD@exchange#1 %
                            expandafterUD@ExtractFirstArgLoopexpandafterUD@RemoveTillUD@SelDOm#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.%
                            %
                            %%------------------------------------------------------------------------------
                            %% The triangles-list:
                            %%..............................................................................
                            newcommandtriangles[1]%
                            romannumeral0UD@CheckWhetherBlank#1 no triangletriangleloop#1%
                            %
                            newcommandtriangleloop[3]%
                            UD@CheckWhetherBlank#1 #2%
                            expandafterUD@exchangeexpandafter%
                            romannumeral0UD@exchange expandafterexpandafterexpandafter
                            expandafterexpandafterexpandafterexpandafter%
                            expandafterUD@exchangeexpandafter%
                            romannumeral0%
                            expandafterUD@CheckWhetherBlankexpandafterUD@gobble#1 %
                            UD@CheckWhetherBlank#2 ,%
                            %
                            expandafter%
                            romannumeral0expandafterUD@exchangeexpandafter
                            %
                            romannumeral0expandafterexpandafterexpandafterUD@exchange
                            expandafterexpandafterexpandafterUD@ExtractFirstArg#1$ $triangle%
                            %
                            expandafterUD@CheckWhetherBlankexpandafterUD@gobble#1%
                            UD@CheckWhetherBlank#2 triangle triangles #2#3 and %
                            %
                            UD@CheckWhetherBlank#2 #2, %
                            %
                            %
                            %
                            %
                            expandaftertriangleloopexpandafterUD@gobble#1%
                            %
                            %
                            %
                            makeatother


                            begindocument

                            trianglespar
                            trianglesABCpar
                            trianglesABC DEFpar
                            trianglesABC DEF GHIpar
                            trianglesABC DEF GHI JKLpar

                            expandafterexpandafterexpandafterdef
                            expandafterexpandafterexpandafterThisTrianglelist
                            expandafterexpandafterexpandafter%
                            trianglesABC DEF GHI JKL%
                            %

                            textttfrenchspacing

                            enddocument


                            enter image description here






                            share|improve this answer















                            What about
                            trianglesABCDEFGHIJKL large This shall not be part of the triangle-command ?



                            For the sake of unambiguity regarding the question which brace groups belong to triangles and which do not, I strongly recommend a syntax like trianglesABCDEFGHI.



                            Or a syntax without brace-groups at all, as suggested by egreg, trianglesABC,DEF,GHI



                            The following example exhibits a romannumeral-expansion-based way of implementing the trianglesABCDEFGHI-syntax:



                            documentclassarticle

                            makeatletter
                            %%----------------------------------------------------------------------
                            newcommandUD@gobble[1]%
                            newcommandUD@firstoftwo[2]#1%
                            newcommandUD@secondoftwo[2]#2%
                            newcommandUD@exchange[2]#2#1%
                            newcommandUD@PassFirstToSecond[2]#2#1%
                            %%-----------------------------------------------------------------------------
                            %% Extract first inner undelimited argument:
                            %%.............................................................................
                            %% UD@ExtractFirstArgABCDE yields A
                            %%
                            %% UD@ExtractFirstArgABCDE yields AB
                            %%
                            %% !!! The argument of UD@ExtractFirstArg must not be empty. !!!
                            %% You can check for emptiness via UD@CheckWhetherNull before applying
                            %% UD@ExtractFirstArg.
                            %% The argument of UD@ExtractFirstArg may contain the token UD@SelDOm.
                            %%
                            %%.............................................................................
                            newcommandUD@RemoveTillUD@SelDOm%
                            longdefUD@RemoveTillUD@SelDOm#1#2UD@SelDOm#1%
                            newcommandUD@ExtractFirstArg[1]%
                            romannumeral0%
                            UD@ExtractFirstArgLoop#1UD@SelDOm%
                            %
                            newcommandUD@ExtractFirstArgLoop[1]%
                            expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
                            UD@exchange#1 %
                            expandafterUD@ExtractFirstArgLoopexpandafterUD@RemoveTillUD@SelDOm#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.%
                            %
                            %%------------------------------------------------------------------------------
                            %% The triangles-list:
                            %%..............................................................................
                            newcommandtriangles[1]%
                            romannumeral0UD@CheckWhetherBlank#1 no triangletriangleloop#1%
                            %
                            newcommandtriangleloop[2]%
                            UD@CheckWhetherBlank#1 #2%
                            expandafterUD@PassFirstToSecondexpandafter%
                            romannumeral0expandafterUD@exchangeexpandafter
                            %
                            romannumeral0expandafterexpandafterexpandafterUD@exchange
                            expandafterexpandafterexpandafterUD@ExtractFirstArg#1$ $triangle%
                            %
                            expandafterUD@CheckWhetherBlankexpandafterUD@gobble#1%
                            UD@CheckWhetherBlank#2 triangle triangles #2 and %
                            %
                            UD@CheckWhetherBlank#2 #2, %
                            %
                            %
                            %
                            expandaftertriangleloopexpandafterUD@gobble#1%
                            %
                            %
                            %
                            makeatother


                            begindocument

                            trianglespar
                            trianglesABCpar
                            trianglesABC DEF GHIpar
                            trianglesABC DEFpar
                            trianglesABC DEF GHI JKLpar

                            expandafterexpandafterexpandafterdef
                            expandafterexpandafterexpandafterThisTrianglelist
                            expandafterexpandafterexpandafter%
                            trianglesABC DEF GHI JKL%
                            %

                            textttfrenchspacing

                            enddocument


                            enter image description here




                            In case you wish a comma before the "and" when the list has more than two items:



                            documentclassarticle

                            makeatletter
                            %%----------------------------------------------------------------------
                            newcommandUD@gobble[1]%
                            newcommandUD@firstoftwo[2]#1%
                            newcommandUD@secondoftwo[2]#2%
                            newcommandUD@exchange[2]#2#1%
                            newcommandUD@PassFirstToSecond[2]#2#1%
                            %%-----------------------------------------------------------------------------
                            %% Extract first inner undelimited argument:
                            %%.............................................................................
                            %% UD@ExtractFirstArgABCDE yields A
                            %%
                            %% UD@ExtractFirstArgABCDE yields AB
                            %%
                            %% !!! The argument of UD@ExtractFirstArg must not be empty. !!!
                            %% You can check for emptiness via UD@CheckWhetherNull before applying
                            %% UD@ExtractFirstArg.
                            %% The argument of UD@ExtractFirstArg may contain the token UD@SelDOm.
                            %%
                            %%.............................................................................
                            newcommandUD@RemoveTillUD@SelDOm%
                            longdefUD@RemoveTillUD@SelDOm#1#2UD@SelDOm#1%
                            newcommandUD@ExtractFirstArg[1]%
                            romannumeral0%
                            UD@ExtractFirstArgLoop#1UD@SelDOm%
                            %
                            newcommandUD@ExtractFirstArgLoop[1]%
                            expandafterUD@CheckWhetherNullexpandafterUD@firstoftwo#1%
                            UD@exchange#1 %
                            expandafterUD@ExtractFirstArgLoopexpandafterUD@RemoveTillUD@SelDOm#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.%
                            %
                            %%------------------------------------------------------------------------------
                            %% The triangles-list:
                            %%..............................................................................
                            newcommandtriangles[1]%
                            romannumeral0UD@CheckWhetherBlank#1 no triangletriangleloop#1%
                            %
                            newcommandtriangleloop[3]%
                            UD@CheckWhetherBlank#1 #2%
                            expandafterUD@exchangeexpandafter%
                            romannumeral0UD@exchange expandafterexpandafterexpandafter
                            expandafterexpandafterexpandafterexpandafter%
                            expandafterUD@exchangeexpandafter%
                            romannumeral0%
                            expandafterUD@CheckWhetherBlankexpandafterUD@gobble#1 %
                            UD@CheckWhetherBlank#2 ,%
                            %
                            expandafter%
                            romannumeral0expandafterUD@exchangeexpandafter
                            %
                            romannumeral0expandafterexpandafterexpandafterUD@exchange
                            expandafterexpandafterexpandafterUD@ExtractFirstArg#1$ $triangle%
                            %
                            expandafterUD@CheckWhetherBlankexpandafterUD@gobble#1%
                            UD@CheckWhetherBlank#2 triangle triangles #2#3 and %
                            %
                            UD@CheckWhetherBlank#2 #2, %
                            %
                            %
                            %
                            %
                            expandaftertriangleloopexpandafterUD@gobble#1%
                            %
                            %
                            %
                            makeatother


                            begindocument

                            trianglespar
                            trianglesABCpar
                            trianglesABC DEFpar
                            trianglesABC DEF GHIpar
                            trianglesABC DEF GHI JKLpar

                            expandafterexpandafterexpandafterdef
                            expandafterexpandafterexpandafterThisTrianglelist
                            expandafterexpandafterexpandafter%
                            trianglesABC DEF GHI JKL%
                            %

                            textttfrenchspacing

                            enddocument


                            enter image description here







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Mar 28 at 3:57

























                            answered Mar 28 at 2:03









                            Ulrich DiezUlrich Diez

                            5,625620




                            5,625620



























                                draft saved

                                draft discarded
















































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


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

                                But avoid


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

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

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




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function ()
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f481707%2fa-command-with-a-variable-number-of-arguments-comma-versus-and%23new-answer', 'question_page');

                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                -macros

                                Popular posts from this blog

                                Frič See also Navigation menuinternal link

                                Identify plant with long narrow paired leaves and reddish stems Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern) Announcing the arrival of Valued Associate #679: Cesar Manara Unicorn Meta Zoo #1: Why another podcast?What is this plant with long sharp leaves? Is it a weed?What is this 3ft high, stalky plant, with mid sized narrow leaves?What is this young shrub with opposite ovate, crenate leaves and reddish stems?What is this plant with large broad serrated leaves?Identify this upright branching weed with long leaves and reddish stemsPlease help me identify this bulbous plant with long, broad leaves and white flowersWhat is this small annual with narrow gray/green leaves and rust colored daisy-type flowers?What is this chilli plant?Does anyone know what type of chilli plant this is?Help identify this plant

                                fontconfig warning: “/etc/fonts/fonts.conf”, line 100: unknown “element blank” The 2019 Stack Overflow Developer Survey Results Are In“tar: unrecognized option --warning” during 'apt-get install'How to fix Fontconfig errorHow do I figure out which font file is chosen for a system generic font alias?Why are some apt-get-installed fonts being ignored by fc-list, xfontsel, etc?Reload settings in /etc/fonts/conf.dTaking 30 seconds longer to boot after upgrade from jessie to stretchHow to match multiple font names with a single <match> element?Adding a custom font to fontconfigRemoving fonts from fontconfig <match> resultsBroken fonts after upgrading Firefox ESR to latest Firefox