# Using a parameter reference as the optional argument of a macro

I'm currently trying to get index entries to be automatically shown in italic in the text, i.e. instead of \textit{Term}\index{Term}, I want to be able to use \index{Term}, which should render the same thing as the first piece of code.

Now so far, I've been able to get something similar to work by defining the following macro:

\newcommand{\Index}[1]{\textit{#1}\index{#1}}


Credit goes to https://www.namsu.de/Extra/pakete/Makeidx.html

Now by using \Index (note the capitalized "I"), I partly get the desired result. I cannot, however, use the other possibilities that index offers, such as \index{term@termActuallyDisplayed}.

My next approach was using:

\newcommand{\Index}[2][#2]{\textit{#2}\index{#1@#1}}


so that \Index{Term} renders \textit{Term}\index{Term@Term}, while \Index[ActualIndexTerm]{Term} renders \textit{Term}\index{ActualIndexTerm@ActualIndexTerm}.

My problem, however, is that using the code above will render an error saying "Illegal parameter number in definition [...]". Hence my question - does anyone know how to circumvent this problem, such as using another package or anything?
(I know that I could just define 2 different commands, but that feels somewhat primitive)

• How about this: \newcommand\Index[2][\relax]{\ifx\relax#1\def\actualarg{#2@#2}\else\def\actualarg{#2@#1}\fi\textit{#2}\expandafter\index\expandafter{\actualarg}}. P.s. It would help if you provided a full MWE, and not just a code snippet. – Steven B. Segletes Sep 11 '17 at 10:35

This kind of “self-reference” is easy to obtain with xparse:

\documentclass{article}
\usepackage{xparse}
\usepackage{imakeidx}

\NewDocumentCommand{\Index}{O{#2}m}{%
\textit{#1}\index{#2@#1}%
}

\makeindex

\begin{document}

Here I index Term': \Index{Term}

Here I index Actually Used Term' \Index[Actually Used Term]{z}

\printindex

\end{document}


Adjust to suit; in the example, the second term will be sorted as “z”, so it will appear second.

The traditional method uses \@dblarg:

\makeatletter
\DeclareRobustCommand{\Index}{\@dblarg\@Index}
\def\@Index[#1]#2{%
\textit{#1}\index{#2@#1}%
}
\makeatother


If you want to avoid the problem that \Index{Term} and \index{Term} will index twice, because the former would do \index{Term@Term} that's different from \index{Term} to MakeIndex’s point of view, you can modify the command into

\NewDocumentCommand{\Index}{om}{%
\IfNoValueTF{#1}
{\textit{#2}\index{#2}}
{\textit{#1}\index{#2@#1}}%
}


The xparse package is a great tool which can do what you want (it can declare a command with an optional argument with its default value taken from another argument). See the following example:

\documentclass{article}
\usepackage{xparse}
\usepackage{imakeidx}
\makeindex

\NewDocumentCommand\Index{O{#2}m}{%
\textit{#2}\index{#2@#1}%
}
\begin{document}

\Index{xyz}

\Index[xyz|textbf]{xyz}
\printindex
\end{document}


Here both words xyz are italicized in the text, and the optional argument can add some additional formatting info for the index itself. The resulting .idx file:

\indexentry{xyz@xyz}{1}
\indexentry{xyz@xyz|textbf}{1}


and .ind (basically, the default formatting):

\begin{theindex}

\item xyz, 1, \textbf{1}

\end{theindex}


EDITED to actually use \index.

\documentclass{article}
\usepackage{imakeidx}
\newcommand\Index[2][\relax]{%
\ifx\relax#1\def\actualarg{#2@#2}\else\def\actualarg{#2@#1}\fi%
\textit{#2}%
\expandafter\index\expandafter{\actualarg}%
}
\makeindex
\begin{document}

\Index{term}

\Index[TermActuallyDisplayed]{term}

\printindex

\end{document}


If it is acceptable to slightly change the macro input design to \Index{...}[...]:

\documentclass{article}
\makeatletter
\def\Index#1{%
\textit{#1}%
\kernel@ifnextchar[{\Index@optarg{#1}}{\index{#1@#1}}%
}
\def\Index@optarg#1[#2]{\index{#1@#2}}
\makeatother

\begin{document}
\Index{Term}

\Index{foo}[bar]
\end{document}