Como melhorar a manutenção de versões de comandos ou ambientes com/sem estrela

Como melhorar a manutenção de versões de comandos ou ambientes com/sem estrela

Todas as documentações que li sobre versões de comandos com/sem estrela recomendam mais ou menos a seguinte maneira de fazer (seguindo por exemploa lista de perguntas frequentes do TeX):

\newcommand{\mycommand}{\@ifstar\mycommandStar\mycommandNoStar}
\newcommand{\mycommandStar}{%
  <few lines of code only for starred mycommand>
  <many lines of code common to starred/non starred mycommand>
}
\newcommand{\mycommandNoStar}{%
  <few lines of code only for non starred mycommand>
  <many lines of code common to starred/non starred mycommand>
}

Para ambientes, o esquema é semelhante (seguindo por exemploesta resposta):

\newenvironment{myenvironment}{%
  <few lines of code only for non starred myenvironment>
  <many lines of code common to starred/non starred myenvironment>
}{%
  <few lines of code only for non starred myenvironment>
  <many lines of code common to starred/non starred myenvironment>
}
\newenvironment{myenvironment*}{%
  <few lines of code only for starred myenvironment>
  <many lines of code common to starred/non starred myenvironment>
}{%
  <few lines of code only for starred myenvironment>
  <many lines of code common to starred/non starred myenvironment>
}

Mas, na maioria dos casos, existem apenas pequenas diferenças entre as versões com e sem estrela e esta forma de fazer requer a cópia de todas as alterações no código comum entre as duas versões, o que é uma tarefa difícil de manutenção (especialmente se o código comum for longo).

Existe uma maneira mais eficiente de fazer?

Responder1

Depende principalmente do que os comandos devem fazer. Se \mycommand*for diferente \mycommandapenas porque algum código diferente precisa ser executado no início, a seguinte abordagem deve funcionar:

\newcommand{\mycommand}{\@ifstar{\@tempswatrue\@mycommand}{\@tempswafalse\@mycommand}}
\newcommand{\@mycommand}{%
  \if@tempswa
    <few lines of code only for starred mycommand>
  \else
    <few lines of code only for non starred mycommand>
  \fi
  <many lines of code common to starred/non starred mycommand>
}

Com xparseisso fica mais fácil:

\usepackage{xparse}
\NewDocumentCommand{\mycommand}{s}
 {\IfBooleanTF{#1}
    {<few lines of code only for starred mycommand>}
    {<few lines of code only for non starred mycommand>}%
  <many lines of code common to starred/non starred mycommand>%
 }

Para a forma ambiental há complicações adicionais, pois não há \@ifstardisponível.

\newenvironment{myenvironment}{%
  <few lines of code only for non starred myenvironment>
  \@myenvironmentstart
}{%
  <few lines of code only for non starred myenvironment>
  \@myenvironmentfinish
}
\newenvironment{myenvironment*}{%
  <few lines of code only for starred myenvironment>
  \@myenvironmentstart
}{%
  <few lines of code only for starred myenvironment>
  \@myenvironmentfinish
}

\newcommand{\@myenvironmentstart}{%
  <many lines of code common to starred/non starred myenvironment>
}
\newcommand{\@myenvironmentfinish}{%
  <many lines of code common to starred/non starred myenvironment>
}

Nenhuma simplificação real é possível com xparse.

Responder2

O xparsepacote, parte do pacote LaTeX3, é muito útil nesse aspecto. Por exemplo:

\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\foo}{s}{This is the \IfBooleanTF{#1}{starred }{}foo command.}
\begin{document}
\foo{}

\foo*{}
\end{document}

insira a descrição da imagem aqui

informação relacionada