格式化包含子项的两列索引

格式化包含子项的两列索引

在格式化带有子项的双列索引时,我遇到两个问题:

\documentclass{scrartcl}

\usepackage{imakeidx}
\usepackage[indentunit=15pt,justific=raggedright, columnsep=10pt, font=footnotesize]{idxlayout}

\makeindex

\begin{document}

Some text.

\index{Donahue!Alice}
\index{Donahue!Barney}

\index{Jones!Alvin}
\index{Jones!Billy}
\index{Jones!Carter}
\index{Jones!Dennis}

\index{Smith!Alex}
\index{Smith!Brian}
\index{Smith!Carrie}
\index{Smith!Dewey}
\index{Smith!Eric}
\index{Smith!Frank}
\index{Smith!Gary}
\index{Smith!Huey}
\index{Smith!Irma}
\index{Smith!Joey}
\index{Smith!Kevin}

\index{Scullion!Alex}
\index{Scullion!Brian}
\index{Scullion!Carrie}

\index{White!Alice}
\index{White!Barney}

\idxlayout{columns=2, font=small, columnsep=20pt}

\printindex

\end{document}

在此处输入图片描述

在此 MWE 中,(1) 索引条目 »Smith« 与其子条目分离,并且 (2) 组 (条目 + 子条目) 之间的空间不均匀。

我有两个问题:是否有可能(1)修复项目组之间的空间,以及(2)实现一种算法,使条目与同一列中至少一个(或两个或三个)子条目粘在一起?

对于 MWE,这会导致右列比左列短一点。»Alex, 1« 将被拉向 »Smith«。在我看来,这比现在的情况要好一点。

答案1

您可以重新定义\@idxitem(让其\item等于里面的theindex)来做一些簿记,即重置一个计数器,使后续每个计数器\subitem都会减少。

\subitem当计数器的值为正时还会增加惩罚,因此禁止分页/分列。

\documentclass{scrartcl}

\usepackage{imakeidx}
\usepackage[indentunit=15pt,justific=raggedright, columnsep=10pt, font=footnotesize]{idxlayout}

\makeindex

\makeatletter
\let\ori@idxitem\@idxitem
\def\@idxitem{\clear@penalties\ori@idxitem}
\def\clear@penalties{\subitem@count=3 }
\newcount\subitem@count
\def\subitem{%
  \advance\subitem@count -1
  \par
  \ifnum\subitem@count>0 \penalty10000 \fi
  \ori@idxitem\hspace*{\ila@subindent}%
}
\makeatother

\begin{document}

Some text.

\index{Donahue!Alice}
\index{Donahue!Barney}

\index{Jones!Alvin}
\index{Jones!Billy}
\index{Jones!Carter}
\index{Jones!Dennis}

\index{Smith!Alex}
\index{Smith!Brian}
\index{Smith!Carrie}
\index{Smith!Dewey}
\index{Smith!Eric}
\index{Smith!Frank}
\index{Smith!Gary}
\index{Smith!Huey}
\index{Smith!Irma}
\index{Smith!Joey}
\index{Smith!Kevin}

\index{Scullion!Alex}
\index{Scullion!Brian}
\index{Scullion!Carrie}

\index{White!Alice}
\index{White!Barney}

\idxlayout{columns=2, font=small, columnsep=20pt}

\printindex

\end{document}

在此处输入图片描述

这将使两个子项与主条目保持在一起。使用

\def\clear@penalties{\subitem@count=2 }

您只会获得一个附加的子项目。

在此处输入图片描述

答案2

垂直间距不同,因为只有当有新字母时才会插入空格(根据此文档)。既然你不喜欢,我无论如何都要修复它。

我尝试用 LaTeX3 写解决方案,但不知何故正则表达式在布尔表达式中不起作用。为了方便,我改用 Lua。也就是说,下面的代码只能在 LuaLaTeX 中运行。想法很简单:读取ind生成的文件makeindex并根据我们的目的对其进行微调。

您可能需要编译该文档两次才能使其正常工作。

在此处输入图片描述

\documentclass{scrartcl}

\usepackage{imakeidx}
\usepackage[indentunit=15pt,justific=raggedright, columnsep=10pt, font=footnotesize]{idxlayout}
\usepackage{etoolbox}
\usepackage{luacode}
\usepackage{expl3}
\usepackage{hyperref}

