How to define a command with two optional arguments?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
7
down vote

favorite
2












I would like to have a single command that can take either 1, 2, or 3 arguments and do something different for each number of arguments.



ca -> C_a
cab -> C_a^[b]
cabc -> C_a,c^[b]


Since Latex has no command overloading, I decided that optional arguments are good enough:



ca -> C_a
c[b]a -> C_a^[b]
c[c][b]a -> C_a,c^[b]


I found that this great answer using xparse might do exactly what I need. However his answer works only for 2 optional arguments. He mentions how to extend it to any number of arguments, but I couldn't figure it out. I tried:



usepackagexparse
....
DeclareDocumentCommand c o o m %
IfNoValueTF #1 %
IfNoValueTF #2 %
C_#3%
%
C_#3^[#2]%
%
%
C_#2, #3^[#1]%
%


$ca c[b]a c[c][b]a$


But it seems that I cannot get the branch with two arguments to work:



enter image description here



What am I doing wrong?







share|improve this question




















  • In LaTeX you don't need braces with undelimited single-token-arguments. Thus: How to handle cabc? Shall this mean c has one arg and the one-arg-call to c is trailed by letters b and c which do not form args of c? Shall this mean a three-argument-call to c with two args just not being nested in braces as braces are not really needed with single-token-arguments? You can check if a single-argument-macro's arg in turn consists of three or two or one brace-delimited arguments, i.e., cabc, but then you need to specify behavior for other cases and spaces as well.
    – Ulrich Diez
    Aug 31 at 16:56















up vote
7
down vote

favorite
2












I would like to have a single command that can take either 1, 2, or 3 arguments and do something different for each number of arguments.



ca -> C_a
cab -> C_a^[b]
cabc -> C_a,c^[b]


Since Latex has no command overloading, I decided that optional arguments are good enough:



ca -> C_a
c[b]a -> C_a^[b]
c[c][b]a -> C_a,c^[b]


I found that this great answer using xparse might do exactly what I need. However his answer works only for 2 optional arguments. He mentions how to extend it to any number of arguments, but I couldn't figure it out. I tried:



usepackagexparse
....
DeclareDocumentCommand c o o m %
IfNoValueTF #1 %
IfNoValueTF #2 %
C_#3%
%
C_#3^[#2]%
%
%
C_#2, #3^[#1]%
%


$ca c[b]a c[c][b]a$


But it seems that I cannot get the branch with two arguments to work:



enter image description here



What am I doing wrong?







share|improve this question




















  • In LaTeX you don't need braces with undelimited single-token-arguments. Thus: How to handle cabc? Shall this mean c has one arg and the one-arg-call to c is trailed by letters b and c which do not form args of c? Shall this mean a three-argument-call to c with two args just not being nested in braces as braces are not really needed with single-token-arguments? You can check if a single-argument-macro's arg in turn consists of three or two or one brace-delimited arguments, i.e., cabc, but then you need to specify behavior for other cases and spaces as well.
    – Ulrich Diez
    Aug 31 at 16:56













up vote
7
down vote

favorite
2









up vote
7
down vote

favorite
2






2





I would like to have a single command that can take either 1, 2, or 3 arguments and do something different for each number of arguments.



ca -> C_a
cab -> C_a^[b]
cabc -> C_a,c^[b]


Since Latex has no command overloading, I decided that optional arguments are good enough:



ca -> C_a
c[b]a -> C_a^[b]
c[c][b]a -> C_a,c^[b]


I found that this great answer using xparse might do exactly what I need. However his answer works only for 2 optional arguments. He mentions how to extend it to any number of arguments, but I couldn't figure it out. I tried:



usepackagexparse
....
DeclareDocumentCommand c o o m %
IfNoValueTF #1 %
IfNoValueTF #2 %
C_#3%
%
C_#3^[#2]%
%
%
C_#2, #3^[#1]%
%


$ca c[b]a c[c][b]a$


But it seems that I cannot get the branch with two arguments to work:



enter image description here



What am I doing wrong?







share|improve this question












I would like to have a single command that can take either 1, 2, or 3 arguments and do something different for each number of arguments.



ca -> C_a
cab -> C_a^[b]
cabc -> C_a,c^[b]


Since Latex has no command overloading, I decided that optional arguments are good enough:



ca -> C_a
c[b]a -> C_a^[b]
c[c][b]a -> C_a,c^[b]


I found that this great answer using xparse might do exactly what I need. However his answer works only for 2 optional arguments. He mentions how to extend it to any number of arguments, but I couldn't figure it out. I tried:



usepackagexparse
....
DeclareDocumentCommand c o o m %
IfNoValueTF #1 %
IfNoValueTF #2 %
C_#3%
%
C_#3^[#2]%
%
%
C_#2, #3^[#1]%
%


$ca c[b]a c[c][b]a$


But it seems that I cannot get the branch with two arguments to work:



enter image description here



What am I doing wrong?









