页码特定的命令/环境

页码特定的命令/环境

是否有任何直接的方法可以告诉 tex 以某种方式在某些页码上运行命令?

在继续之前,我应该声明我正在使用回忆录包来格式化我的文档。

具体来说,我想要实现的是,在页边空白处生成一个动态列表,其中包含一些小的数学方程式或简短的文本片段(这些方程式或文本片段通过下面阐明的命令在文档主体的某个地方定义)。具体来说,我希望首次亮相列表的边距与第一个列表项创建所在的页面的边距相同。然后我希望相同的每隔一页生成一个列表(IE,每个偶数页或奇数页,取决于列表的第一个实例出现的位置)直到到达已创建新列表项的页面时,我希望所有后续列表都包含这两个项目。然后应重复此过程,拾取新列表项,直到当前部分结束。

为了突出显示一个具体示例,假设我在第 1、2、7 和 8 页创建列表条目。那么我应该有以下内容:

  • 第 1 页边距列表:一项。
  • 第 3 页边距列表:两项。
  • 第 5 页边距列表:两项。
  • 第 7 页边距列表:三项。
  • 第 9 页边距列表:四项。

到目前为止,我已经设法拼凑了一些命令(这​​在很大程度上要感谢这个网站上的问题),这些命令可以满足我的大部分需求。我有一个命令构建命令,可以与计数器结合使用,以创建包含我的列表条目的索引命令:

\newcounter{CountItems}[section] % This creates a counter that counts how many list-items have appeared in a given section.

\newcommand\addindex[4][g]{\csname #1def\expandafter\endcsname\csname #2\roman{#3}\endcsname{#4}} % This is a command-creating command that uses concatenation to create indexed commands using a counter. #2 is the root-name of the function, #3 uses a counter to create an index to be appended to the root-name, #4 is the content stored by the command, and #1 is used to modify the behaviour of the "def" command.

\newcommand{\DeriveCond}[3]{\stepcounter{CountItems}{\addindex{conditem}{CountItems}{#1}}} % This command takes as input #1, which is the actual text to appear in the list. Using the above command (\addindex), this command creates indexed commands "conditemi", "conditemii", "conditemiii", etc, that contain the content for the list.

然后我可以使用 for 循环在文档中的任何页面上构建一个列表逐项列举环境。我在开始时提到过,我使用的是回忆录类,所以我可以包装逐项列举环境\侧边栏{}发出命令 –保证金清单– 无论在哪个页面上调用它,它都会生成最新的边距列表:

\newcounter{itemloopcounter}[section] % This creates a counter to be used in list-generation. This is a dummy-counter created for use in the loop in the next command. It keeps track of the value of the loop variable \cond so that each of the "contitem" commands can be called easily.

\newcommand{\marginlist}[1]{
\sidebar{
\begin{itemize}{\usecounter{itemloopcounter}}
        \foreach \cond in {1,...,\value{CountItems}}
        {
            \stepcounter{itemloopcounter}
            \item[\roman{itemloopcounter})] \csname conditem\roman{itemloopcounter}\endcsname
        }
    \end{itemize}
    \setcounter{itemloopcounter}{0}
}
}

但是,此时,我必须在我希望列表出现的每个页面上手动运行此命令;如果我随后在两个实例之间添加新内容/删除旧内容,这可能会很烦人。\边距列表因为我可能必须找到新的地方来执行命令的后一个实例,以便它位于正确的页面上(左侧或右侧)。这不是什么大问题,但在编辑过程中可能会被忽略。我有点不知道下一步该去哪里才能实现我想要的自动化类型。

我不太熟悉 tex 的内部工作原理(这可能是我深入研究过的最深的一次),所以我尝试了一下,并假设也许命令\侧边栏{}用途\这一页为了弄清楚在哪里构建环境;我在本地(暂时)更改了\这一页在我的\边距列表命令,希望能够欺骗 tex,让其认为该命令是在不同的页面上执行的,但遗憾的是,tex 似乎比这更聪明。

如能就如何实现这一目标提供任何指点,我们将不胜感激。

答案1

\AtBeginShipout为了实现此自动化,您需要自动将列表添加到每个页面,您可以使用阿特别格什包。(原始 TeX\shipout用于构建 (La)TeX 生成的每个页面;请参阅关于 \shipout更多细节。)

下面的代码可以实现你想要的功能LaTeX3 序列存储侧边栏条目列表。我没有使用你的代码,部分原因是你没有提供最小工作示例但主要是因为我认为LaTeX3为完成这类事情提供了更好的编程接口。

在使用方面,您需要知道的只是命令\AddListEntry,该命令用于将列表条目添加到侧边栏。使用此命令,下面 MWE 的第四页顶部如下所示:

在此处输入图片描述

完整代码如下:

\documentclass[a4paper, twoside]{memoir}
\usepackage{lipsum}

\usepackage{expl3}
% track the section of the current list, resetting when section changes
\newcounter{listsection}[section]

\ExplSyntaxOn
\seq_new:N \l_list_entries_seq% holds the sequence of sidebar entries
\int_new:N \l_list_page_int% page number of first entry in section

% add the current side list to the sidebar if it is non-empty and
% the page number has the same parity as \l_list_page_int
\newcommand\PrintPageList{
  \seq_if_empty:NF \l_list_entries_seq
  { % only print the list if it is non-empty
    \int_if_even:nT { \thepage - \int_use:N \l_list_page_int }
    { % if page number has same parity as list start page
      \sidebar{
        \begin{itemize}
          \item\seq_use:Nn \l_list_entries_seq {\item}
        \end{itemize}
      }
    }
  }
}

% reset the sidebar list - not strictly necessary as the list resets
% automatically but this gives a way of manually resetting the list
\newcommand\ResetList
{
    \seq_clear:N \l_list_entries_seq
}

% add a sidebar list entry
\newcommand\AddListEntry[1]
{
    % reset the sidebar list if the section has changed
    \int_compare:nT { \arabic{section} != \arabic{listsection}}
    {
        \ResetList
    }
    \seq_if_empty:NT \l_list_entries_seq {
        % record the starting page if sequence is empty
        \int_set:Nn \l_list_page_int {\thepage}
        % set listsection to reset the list in a new section
        \setcounter{listsection} {\arabic{section}}
    }
    \seq_put_right:Nn \l_list_entries_seq {#1}
}
\ExplSyntaxOff

% add the list to every page
\usepackage{atbegshi}
\AtBeginShipout{\PrintPageList}

\begin{document}

  \chapter{First chapter}
  \section{First section}

   \AddListEntry{One: $1$}
   \lipsum

   \AddListEntry{Two $2$}
   \lipsum

   \AddListEntry{Three $3$}
   \lipsum

   \section{Second section}

   \AddListEntry{Four $4$}
   \lipsum

   \AddListEntry{Five $5$}
   \lipsum

\end{document}

代码中有一些注释解释了发生了什么。主要思想是该\AddListEntry命令将新的列表条目添加到序列中\l_list_entries_seq。在执行此操作之前,它会检查新部分是否已开始,如果是,则重置列表。此宏还会跟踪部分中第一个列表条目的页码和部分编号。

另一个主要命令是\PrintPageList,由于 ,所以它在每个页面上使用\AtBeginShipout{\PrintPageList}\PrintPageList检查当前页码与第一个列表条目的页码的奇偶性,如果奇偶性和\l_list_entries_seq不为空,则插入一个\sidebar列表。

相关内容