我正在写一份文件,其中每个段落都进行了分类。我将类别编码为一个简单的数字变量: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}