share|improve this question











share|improve this question




share|improve this question










asked Aug 30 at 17:34









Martin Drozdik

82931527




82931527











  • In LaTeX you don't need braces with undelimited single-token-arguments. Thus: How to handle cabc? Shall this mean c has one arg and the one-arg-call to c is trailed by letters b and c which do not form args of c? Shall this mean a three-argument-call to c with two args just not being nested in braces as braces are not really needed with single-token-arguments? You can check if a single-argument-macro's arg in turn consists of three or two or one brace-delimited arguments, i.e., cabc, but then you need to specify behavior for other cases and spaces as well.
    – Ulrich Diez
    Aug 31 at 16:56

















  • In LaTeX you don't need braces with undelimited single-token-arguments. Thus: How to handle cabc? Shall this mean c has one arg and the one-arg-call to c is trailed by letters b and c which do not form args of c? Shall this mean a three-argument-call to c with two args just not being nested in braces as braces are not really needed with single-token-arguments? You can check if a single-argument-macro's arg in turn consists of three or two or one brace-delimited arguments, i.e., cabc, but then you need to specify behavior for other cases and spaces as well.
    – Ulrich Diez
    Aug 31 at 16:56
















In LaTeX you don't need braces with undelimited single-token-arguments. Thus: How to handle cabc? Shall this mean c has one arg and the one-arg-call to c is trailed by letters b and c which do not form args of c? Shall this mean a three-argument-call to c with two args just not being nested in braces as braces are not really needed with single-token-arguments? You can check if a single-argument-macro's arg in turn consists of three or two or one brace-delimited arguments, i.e., cabc, but then you need to specify behavior for other cases and spaces as well.
– Ulrich Diez
Aug 31 at 16:56





In LaTeX you don't need braces with undelimited single-token-arguments. Thus: How to handle cabc? Shall this mean c has one arg and the one-arg-call to c is trailed by letters b and c which do not form args of c? Shall this mean a three-argument-call to c with two args just not being nested in braces as braces are not really needed with single-token-arguments? You can check if a single-argument-macro's arg in turn consists of three or two or one brace-delimited arguments, i.e., cabc, but then you need to specify behavior for other cases and spaces as well.
– Ulrich Diez
Aug 31 at 16:56











2 Answers
2






active

oldest

votes

















up vote
7
down vote



accepted










You should start from examining #2 rather than #1, because #2 only can have a value if #1 has, too.



documentclassarticle
usepackagexparse

NewDocumentCommand C o o m %
IfNoValueTF#2
%
IfNoValueTF #1
%
C_#3%

%
C_#3^[#1]%
%

%
C_#3, #1^[#2]%
%


begindocument

$Ca quad C[b]a quad C[c][b]a$

enddocument


And don't use DeclareDocumentCommand to override the meaning of c: you'll regret it when you have to cite some French or Turkish author with “ç” in their name.



enter image description here






