调用嵌套索引宏

调用嵌套索引宏

这是我的简化文档示例,它因注释中提到的错误而失败。我尝试用 和 括住嵌套宏,{}没有成功,用 和 括住它\csname也是一样\endcsname。您能帮我一下如何嵌套索引宏吗?

\documentclass{memoir}

\newcounter{pqrC}
\newcommand{\pqr}[1]
{%
  \stepcounter{pqrC}%
  #1%
  \index{PQR!\thepqrC. #1}%
}%

\newcounter{xyzC}
\newcommand{\xyz}[1]
{%
  \stepcounter{xyzC}%
  #1%
  \index{XYZ!\thexyzC. #1}%
}%

\newcommand{\x}[1]{#1\index{X!#1}}
\newcommand{\y}[1]{#1\index{Y!#1}}

\makeindex

\begin{document}

\xyz{Some text here!}\\
\pqr{Some other text here!}\\
\xyz{\pqr{Related to pqr} and also xyz}\\ % ERROR: Missing \endcsname inserted.

More text asldfjasdlf adlsfkja fasldfk ja\\
asldfkjasdlfkajsdlf adslfkasjdf\\

\x{sldkf \y{dlfkj}} % ERROR: Use of \@index doesn't match its definition.

\printindex
\end{document}

答案1

在您的宏中,您可以使用\if..-switch(及其\..true/ \..false-命令)作为标志,表示所讨论的宏的参数是否作为\index-命令的参数的一部分进行处理,而该命令又由您的一个宏“启动”。

反之亦然,\index只有当执行这些操作的宏是不是作为此类命令的参数的一部分进行调用\index。;-)

\documentclass{memoir}

\makeatletter
\newif\ifnotindexarg
\global\notindexargtrue
\newcommand\IfNotWithinIndexArgGroupDoWithinIndexArgGroup[1]{%
  \romannumeral0%
  \ifnotindexarg\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  {\@firstofone{\expandafter} \@firstofone}%
  {\@firstofone{\expandafter} \@gobble}%
  {\begingroup\notindexargfalse#1\endgroup}%
}%
\makeatother


\newcounter{pqrC}%
\newcommand{\pqr}[1]{%
  #1%
  \IfNotWithinIndexArgGroupDoWithinIndexArgGroup{%
     \stepcounter{pqrC}%
     \index{PQR!\thepqrC. #1}%
  }%
}%

\newcounter{xyzC}%
\newcommand{\xyz}[1]{%
  #1%
  \IfNotWithinIndexArgGroupDoWithinIndexArgGroup{%
    \stepcounter{xyzC}%
    \index{XYZ!\thexyzC. #1}%
  }%
}%

\newcommand{\x}[1]{#1\IfNotWithinIndexArgGroupDoWithinIndexArgGroup{\index{X!#1}}}%
\newcommand{\y}[1]{#1\IfNotWithinIndexArgGroupDoWithinIndexArgGroup{\index{Y!#1}}}%

\makeindex

\begin{document}

\xyz{Some text here!}\\
\pqr{Some other text here!}\\
\xyz{\pqr{Related to pqr} and also xyz}\\

More text asldfjasdlf adlsfkja fasldfk ja\\
asldfkjasdlfkajsdlf adslfkasjdf\\

\x{sldkf \y{dlfkj}}

\printindex
\end{document}

上面的例子产生了以下索引——我希望这是你所想到的:

在此处输入图片描述


自动化的更高层次可能是:

\documentclass{memoir}

\makeatletter
\newif\ifnotindexarg
\global\notindexargtrue
%\mygenericindexsubentry{<main-entry>}{<name of counter or emptiness>}{<sub-entry>}
% (Be aware that you cannot use \mygenericindexsubentry with 
%  the nameless counter.;-) )
\newcommand\mygenericindexsubentry[3]{%
  #3%
  \ifnotindexarg\expandafter\@firstofone\else\expandafter\@gobble\fi
  {%
    \begingroup
    \notindexargfalse
    \ifx\relax#2\relax
      \index{#1!#3}%
    \else
      \stepcounter{#2}%
      \index{#1!\csname the#2\endcsname. #3}%
    \fi
    \endgroup
  }%
}%
\makeatother

\newcounter{pqrC}%
\newcommand{\pqr}{\mygenericindexsubentry{PQR}{pqrC}}%
\newcounter{xyzC}%
\newcommand\xyz{\mygenericindexsubentry{XYZ}{xyzC}}%
\newcommand{\x}{\mygenericindexsubentry{X}{}}%
\newcommand{\y}{\mygenericindexsubentry{Y}{}}%

\makeindex

\begin{document}

\xyz{Some text here!}\\
\pqr{Some other text here!}\\
\xyz{\pqr{Related to pqr} and also xyz}\\

More text asldfjasdlf adlsfkja fasldfk ja\\
asldfkjasdlfkajsdlf adslfkasjdf\\

\x{sldkf \y{dlfkj}}

\printindex
\end{document}

输出与第一个例子相同。


顺便一提:

如果您不想浪费计数寄存器,您可以使用宏和例程进行可扩展的递增。

这是 Heiko Oberdiek 的包裹计算bigintcalc.
如果有 eTeX 扩展可用,那么还有\numexpr

下面我自己弄了一些东西,不需要额外的软件包,也不需要 eTeX 扩展。

\makeatletter
%%//////////////////////////////////////////////////////////////////////////////
%% SECTION EXPANDABLE INCREMENTING OF NATURAL NUMBER FORMED BY A SEQUENCE OF
%% EXPLICIT CATCODE-12-CHARACTER-TOKENS FROM THE SET {0,1,2,3,4,5,6,7,8,9}
%%
%% \UD@increment{<natural number k as sequence of explicit catcode-12-character-
%%               tokens from the set 0123456789>}
%% ->
%% <natural number (k+1) as sequence of explicit catcode-12-character-tokens
%%  from the set 0123456789>
%%
%% Emptiness is interpreted as "0".
%%
%% Due to \romannumeral0-expansion the result is delivered after 
%% two expansion-steps.
%%..............................................................................
%% Examples: \UD@increment{999} -> 1000
%%           \UD@increment{0} -> 1
%%           \UD@increment{} -> 1
%%==============================================================================
\newcommand\UD@increment[1]{%
  % #1 = digit sequence to increment.
  \romannumeral0%
  % Start the loop for reversing the digit-sequence so that less significant
  % digits are at the beginning and not at the end of the digit sequence; when
  % reversing is done, apply \UD@incrementfork{} and a terminating \relax to
  % start replacing least significant digits by digits whose value is larger
  % by 1:
  \UD@incrementreverse{\UD@incrementfork{}}{\relax}{}#1\relax
}%
%%------------------------------------------------------------------------------
%% Reverse digit sequence and prepend and append tokens afterwards:
%%------------------------------------------------------------------------------
\newcommand\UD@incrementreverse[4]{%
  % #1 = tokens to prepend to reversed digit sequence.
  % #2 = tokens to append to reversed digit sequence.
  % #3 = digit sequence reversed so far.
  % #4 = first digit of remaining digit sequence to reverse.
  \ifx\relax#4%
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {#1#3#2}{\UD@incrementreverse{#1}{#2}{#4#3}}%
}%
\newcommand\UD@incrementselect{}%
\long\def\UD@incrementselect#10123456789\relax#2#3!!{#2}%
\newcommand\UD@incrementfork[2]{%
  % #1 = carry-zeros collected so far
  % #2 = to-be incremented first digit/least significant digit of digit sequence
  \UD@incrementselect
  #2123456789\relax{\UD@incrementreverse{ }{}{}#11}%<-this means the current
                                                  %   least significant digit is
                                                  %   0 and to be replaced by 1.
  0#223456789\relax{\UD@incrementreverse{ }{}{}#12}%<-this means the current
                                                  %   least significant digit is
                                                  %   1 and to be replaced by 2.
  01#23456789\relax{\UD@incrementreverse{ }{}{}#13}%<-this means the current
                                                  %   least significant digit is
                                                  %   2 and to be replaced by 3.
  012#2456789\relax{\UD@incrementreverse{ }{}{}#14}%<-this means the current
                                                  %   least significant digit is
                                                  %   3 and to be replaced by 4.
  0123#256789\relax{\UD@incrementreverse{ }{}{}#15}%<-this means the current
                                                  %   least significant digit is
                                                  %   4 and to be replaced by 5.
  01234#26789\relax{\UD@incrementreverse{ }{}{}#16}%<-this means the current
                                                  %   least significant digit is
                                                  %   5 and to be replaced by 6.
  012345#2789\relax{\UD@incrementreverse{ }{}{}#17}%<-this means the current
                                                  %   least significant digit is
                                                  %   6 and to be replaced by 7.
  0123456#289\relax{\UD@incrementreverse{ }{}{}#18}%<-this means the current
                                                  %   least significant digit is
                                                  %   7 and to be replaced by 8.
  01234567#29\relax{\UD@incrementreverse{ }{}{}#19}%<-this means the current
                                                  %   least significant digit is
                                                  %   8 and to be replaced by 9.
  012345678#2\relax{\UD@incrementfork{#10}}%       <- this means the current
                                           %          least significant digit is
                                           %          9 and to be replaced by 0,
                                           %          which will be a carry-zero
                                           %          , and the next digit needs
                                           %          to be incremented.
  0123456789#2{\UD@incrementreverse{ }{}{}#11\relax}%<-this means the natural
                                                    % number to increment
                                                    % consisted of digits "9" 
                                                    % only and the terminating
                                                    % \relax was encountered.
  0123456789\relax{\UD@incrementreverse{ }{}{}#11#2}%<- this should not happen
                                                 %    as it means there is a
                                                 %    non-digit.
  !!%
}%
%%
%% EOF SECTION EXPANDABLE INCREMENTING OF NATURAL NUMBER FORMED BY A SEQUENCE OF
%%     EXPLICIT CATCODE-12-CHARACTER-TOKENS FROM THE SET {0,1,2,3,4,5,6,7,8,9}
%%//////////////////////////////////////////////////////////////////////////////
\makeatother    

\documentclass{memoir}

\makeatletter
\newif\ifnotindexarg
\global\notindexargtrue
%\mygenericindexsubentry{<main-entry>}{<counter-macro or emptiness>}{<sub-entry>}
\newcommand\mygenericindexsubentry[3]{%
  #3%
  \ifnotindexarg\expandafter\@firstofone\else\expandafter\@gobble\fi
  {%
    \begingroup
    \notindexargfalse
    \ifx\relax#2\relax
      \index{#1!#3}%
    \else
      \xdef#2{\expandafter\UD@increment\expandafter{#2}}%
      \index{#1!\@arabic{#2 }. #3}%
    \fi
    \endgroup
  }%
}%
\makeatother

\newcommand{\pqrC}{0}%
\newcommand{\pqr}{\mygenericindexsubentry{PQR}{\pqrC}}%
\newcommand{\xyzC}{0}%
\newcommand\xyz{\mygenericindexsubentry{XYZ}{\xyzC}}%
\newcommand{\x}{\mygenericindexsubentry{X}{}}%
\newcommand{\y}{\mygenericindexsubentry{Y}{}}%

\makeindex

\begin{document}

\xyz{Some text here!}\\
\pqr{Some other text here!}\\
\xyz{\pqr{Related to pqr} and also xyz}\\

More text asldfjasdlf adlsfkja fasldfk ja\\
asldfkjasdlfkajsdlf adslfkasjdf\\

\x{sldkf \y{dlfkj}}

\printindex
\end{document}

输出与第一个例子相同。

相关内容