newcommand: Combine (optional) star and optional parameter












5















How may I define a new command that admits starred and non-starred variants, and that also admits an optional argument?



I tried the following:



documentclass{minimal}
makeatletter
newcommandMyCommand[1][1]{%
@ifstar{%
The starred variant with parameter: #1%
}{%
The non-starred variant with parameter: #1%
}
}
makeatother
begin{document}
MyCommand \
MyCommand* \
MyCommand[2] \
MyCommand*[2]
end{document}


But this gives:




The non-starred variant with parameter: 1

The starred variant with parameter: 1

The non-starred variant with parameter: 2

The starred variant with parameter: 1[2]




Yet, one can write MyCommand[2]* to obtain "The starred variant with parameter: 2" but somehow I'd like the above version to work.










share|improve this question




















  • 2





    Please, avoid using the minimal class; it is not meant for minimal examples.

    – egreg
    yesterday











  • I learned many things with this question, including the fact that the minimal class is not made for minimal examples!

    – Bruno
    yesterday
















5















How may I define a new command that admits starred and non-starred variants, and that also admits an optional argument?



I tried the following:



documentclass{minimal}
makeatletter
newcommandMyCommand[1][1]{%
@ifstar{%
The starred variant with parameter: #1%
}{%
The non-starred variant with parameter: #1%
}
}
makeatother
begin{document}
MyCommand \
MyCommand* \
MyCommand[2] \
MyCommand*[2]
end{document}


But this gives:




The non-starred variant with parameter: 1

The starred variant with parameter: 1

The non-starred variant with parameter: 2

The starred variant with parameter: 1[2]




Yet, one can write MyCommand[2]* to obtain "The starred variant with parameter: 2" but somehow I'd like the above version to work.










share|improve this question




















  • 2





    Please, avoid using the minimal class; it is not meant for minimal examples.

    – egreg
    yesterday











  • I learned many things with this question, including the fact that the minimal class is not made for minimal examples!

    – Bruno
    yesterday














5












5








5








How may I define a new command that admits starred and non-starred variants, and that also admits an optional argument?



I tried the following:



documentclass{minimal}
makeatletter
newcommandMyCommand[1][1]{%
@ifstar{%
The starred variant with parameter: #1%
}{%
The non-starred variant with parameter: #1%
}
}
makeatother
begin{document}
MyCommand \
MyCommand* \
MyCommand[2] \
MyCommand*[2]
end{document}


But this gives:




The non-starred variant with parameter: 1

The starred variant with parameter: 1

The non-starred variant with parameter: 2

The starred variant with parameter: 1[2]




Yet, one can write MyCommand[2]* to obtain "The starred variant with parameter: 2" but somehow I'd like the above version to work.










share|improve this question
















How may I define a new command that admits starred and non-starred variants, and that also admits an optional argument?



I tried the following:



documentclass{minimal}
makeatletter
newcommandMyCommand[1][1]{%
@ifstar{%
The starred variant with parameter: #1%
}{%
The non-starred variant with parameter: #1%
}
}
makeatother
begin{document}
MyCommand \
MyCommand* \
MyCommand[2] \
MyCommand*[2]
end{document}


But this gives:




The non-starred variant with parameter: 1

The starred variant with parameter: 1

The non-starred variant with parameter: 2

The starred variant with parameter: 1[2]




Yet, one can write MyCommand[2]* to obtain "The starred variant with parameter: 2" but somehow I'd like the above version to work.







macros






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited yesterday







Bruno

















asked yesterday









BrunoBruno

1,0921822




1,0921822








  • 2





    Please, avoid using the minimal class; it is not meant for minimal examples.

    – egreg
    yesterday











  • I learned many things with this question, including the fact that the minimal class is not made for minimal examples!

    – Bruno
    yesterday














  • 2





    Please, avoid using the minimal class; it is not meant for minimal examples.

    – egreg
    yesterday











  • I learned many things with this question, including the fact that the minimal class is not made for minimal examples!

    – Bruno
    yesterday








2




2





Please, avoid using the minimal class; it is not meant for minimal examples.

– egreg
yesterday





Please, avoid using the minimal class; it is not meant for minimal examples.

– egreg
yesterday













I learned many things with this question, including the fact that the minimal class is not made for minimal examples!

– Bruno
yesterday





I learned many things with this question, including the fact that the minimal class is not made for minimal examples!

– Bruno
yesterday










2 Answers
2






active

