使用 imakeidx 截断页面范围

使用 imakeidx 截断页面范围

这是 egreg 回答的后续问题可以使用 splitidx 截断索引中的页面范围吗?如果索引主题出现在多个页面范围内,则答案会遇到问题。以下 MWE 基于 egreg 的答案:

\begin{filecontents*}{subjind.ist}
delim_0 ", \\checkrange{"
delim_t "}"
\end{filecontents*}

\documentclass{book}
\usepackage{xparse}
\usepackage{imakeidx}

\makeindex[title=Subject Index,options=-s subjind]

\ExplSyntaxOn
\NewDocumentCommand{\checkrange}{>{\SplitArgument{1}{--}}m}
 {
  \formatrange#1
 }
\NewDocumentCommand{\formatrange}{mm}
 {
  \IfNoValueTF { #2 }
   { % no --, it's not a range
    #1
   }
   { % it's a range
    \egreg_range:nn { #1 } { #2 }
   }
 }

\bool_new:N \l__egreg_range_compare_bool

\cs_new_protected:Nn \egreg_range:nn
 {
  % print the start number
  #1--
  \int_compare:nNnTF { \str_count:n { #1 } } = { \str_count:n { #2 } }
   {% same number of digits, remove equal ones at the start
    \__egreg_range_compare:nn { #1 } { #2 }
   }
   {% different number of digits, print both
    #2
   }
 }
\cs_new_protected:Nn \__egreg_range_compare:nn
 {
  \bool_set_true:N \l__egreg_range_compare_bool
  % do a loop on the digits in the first number
  \int_step_inline:nn { \str_count:n { #1 } }
   {
    \bool_if:NTF \l__egreg_range_compare_bool
     {
      % if the digits coincide, print nothing
      \str_if_eq:eeF { \str_item:nn { #1 } { ##1 } } { \str_item:nn { #2 } { ##1 } }
       {
        \str_item:nn { #2 } { ##1 }
        % at the first differing digit, don't compare any longer
        \bool_set_false:N \l__egreg_range_compare_bool
       }
     }
     { \str_item:nn { #2 } { ##1 } }
   }
 }
\ExplSyntaxOff

\begin{document}
\setcounter{page}{95}\index{Topic0|(}Text\newpage
\setcounter{page}{101}\index{Topic0|)}Text\newpage
\setcounter{page}{124}\index{Topic1|(}\index{Topic2|(}Text\newpage
\setcounter{page}{126}\index{Topic1|)}Text\newpage
\setcounter{page}{134}\index{Topic2|)}Text\newpage
\setcounter{page}{141}\index{Topic0}Text\newpage
\index{Topic0}Text\newpage
\index{Topic0}Text
\printindex
\end{document}

产生以下错误消息:

! LaTeX3 Error: Too many '--' tokens when trying to split argument.

For immediate help type H <return>.
 ...                                              

l.3   \item Topic0, \checkrange{95--101, 141--143}

输入 non-stop 会产生以下输出:

在此处输入图片描述

它从 Topic0 的第二个索引条目中省略了“-3”。问题是如何解决这个问题。

编辑跟进 egreg 的巧妙解决方案。我不知道是否应该提出一个新的跟进问题,所以我首先在此编辑中提出它。egreg 的解决方案似乎无法处理索引子主题。如果添加以下 4 行

\setcounter{page}{135}\index{Topic0!sub0|(}Text\newpage
\setcounter{page}{136}\index{Topic0!sub0!subsub0|(}Text\newpage
\setcounter{page}{139}\index{Topic0!sub0!subsub0|)}Text\newpage
\setcounter{page}{140}\index{Topic0!sub0|)}Text\newpage

\setcounter{page}{134}\index{Topic2|)}Text\newpage

在解决方案中,会出现以下错误:

Output written in mwe.ind.
Transcript written in mwe.ilg.
 (mwe.ind
! Extra }, or forgotten \endgroup.
l.4     \subitem sub0, 135--140}

? r
OK, entering \nonstopmode...
! Extra }, or forgotten \endgroup.
l.5       \subsubitem subsub0, 136--139}

) [145] (mwe.aux) )

输出如下:

在此处输入图片描述

唉,我对 egreg 的代码了解不够多,无法做出必要的更改。

答案1

这里是:

\begin{filecontents*}{subjind.ist}
delim_0 ", \\checkrange{"
delim_1 ", \\checkrange{"
delim_2 ", \\checkrange{"
delim_t "}"
\end{filecontents*}

\documentclass{book}
\usepackage{xparse}
\usepackage{imakeidx}

\makeindex[title=Subject Index,options=-s subjind]

\ExplSyntaxOn
\NewDocumentCommand{\checkrange}{m}
 {
  \seq_set_from_clist:Nn \l__ssind_in_seq { #1 }
  \seq_set_map:NNn \l__ssind_out_seq \l__ssind_in_seq { \checkrangeaux{##1} }
  \seq_use:Nn \l__ssind_out_seq {,~}
 }
\seq_new:N \l__ssind_in_seq
\seq_new:N \l__ssind_out_seq

\NewDocumentCommand{\checkrangeaux}{>{\SplitArgument{1}{--}}m}
 {
  \formatrange#1
 }
\NewDocumentCommand{\formatrange}{mm}
 {
  \IfNoValueTF { #2 }
   { % no --, it's not a range
    #1
   }
   { % it's a range
    \egreg_range:nn { #1 } { #2 }
   }
 }

\bool_new:N \l__egreg_range_compare_bool

\cs_new_protected:Nn \egreg_range:nn
 {
  % print the start number
  #1--
  \int_compare:nNnTF { \str_count:n { #1 } } = { \str_count:n { #2 } }
   {% same number of digits, remove equal ones at the start
    \__egreg_range_compare:nn { #1 } { #2 }
   }
   {% different number of digits, print both
    #2
   }
 }
\cs_new_protected:Nn \__egreg_range_compare:nn
 {
  \bool_set_true:N \l__egreg_range_compare_bool
  % do a loop on the digits in the first number
  \int_step_inline:nn { \str_count:n { #1 } }
   {
    \bool_if:NTF \l__egreg_range_compare_bool
     {
      % if the digits coincide, print nothing
      \str_if_eq:eeF { \str_item:nn { #1 } { ##1 } } { \str_item:nn { #2 } { ##1 } }
       {
        \str_item:nn { #2 } { ##1 }
        % at the first differing digit, don't compare any longer
        \bool_set_false:N \l__egreg_range_compare_bool
       }
     }
     { \str_item:nn { #2 } { ##1 } }
   }
 }
\ExplSyntaxOff

\begin{document}
\setcounter{page}{95}\index{Topic0|(}Text\newpage
\setcounter{page}{101}\index{Topic0|)}Text\newpage
\setcounter{page}{124}\index{Topic1|(}\index{Topic2|(}Text\newpage
\setcounter{page}{126}\index{Topic1|)}Text\newpage
\setcounter{page}{134}\index{Topic2|)}Text\newpage
\setcounter{page}{135}\index{Topic0!sub0|(}Text\newpage
\setcounter{page}{136}\index{Topic0!sub0!subsub0|(}Text\newpage
\setcounter{page}{139}\index{Topic0!sub0!subsub0|)}Text\newpage
\setcounter{page}{140}\index{Topic0!sub0|)}Text\newpage
\setcounter{page}{141}\index{Topic0}Text\newpage
\index{Topic0}Text\newpage
\index{Topic0}Text
\printindex
\end{document}

现在\checkrange用逗号分割输入,并像以前一样对每个项目进行处理。这也适用于子项目。

在此处输入图片描述

相关内容