\makeindex

\begin{luacode*}

local inspect = require"inspect"

function fine_tune_index()
    local index_filename = tex.jobname .. ".ind"
    local newindex_filename = tex.jobname .. "-new.ind"
    local attr = lfs.attributes(index_filename)
    if attr == nil then
        return
    end

    local index_lines = {}
    for line in io.lines(index_filename) do
        table.insert(index_lines, line)
    end
    
    local new_lines = {}
    local new_line_buffer = {}
    local line=nil
    local has_space=true
    local search_end = #index_lines - 1
    local item_count = 0
    
    function flush_line_buffer()
        if #new_line_buffer > 1 then
            table.insert(new_line_buffer, 1, [[\begin{minipage}{\linewidth}]])
            table.insert(new_line_buffer, 4, [[\end{minipage}]])
        end
        for _, item in ipairs(new_line_buffer) do
            table.insert(new_lines, item)
        end
        new_line_buffer = {}
    end
    
    for i=2,search_end do
        line = index_lines[i]
        if line:find("\\item") then
            item_count = item_count + 1
            flush_line_buffer()
            if not has_space then
                table.insert(new_lines, "\\indexspace")
            end
            has_space = false
            table.insert(new_line_buffer, line)
        elseif line:find("\\indexspace") then
            has_space=true
            flush_line_buffer()
            table.insert(new_lines, line)
        else
            table.insert(new_line_buffer, line)
        end
    end
    
    flush_line_buffer()
    table.insert(new_lines, 1, index_lines[1])
    table.insert(new_lines, index_lines[#index_lines])
    local out_text = table.concat(new_lines, "\n")
    local outfile = io.open(newindex_filename, "w")
    outfile:write(out_text)
    outfile:close()
end


\end{luacode*}

\AtEndDocument{
    \directlua{fine_tune_index()}
}

\begin{document}

Some text.

\index{Donahue!Alice}
\index{Donahue!Barney}

\index{Jones!Alvin}
\index{Jones!Billy}
\index{Jones!Carter}
\index{Jones!Dennis}

\index{Smith!Alex}
\index{Smith!Brian}
\index{Smith!Carrie}
\index{Smith!Dewey}
\index{Smith!Eric}
\index{Smith!Frank}
\index{Smith!Gary}
\index{Smith!Huey}
\index{Smith!Irma}
\index{Smith!Joey}
\index{Smith!Kevin}

\index{Scullion!Alex}
\index{Scullion!Brian}
\index{Scullion!Carrie}

\index{White!Alice}
\index{White!Barney}

\idxlayout{columns=2, font=small, columnsep=20pt}


\ExplSyntaxOn
% create a new int variable to bypass checks
\int_new:c {\jobname-new@idxfile}
\ExplSyntaxOff
\printindex[\jobname-new]


\end{document}

答案3

好的,这是一个 LaTeX 解决方案。

不幸的是,该idxlayout软件包没有提供很多钩子来进行这种修改,所以我的更改有些侵入性,如果您使用不同的布局选项,更改就会中断。

如果您遇到问题,以下内容可以变得更通用一些。

您应该将此代码放入序言中,例如在加载之后idxlayout。它的作用是重新定义所需的内部结构以idxlayout进行所需的更改。我试图尽可能地减少侵入性,但效果不佳。

% Could put this into a separate package which loads idxlayout
\makeatletter
% no additional space before new letters
\let\indexspace\relax
% rescue original definition
\let\orig@idxitem\@idxitem
% we need to know if a subitem is the first after an item
\newif\ifafteritem

% \item should do what it originally does, plus add vertical space,
% plus set the flag for \subitem
\renewcommand{\@idxitem}{%
  \orig@idxitem
  \vspace{\ila@initsep}%
  \afteritemtrue
}

% \subitem should refer to original definition of \@idxitem (to avoid
% adding vertical space), plus add penalty if it's the first subitem.
\renewcommand{\subitem}{%
  \orig@idxitem
  \ifafteritem\nobreak\fi
  \hspace*{\ila@subindent}%
  \afteritemfalse
}%
\renewcommand{\subsubitem}{\orig@idxitem\hspace*{\ila@subsubindent}}%
\makeatother

结果:

生成的索引布局

相关内容