share|improve this answer



























    up vote
    1
    down vote













    You wish to define a macro c. But c is already defined in LaTeX.

    Therefore I will henceforth not refer to the macro in question as c.

    Instead I will refer to the macro in question as macroc.




    Are you aware that in TeX/LaTeX undelimited arguments consisting of a single token don't need to be nested in braces?



    After defining newcommandfoo[1]This is argument 1: #1.,
    foob will yield the same result as
    foo b.



    After defining newcommandbar[2]This is argument 1: #1. This is argument 2: #2., the following calls will all yield the same result:
    barab
    bar ab
    bar ab
    bar ab
    bara b
    bar a b
    bar a b
    bar a b



    This is because



    1. you don't need braces when undelimited arguments consist of a single token.

    2. (La)TeX does discard space tokens preceding undelimited arguments.

    When called as macrocabc—how shall macroc "know" whether the user intends to have c as macroc's third argument which consists of the single token c or whether the user intends to have macroc called with only two arguments, namely a and b while c shall not be considered a third argument?



    The situation is ambiguous.



    You can turn the situation into something unambiguous by having macroc process only one undelimited argument and having macroc check whether that argument in turn is of one of the patterns



    ⟨argument 1⟩



    ⟨argument 1⟩⟨argument 2⟩



    ⟨argument 1⟩⟨argument 2⟩⟨argument 3⟩



    and having macroc act accordingly in case one of these patterns is detected and having macroc deliver an error-message otherwise.



    I.e.,



    macroc⟨argument 1⟩



    macroc⟨argument 1⟩⟨argument 2⟩



    macroc⟨argument 1⟩⟨argument 2⟩⟨argument 3⟩




    With the example below, macroc does process one undelimited argument.



    Syntax: macroc⟨argument⟩.



    In case ⟨argument⟩ is of pattern ⟨argument 1⟩,
    macrocatonearg⟨argument 1⟩ will be carried out.



    In case ⟨argument⟩ is of pattern ⟨argument 1⟩⟨argument 2⟩,
    macrocattwoargs⟨argument 1⟩⟨argument 2⟩ will be carried out.



    In case ⟨argument⟩ is of pattern ⟨argument 1⟩⟨argument 2⟩⟨argument 3⟩,
    macrocatthreeargs⟨argument 1⟩⟨argument 2⟩⟨argument 3⟩ will be carried out.



    In all other cases an error-message will inform the user about a syntax-error.



    Thus you can do, e.g., :



    macroca



    macrocab



    macrocabc



    documentclassarticle

    makeatletter
    %%=============================================================================
    %% Paraphernalia:
    %% UD@firstoftwo, UD@secondoftwo,
    %% UD@gobble, UD@gobbletwo, UD@gobblethree
    %% UD@CheckWhetherNull, UD@CheckWhetherBrace,
    %%=============================================================================
    newcommandUD@firstoftwo[2]#1%
    newcommandUD@secondoftwo[2]#2%
    newcommandUD@gobble[1]%
    newcommandUD@gobbletwo[2]%
    newcommandUD@gobblethree[3]%
    %%-----------------------------------------------------------------------------
    %% 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's first token is a catcode-1-character
    %%.............................................................................
    %% UD@CheckWhetherBrace<Argument which is to be checked>%
    %% <Tokens to be delivered in case that argument
    %% which is to be checked has leading
    %% catcode-1-token>%
    %% <Tokens to be delivered in case that argument
    %% which is to be checked has no leading
    %% catcode-1-token>%
    newcommandUD@CheckWhetherBrace[1]%
    romannumeral0expandafterUD@secondoftwoexpandafterexpandafter%
    string#1.expandafterUD@firstoftwoexpandafterexpandafter
    UD@secondoftwostringexpandafterexpandafterUD@firstoftwo %
    UD@firstoftwoexpandafterexpandafterUD@firstoftwo UD@secondoftwo%
    %
    %%=============================================================================
    %% macroc for processing one argument within which
    %% you may have one or two or three brace-nested arguments:
    %%-----------------------------------------------------------------------------
    newcommandmacrocatonearg[1]C_#1%
    newcommandmacrocattwoargs[2]C_#1^[#2]%
    newcommandmacrocatthreeargs[3]C_#1,#3^[#2]%
    newcommandmacrocatsyntaxerror%
    @latex@errorIncorrect SyntaxSpecify either one or two or three arguments that are nested in braces.%
    %
    newcommandmacroc[1]%
    UD@CheckWhetherBrace#1%
    expandafterUD@CheckWhetherNullexpandafterUD@gobble#1%
    macrocatonearg#1%
    %
    expandafterUD@CheckWhetherBraceexpandafterUD@gobble#1%
    expandafterUD@CheckWhetherNullexpandafterUD@gobbletwo#1%
    macrocattwoargs#1%
    %
    expandafterUD@CheckWhetherBraceexpandafterUD@gobbletwo#1%
    expandafterUD@CheckWhetherNullexpandafterUD@gobblethree#1%
    macrocatthreeargs#1%
    macrocatsyntaxerror%
    macrocatsyntaxerror%
    %
    macrocatsyntaxerror%
    %
    macrocatsyntaxerror%
    %
    makeatother
    begindocument

    verb|$macroca$|: $macroca$ bigskip

    verb|$macrocab$|: $macrocab$ bigskip

    verb|$macrocabc$|: $macrocabc$ bigskip

    % Syntax-errors:
    %
    % $macrocabcd$
    %
    % $macroc a$
    %
    % $macroca b$
    %
    % $macroca$
    %
    % $macroc$

    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',
      convertImagesToLinks: false,
      noModals: false,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      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%2f448542%2fhow-to-define-a-command-with-two-optional-arguments%23new-answer', 'question_page');

      );

      Post as a guest






























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      7
      down vote



      accepted










      You should start from examining #2 rather than #1, because #2 only can have a value if #1 has, too.



      documentclassarticle
      usepackagexparse

      NewDocumentCommand C o o m %
      IfNoValueTF#2
      %
      IfNoValueTF #1
      %
      C_#3%

      %
      C_#3^[#1]%
      %

      %
      C_#3, #1^[#2]%
      %


      begindocument

      $Ca quad C[b]a quad C[c][b]a$

      enddocument


      And don't use DeclareDocumentCommand to override the meaning of c: you'll regret it when you have to cite some French or Turkish author with “ç” in their name.



      enter image description here






      share|improve this answer
























        up vote
        7
        down vote



        accepted










        You should start from examining #2 rather than #1, because #2 only can have a value if #1 has, too.



        documentclassarticle
        usepackagexparse

        NewDocumentCommand C o o m %
        IfNoValueTF#2
        %
        IfNoValueTF #1
        %
        C_#3%

        %
        C_#3^[#1]%
        %

        %
        C_#3, #1^[#2]%
        %


        begindocument

        $Ca quad C[b]a quad C[c][b]a$

        enddocument


        And don't use DeclareDocumentCommand to override the meaning of c: you'll regret it when you have to cite some French or Turkish author with “ç” in their name.



        enter image description here






        share|improve this answer






















          up vote
          7
          down vote



          accepted







          up vote
          7
          down vote



          accepted






          You should start from examining #2 rather than #1, because #2 only can have a value if #1 has, too.



          documentclassarticle
          usepackagexparse

          NewDocumentCommand C o o m %
          IfNoValueTF#2
          %
          IfNoValueTF #1
          %
          C_#3%

          %
          C_#3^[#1]%
          %

          %
          C_#3, #1^[#2]%
          %


          begindocument

          $Ca quad C[b]a quad C[c][b]a$

          enddocument


          And don't use DeclareDocumentCommand to override the meaning of c: you'll regret it when you have to cite some French or Turkish author with “ç” in their name.



          enter image description here






          share|improve this answer












          You should start from examining #2 rather than #1, because #2 only can have a value if #1 has, too.



          documentclassarticle
          usepackagexparse

          NewDocumentCommand C o o m %
          IfNoValueTF#2
          %
          IfNoValueTF #1
          %
          C_#3%

          %
          C_#3^[#1]%
          %

          %
          C_#3, #1^[#2]%
          %


          begindocument

          $Ca quad C[b]a quad C[c][b]a$

          enddocument


          And don't use DeclareDocumentCommand to override the meaning of c: you'll regret it when you have to cite some French or Turkish author with “ç” in their name.



          enter image description here







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Aug 30 at 17:48









          egreg

          681k8318083056




          681k8318083056




















              up vote
              1
              down vote













              You wish to define a macro c. But c is already defined in LaTeX.

              Therefore I will henceforth not refer to the macro in question as c.

              Instead I will refer to the macro in question as macroc.




              Are you aware that in TeX/LaTeX undelimited arguments consisting of a single token don't need to be nested in braces?



              After defining newcommandfoo[1]This is argument 1: #1.,
              foob will yield the same result as
              foo b.



              After defining newcommandbar[2]This is argument 1: #1. This is argument 2: #2., the following calls will all yield the same result:
              barab
              bar ab
              bar ab
              bar ab
              bara b
              bar a b
              bar a b
              bar a b



              This is because



              1. you don't need braces when undelimited arguments consist of a single token.

              2. (La)TeX does discard space tokens preceding undelimited arguments.

              When called as macrocabc—how shall macroc "know" whether the user intends to have c as macroc's third argument which consists of the single token c or whether the user intends to have macroc called with only two arguments, namely a and b while c shall not be considered a third argument?



              The situation is ambiguous.



              You can turn the situation into something unambiguous by having macroc process only one undelimited argument and having macroc check whether that argument in turn is of one of the patterns



              &langle;argument 1&rangle;



              &langle;argument 1&rangle;&langle;argument 2&rangle;



              &langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle;



              and having macroc act accordingly in case one of these patterns is detected and having macroc deliver an error-message otherwise.



              I.e.,



              macroc&langle;argument 1&rangle;



              macroc&langle;argument 1&rangle;&langle;argument 2&rangle;



              macroc&langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle;




              With the example below, macroc does process one undelimited argument.



              Syntax: macroc&langle;argument&rangle;.



              In case &langle;argument&rangle; is of pattern &langle;argument 1&rangle;,
              macrocatonearg&langle;argument 1&rangle; will be carried out.



              In case &langle;argument&rangle; is of pattern &langle;argument 1&rangle;&langle;argument 2&rangle;,
              macrocattwoargs&langle;argument 1&rangle;&langle;argument 2&rangle; will be carried out.



              In case &langle;argument&rangle; is of pattern &langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle;,
              macrocatthreeargs&langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle; will be carried out.



              In all other cases an error-message will inform the user about a syntax-error.



              Thus you can do, e.g., :



              macroca



              macrocab



              macrocabc



              documentclassarticle

              makeatletter
              %%=============================================================================
              %% Paraphernalia:
              %% UD@firstoftwo, UD@secondoftwo,
              %% UD@gobble, UD@gobbletwo, UD@gobblethree
              %% UD@CheckWhetherNull, UD@CheckWhetherBrace,
              %%=============================================================================
              newcommandUD@firstoftwo[2]#1%
              newcommandUD@secondoftwo[2]#2%
              newcommandUD@gobble[1]%
              newcommandUD@gobbletwo[2]%
              newcommandUD@gobblethree[3]%
              %%-----------------------------------------------------------------------------
              %% 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's first token is a catcode-1-character
              %%.............................................................................
              %% UD@CheckWhetherBrace<Argument which is to be checked>%
              %% <Tokens to be delivered in case that argument
              %% which is to be checked has leading
              %% catcode-1-token>%
              %% <Tokens to be delivered in case that argument
              %% which is to be checked has no leading
              %% catcode-1-token>%
              newcommandUD@CheckWhetherBrace[1]%
              romannumeral0expandafterUD@secondoftwoexpandafterexpandafter%
              string#1.expandafterUD@firstoftwoexpandafterexpandafter
              UD@secondoftwostringexpandafterexpandafterUD@firstoftwo %
              UD@firstoftwoexpandafterexpandafterUD@firstoftwo UD@secondoftwo%
              %
              %%=============================================================================
              %% macroc for processing one argument within which
              %% you may have one or two or three brace-nested arguments:
              %%-----------------------------------------------------------------------------
              newcommandmacrocatonearg[1]C_#1%
              newcommandmacrocattwoargs[2]C_#1^[#2]%
              newcommandmacrocatthreeargs[3]C_#1,#3^[#2]%
              newcommandmacrocatsyntaxerror%
              @latex@errorIncorrect SyntaxSpecify either one or two or three arguments that are nested in braces.%
              %
              newcommandmacroc[1]%
              UD@CheckWhetherBrace#1%
              expandafterUD@CheckWhetherNullexpandafterUD@gobble#1%
              macrocatonearg#1%
              %
              expandafterUD@CheckWhetherBraceexpandafterUD@gobble#1%
              expandafterUD@CheckWhetherNullexpandafterUD@gobbletwo#1%
              macrocattwoargs#1%
              %
              expandafterUD@CheckWhetherBraceexpandafterUD@gobbletwo#1%
              expandafterUD@CheckWhetherNullexpandafterUD@gobblethree#1%
              macrocatthreeargs#1%
              macrocatsyntaxerror%
              macrocatsyntaxerror%
              %
              macrocatsyntaxerror%
              %
              macrocatsyntaxerror%
              %
              makeatother
              begindocument

              verb|$macroca$|: $macroca$ bigskip

              verb|$macrocab$|: $macrocab$ bigskip

              verb|$macrocabc$|: $macrocabc$ bigskip

              % Syntax-errors:
              %
              % $macrocabcd$
              %
              % $macroc a$
              %
              % $macroca b$
              %
              % $macroca$
              %
              % $macroc$

              enddocument


              enter image description here






              share|improve this answer


























                up vote
                1
                down vote













                You wish to define a macro c. But c is already defined in LaTeX.

                Therefore I will henceforth not refer to the macro in question as c.

                Instead I will refer to the macro in question as macroc.




                Are you aware that in TeX/LaTeX undelimited arguments consisting of a single token don't need to be nested in braces?



                After defining newcommandfoo[1]This is argument 1: #1.,
                foob will yield the same result as
                foo b.



                After defining newcommandbar[2]This is argument 1: #1. This is argument 2: #2., the following calls will all yield the same result:
                barab
                bar ab
                bar ab
                bar ab
                bara b
                bar a b
                bar a b
                bar a b



                This is because



                1. you don't need braces when undelimited arguments consist of a single token.

                2. (La)TeX does discard space tokens preceding undelimited arguments.

                When called as macrocabc—how shall macroc "know" whether the user intends to have c as macroc's third argument which consists of the single token c or whether the user intends to have macroc called with only two arguments, namely a and b while c shall not be considered a third argument?



                The situation is ambiguous.



                You can turn the situation into something unambiguous by having macroc process only one undelimited argument and having macroc check whether that argument in turn is of one of the patterns



                &langle;argument 1&rangle;



                &langle;argument 1&rangle;&langle;argument 2&rangle;



                &langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle;



                and having macroc act accordingly in case one of these patterns is detected and having macroc deliver an error-message otherwise.



                I.e.,



                macroc&langle;argument 1&rangle;



                macroc&langle;argument 1&rangle;&langle;argument 2&rangle;



                macroc&langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle;




                With the example below, macroc does process one undelimited argument.



                Syntax: macroc&langle;argument&rangle;.



                In case &langle;argument&rangle; is of pattern &langle;argument 1&rangle;,
                macrocatonearg&langle;argument 1&rangle; will be carried out.



                In case &langle;argument&rangle; is of pattern &langle;argument 1&rangle;&langle;argument 2&rangle;,
                macrocattwoargs&langle;argument 1&rangle;&langle;argument 2&rangle; will be carried out.



                In case &langle;argument&rangle; is of pattern &langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle;,
                macrocatthreeargs&langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle; will be carried out.



                In all other cases an error-message will inform the user about a syntax-error.



                Thus you can do, e.g., :



                macroca



                macrocab



                macrocabc



                documentclassarticle

                makeatletter
                %%=============================================================================
                %% Paraphernalia:
                %% UD@firstoftwo, UD@secondoftwo,
                %% UD@gobble, UD@gobbletwo, UD@gobblethree
                %% UD@CheckWhetherNull, UD@CheckWhetherBrace,
                %%=============================================================================
                newcommandUD@firstoftwo[2]#1%
                newcommandUD@secondoftwo[2]#2%
                newcommandUD@gobble[1]%
                newcommandUD@gobbletwo[2]%
                newcommandUD@gobblethree[3]%
                %%-----------------------------------------------------------------------------
                %% 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's first token is a catcode-1-character
                %%.............................................................................
                %% UD@CheckWhetherBrace<Argument which is to be checked>%
                %% <Tokens to be delivered in case that argument
                %% which is to be checked has leading
                %% catcode-1-token>%
                %% <Tokens to be delivered in case that argument
                %% which is to be checked has no leading
                %% catcode-1-token>%
                newcommandUD@CheckWhetherBrace[1]%
                romannumeral0expandafterUD@secondoftwoexpandafterexpandafter%
                string#1.expandafterUD@firstoftwoexpandafterexpandafter
                UD@secondoftwostringexpandafterexpandafterUD@firstoftwo %
                UD@firstoftwoexpandafterexpandafterUD@firstoftwo UD@secondoftwo%
                %
                %%=============================================================================
                %% macroc for processing one argument within which
                %% you may have one or two or three brace-nested arguments:
                %%-----------------------------------------------------------------------------
                newcommandmacrocatonearg[1]C_#1%
                newcommandmacrocattwoargs[2]C_#1^[#2]%
                newcommandmacrocatthreeargs[3]C_#1,#3^[#2]%
                newcommandmacrocatsyntaxerror%
                @latex@errorIncorrect SyntaxSpecify either one or two or three arguments that are nested in braces.%
                %
                newcommandmacroc[1]%
                UD@CheckWhetherBrace#1%
                expandafterUD@CheckWhetherNullexpandafterUD@gobble#1%
                macrocatonearg#1%
                %
                expandafterUD@CheckWhetherBraceexpandafterUD@gobble#1%
                expandafterUD@CheckWhetherNullexpandafterUD@gobbletwo#1%
                macrocattwoargs#1%
                %
                expandafterUD@CheckWhetherBraceexpandafterUD@gobbletwo#1%
                expandafterUD@CheckWhetherNullexpandafterUD@gobblethree#1%
                macrocatthreeargs#1%
                macrocatsyntaxerror%
                macrocatsyntaxerror%
                %
                macrocatsyntaxerror%
                %
                macrocatsyntaxerror%
                %
                makeatother
                begindocument

                verb|$macroca$|: $macroca$ bigskip

                verb|$macrocab$|: $macrocab$ bigskip

                verb|$macrocabc$|: $macrocabc$ bigskip

                % Syntax-errors:
                %
                % $macrocabcd$
                %
                % $macroc a$
                %
                % $macroca b$
                %
                % $macroca$
                %
                % $macroc$

                enddocument


                enter image description here






                share|improve this answer
























                  up vote
                  1
                  down vote










                  up vote
                  1
                  down vote









                  You wish to define a macro c. But c is already defined in LaTeX.

                  Therefore I will henceforth not refer to the macro in question as c.

                  Instead I will refer to the macro in question as macroc.




                  Are you aware that in TeX/LaTeX undelimited arguments consisting of a single token don't need to be nested in braces?



                  After defining newcommandfoo[1]This is argument 1: #1.,
                  foob will yield the same result as
                  foo b.



                  After defining newcommandbar[2]This is argument 1: #1. This is argument 2: #2., the following calls will all yield the same result:
                  barab
                  bar ab
                  bar ab
                  bar ab
                  bara b
                  bar a b
                  bar a b
                  bar a b



                  This is because



                  1. you don't need braces when undelimited arguments consist of a single token.

                  2. (La)TeX does discard space tokens preceding undelimited arguments.

                  When called as macrocabc—how shall macroc "know" whether the user intends to have c as macroc's third argument which consists of the single token c or whether the user intends to have macroc called with only two arguments, namely a and b while c shall not be considered a third argument?



                  The situation is ambiguous.



                  You can turn the situation into something unambiguous by having macroc process only one undelimited argument and having macroc check whether that argument in turn is of one of the patterns



                  &langle;argument 1&rangle;



                  &langle;argument 1&rangle;&langle;argument 2&rangle;



                  &langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle;



                  and having macroc act accordingly in case one of these patterns is detected and having macroc deliver an error-message otherwise.



                  I.e.,



                  macroc&langle;argument 1&rangle;



                  macroc&langle;argument 1&rangle;&langle;argument 2&rangle;



                  macroc&langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle;




                  With the example below, macroc does process one undelimited argument.



                  Syntax: macroc&langle;argument&rangle;.



                  In case &langle;argument&rangle; is of pattern &langle;argument 1&rangle;,
                  macrocatonearg&langle;argument 1&rangle; will be carried out.



                  In case &langle;argument&rangle; is of pattern &langle;argument 1&rangle;&langle;argument 2&rangle;,
                  macrocattwoargs&langle;argument 1&rangle;&langle;argument 2&rangle; will be carried out.



                  In case &langle;argument&rangle; is of pattern &langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle;,
                  macrocatthreeargs&langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle; will be carried out.



                  In all other cases an error-message will inform the user about a syntax-error.



                  Thus you can do, e.g., :



                  macroca



                  macrocab



                  macrocabc



                  documentclassarticle

                  makeatletter
                  %%=============================================================================
                  %% Paraphernalia:
                  %% UD@firstoftwo, UD@secondoftwo,
                  %% UD@gobble, UD@gobbletwo, UD@gobblethree
                  %% UD@CheckWhetherNull, UD@CheckWhetherBrace,
                  %%=============================================================================
                  newcommandUD@firstoftwo[2]#1%
                  newcommandUD@secondoftwo[2]#2%
                  newcommandUD@gobble[1]%
                  newcommandUD@gobbletwo[2]%
                  newcommandUD@gobblethree[3]%
                  %%-----------------------------------------------------------------------------
                  %% 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's first token is a catcode-1-character
                  %%.............................................................................
                  %% UD@CheckWhetherBrace<Argument which is to be checked>%
                  %% <Tokens to be delivered in case that argument
                  %% which is to be checked has leading
                  %% catcode-1-token>%
                  %% <Tokens to be delivered in case that argument
                  %% which is to be checked has no leading
                  %% catcode-1-token>%
                  newcommandUD@CheckWhetherBrace[1]%
                  romannumeral0expandafterUD@secondoftwoexpandafterexpandafter%
                  string#1.expandafterUD@firstoftwoexpandafterexpandafter
                  UD@secondoftwostringexpandafterexpandafterUD@firstoftwo %
                  UD@firstoftwoexpandafterexpandafterUD@firstoftwo UD@secondoftwo%
                  %
                  %%=============================================================================
                  %% macroc for processing one argument within which
                  %% you may have one or two or three brace-nested arguments:
                  %%-----------------------------------------------------------------------------
                  newcommandmacrocatonearg[1]C_#1%
                  newcommandmacrocattwoargs[2]C_#1^[#2]%
                  newcommandmacrocatthreeargs[3]C_#1,#3^[#2]%
                  newcommandmacrocatsyntaxerror%
                  @latex@errorIncorrect SyntaxSpecify either one or two or three arguments that are nested in braces.%
                  %
                  newcommandmacroc[1]%
                  UD@CheckWhetherBrace#1%
                  expandafterUD@CheckWhetherNullexpandafterUD@gobble#1%
                  macrocatonearg#1%
                  %
                  expandafterUD@CheckWhetherBraceexpandafterUD@gobble#1%
                  expandafterUD@CheckWhetherNullexpandafterUD@gobbletwo#1%
                  macrocattwoargs#1%
                  %
                  expandafterUD@CheckWhetherBraceexpandafterUD@gobbletwo#1%
                  expandafterUD@CheckWhetherNullexpandafterUD@gobblethree#1%
                  macrocatthreeargs#1%
                  macrocatsyntaxerror%
                  macrocatsyntaxerror%
                  %
                  macrocatsyntaxerror%
                  %
                  macrocatsyntaxerror%
                  %
                  makeatother
                  begindocument

                  verb|$macroca$|: $macroca$ bigskip

                  verb|$macrocab$|: $macrocab$ bigskip

                  verb|$macrocabc$|: $macrocabc$ bigskip

                  % Syntax-errors:
                  %
                  % $macrocabcd$
                  %
                  % $macroc a$
                  %
                  % $macroca b$
                  %
                  % $macroca$
                  %
                  % $macroc$

                  enddocument


                  enter image description here






                  share|improve this answer














                  You wish to define a macro c. But c is already defined in LaTeX.

                  Therefore I will henceforth not refer to the macro in question as c.

                  Instead I will refer to the macro in question as macroc.




                  Are you aware that in TeX/LaTeX undelimited arguments consisting of a single token don't need to be nested in braces?



                  After defining newcommandfoo[1]This is argument 1: #1.,
                  foob will yield the same result as
                  foo b.



                  After defining newcommandbar[2]This is argument 1: #1. This is argument 2: #2., the following calls will all yield the same result:
                  barab
                  bar ab
                  bar ab
                  bar ab
                  bara b
                  bar a b
                  bar a b
                  bar a b



                  This is because



                  1. you don't need braces when undelimited arguments consist of a single token.

                  2. (La)TeX does discard space tokens preceding undelimited arguments.

                  When called as macrocabc—how shall macroc "know" whether the user intends to have c as macroc's third argument which consists of the single token c or whether the user intends to have macroc called with only two arguments, namely a and b while c shall not be considered a third argument?



                  The situation is ambiguous.



                  You can turn the situation into something unambiguous by having macroc process only one undelimited argument and having macroc check whether that argument in turn is of one of the patterns



                  &langle;argument 1&rangle;



                  &langle;argument 1&rangle;&langle;argument 2&rangle;



                  &langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle;



                  and having macroc act accordingly in case one of these patterns is detected and having macroc deliver an error-message otherwise.



                  I.e.,



                  macroc&langle;argument 1&rangle;



                  macroc&langle;argument 1&rangle;&langle;argument 2&rangle;



                  macroc&langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle;




                  With the example below, macroc does process one undelimited argument.



                  Syntax: macroc&langle;argument&rangle;.



                  In case &langle;argument&rangle; is of pattern &langle;argument 1&rangle;,
                  macrocatonearg&langle;argument 1&rangle; will be carried out.



                  In case &langle;argument&rangle; is of pattern &langle;argument 1&rangle;&langle;argument 2&rangle;,
                  macrocattwoargs&langle;argument 1&rangle;&langle;argument 2&rangle; will be carried out.



                  In case &langle;argument&rangle; is of pattern &langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle;,
                  macrocatthreeargs&langle;argument 1&rangle;&langle;argument 2&rangle;&langle;argument 3&rangle; will be carried out.



                  In all other cases an error-message will inform the user about a syntax-error.



                  Thus you can do, e.g., :



                  macroca



                  macrocab



                  macrocabc



                  documentclassarticle

                  makeatletter
                  %%=============================================================================
                  %% Paraphernalia:
                  %% UD@firstoftwo, UD@secondoftwo,
                  %% UD@gobble, UD@gobbletwo, UD@gobblethree
                  %% UD@CheckWhetherNull, UD@CheckWhetherBrace,
                  %%=============================================================================
                  newcommandUD@firstoftwo[2]#1%
                  newcommandUD@secondoftwo[2]#2%
                  newcommandUD@gobble[1]%
                  newcommandUD@gobbletwo[2]%
                  newcommandUD@gobblethree[3]%
                  %%-----------------------------------------------------------------------------
                  %% 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's first token is a catcode-1-character
                  %%.............................................................................
                  %% UD@CheckWhetherBrace<Argument which is to be checked>%
                  %% <Tokens to be delivered in case that argument
                  %% which is to be checked has leading
                  %% catcode-1-token>%
                  %% <Tokens to be delivered in case that argument
                  %% which is to be checked has no leading
                  %% catcode-1-token>%
                  newcommandUD@CheckWhetherBrace[1]%
                  romannumeral0expandafterUD@secondoftwoexpandafterexpandafter%
                  string#1.expandafterUD@firstoftwoexpandafterexpandafter
                  UD@secondoftwostringexpandafterexpandafterUD@firstoftwo %
                  UD@firstoftwoexpandafterexpandafterUD@firstoftwo UD@secondoftwo%
                  %
                  %%=============================================================================
                  %% macroc for processing one argument within which
                  %% you may have one or two or three brace-nested arguments:
                  %%-----------------------------------------------------------------------------
                  newcommandmacrocatonearg[1]C_#1%
                  newcommandmacrocattwoargs[2]C_#1^[#2]%
                  newcommandmacrocatthreeargs[3]C_#1,#3^[#2]%
                  newcommandmacrocatsyntaxerror%
                  @latex@errorIncorrect SyntaxSpecify either one or two or three arguments that are nested in braces.%
                  %
                  newcommandmacroc[1]%
                  UD@CheckWhetherBrace#1%
                  expandafterUD@CheckWhetherNullexpandafterUD@gobble#1%
                  macrocatonearg#1%
                  %
                  expandafterUD@CheckWhetherBraceexpandafterUD@gobble#1%
                  expandafterUD@CheckWhetherNullexpandafterUD@gobbletwo#1%
                  macrocattwoargs#1%
                  %
                  expandafterUD@CheckWhetherBraceexpandafterUD@gobbletwo#1%
                  expandafterUD@CheckWhetherNullexpandafterUD@gobblethree#1%
                  macrocatthreeargs#1%
                  macrocatsyntaxerror%
                  macrocatsyntaxerror%
                  %
                  macrocatsyntaxerror%
                  %
                  macrocatsyntaxerror%
                  %
                  makeatother
                  begindocument

                  verb|$macroca$|: $macroca$ bigskip

                  verb|$macrocab$|: $macrocab$ bigskip

                  verb|$macrocabc$|: $macrocabc$ bigskip

                  % Syntax-errors:
                  %
                  % $macrocabcd$
                  %
                  % $macroc a$
                  %
                  % $macroca b$
                  %
                  % $macroca$
                  %
                  % $macroc$

                  enddocument


                  enter image description here







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Sep 3 at 16:02

























                  answered Aug 31 at 17:42









                  Ulrich Diez

                  3,250414




                  3,250414



























                       

                      draft saved


                      draft discarded















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f448542%2fhow-to-define-a-command-with-two-optional-arguments%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      Comments

                      Popular posts from this blog

                      What does second last employer means? [closed]

                      List of Gilmore Girls characters

                      Confectionery