% \iffalse meta-comment
%
% Copyright (C) 2019 by Richard Zach <rzach@ucalgary.ca>
% -------------------------------------------------------
% 
% This file may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
% of this license or (at your option) any later version.
% The latest version of this license is in:
%
%    http://www.latex-project.org/lppl.txt
%
% and version 1.3 or later is part of all distributions of LaTeX 
% version 2005/12/01 or later.
%
% \fi
%
% \iffalse
%<*driver>
\ProvidesFile{keyindex.sty}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{keyindex}
%<*package>
    [2019/04/05 1.0 Index entries by key lookup]
%</package>
%
%<*driver>
\documentclass{ltxdoc}
\usepackage{keyindex}
\usepackage[hidelinks]{hyperref}
\CodelineIndex
\RecordChanges
\begin{document}
  \DocInput{keyindex.dtx}
  \PrintChanges
\end{document}
%</driver>
% \fi
%
% \CheckSum{61}
%
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than  \>     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}
%
%
% \changes{v1.0}{2019/04/05}{Initial version}
%
% \GetFileInfo{keyindex.sty}
%
% \DoNotIndex{\newcommand,\newenvironment} 
%
% \title{The \textsf{keyindex} package\thanks{This document
%   corresponds to \textsf{keyindex}~\fileversion, dated \filedate.}}
% \author{\href{http://richardzach.org/}{Richard Zach}}
% \date{}
%
% \maketitle
%
% \section{Introduction}
%
% The |keyindex| package provides functionality for producing an index
% without directly entering index entries into the text using the
% |\index| command, but instead by looking up short keys and printing a
% predefined string in the main text and adding a corresponding index
% entry. The standard use case is the production of an index of names:
% Rather than having to write in the text, e.g.,
% ``|Einstein\index{Einstein, Albert}|'' every time, write
% ``|\keyindex{Einstein}|,'' which produces ``Einstein'' in the text
% and an index entry under ``Einstein, Albert''.  Of course, the
% correct index entries must be collected somewhere.
%
% The package distribution also includes a bash script |makenameindex|
% which produces a key index file for use with |keyindex| from a text
% file with entries of the form 
% \begin{quote}
% \meta{last name}, \meta{first name}\\
% \meta{key}\verb+|+\meta{last name}, \meta{first name}\\
% \meta{key}\verb+@+\meta{indexentry}
% \end{quote}
%
% \section{Interactions} 
%
% |keyindex| requires the |ifthen| package.
%
% \section{Usage} 
%
% \DescribeMacro{\keyindex}
% |\keyindex|\oarg{index option}\marg{key}
% prints the text associated with index key \meta{key} (using the hooks
% |\keyindexformat| and |\missingkeyindexformat|) followed by an index
% entry for \meta{key}. The
% index entry is generated using the hook |\keyindexcommand| and the
% optional argument \meta{index option} is added to the argument of
% |\keyindexcommand| after a \verb+|+. For instance,
% |\keyindex[(]{Einstein}| might produce the same as \begin{center}
% \verb+Einstein\index{Einstein, Albert|(}+.\end{center}
% \DescribeMacro{\keyindexprint}
% \DescribeMacro{\keyindexonly}
% |\keyindexprint|\marg{key} prints only the text corresponding to 
% \meta{key}, but doesn't add anything to the index. 
% |\keyindexonly|\marg{key}\oarg{index option} only adds the index entry
% but doesn't print anything in the text.
%
% \DescribeMacro{\keyindexfile} |\keyindexfile|\marg{file} will load
% the index key definitions from \meta{file}|.kix|, which is assumed to
% contain only a list of lines of the form \begin{center}|\keyindexentry|
% \marg{key}\marg{print text}\marg{index text}\end{center}
% If it is not called, |keyindex| will use
% |\jobname.kix| as default. This must be used in the preamble.
%
% \DescribeMacro{\keyindexformat}
% \DescribeMacro{\missingkeyindexformat}
% \DescribeMacro{\keyindexcommand}
% These are hooks to carry out the formatting in the text of the text
% corresponding to an index entry, or adding the entry to the index.
% They can be redefined using |\renewcommand|. By default,
% |\keyindexformat|\marg{text} just adds \meta{text} to the document,
% |\missingkeyindexformat|\marg{text} adds |\textbf|\marg{text}, and
% |\keyindexcommand|\marg{text} issues |\index|\marg{text}.
% \StopEventually{}
% \section{Implementation}
% \subsection{Setup}
% \begin{macrocode}
\RequirePackage{ifthen}
%    \end{macrocode}
% |\keyindexfile| sets |\@keyindexfile| to its argument; we set
% |\@keyindexfile| to default to |\jobname.kix|
%    \begin{macrocode}
\newcommand*{\keyindexfile}[1]{%
  \renewcommand*{\@keyindexfile}{#1}}
\newcommand*{\@keyindexfile}{\jobname.kix}
%    \end{macrocode}
% |\keyindexformat| formats index text;
% default: just prints argument.
%    \begin{macrocode}
\newcommand*{\keyindexformat}[1]{#1}
%    \end{macrocode}
% |\missingkeyindexformat| prints index key when not defined;
% by default, |\textbf|.
%    \begin{macrocode}
\newcommand*{\missingkeyindexformat}[1]{%
  \textbf{#1}}
%    \end{macrocode}
% |\keyindexcommand|\marg{index text} adds \marg{index text} to the
% index; by default, it does |\index|\marg{index text} but can be redefined.
%    \begin{macrocode}
\newcommand*{\keyindexcommand}[1]{\index{#1}}
%    \end{macrocode}
% At the beginning of the document, we read the index key definition file
%    \begin{macrocode}
\AtBeginDocument{%
  \InputIfFileExists{\@keyindexfile}{%
    \PackageInfo{keyindex}{Using index key definition file
      \@keyindexfile.}}{%
    \PackageWarning{keyindex}{No index key definition file
      \@keyindexfile!}}}
%    \end{macrocode}
% |\keyindex|\oarg{index option}\marg{key} prints text for key \meta{key}, and indexes it (with
% \verb+|+\meta{index option}, if present). Printing is done by |\keyindexprint|,
% indexing by |\keyindexonly|. If the key is undefined, we issue a
% warning and print the key (using |\missingkeyindexformat|), not its replacement text. 
%    \begin{macrocode}
\newcommand*{\keyindexprint}[1]{\@ifundefined{kix@e@\detokenize{#1}}{%
    \PackageWarning{keyindex}{Index key \detokenize{#1}
      undefined}%
    \missingkeyindexformat{#1}}{%
    \keyindexformat{\@nameuse{kix@e@\detokenize{#1}}}}}
\newcommand*{\keyindexonly}[2][]{\@ifundefined{kix@e@\detokenize{#2}}{%
    \PackageWarning{keyindex}{Index key \detokenize{#2}
      undefined}}{%
    \ifthenelse{\equal{#1}{}}{%
      \keyindexcommand{\@nameuse{kix@i@\detokenize{#2}}}}{%
      \keyindexcommand{\@nameuse{kix@i@\detokenize{#2}}|#1}}}}
\newcommand{\keyindex}[2][]{\keyindexprint{#2}\keyindexonly[#1]{#2}}
%    \end{macrocode}
% The file |\@keyindexfile| must contain lines of the form 
% |\keyindexentry|\marg{key}\marg{text}\marg{index entry}. It is read at
% the beginning of the document and for each key, defines commands
% |\kix@e@|\meta{key} and |\kix@i@|\meta{key} which evaluate to \meta{text}
% and \meta{index entry}, respectively. Duplicate definitions are
% ignored but generate a warning.
%    \begin{macrocode}
\newcommand*{\keyindexentry}[3]{%
  \@ifundefined{kix@e@\detokenize{#1}}{%
    \@namedef{kix@e@\detokenize{#1}}{#2}%
    \@namedef{kix@i@\detokenize{#1}}{#3}}{%
    \PackageWarning{keyindex}{Duplicate definition for keyindex key
      \detokenize{#1} ignored}}}
%    \end{macrocode}
% \Finale
% \PrintChanges
\endinput
