Novo comando com dois valores, um deles mencionado apenas na primeira vez

Novo comando com dois valores, um deles mencionado apenas na primeira vez

Gostaria de definir um novo comando que possua dois valores, um é o nome do Autor e o outro é a data de seu falecimento, enquanto o segundo valor só é mencionado na primeira vez que o comando é utilizado e posteriormente apenas o nome do Autor é mencionado. Como fazer isso?

Responder1

Você pode usar um par de comandos, um dos quais se redefine:

\makeatletter
\newcommand*\einstein{Albert Einstein\death@einstein}
\def\death@einstein{ ($\dagger$~1955/04/18)\def\death@einstein{}}
\makeatother

Então, toda vez que você usá \einstein-lo, o nome será impresso Albert Einsteinimediatamente seguido pela chamada de \death@einstein. Este último irá imprimir ($\dagger$~1955/04/18)e definirem sipara nada na próxima vez que for usado.

\documentclass{article}

\makeatletter
\newcommand*\einstein{Albert Einstein\death@einstein}
\def\death@einstein{ ($\dagger$~1955/04/18)\def\death@einstein{}}
\makeatother

\begin{document}

\einstein \par
\einstein

\end{document}

insira a descrição da imagem aqui

Isso pode ser automatizado se você precisar mais de uma ou duas vezes:

\documentclass{article}

\makeatletter
\newcommand*\newperson[3]{%
  \def#1{#2\csname death@#2\endcsname}%
  \@namedef{death@#2}{ ($\dagger$~#3)\@namedef{death@#2}{}}%
}
\makeatother

\newperson\einstein{Albert Einstein}{1955/04/18}
\newperson\planck{Max Planck}{1947/10/04}

\begin{document}

\einstein \par
\einstein

\planck \par
\planck

\end{document}

insira a descrição da imagem aqui

Responder2

Versão alternativa com verificação booleana:

\documentclass{article}
\usepackage{xspace}
\newif\ifauthordisplayed         % create boolean
\authordisplayedfalse            % set to false
\def\am{%
\ifauthordisplayed%              % if boolean true
Ali Mabrook\xspace%              % print only the name
\else
Ali Mabrook (died 2016)\xspace%  % print name and date
\authordisplayedtrue%            % and set boolean to true
\fi%
}
\begin{document}
\am was an author. His name is \am.
\end{document}

A \xspacemacro do pacote com o mesmo nome insere um espaço após uma palavra, exceto quando ela é seguida por pontuação, notas de rodapé, etc. Isso é útil porque o espaço original é removido pelo procedimento de processamento da macro quando a macro é chamada no documento.

Resultado:

insira a descrição da imagem aqui

Isso pode ser generalizado para mais de um autor usando o xkeyvalpacote. Para fazer esta solução funcionar existem alguns comandos que precisam ser construídos com \csname, por exemplo, um booleano para uma chave contida no argumento #1pode ser construído usando \expandafter\newif\csname if#1displayed\endcsname, e semelhante para ler os valores das chaves das \KV@macros criadas por \define@key. É certo que isso não é muito fácil de ler, mas espero que as etapas sejam claras.

MWE:

\documentclass{article}
\usepackage{xkeyval}
\usepackage{xspace}
\makeatletter
\newcommand{\addauthor}[3]{%
% create boolean for the key in argument #1
\expandafter\newif\csname if#1displayed\endcsname
% set boolean to false
\csname #1displayedfalse\endcsname
% define function for this key
\define@key{myauthors}{#1}{%
% if displayed before
\csname if#1displayed\endcsname
% print just the name
#2%
\else%
% print full info and set boolean to true
#2 (died #3)%
\csname #1displayedtrue\endcsname
\fi%
}
}

% call command that is created by define@key
\newcommand{\displayauthor}[1]{%
\csname KV@myauthors@#1\endcsname{}\xspace%
}
\makeatother

\begin{document}
\addauthor{am}{Ali Mabrook}{2016}
\addauthor{js}{John Smith}{2004}

\displayauthor{am} was an author. His name was \displayauthor{am}.

\displayauthor{js} was an author. His name was \displayauthor{js}.

\end{document}

Resultado:

insira a descrição da imagem aqui

informação relacionada