每页上的最高变量值

每页上的最高变量值

我正在写一份文件,其中每个段落都进行了分类。我将类别编码为一个简单的数字变量:1、2、3 等。在每一页上,我都想知道并尽可能显示页面上任何内容的最高类别值。我使用一个简单的计数器,并将每个段落包装在一个宏中,如果段落类别高于迄今为止遇到的任何类别,则该宏会更新计数器值。我使用 everypage 或 everyshi 重置每一页的计数器。到目前为止,它几乎可以正常工作。

另外,我真的不想让段落跨页。当我设置

\widowpenalties 1 10000

尝试执行此操作时,类别计数器的行为非常奇怪。这种奇怪的行为让我很头疼。

页面类别计数器总是会将两个段落重置为下一页,这太晚了。我完全搞不懂。有人能解释一下吗?

我也很乐意接受有关以其他方式实现我的目标的建议。

这是一个不是很简单的工作示例。它有 9 页长。开头有四页显示了未设置 widowpenalties 的行为。然后是分隔页,之后是另外四页相同的页面,其中 widowpenalties 调高到 10,000。

运行代码时,每个段落都标有两个数字,如 2-1。第一个数字是该页面上迄今为止遇到的最高类别,第二个数字是该段落的类别。要查看奇怪的行为,请注意第 2 页,您会看到前两个段落标记为 1-1,但在第 7 页,您会看到完全相同的两个段落标记为 3-1。


    \documentclass{article}

    \usepackage{xifthen}
    \usepackage{lipsum}
    \usepackage{etoolbox}
    \usepackage{everypage}


    \newcommand\settext[3]{\csdef{#1#2}{#3}}
    \newcommand\gettext[2]{\csuse{#1#2}}

    \newcounter{pageCategoryCntr}
    \setcounter{pageCategoryCntr}{1}
    \AddEverypageHook{\setcounter{pageCategoryCntr}{1}}
    %\zmakeperpage{pageCategoryCntr}
    %\EveryShipout{\setcounter{pageCategoryCntr}{1}}

    \newcommand{\category}[2]{
      \ifthenelse{#1 > \value{pageCategoryCntr}}{
        \setcounter{pageCategoryCntr}{#1}
      }{}
      \thepageCategoryCntr\ - #1 -
      #2
    }

    \begin{document}
    \category{1}{\lipsum[2]}

    \category{1}{\lipsum[3]}

    \category{1}{\lipsum[2]}

    \category{3}{\lipsum[3]}

    \category{1}{\lipsum[2]}

    \category{1}{\lipsum[3]}

    \category{1}{\lipsum[4]}

    \category{1}{\lipsum[5]}

    \category{1}{\lipsum[2]}

    \category{1}{\lipsum[3]}

    \category{1}{\lipsum[2]}

    \category{1}{\lipsum[3]}

    \category{3}{\lipsum[2]}

    \category{1}{\lipsum[3]}

    \category{1}{\lipsum[4]}

    \category{1}{\lipsum[5]}

    \newpage
    \widowpenalties 1 10000
    \clubpenalties 1 10000
    \raggedbottom
    Now another copy of the same but we set the widowpenalties and
    clubpenalties to avoid breaking paragraphs across pages.
    \newpage
    \category{1}{\lipsum[2]}

    \category{1}{\lipsum[3]}

    \category{1}{\lipsum[2]}

    \category{3}{\lipsum[3]}

    \category{1}{\lipsum[2]}

    \category{1}{\lipsum[3]}

    \category{1}{\lipsum[4]}

    \category{1}{\lipsum[5]}

    \category{1}{\lipsum[2]}

    \category{1}{\lipsum[3]}

    \category{1}{\lipsum[2]}

    \category{1}{\lipsum[3]}

    \category{3}{\lipsum[2]}

    \category{1}{\lipsum[3]}

    \category{1}{\lipsum[4]}

    \category{1}{\lipsum[5]}
    \end{document}

答案1

这是辅助文件解决方案。有趣的是,您至少需要\leavevmode将其放在\protected@write段落内部,而不是段落前面。

我确实只需要一个计数器(CategoryCntr),但使用\setcounter更容易理解。

\documentclass{article}

%\usepackage{xifthen}
\usepackage{lipsum}
%\usepackage{etoolbox}
%\usepackage{everypage}

\newcommand\settext[3]{\csdef{#1#2}{#3}}
\newcommand\gettext[2]{\csuse{#1#2}}

\newcounter{CategoryMax}% used to compute max category per page
\newcounter{CategoryCntr}% increment every \category
\newcounter{CategoryPage}% used instead of the page counter

\newcommand{\newcategory}[3]{% #1 = index, #2 = category, #3 = page
  \expandafter\gdef\csname CategoryPage#1\endcsname{#3}% save page per index
  \ifnum\value{CategoryPage}=#3\relax
    \ifnum\value{CategoryMax}<#2\relax \setcounter{CategoryMax}{#2}\fi
  \else
    \ifnum\value{CategoryPage}>0\relax
      \expandafter\xdef\csname CategoryMax\theCategoryPage\endcsname{\theCategoryMax}% save max category
    \fi
    \setcounter{CategoryMax}{#2}%
    \setcounter{CategoryPage}{#3}%
  \fi
}
\AtBeginDocument{% save last page 
  \ifnum\value{CategoryPage}>0\relax
    \expandafter\xdef\csname CategoryMax\theCategoryPage\endcsname{\theCategoryMax}%
  \fi
}
\makeatletter
\newcommand{\category}[2]{% #1 = category, #2 = text
  \par\leavevmode
  \stepcounter{CategoryCntr}%
  \protected@write\@auxout{}{\string\newcategory{\theCategoryCntr}{#1}{\thepage}}%
  %\protected@write\@auxout{\let\arabic\relax}{\string\newcategory{\theCategoryCntr}{#1}{\arabic{page}}}%
  \@ifundefined{CategoryPage\theCategoryCntr}{?? - #1 - #2}{%
    \setcounter{CategoryPage}{\csname CategoryPage\theCategoryCntr\endcsname}%
    {\csname CategoryMax\theCategoryPage\endcsname} - #1 - #2
  }%
}
\makeatother

\begin{document}
\widowpenalties 1 10000
\clubpenalties 1 10000
\raggedbottom

\category{1}{\lipsum[2]}

\category{1}{\lipsum[3]}

\category{1}{\lipsum[2]}

\category{3}{\lipsum[3]}

\category{1}{\lipsum[2]}

\category{1}{\lipsum[3]}

\category{1}{\lipsum[4]}

\category{1}{\lipsum[5]}

\category{1}{\lipsum[2]}

\category{1}{\lipsum[3]}

\category{1}{\lipsum[2]}

\category{1}{\lipsum[3]}

\category{3}{\lipsum[2]}

\category{1}{\lipsum[3]}

\category{1}{\lipsum[4]}

\category{1}{\lipsum[5]}

\end{document}

答案2

这是一个解决方案。

\documentclass{article}
\usepackage{lipsum}
\usepackage{everypage}

\newcounter{pageCategoryCntr}
\AddEverypageHook{\setcounter{pageCategoryCntr}{1}}

\newcommand{\category}[2]{% 
\par \penalty-100\begingroup %from needspace package
\setbox0=\vbox{#2}%
\ifdim\ht0>\dimexpr\pagegoal-\pagetotal\relax
    \break
\fi\endgroup
\ifnum #1 > \value{pageCategoryCntr}
    \setcounter{pageCategoryCntr}{#1}%
\fi  
\thepageCategoryCntr\ - #1 - #2
}

\begin{document}

\category{1}{\lipsum[2]}

\category{1}{\lipsum[3]}

\category{1}{\lipsum[2]}

\category{3}{\lipsum[3]}

\category{1}{\lipsum[2]}

\category{1}{\lipsum[3]}

\category{1}{\lipsum[4]}

\category{1}{\lipsum[5]}

\category{1}{\lipsum[2]}

\category{1}{\lipsum[3]}

\category{1}{\lipsum[2]}

\category{1}{\lipsum[3]}

\category{3}{\lipsum[2]}

\category{1}{\lipsum[3]}

\category{1}{\lipsum[4]}

\category{1}{\lipsum[5]}

\end{document}

相关内容