8

I would like to define a new command which has two values, one is name of Author and the other is his death date, while the second value is only mentioned the first time the command is used and later only Author name is mentioned. How to do that?

4
  • Welcome to TeX.SE! Could you give a code example of how you want to use these commands and what the desired output is? That would make your question more clear. Currently it is not fully clear to me what you want, do you want to do this one time for one author, or do you want to use the same command for different authors? If you want to use multiple authors, how should it be indicated in the command which author needs to be displayed?
    – Marijn
    Commented Dec 29, 2019 at 13:49
  • 1
    Say the new command \am types the following "Ali Mabrook (died. 2016)" What I would like to have is a code that gives both name and death date at first time I use the command and then when the command is further uses it only gives the name. so first time use command \am, result is "Ali Mabrook (died 2016)" each time after that, result is "Ali Mabrook" Commented Dec 29, 2019 at 14:08
  • Can the command \am also occur in so-called moving arguments? E.g., in the heading of a section, which gets also written to the .toc-file, and which also occurs in the table of contents, and which probably gets repeated in page-headers? What to do in case \am (as part of a moving argument) is moved to a place prior to that place where you typed=used it the first time? Commented Dec 29, 2019 at 14:50
  • I think you can make all macros and commands in a separate tex file and use command include file at the beginning. That would be helpful when working on a large project Commented Dec 29, 2019 at 15:01

2 Answers 2

18

You can use a pair of commands one of which redefines itself:

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

Then every time you use \einstein it will print the name Albert Einstein immediatly followed by the call of \death@einstein. The latter will then print ($\dagger$~1955/04/18) and then define itself to to nothing the next time it is used.

\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}

enter image description here

This can be automated if you need it more than once or twice:

\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}

enter image description here

5
  • 1
    Thanks a lot, it worked for me just fine. I am beginner at LaTeX, what should I learn to be able to make such soloutions Commented Dec 29, 2019 at 14:56
  • Well, the first step is, do you understand what the code in this answer does?
    – Stan
    Commented Dec 30, 2019 at 16:20
  • The first method you created a command with the name of the person which consists of the name and another variable called death@person. Then you defined this death@person as it consistes of the symbol dagger and the this variable. The second method you defined a command newperson that defines a new command with the name of the person and his death date What I don't understand in the codes is that how it mention the death date at the first time only. Commented Dec 30, 2019 at 20:03
  • @MuhammedRagab I added some explanation
    – cgnieder
    Commented Jan 5, 2020 at 11:02
  • I was able to further develop the first solution to only mention the last name of the person upon further using of the command. \makeatletter \newcommand*\einstein{\vorname Einstein \death@einstein} \def\vorname{ Albert \def\vorname{}} \def\death@einstein{(gest. 1955) \def\death@einstein{}} \makeatother \begin{document} \einstein \par \einstein \par \end{document} But I am confused with the second automated solution. I tried defining other csname but it only mentions the first name. What would be the right way to do it. Commented Jan 8, 2020 at 12:22
7

Alternative version with a boolean check:

\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}

The \xspace macro from the package with the same name inserts a space after a word except when it is followed by punctuation, footnote marks etc. This is useful because the original space is removed by the macro processing procedure when the macro is called in the document.

Result:

enter image description here

This can be generalized for more than one author using the xkeyval package. To make this solution work there are some commands that need to be constructed with \csname, for example a boolean for a key contained in the argument #1 can be constructed using \expandafter\newif\csname if#1displayed\endcsname, and similar for reading the values of the keys from the \KV@ macros created by \define@key. Admittedly this is not very easy to read but hopefully the steps are clear.

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}

Result:

enter image description here

1
  • It also worked, thanks a lot Commented Dec 30, 2019 at 20:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .