% --------------------------------------------------------------------------
% the IDXCMDS package
% 
%   create commands for adding formatted index entries
% 
% --------------------------------------------------------------------------
% Clemens Niederberger
% Web:    https://bitbucket.org/cgnieder/idxcmds/
% E-Mail: contact@mychemistry.eu
% --------------------------------------------------------------------------
% Copyright 2012-2013 Clemens Niederberger
% 
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% 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.
% 
% This work has the LPPL maintenance status `maintained'.
% 
% The Current Maintainer of this work is Clemens Niederberger.
% --------------------------------------------------------------------------
% The idxcmds package consists of the files
%  - idxcmds.sty
%  - idxcmds_en.tex, idxcmds_en.pdf
%  - README
% --------------------------------------------------------------------------
% If you have any ideas, questions, suggestions or bugs to report, please
% feel free to contact me.
% --------------------------------------------------------------------------
\def\@idxcmds@date{2013/08/31}
\def\@idxcmds@version{v0.2b}
\def\@idxcmds@description{create commands for adding formatted index entries}

\ProvidesPackage{idxcmds}[\@idxcmds@date\space \@idxcmds@version\space
  \@idxcmds@description\space (CN)]
\RequirePackage{etoolbox,pgfopts,ltxcmds}

% --------------------------------------------------------------------------
% message handling:
\def\@idxcmds@create@message#1{%
  \ifstrequal{#1}{Error}
    {%
      \lowercase{\csdef{@idxcmds@#1}}##1##2{%
        \csuse{Package#1}{idxcmds}{##1}{##2}}%
    }{%
      \lowercase{\csdef{@idxcmds@#1}}##1{%
        \csuse{Package#1}{idxcmds}{##1}}%
    }}
\@idxcmds@create@message{Error}
\@idxcmds@create@message{Warning}
\@idxcmds@create@message{WarningNoLine}
\@idxcmds@create@message{Info}

% --------------------------------------------------------------------------
% package options:
\def\@idxcmds@sortsep{@}
\def\@idxcmds@subsep{!}
\def\@idxcmds@default@index{\index}

\pgfkeys{
  idxcmds/.cd,
    sort-sep/.code = \def\@idxcmds@sortsep{#1} ,
    sub-sep/.code  = \def\@idxcmds@subsep{#1} ,
    idx-cmd/.code  = \def\@idxcmds@default@index{#1}
}
\ProcessPgfOptions*

\newrobustcmd*\setidxcmds[1]{\pgfqkeys{/idxcmds}{#1}}

% --------------------------------------------------------------------------
% a few helpers:
\def\@idxcmds@stripbs{\expandafter\@gobble\string}
\def\@idxcmds@csdef#1{\csdef{\@idxcmds@stripbs#1}}
\def\@idxcmds@csuse#1{\csuse{\@idxcmds@stripbs#1}}
\def\@idxcmds@appdef#1[#2]{\@idxcmds@csdef{#1@idx@app}{#2}}
\def\@idxcmds@newcommand{%
  \@ifstar
    {\@idxcmds@newcommand@star}
    {\@idxcmds@newcommand@nostar}%
}
\def\@idxcmds@newcommand@nostar#1{%
  \expandafter\newrobustcmd\csname\@idxcmds@stripbs#1\endcsname}
\def\@idxcmds@newcommand@star#1{%
  \expandafter\newrobustcmd\expandafter*\csname\@idxcmds@stripbs#1\endcsname}

% --------------------------------------------------------------------------
% \newidxcmd[<index cmd>]{<cs>}{<formatting specs>}[<app to idx entry>]
% new commands will have the syntax
%   \cmd*{<text>}            => no index entry
%   \cmd{<text>}             => index entry
%   \cmd[<sort idx>]{<text>} => alt. sort index
%

\newrobustcmd\newidxcmd[3][\@idxcmds@default@index]{%
  \@idxcmds@csdef{#2@base}##1{#3}%
  \@idxcmds@csdef{#2@idx}##1##2##3{%
    \ifblank{##1}
      {%
        #1{%
          ##2\@idxcmds@sortsep
          \@idxcmds@csuse{#2@base}{##2}%
          \@idxcmds@csuse{#2@idx@app}%
          ##3%
        }%
      }
      {%
        #1{%
          ##1\@idxcmds@sortsep
          \@idxcmds@csuse{#2@base}{##2}%
          \@idxcmds@csuse{#2@idx@app}%
          ##3%
        }%
      }%
    }%
  \@idxcmds@csdef{#2@star}##1{\@idxcmds@csuse{#2@base}{##1}}%
  \@idxcmds@csdef{#2@nostar}{%
    \ltx@ifnextchar[%
      {\@idxcmds@csuse{#2@nostar@opt}}
      {\@idxcmds@csuse{#2@nostar@opt}[]}}%
  \@idxcmds@csdef{#2@nostar@opt}[##1]##2{%
    \@idxcmds@csuse{#2@base}{##2}%
    \ltx@ifnextchar@nospace[%
      {\@idxcmds@csuse{#2@idx@optarg}{##1}{##2}}
      {\@idxcmds@csuse{#2@idx}{##1}{##2}{}}}%
  \@idxcmds@csdef{#2@idx@optarg}##1##2[##3]{%
    \@idxcmds@csuse{#2@idx}{##1}{##2}{##3}}%
  \newrobustcmd*#2{%
    \@ifstar
      {\@idxcmds@csuse{#2@star}}
      {\@idxcmds@csuse{#2@nostar}}}%
  \@idxcmds@newcommand*{#2idx}[2][]{%
    \ltx@ifnextchar@nospace[
      {\@idxcmds@csuse{#2@idx@optarg}{##1}{##2}}
      {\@idxcmds@csuse{#2@idx}{##1}{##2}{}}}%
  \ltx@ifnextchar[%
    {\@idxcmds@appdef{#2}}
    {\@idxcmds@appdef{#2}[]}%
}

% ---------------------------------------------------------------------------
% \newsubmainidxcmd[<index cmd>]{<cs>}{<formatting specs>}[<app to idx entry>]
\newrobustcmd\newsubmainidxcmd[3][\@idxcmds@default@index]{%
  \@idxcmds@csdef{#2@base}##1{#3}%
  \@idxcmds@csdef{#2@idx}##1##2##3##4{%
    \ifblank{##1}
      {%
        #1{%
          ##3\@idxcmds@subsep##2\@idxcmds@sortsep
          \@idxcmds@csuse{#2@base}{##2}%
          \@idxcmds@csuse{#2@idx@app}%
          ##4%
        }%
      }{%
        #1{%
          ##3\@idxcmds@subsep##1\@idxcmds@sortsep
          \@idxcmds@csuse{#2@base}{##2}%
          \@idxcmds@csuse{#2@idx@app}%
          ##4%
        }%
      }%
    }%
  \@idxcmds@csdef{#2@star}##1{\@idxcmds@csuse{#2@base}{##1}}%
  \@idxcmds@csdef{#2@nostar}{%
    \ltx@ifnextchar[%
      {\@idxcmds@csuse{#2@nostar@opt}}
      {\@idxcmds@csuse{#2@nostar@opt}[]}}%
    \@idxcmds@csdef{#2@nostar@opt}[##1]##2##3{%
    \@idxcmds@csuse{#2@base}{##2}%
    \ltx@ifnextchar@nospace[%
      {\@idxcmds@csuse{#2@idx@optarg}{##1}{##2}{##3}}
      {\@idxcmds@csuse{#2@idx}{##1}{##2}{##3}{}}}%
  \@idxcmds@csdef{#2@idx@optarg}##1##2##3[##4]{%
    \@idxcmds@csuse{#2@idx}{##1}{##2}{##3}{##4}}%
  \newrobustcmd*#2{%
    \@ifstar
      {\@idxcmds@csuse{#2@star}}
      {\@idxcmds@csuse{#2@nostar}}}%
  \@idxcmds@newcommand*{#2idx}[3][]{%
    \@idxcmds@csuse{#2@idx}{##1}{##2}{##3}}%
  \ltx@ifnextchar[%
    {\@idxcmds@appdef{#2}}
    {\@idxcmds@appdef{#2}[]}%
}

% ---------------------------------------------------------------------------
% \newsubidxcmd[<index cmd>]{<cs>}{<idx cmd>}{<formatting specs>}[<app to idx entry>]
% \newsubidxcmd*[<index cmd>]{<cs>}{<main entry>}{<formatting specs>}[<app to idx entry>]
\newif\if@idxcmds@sub@star

% get main if starred
\def\@idxcmds@extract@main#1#2{%
  \ltx@ifnextchar[%
    {\@idxcmds@extract@main@aux{#1}{#2}}
    {\@idxcmds@extract@main@aux{#1}{#2}[]}}
\def\@idxcmds@extract@main@aux#1#2[#3]#4{%
  \@idxcmds@csdef{#1@main}{\@idxcmds@csuse{#2@base}{#4}}%
  \ifstrempty{#3}
    {\@idxcmds@csdef{#1@main@sort}{#4}}
    {\@idxcmds@csdef{#1@main@sort}{#3}}}

\newcommand*\newsubidxcmd{%
  \@ifstar
    {\@idxcmds@sub@startrue\@idxcmds@subidx}
    {\@idxcmds@sub@starfalse\@idxcmds@subidx}}
\newrobustcmd\@idxcmds@subidx[4][\@idxcmds@default@index]{%
  \@idxcmds@csdef{#2@base}##1{#4}%
  \if@idxcmds@sub@star
    \@idxcmds@extract@main#2#3%
    \@idxcmds@csdef{#2@idx}##1##2##3{%
      \ifblank{##1}
        {%
          #1{%
            \@idxcmds@csuse{#2@main@sort}\@idxcmds@sortsep
            \@idxcmds@csuse{#2@main}%
            \@idxcmds@subsep##2\@idxcmds@sortsep
            \@idxcmds@csuse{#2@base}{##2}%
            \@idxcmds@csuse{#2@idx@app}%
            ##3%
          }%
        }{%
          #1{%
            \@idxcmds@csuse{#2@main@sort}\@idxcmds@sortsep
            \@idxcmds@csuse{#2@main}%
            \@idxcmds@subsep##1\@idxcmds@sortsep
            \@idxcmds@csuse{#2@base}{##2}%
            \@idxcmds@csuse{#2@idx@app}%
            ##3%
          }%
        }}%
  \else
    \@idxcmds@csdef{#2@idx}##1##2##3{%
      \ifblank{##1}
        {%
          #1{%
            #3%
            \@idxcmds@subsep##2\@idxcmds@sortsep
            \@idxcmds@csuse{#2@base}{##2}%
            \@idxcmds@csuse{#2@idx@app}%
            ##3%
          }%
        }{%
          #1{%
            #3%
            \@idxcmds@subsep##1\@idxcmds@sortsep
            \@idxcmds@csuse{#2@base}{##2}%
            \@idxcmds@csuse{#2@idx@app}%
            ##3%
          }%
        }}%
  \fi
  \@idxcmds@csdef{#2@star}##1{\@idxcmds@csuse{#2@base}{##1}}%
  \@idxcmds@csdef{#2@nostar}{%
    \ltx@ifnextchar[%
      {\@idxcmds@csuse{#2@nostar@opt}}
      {\@idxcmds@csuse{#2@nostar@opt}[]}}%
  \@idxcmds@csdef{#2@nostar@opt}[##1]##2{%
    \@idxcmds@csuse{#2@base}{##2}%
    \ltx@ifnextchar@nospace[%
      {\@idxcmds@csuse{#2@idx@optarg}{##1}{##2}}
      {\@idxcmds@csuse{#2@idx}{##1}{##2}{}}}%
  \@idxcmds@csdef{#2@idx@optarg}##1##2[##3]{%
    \@idxcmds@csuse{#2@idx}{##1}{##2}{##3}}%
  \newrobustcmd*#2{%
    \@ifstar
      {\@idxcmds@csuse{#2@star}}
      {\@idxcmds@csuse{#2@nostar}}}%
  \@idxcmds@newcommand*{#2idx}[2][]{%
    \@idxcmds@csuse{#2@idx}{##1}{##2}}%
  \ltx@ifnextchar[%
    {\@idxcmds@appdef{#2}}
    {\@idxcmds@appdef{#2}[]}%
}

\endinput
% --------------------------------------------------------------------------
% HISTORY:
2012/11/02 v0.1  - first working version
2013/04/11 v0.1a - made \newidxcmd, \newsubmainidxcmd and \newsubidxcmd robust
2013/04/16 v0.2  - added trailing optional argument to defined commands
                   that allows appending stuff to the index entry at use-time
2013/05/14 v0.2a - added \setidxcmds
2013/08/31 v0.2b - added option `idx-cmd'

