实施

实施

对于一本每日灵修的书,我根本没有页码,但每个部分对应一年中的一天,每页一天。我在书的末尾生成一个圣经参考文献索引,并将圣经参考文献链接到引用它们的页面。但由于书中没有页码,索引必须包含日期(即部分,例如“13 Mai”而不是 151)而不是页码。

到目前为止,我的(丑陋的)解决方案是在日志中使用以下命令输出部分名称和页面:

 \typeout{Date on page \thepage:\thesection:\chaphead}%

然后使用 shell 脚本解析日志并使用 sed 修改生成的索引(.ind 文件):

#!/bin/bash                                                                     

NAME="$1"                                                                       

while read -r page day month; do                                                
   bsmonth=$(sed -e 's@\\@\\\\@g' <<<$month)                                    
   sed -i "s@textrm{\([^,]*, \)\?$page\(, [^,]*\)\?}@textrm{\1\\\\hyperlink{page.$page}{\\\\mbox{\\\\scshape\\\\makedate{$day}~$bsmonth}}\2}@g" $NAME.ind
done < <(sed -n 's@Date on page \([0-9]\+\):\([0-9]\+\):\(.*\)@\1 \2 \3@p' $NAME.log)

我会这样调用 LaTeX:

%.pdf: %.tex            
    TEXINPUTS=$(TEXINPUTS) pdflatex -shell-escape -interaction=batchmode $< 
    # Modify index to use dates instead of pages                            
    ./index_dates.sh $*                                                     
    # No -shell-escape to prevent re-creation of index                      
    TEXINPUTS=$(TEXINPUTS) pdflatex -interaction=batchmode $<   

我正在使用imakeidx,因此在编译文档时索引会自动重新生成。在 TeXLive 2009 中,不传递-shell-escape会阻止imakeidx重建索引,从而阻止擦除所做的更改index_dates.sh,因此它工作正常(尽管仍然很丑陋)。

现在在 TeXLive 2010 中,这个-shell-escape技巧不起作用了,在我切换到另一个丑陋的技巧之前,我想考虑用正确的 TeX 重写这段代码。你能给我一些提示,告诉我如何正确地做到这一点吗?

  • 我应该生成如下动态宏吗:

    \def\pagemonth@\csname \thepage{\thesection~\chaphead}
    

然后修改索引?如果是的话,我该如何修改索引?

  • 我是否应该将这些宏写入单独的文件并稍后导入它(以及如何做到这一点)?

  • 我应该加入吗imakeidx(以及如何加入)?

  • 我是否应该imakeidx用另一个可以更容易实现这一点的包来替换它?

  • 我是否应该切换到另一个索引生成器(例如xindy)并且我应该向它传递哪些参数?

  • 我是否应该为索引中的页码添加“样式”,这实际上是对用我的内容替换的宏的调用?

答案1

这是一个可能的解决方案。我分部分展示,应该很容易适应您的设置。

(1)我定义一个计数器,并在每次使用命令启动新的部分时对其进行步进\Section,该命令定义一个唯一的命令,保存该部分的标题,其名称取决于计数器的值。

(2) 我获取相关索引命令的副本并对其进行修补:\Indexrequires\@Index反过来又需要\@Wrindex\@Wrindex这是该过程的核心,因为它将条目写入.idx文件中。所以我这样修补它,立即地写入计数器的当前值。这里\protected@iwrite与 相同\protected@write,但执行\immediate\write而不是通常的延迟\write,因为我们不需要仅在输出例程期间才知道的页码。

(3)真正的\Index命令是对以下有用函数的包装制作索引,通常用于表示“看……”。

(4)我们通过制作索引选项-s raphink,其中raphink.ist是仅包含样式的文件

delim_0 ""

不会在条目后添加逗号。

\Index{Veni Sancte Spiritus}现在,诸如“1 月 1 日”部分中的命令将会写入

\indexentry{Veni Sancte Spiritus|transform}{1}

.idx文件中(假设计数器的当前值为 1)。如果我们\Index{Veni Sancte Spiritus}在五旬节也写上,我们将得到如下条目

\indexentry{Veni Sancte Spiritus|transform}{150}

处理makeindex -s raphink(由伊玛克) 将在文件中提供以下内容.ind

\item Veni Sancte Spiritus \transform{1, 150}

宏读取逗号分隔的列表,然后使用包含正确章节标题的\transform命令\csname cursec1\endcsname和进行拆分。\csname cursec150\endcsname

实施

以下是示例文档中的宏。

\begin{filecontents*}{raphink.ist}
delim_0 ""
\end{filecontents*}
\documentclass[a4paper]{report}
\usepackage{etoolbox}
\newcounter{indexcnt}
\newcommand\Section[1]{%
  \stepcounter{indexcnt}%
  \expandafter\gdef\csname cursec\theindexcnt\endcsname{#1}%
  \section{#1}}

\usepackage{imakeidx}
\makeindex[options=-s raphink]

\makeatletter
\let\@Index\@index
\patchcmd{\@Index}{\@wrindex}{\@Wrindex}{}{}
\let\@Wrindex\@wrindex
\patchcmd{\@Wrindex}{\thepage}{\theindexcnt}{}{}
\let\xIndex\index
\patchcmd{\xIndex}{\@index}{\@Index}{}{}
\patchcmd{\xIndex}{\@index}{\@Index}{}{}
\let\protected@iwrite\protected@write
\patchcmd{\protected@iwrite}{\write}{\immediate\write}{}{}
\patchcmd{\@Wrindex}{\protected@write}{\protected@iwrite}{}{}
\makeatother

\newcommand{\Index}[1]{\xIndex{#1|transform}}
\newcommand{\transform}[1]{\forcsvlist\decodesec{#1}}
\newcommand{\decodesec}[1]{, \csname cursec#1\endcsname}

\begin{document}

\chapter{Christmas}

\Section{January 1st}

...
Veni Sancte Spiritus\Index{Veni Sancte Spiritus}
...

\chapter{Easter}

\Section{Pentecost}

...
Veni Sancte Spiritus\Index{Veni Sancte Spiritus}
...


\printindex

\end{document}

答案2

这是我对 @egreg 的答案的最终实现。\thepage尽管他的想法是使用计数器,但它还是使用了。这样做的原因是我想在索引中生成超链接,如果我不知道要链接到的页面,这是不可能的,而且我不想玩数百个动态标签。总而言之,这很有效,我对此很满意:

\newcommand{\getpagedate}[1]{%                                                  
  \csname pagedate#1\endcsname                                                  
}                                                                               

\usepackage{etoolbox}                                                           
\newcommand{\transform}[1]{                                                     
  \def\secondparam{0}%                                                          
  \forcsvlist\decodesec{#1}}                                                    
\newcommand{\decodesec}[1]{%                                                    
  \ifthenelse{\secondparam=1}{, }{}%                                            
  \hyperlink{page.#1}{\mbox{\scshape\getpagedate{#1}}}%                         
  \def\secondparam{1}}                                                          
\renewcommand*{\bvidxpgformat}{transform} 

\newcommand{\dvday}[1]{\newpage\section{#1}%                                   
  \expandafter\xdef\csname pagedate\thepage\endcsname{\noexpand\makedate{\thesection}~\chaphead}%                                                                         
}

结果图如下:

带日期的索引

相关内容