添加:支持列表参数(和三位数字)

添加:支持列表参数(和三位数字)

我正在撰写博士论文,需要创建所有引用的主要来源的索引。我创建了“引用”命令,这样每当我引用以下内容时,它都会自动添加索引行:

\newcommand{\citeherm}[1]{\emph{Shepherd of Hermas}~#1\index{Shepherd of Hermas!#1}}

效果很好,只是索引的数字顺序不正确。'11' 会位于 '1' 和 '2' 之间,在这种情况下显然是不正确的。

我附上了一个最简单的例子。谁能帮忙?

(顺便说一句,我以为你可以通过使用不打印的运行零来手动完成此操作,但我不知道如何在上面的命令中自动执行此操作。

\index{Shepherd of Hermas!03.13–[email protected]–8}

最小示例

\documentclass[12pt]{memoir}
\newcommand{\citeherm}[1]{\emph{Shepherd of Hermas}~#1\index{Shepherd of Hermas!#1}}
\newcommand{\citeash}[1]{\emph{Testament of Asher}~#1\index{Testament of Asher!#1}}
\makeindex

\begin{document}

“bla bla bla” \citeherm{12.1}
“bla bla bla” \citeherm{12.2}
“bla bla bla” \citeherm{12.3}
“bla bla bla” \citeherm{12.4}
“bla bla bla” \citeherm{12.10}
“bla bla bla” \citeherm{12.11}
“bla bla bla” \citeherm{12.20}
“bla bla bla” \citeherm{12.21}


“bla bla bla” \citeash{1.1}
“bla bla bla” \citeash{2.1}
“bla bla bla” \citeash{10.1}
\printindex

\end{document}  

答案1

我假设您的参考文献具有以下形式x.y-z,可能省略了-z部分,其中xyz是小于 100 的数字:

\documentclass[12pt]{memoir}

\makeatletter
\def\bruin@normalize#1{\@bruin@normalizei#1-\@nil}
\def\@bruin@normalizei#1.#2-#3\@nil{%
    \two@digits{#1}.\two@digits{#2}%
  \if\relax\detokenize{#3}\relax\else
     -\expandafter\two@digits\expandafter{\@gobblehyphen#3}%
  \fi}
\def\@gobblehyphen#1-{#1}
\newcommand{\defcite}[2]{%
  \newcommand{#1}[1]{\emph{#2}~##1\index{#2!\bruin@normalize{##1}@##1}}%
}
\makeatother

\defcite{\citeherm}{Shepherd of Hermas}
\defcite{\citeash}{Testament of Asher}

\makeindex

\begin{document}

bla bla bla \citeherm{12.1}
bla bla bla \citeherm{12.2}
bla bla bla \citeherm{12.3}
bla bla bla \citeherm{12.4}
bla bla bla \citeherm{12.10}
bla bla bla \citeherm{12.11}
bla bla bla \citeherm{12.20}
bla bla bla \citeherm{12.21}


bla bla bla \citeash{1.1}
bla bla bla \citeash{2.1}
bla bla bla \citeash{10.1}
\printindex

\end{document}  

如果格式不同,则必须进行一些更正。例如,如果数字可以是三位数,则添加

\def\three@digits#1{\ifnum#1<1000 0\ifnum#1<10 0\fi\fi#1}

并使用\three@digits代替\two@digits

我还定义了一个“catch-all”命令,用于统一定义索引命令。

添加:支持列表参数(和三位数字)

\makeatletter
\def\three@digits#1{\ifnum#1<100 0\ifnum#1<10 0\fi\fi#1}
\def\bruin@normalize#1{\@bruin@normalizei#1-\@nil}
\def\@bruin@normalizei#1.#2-#3\@nil{%
    \three@digits{#1}.\three@digits{#2}%
  \if\relax\detokenize{#3}\relax\else
     -\expandafter\three@digits\expandafter{\@gobblehyphen#3}%
  \fi}
\def\@gobblehyphen#1-{#1}
\newcommand{\defcite}[2]{%
  \newcommand{#1}[1]{\emph{#2}\bruin@dolist{#2}{##1}}}
\def\bruin@dolist#1#2{%
  \toks@={~\@gobbletwo}%
  \@for\next:=#2\do{%
    \edef\next{,\noexpand\space\next
      \noexpand\index{#1!\expandafter\bruin@normalize\expandafter{\next}@\next}}%
    \toks@=\expandafter{\the\expandafter\toks@\next}%
  }\the\toks@
}
\makeatother

\defcite{\citeherm}{Shepherd of Hermas}
\defcite{\citeash}{Testament of Asher}

现在输入如下内容\citeherm{12.1,35.4,28.2}将会打印

赫马牧人 12.1, 35.4, 28.2

在“Hermas”和第一个数字之间有一个不间断的空格;它将索引所有三个参考。

新增:支持章节范围

\makeatletter
\def\three@digits#1{\ifnum#1<100 0\ifnum#1<10 0\fi\fi#1}
\def\bruin@normalize#1{\@bruin@normalizei#1-.\@nil}
\def\@bruin@normalizei#1.#2-#3.#4\@nil{%
    \three@digits{#1}.\three@digits{#2}%
  \if\relax\detokenize{#4}\relax
     % same chapter range
     \if\relax\detokenize{#3}\relax
       % simple range
       % already set
     \else
       -\expandafter\three@digits\expandafter{\@gobblehyphen#3}%
     \fi
  \else
     % different chapters range
     -\three@digits{#3}.\expandafter\three@digits\expandafter{\@gobblehyphenperiod#4}%
  \fi}
\def\@gobblehyphen#1-{#1}
\def\@gobblehyphenperiod#1-.{#1}

\newcommand{\defcite}[2]{%
  \newcommand{#1}[1]{\emph{#2}\bruin@dolist{#2}{##1}}}
\def\bruin@dolist#1#2{%
  \toks@={~\@gobbletwo}%
  \@for\next:=#2\do{%
    \edef\next{,\noexpand\space\next
      \noexpand\index{#1!\expandafter\bruin@normalize\expandafter{\next}@\next}}%
    \toks@=\expandafter{\the\expandafter\toks@\next}%
  }\showthe\toks@\the\toks@
}
\makeatother

\defcite{\citeherm}{Shepherd of Hermas}
\defcite{\citeash}{Testament of Asher}

现在也\citeherm{1.2-3.4}将被编入索引。列表将继续像以前一样工作。

新增:还支持简单引用

\makeatletter
\def\three@digits#1{\ifnum#1<100 0\ifnum#1<10 0\fi\fi#1}
\def\bruin@normalize#1{\@bruin@normalizei#1.\@nil}
\def\@bruin@normalizei#1.#2\@nil{%
  \if\relax\detokenize{#2}\relax
     % only one number
     \three@digits{#1}\expandafter\@gobble
  \else
     \expandafter\@firstofone
  \fi{\@bruin@gobbleperiod#1.#2\@nil}
}
\def\@bruin@gobbleperiod#1.\@nil{\@bruin@normalizeii#1-.\@nil}
\def\@bruin@normalizeii#1.#2-#3.#4\@nil{%
    \three@digits{#1}.\three@digits{#2}%
  \if\relax\detokenize{#4}\relax
     % same chapter range
     \if\relax\detokenize{#3}\relax
       % simple range
       % already set
     \else
       -\expandafter\three@digits\expandafter{\@gobblehyphen#3}%
     \fi
  \else
     % different chapters range
     -\three@digits{#3}.\expandafter\three@digits\expandafter{\@gobblehyphenperiod#4}%
  \fi}
\def\@gobblehyphen#1-{#1}
\def\@gobblehyphenperiod#1-.{#1}

\newcommand{\defcite}[2]{%
  \newcommand{#1}[1]{\emph{#2}\bruin@dolist{#2}{##1}}}
\def\bruin@dolist#1#2{%
  \toks@={~\@gobbletwo}%
  \@for\next:=#2\do{%
    \edef\next{,\noexpand\space\next
      \noexpand\index{#1!\expandafter\bruin@normalize\expandafter{\next}@\next}}%
    \toks@=\expandafter{\the\expandafter\toks@\next}%
  }\the\toks@
}

\makeatother

\defcite{\citeherm}{Shepherd of Hermas}
\defcite{\citeash}{Testament of Asher}

这也应该允许类似引用\citeherm{12}

最后(?)补充

这是一个“LaTeX3”的实现:

\documentclass[12pt]{memoir}
\usepackage{xparse}
\ExplSyntaxOn

\tl_new:N \l_bruin_argi_tl
\tl_new:N \l_bruin_argii_tl
\tl_new:N \l_bruin_argx_tl
\tl_new:N \l_bruin_temp_tl
\tl_new:N \l_bruin_final_tl

% First of all we split the comma separated list; we store |#1|, the
% title of the book, in |\bruin_argi_tl| and |\bruin_argx_tl| to
% contain |\use_none:nn| that at the end will gobble the first two
% tokens (a comma and a space); then we put the split list of
% arguments followed by |{\NoValue}| after |\bruin_process:n|, because
% it will be used to terminate the recursion.
\NewDocumentCommand\bruin_dolist:nn {m >{\SplitList{,}}m}{
  \tl_set:Nn \l_bruin_argi_tl { #1 }
  \tl_set:Nn \l_bruin_argx_tl { \use_none:nn }
  \bruin_process:n #2 {\NoValue}
}
% |\bruin_process:n| initiates the recursion; it examines the contents
% of the first pair of braces after it and, if different from
% |\NoValue|, stores it into |\bruin_argii_tl|. Then it appends also
% it to the list |\bruin_argx_tl|, after a comma and a space. The same
% contents is also processed by |\bruin_normalize:n|. Then we execute
% |\bruin_do:| and call again |\bruin_process:n| to restart the recursion.
\cs_new:Nn \bruin_process:n {
  \IfNoValueTF{#1}
    {}% end of recursion
    {
     \tl_set:Nn \l_bruin_argii_tl {#1}
     \tl_set:Nx \l_bruin_argx_tl { \l_bruin_argx_tl , \c_space_tl #1 }
     \bruin_normalize:n {#1} \bruin_do: \bruin_process:n
    }
}
% |\bruin_normalize:n| is responsible for splitting an entry of the
% form |A-B| (|A| and |B| will actually be something like |1.2|) into
% the two components, which are passed to |\bruin_normalizei:nn|
\NewDocumentCommand\bruin_normalize:n {>{\SplitArgument{1}{-}}m}{
  \bruin_normalizei:nn #1
}
% If the entry was |A-B|, |\bruin_normalizei:nn| is passed |{A}{B}|,
% otherwise it is passed |{A}{\NoValue}|
\cs_new:Nn \bruin_normalizei:nn {
  \IfNoValueTF{#2}
    {\bruin_three:n {#1}} % simple entry
    {\bruin_three:nn {#1}{#2}} % complex entry
}
% |\bruin_three:n| splits an argument of the form |1.2.3| into the
% components; it's quite similar to |\bruin_normalize:n|
\NewDocumentCommand\bruin_three:n {>{\SplitArgument{2}{.}}m}{
  \bruin_threedo:nnn #1
  \tl_set:Nx \l_bruin_final_tl {\l_bruin_temp_tl}
}
% |\bruin_threedo:nnn| sets |\l_bruin_final_tl| to the components but
% with three digits; |1| is transformed into |001| and |1.2| becomes
% |001.002|, while |1.2.3| becomes |001.002.003|
\cs_new:Nn \bruin_threedo:nnn {
  \IfNoValueTF{#3}
    {\IfNoValueTF{#2}
       {\tl_set:Nx \l_bruin_temp_tl
          {\bruin_threedig:n{#1}}}
       {\tl_set:Nx \l_bruin_temp_tl
          {\bruin_threedig:n{#1}.\bruin_threedig:n{#2}}}
    }
    {\tl_set:Nx \l_bruin_temp_tl
       {\bruin_threedig:n{#1}.\bruin_threedig:n{#2}.\bruin_threedig:n{#3}}
    }
}
% we do similarly for |\bruin_three:nn|, calling |\bruin_threedo:nnn| twice.
\NewDocumentCommand\bruin_three:nn
  {>{\SplitArgument{2}{.}}m >{\SplitArgument{2}{.}}m}
  { \bruin_threedo:nnn #1
    \tl_set:Nx \l_bruin_final_tl {\l_bruin_temp_tl }
    \bruin_threedo:nnn #2
    \tl_set:Nx \l_bruin_final_tl {\l_bruin_final_tl -- \l_bruin_temp_tl}
  }

\cs_new:Nn \bruin_do: {
  \cs_set:Nx \bruin_next: {
    \exp_not:N \index 
      {\l_bruin_argi_tl ! \l_bruin_final_tl \c_space_tl @ \l_bruin_argii_tl }
  }
  \bruin_next: 
}
\cs_new:Nn \bruin_threedig:n {
  \int_compare:nNnTF {#1} < {100}
    { 0 \int_compare:nNnTF {#1} < {10} {0}{} }
    {} #1
}

% |\bruin_defcite:nn| defines |#1| as a macro with one argument, first
% storing its second argument in it. So
%
% |\defcite{\citeT}{Title}|
%
% defines |\citeT| as if it were
%
% |\def\citeT#1{\emph{Title}\space\bruin_dolist:nn{Title}{#1}\l_bruin_argx_tl}|
%
% The token list |\l_bruin_argx_tl| will be built by |\bruin_dolist:nn|
\cs_new:Nn \bruin_defcite:nn {
  \cs_new:Npn #1##1{\emph{#2}\space\bruin_dolist:nn {#2}{##1} \l_bruin_argx_tl }}
\cs_set_eq:NN \defcite \bruin_defcite:nn
\ExplSyntaxOff

\defcite{\citeherm}{Shepherd of Hermas}
\defcite{\citeash}{Testament of Asher}

\makeindex

\begin{document}

%\tracingmacros=1
bla bla bla \citeherm{12.1-2}
\newpage
bla bla bla \citeherm{12.2,13.9}
\newpage
bla bla bla \citeherm{12.3-13.4}
\newpage
bla bla bla \citeherm{12}
\newpage
bla bla bla \citeherm{12.10}
\newpage
bla bla bla \citeherm{12.11}
\newpage
bla bla bla \citeherm{12.20}
\newpage
bla bla bla \citeherm{12.21}
\newpage


bla bla bla \citeash{1.2.3}
\newpage
bla bla bla \citeash{2.1}.
\newpage
bla bla bla \citeash{10.1,1.1,2.9-19}.
\newpage
\printindex

\end{document}

正如您在示例中看到的,这也应该支持三个级别\citeash


LaTeX3 2012 年 7 月更新后的版本

\documentclass[12pt]{memoir}
\usepackage{xparse}
\ExplSyntaxOn

\tl_new:N \l_bruin_argi_tl
\tl_new:N \l_bruin_argii_tl
\tl_new:N \l_bruin_argx_tl
\tl_new:N \l_bruin_temp_tl
\tl_new:N \l_bruin_final_tl

% First of all we split the comma separated list; we store |#1|, the
% title of the book, in |\bruin_argi_tl| and |\bruin_argx_tl| to
% contain |\use_none:nn| that at the end will gobble the first two
% tokens (a comma and a space); then we put the split list of
% arguments followed by |{\NoValue}| after |\bruin_process:n|, because
% it will be used to terminate the recursion.
\NewDocumentCommand\bruin_dolist:nn {m >{\SplitList{,}}m}{
  \tl_set:Nn \l_bruin_argi_tl { #1 }
  \tl_set:Nn \l_bruin_argx_tl { \use_none:nn }
  \ProcessList{#2}{\bruin_process:n}
}
% |\bruin_process:n| does the recursion via \ProcessList; it
% stores its argument into |\bruin_argii_tl|. Then it appends also
% it to the list |\bruin_argx_tl|, after a comma and a space. The same
% contents is also processed by |\bruin_normalize:n|. Then we execute
% |\bruin_do:|.
\cs_new:Nn \bruin_process:n {
     \tl_set:Nn \l_bruin_argii_tl {#1}
     \tl_set:Nx \l_bruin_argx_tl { \l_bruin_argx_tl , \c_space_tl #1 }
     \bruin_normalize:n {#1} \bruin_do: 
}
% |\bruin_normalize:n| is responsible for splitting an entry of the
% form |A-B| (|A| and |B| will actually be something like |1.2|) into
% the two components, which are passed to |\bruin_normalizei:nn|
\NewDocumentCommand\bruin_normalize:n {>{\SplitArgument{1}{-}}m}{
  \bruin_normalizei:nn #1
}
% If the entry was |A-B|, |\bruin_normalizei:nn| is passed |{A}{B}|,
% otherwise it is passed |{A}{\NoValue}|
\cs_new:Nn \bruin_normalizei:nn {
  \IfNoValueTF{#2}
    {\bruin_three:n {#1}} % simple entry
    {\bruin_three:nn {#1}{#2}} % complex entry
}
% |\bruin_three:n| splits an argument of the form |1.2.3| into the
% components; it's quite similar to |\bruin_normalize:n|
\NewDocumentCommand\bruin_three:n {>{\SplitArgument{2}{.}}m}{
  \bruin_threedo:nnn #1
  \tl_set:Nx \l_bruin_final_tl {\l_bruin_temp_tl}
}
% |\bruin_threedo:nnn| sets |\l_bruin_final_tl| to the components but
% with three digits; |1| is transformed into |001| and |1.2| becomes
% |001.002|, while |1.2.3| becomes |001.002.003|
\cs_new:Nn \bruin_threedo:nnn {
  \IfNoValueTF{#3}
    {\IfNoValueTF{#2}
       {\tl_set:Nx \l_bruin_temp_tl
          {\bruin_threedig:n{#1}}}
       {\tl_set:Nx \l_bruin_temp_tl
          {\bruin_threedig:n{#1}.\bruin_threedig:n{#2}}}
    }
    {\tl_set:Nx \l_bruin_temp_tl
       {\bruin_threedig:n{#1}.\bruin_threedig:n{#2}.\bruin_threedig:n{#3}}
    }
}
% we do similarly for |\bruin_three:nn|, calling |\bruin_threedo:nnn| twice.
\NewDocumentCommand\bruin_three:nn
  {>{\SplitArgument{2}{.}}m >{\SplitArgument{2}{.}}m}
  { \bruin_threedo:nnn #1
    \tl_set:Nx \l_bruin_final_tl {\l_bruin_temp_tl }
    \bruin_threedo:nnn #2
    \tl_set:Nx \l_bruin_final_tl {\l_bruin_final_tl -- \l_bruin_temp_tl}
  }

\cs_new:Nn \bruin_do: {
  \cs_set:Nx \bruin_next: {
    \exp_not:N \index 
      {\l_bruin_argi_tl ! \l_bruin_final_tl \c_space_tl @ \l_bruin_argii_tl }
  }
  \bruin_next: 
}
\cs_new:Nn \bruin_threedig:n {
  \int_compare:nNnTF {#1} < {100}
    { 0 \int_compare:nNnTF {#1} < {10} {0}{} }
    {} #1
}

% |\bruin_defcite:nn| defines |#1| as a macro with one argument, first
% storing its second argument in it. So
%
% |\defcite{\citeT}{Title}|
%
% defines |\citeT| as if it were
%
% |\def\citeT#1{\emph{Title}\space\bruin_dolist:nn{Title}{#1}\l_bruin_argx_tl}|
%
% The token list |\l_bruin_argx_tl| will be built by |\bruin_dolist:nn|
\cs_new:Nn \bruin_defcite:nn {
  \cs_new:Npn #1##1{\emph{#2}\space\bruin_dolist:nn {#2}{##1} \l_bruin_argx_tl }}
\cs_set_eq:NN \defcite \bruin_defcite:nn
\ExplSyntaxOff

\defcite{\citeherm}{Shepherd of Hermas}
\defcite{\citeash}{Testament of Asher}

\makeindex

\begin{document}

%\tracingmacros=1
bla bla bla \citeherm{12.1-2}
\newpage
bla bla bla \citeherm{12.2,13.9}
\newpage
bla bla bla \citeherm{12.3-13.4}
\newpage
bla bla bla \citeherm{12}
\newpage
bla bla bla \citeherm{12.10}
\newpage
bla bla bla \citeherm{12.11}
\newpage
bla bla bla \citeherm{12.20}
\newpage
bla bla bla \citeherm{12.21}
\newpage


bla bla bla \citeash{1.2.3}
\newpage
bla bla bla \citeash{2.1}.
\newpage
bla bla bla \citeash{10.1,1.1,2.9-19}.
\newpage
\printindex

\end{document}

相关内容