如何在 ConTeXt 中按字母顺序排列整个文档的所有部分、章节、节和内容?

如何在 ConTeXt 中按字母顺序排列整个文档的所有部分、章节、节和内容?

我有一份结构如下的文档:

\part{Birds}
    \chapter{North America}
        \section{West Coast}
            \mymacro{Bald Eagle}
            \mymacro{Spotted Owl}
        \section{East Coast}
        \section{Alaska}
    \chapter{South America}
        \section{Peru}
        \section{Brazil}
\part{Bears}
    \chapter{Canada}
  • 序言出现在一个单独的文件中。
  • 所有内容都是使用自定义宏添加的,\mymacro因此每个项目都占一行。

如何按字母顺序对文档中各层级的所有部分、章节、节和宏进行排序?例如,上面的内容将按如下方式排序:

\part{Bears}
    \chapter{Canada}
\part{Birds}
    \chapter{North America}
        \section{Alaska}
        \section{East Coast}
        \section{West Coast}
            \mymacro{Bald Eagle}
            \mymacro{Spotted Owl}
    \chapter{South America}
        \section{Brazil}
        \section{Peru}

答案1

我能想到的最简单、危害最小的方法是拦截普通的结构宏并在 Lua 中执行排序部分。如果你正确地进行分组,你不会注意到差异。我概述了一个带注释的概念验证适用于您的示例。基本上,您所要做的就是指定应排序的结构元素列表以及用于排版条目的命令(\mymacro如您所称,这里我坚持使用 plain \entry)。后者需要一个强制参数,但可以轻松重写代码以允许可选参数。

配置宏\setupsortstructure需要两个参数部分(输入逗号列表)和入口(宏):

\setupsortstructure[
   sections={part,chapter,section,subsection},
   entrycommand=\entry,
]

当然,入口命令需要正确定义。从示例中可以看出:

%%% The macro for entries.
\definehighlight [entryhighlight] [style=italic]
\define[1]\entry{%
  \leavevmode
  \noindentation
  \hbox to2em{\hfill·}\hskip.5em
  \entryhighlight{#1}%
  \blank[line]%
}

大功告成!在\starttext和之间插入内容\stoptext,您将获得如下内容: 已排序的文档结构

答案2

我非常确定在上下文中这应该是可能的。您可以将条目写入 csv 文件或在内存中构建数据库,然后使用 TeX 或 lua 对其进行排序。在 LaTeX 中,例如可以使用 datatool:(我假设始终至少有一个\section条目以保持代码简单,并且我没有尝试保护值中可能脆弱的命令。代码应该只显示原理):

\documentclass{article} 
\usepackage{datatool,ifthen}
\DTLnewdb{animals}
\renewcommand\part[1]{%
 \def\currenttype{#1}}%


 \newcommand\chapter[1]{%
  \def\currentlocation{#1}}

\renewcommand\section[1]{%
  \DTLnewrow{animals}
  \DTLnewdbentry{animals}{type}{\currenttype}
  \DTLnewdbentry{animals}{location}{\currentlocation}
  \DTLnewdbentry{animals}{sublocation}{#1}
  }


\begin{document}     
\dtlexpandnewvalue
\part{Birds} 
     \chapter{North America}
        \section{West Coast}
        \section{East Coast}
        \section{Alaska}    
   \chapter{South America}
        \section{Peru}
        \section{Brazil}
    \chapter{Germany}
      \section{North}
\part{Bears}
    \chapter{Canada}
         \section{Lake}

Unsorted database:

\DTLdisplaydb{animals}

\bigskip

Sorted entries:

\DTLsort{type,location,sublocation}{animals}%
\begin{tabular}{lll}
\bfseries type &
\bfseries location & \bfseries sublocation 
\DTLforeach{animals}{%
\type=type,\location=location,\sublocation=sublocation}{%
\\
\type&\location &\sublocation}
\end{tabular}

\end{document}

答案3

据我所知,ConTeXt 无法对您的输入文件进行排序。

您可能能够通过使用\startchapter ... \stopchapter节头版本、将每个节主体存储在缓冲区中以及使用寄存器来软化每个级别来获得工作版本。

但是,我认为如果你想对输入进行排序,那么 TeX 就是一种错误的输入语言。大多数 XML 处理工具(包括 ConTeXt 中的 XML 解析器)都可以访问完整的 XML 树,这使得对块进行排序和移动变得更加容易。因此,对于此类数据,最好使用 XML 作为输入语言。

如果您的输入文件遵循受限的 TeX 语法,那么您也可以使用更高级的编程语言对其进行解析并在那里进行排序。

另一个选择是简单地将文本输入为 Lua 表:

\startluacode
thirddata = thirddata or {}
thirddata.contents = {
   "bears" = { -- Part level
        "Canada" = {}, -- Chapter level  
   },
   "birds" = { -- Part level
        "North America" = { -- Chapter level
           "West Coast" = {
                "Bald Eagle",
                "Spotted Owl",
           },
           "East Coast" = {},
           "Alaska" = {},
         },
        "South America" = { ---
         --- ....
         },
    }
 }
\stopluacode

然后你可以写一个ConTeXt Lua 文档将这些数据动态转换为 TeX 文档并进行处理。

相关内容