oldest

votes


















7














With xparse it's very easy to play around with optional arguments and starred variants:



documentclass{article}
usepackage{xparse}
NewDocumentCommandMyCommand
{
s % optional *
O{1} % first optional argument (default = 1)
}
{%
IfBooleanTF{#1}
{The starred variant with parameter: #2}
{The non-starred variant with parameter: #2}
}
begin{document}
noindent
MyCommand \
MyCommand* \
MyCommand[2]\
MyCommand*[2]
end{document}


With LaTeX's newcommand it a little trickier. The @ifstar macro looks at the next token after the macro is expanded and has absorbed its arguments, so you need to first check for the * and only then look for the optional argument:



documentclass{article}
makeatletter
newcommandMyCommand
{%
@ifstar
{MyCommand@star}
{MyCommand@nostar}%
}
newcommandMyCommand@star[1][1]{%
The starred variant with parameter: #1%
}
newcommandMyCommand@nostar[1][1]{%
The non-starred variant with parameter: #1%
}
makeatother
begin{document}
noindent
MyCommand \
MyCommand* \
MyCommand[2]\
MyCommand*[2]
end{document}


Both versions print:




enter image description here




Your code works, but not as you expect it to. The MyCommand[1][1] looks for an optional argument “while expanding” MyCommand, which then gives you:



@ifstar{%
The starred variant with parameter: <optional argument or default>%
}{%
The non-starred variant with parameter: <optional argument or default>%
}


and only after that the @ifstar test will be expanded to look for the optional * and choose the text accordingly, so the actual syntax for the command you defined is:



MyCommand[optional argument]<optional star>





share|improve this answer

































    3














    Make MyCommand take no parameters, but just figure out the star. Then fork from there.



    documentclass{minimal}
    makeatletter
    newcommandMyCommand{%
    @ifstar{mycommandstar}{mycommandnostar}
    }
    newcommandmycommandstar[1][1]{The starred variant with parameter: #1}
    newcommandmycommandnostar[1][1]{The non-starred variant with parameter: #1}
    makeatother
    begin{document}
    MyCommand \
    MyCommand* \
    MyCommand[2] \
    MyCommand*[2]
    end{document}


    enter image description here






    share|improve this answer



















    • 2





      I'd add a % at the end of the definition of MyCommand. It works without that because the definition of @ifstar ignores space tokens by design, but... :)

      – Phelype Oleinik
      yesterday











    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%2f479632%2fnewcommand-combine-optional-star-and-optional-parameter%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    7














    With xparse it's very easy to play around with optional arguments and starred variants:



    documentclass{article}
    usepackage{xparse}
    NewDocumentCommandMyCommand
    {
    s % optional *
    O{1} % first optional argument (default = 1)
    }
    {%
    IfBooleanTF{#1}
    {The starred variant with parameter: #2}
    {The non-starred variant with parameter: #2}
    }
    begin{document}
    noindent
    MyCommand \
    MyCommand* \
    MyCommand[2]\
    MyCommand*[2]
    end{document}


    With LaTeX's newcommand it a little trickier. The @ifstar macro looks at the next token after the macro is expanded and has absorbed its arguments, so you need to first check for the * and only then look for the optional argument:



    documentclass{article}
    makeatletter
    newcommandMyCommand
    {%
    @ifstar
    {MyCommand@star}
    {MyCommand@nostar}%
    }
    newcommandMyCommand@star[1][1]{%
    The starred variant with parameter: #1%
    }
    newcommandMyCommand@nostar[1][1]{%
    The non-starred variant with parameter: #1%
    }
    makeatother
    begin{document}
    noindent
    MyCommand \
    MyCommand* \
    MyCommand[2]\
    MyCommand*[2]
    end{document}


    Both versions print:




    enter image description here




    Your code works, but not as you expect it to. The MyCommand[1][1] looks for an optional argument “while expanding” MyCommand, which then gives you:



    @ifstar{%
    The starred variant with parameter: <optional argument or default>%
    }{%
    The non-starred variant with parameter: <optional argument or default>%
    }


    and only after that the @ifstar test will be expanded to look for the optional * and choose the text accordingly, so the actual syntax for the command you defined is:



    MyCommand[optional argument]<optional star>





    share|improve this answer






























      7














      With xparse it's very easy to play around with optional arguments and starred variants:



      documentclass{article}
      usepackage{xparse}
      NewDocumentCommandMyCommand
      {
      s % optional *
      O{1} % first optional argument (default = 1)
      }
      {%
      IfBooleanTF{#1}
      {The starred variant with parameter: #2}
      {The non-starred variant with parameter: #2}
      }
      begin{document}
      noindent
      MyCommand \
      MyCommand* \
      MyCommand[2]\
      MyCommand*[2]
      end{document}


      With LaTeX's newcommand it a little trickier. The @ifstar macro looks at the next token after the macro is expanded and has absorbed its arguments, so you need to first check for the * and only then look for the optional argument:



      documentclass{article}
      makeatletter
      newcommandMyCommand
      {%
      @ifstar
      {MyCommand@star}
      {MyCommand@nostar}%
      }
      newcommandMyCommand@star[1][1]{%
      The starred variant with parameter: #1%
      }
      newcommandMyCommand@nostar[1][1]{%
      The non-starred variant with parameter: #1%
      }
      makeatother
      begin{document}
      noindent
      MyCommand \
      MyCommand* \
      MyCommand[2]\
      MyCommand*[2]
      end{document}


      Both versions print:




      enter image description here




      Your code works, but not as you expect it to. The MyCommand[1][1] looks for an optional argument “while expanding” MyCommand, which then gives you:



      @ifstar{%
      The starred variant with parameter: <optional argument or default>%
      }{%
      The non-starred variant with parameter: <optional argument or default>%
      }


      and only after that the @ifstar test will be expanded to look for the optional * and choose the text accordingly, so the actual syntax for the command you defined is:



      MyCommand[optional argument]<optional star>





      share|improve this answer




























        7












        7








        7







        With xparse it's very easy to play around with optional arguments and starred variants:



        documentclass{article}
        usepackage{xparse}
        NewDocumentCommandMyCommand
        {
        s % optional *
        O{1} % first optional argument (default = 1)
        }
        {%
        IfBooleanTF{#1}
        {The starred variant with parameter: #2}
        {The non-starred variant with parameter: #2}
        }
        begin{document}
        noindent
        MyCommand \
        MyCommand* \
        MyCommand[2]\
        MyCommand*[2]
        end{document}


        With LaTeX's newcommand it a little trickier. The @ifstar macro looks at the next token after the macro is expanded and has absorbed its arguments, so you need to first check for the * and only then look for the optional argument:



        documentclass{article}
        makeatletter
        newcommandMyCommand
        {%
        @ifstar
        {MyCommand@star}
        {MyCommand@nostar}%
        }
        newcommandMyCommand@star[1][1]{%
        The starred variant with parameter: #1%
        }
        newcommandMyCommand@nostar[1][1]{%
        The non-starred variant with parameter: #1%
        }
        makeatother
        begin{document}
        noindent
        MyCommand \
        MyCommand* \
        MyCommand[2]\
        MyCommand*[2]
        end{document}


        Both versions print:




        enter image description here




        Your code works, but not as you expect it to. The MyCommand[1][1] looks for an optional argument “while expanding” MyCommand, which then gives you:



        @ifstar{%
        The starred variant with parameter: <optional argument or default>%
        }{%
        The non-starred variant with parameter: <optional argument or default>%
        }


        and only after that the @ifstar test will be expanded to look for the optional * and choose the text accordingly, so the actual syntax for the command you defined is:



        MyCommand[optional argument]<optional star>





        share|improve this answer















        With xparse it's very easy to play around with optional arguments and starred variants:



        documentclass{article}
        usepackage{xparse}
        NewDocumentCommandMyCommand
        {
        s % optional *
        O{1} % first optional argument (default = 1)
        }
        {%
        IfBooleanTF{#1}
        {The starred variant with parameter: #2}
        {The non-starred variant with parameter: #2}
        }
        begin{document}
        noindent
        MyCommand \
        MyCommand* \
        MyCommand[2]\
        MyCommand*[2]
        end{document}


        With LaTeX's newcommand it a little trickier. The @ifstar macro looks at the next token after the macro is expanded and has absorbed its arguments, so you need to first check for the * and only then look for the optional argument:



        documentclass{article}
        makeatletter
        newcommandMyCommand
        {%
        @ifstar
        {MyCommand@star}
        {MyCommand@nostar}%
        }
        newcommandMyCommand@star[1][1]{%
        The starred variant with parameter: #1%
        }
        newcommandMyCommand@nostar[1][1]{%
        The non-starred variant with parameter: #1%
        }
        makeatother
        begin{document}
        noindent
        MyCommand \
        MyCommand* \
        MyCommand[2]\
        MyCommand*[2]
        end{document}


        Both versions print:




        enter image description here




        Your code works, but not as you expect it to. The MyCommand[1][1] looks for an optional argument “while expanding” MyCommand, which then gives you:



        @ifstar{%
        The starred variant with parameter: <optional argument or default>%
        }{%
        The non-starred variant with parameter: <optional argument or default>%
        }


        and only after that the @ifstar test will be expanded to look for the optional * and choose the text accordingly, so the actual syntax for the command you defined is:



        MyCommand[optional argument]<optional star>






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited yesterday

























        answered yesterday









        Phelype OleinikPhelype Oleinik

        24.2k54688




        24.2k54688























            3














            Make MyCommand take no parameters, but just figure out the star. Then fork from there.



            documentclass{minimal}
            makeatletter
            newcommandMyCommand{%
            @ifstar{mycommandstar}{mycommandnostar}
            }
            newcommandmycommandstar[1][1]{The starred variant with parameter: #1}
            newcommandmycommandnostar[1][1]{The non-starred variant with parameter: #1}
            makeatother
            begin{document}
            MyCommand \
            MyCommand* \
            MyCommand[2] \
            MyCommand*[2]
            end{document}


            enter image description here






            share|improve this answer



















            • 2





              I'd add a % at the end of the definition of MyCommand. It works without that because the definition of @ifstar ignores space tokens by design, but... :)

              – Phelype Oleinik
              yesterday
















            3














            Make MyCommand take no parameters, but just figure out the star. Then fork from there.



            documentclass{minimal}
            makeatletter
            newcommandMyCommand{%
            @ifstar{mycommandstar}{mycommandnostar}
            }
            newcommandmycommandstar[1][1]{The starred variant with parameter: #1}
            newcommandmycommandnostar[1][1]{The non-starred variant with parameter: #1}
            makeatother
            begin{document}
            MyCommand \
            MyCommand* \
            MyCommand[2] \
            MyCommand*[2]
            end{document}


            enter image description here






            share|improve this answer



















            • 2





              I'd add a % at the end of the definition of MyCommand. It works without that because the definition of @ifstar ignores space tokens by design, but... :)

              – Phelype Oleinik
              yesterday














            3












            3








            3







            Make MyCommand take no parameters, but just figure out the star. Then fork from there.



            documentclass{minimal}
            makeatletter
            newcommandMyCommand{%
            @ifstar{mycommandstar}{mycommandnostar}
            }
            newcommandmycommandstar[1][1]{The starred variant with parameter: #1}
            newcommandmycommandnostar[1][1]{The non-starred variant with parameter: #1}
            makeatother
            begin{document}
            MyCommand \
            MyCommand* \
            MyCommand[2] \
            MyCommand*[2]
            end{document}


            enter image description here






            share|improve this answer













            Make MyCommand take no parameters, but just figure out the star. Then fork from there.



            documentclass{minimal}
            makeatletter
            newcommandMyCommand{%
            @ifstar{mycommandstar}{mycommandnostar}
            }
            newcommandmycommandstar[1][1]{The starred variant with parameter: #1}
            newcommandmycommandnostar[1][1]{The non-starred variant with parameter: #1}
            makeatother
            begin{document}
            MyCommand \
            MyCommand* \
            MyCommand[2] \
            MyCommand*[2]
            end{document}


            enter image description here







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered yesterday









            Steven B. SegletesSteven B. Segletes

            158k9204411




            158k9204411








            • 2





              I'd add a % at the end of the definition of MyCommand. It works without that because the definition of @ifstar ignores space tokens by design, but... :)

              – Phelype Oleinik
              yesterday














            • 2





              I'd add a % at the end of the definition of MyCommand. It works without that because the definition of @ifstar ignores space tokens by design, but... :)

              – Phelype Oleinik
              yesterday








            2




            2





            I'd add a % at the end of the definition of MyCommand. It works without that because the definition of @ifstar ignores space tokens by design, but... :)

            – Phelype Oleinik
            yesterday





            I'd add a % at the end of the definition of MyCommand. It works without that because the definition of @ifstar ignores space tokens by design, but... :)

            – Phelype Oleinik
            yesterday


















            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%2f479632%2fnewcommand-combine-optional-star-and-optional-parameter%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Plaza Victoria

            Brian Clough

            Cáceres