我的大多数页面上都有一些段落编号。
如果当前页面包含段落编号 1、2、3,我想在页首写上“(1-3)”。
是否可以读出每页的第一个和最后一个标签页(使用 zref?我真的不了解这个包。)
\documentclass[fontsize=9pt, paper=a5,
twoside, numbers=enddot,headsepline,plainheadsepline,
]{scrreprt}
\usepackage{marginnote}
% \usepackage[savepos,totpages,titleref,dotfill,counter,user]{zref} % ?
% Paragraph numbers
\newcounter{parnumber}
\newcommand\parnum[1][\theparnumber]{%
\leavevmode%
\refstepcounter{parnumber}%
\marginnote{\theparnumber\label{pn:#1}}% Label
}
% Layout
\usepackage[automark]{scrlayer-scrpage}[]
\ohead*{\marginnote{(xxx-yyy)}% range of parnums
\ifstr{\headmark}{}{\rightbotmark}{\headmark}% titles in head
}
\usepackage{blindtext}
\begin{document}
\chapter{First Page: The Range of parnums should be (1-3) = (xxx-yyy)}
\parnum[TPy]
Theorem of Pythagoras \par
\parnum
\blindtext \par
Text without parnum.
\parnum Text.
\chapter{Next Page: The Range of parnums should be (4-5)=(xxx-yyy)}
\parnum Text.
\parnum[mylabel] Text.
\chapter{Only one parnum on this page: The Range of parnums should be (6)=(xxx-yyy)}
\parnum Text.
\end{document}
答案1
下面的代码应该可以满足您的要求(感谢 Ulrike Fischer 的有用评论!)。我使用了(n--p)
style 作为范围,但(n-p)
如果您愿意,可以很容易地切换到 style 或类似的东西(只需查看\__cis_output_parnum_range:nn
:这是对 parnum 信息进行格式化的函数;对于这种更改,应该很容易进行修改)。
\documentclass[fontsize=9pt, paper=a5, twoside, numbers=enddot,
headsepline,plainheadsepline]{scrreprt}
\usepackage{zref}
\usepackage{multicol}
\usepackage{blindtext}
\usepackage{lipsum}
\usepackage{marginnote}
\usepackage{etoolbox}
\usepackage{xparse}
\ExplSyntaxOn
% ****************************************************************************
% * LaTeX3 bindings to macros from the zref package *
% ****************************************************************************
% Extract prop #2 recorded for ref cis-parnum-label-#1 (#1 corresponds to a
% parnum)
\cs_new:Npn \cis_extract_prop:nn #1#2
{
% \zref@extract is expandable
\use:c { zref@extract } { cis-parnum-label-#1 } {#2}
}
\cs_generate_variant:Nn \cis_extract_prop:nn { V }
\cs_new_protected:Npn \cis_ref_used:n #1
{
\use:c { zref@refused } { cis-parnum-label-#1 }
}
\cs_generate_variant:Nn \cis_ref_used:n { V }
\prg_new_conditional:Npnn \cis_if_parnum_ref_defined:n #1 { p }
{
% \zref@ifrefundefined is expandable
\use:c { zref@ifrefundefined } { cis-parnum-label-#1 }
{ \prg_return_false: }
{ \prg_return_true: }
}
\prg_generate_conditional_variant:Nnn \cis_if_parnum_ref_defined:n { V } { p }
% ****************************************************************************
% * Main code for generation of parnum ranges *
% ****************************************************************************
% Most important variable: in the \AtBeginDocument hook, we are going to fill
% it to give the parnum range for each page that has at least one parnum. Keys
% in this property list are page numbers (in decimal notation); values have
% the form '{first}{last}' (without quotes). E.g., {2}{5} or {6}{6}. If a page
% contains no parnum at all, the property list will have no key equal to the
% corresponding page number.
\prop_new:N \g_cis_parnums_for_page_prop
\int_new:N \l__cis_fpfep_parnum_int
\int_new:N \l__cis_fpfep_page_in_ref_int
\int_new:N \l__cis_fpfep_last_page_seen_int
\int_new:N \l__cis_fpfep_first_parnum_for_page_int
\int_new:N \l__cis_fpfep_last_parnum_for_page_int
\cs_generate_variant:Nn \int_compare:nNnF { VN }
\cs_generate_variant:Nn \int_compare:nNnF { VNV }
% #1: first labelled parnum in document (if any)
\cs_new_protected:Npn \__cis_find_parnums_for_each_page:n #1
{
\int_set:Nn \l__cis_fpfep_parnum_int {#1} % next parnum to examine
\int_set:Nn \l__cis_fpfep_last_page_seen_int { -1000 } % sentinel value
\bool_while_do:nn
{ \cis_if_parnum_ref_defined_p:V \l__cis_fpfep_parnum_int }
{
% Get the page for parnum \l__cis_fpfep_parnum_int
\int_set:Nn \l__cis_fpfep_page_in_ref_int
{ \cis_extract_prop:Vn \l__cis_fpfep_parnum_int { page } }
\cis_ref_used:V \l__cis_fpfep_parnum_int
\int_compare:VNVF
\l__cis_fpfep_last_page_seen_int = \l__cis_fpfep_page_in_ref_int
{
% The parnum corresponding to the currently examined ref is on a
% different page than the previously-examined parnum, therefore
% we now have all the info for the last seen page -> store it.
\__cis_store_parnums_if_real_page:VVV
\l__cis_fpfep_last_page_seen_int
\l__cis_fpfep_first_parnum_for_page_int
\l__cis_fpfep_last_parnum_for_page_int
\int_set_eq:NN \l__cis_fpfep_first_parnum_for_page_int
\l__cis_fpfep_parnum_int
}
% Will be overwritten if there are more parnums on the same page
\int_set_eq:NN \l__cis_fpfep_last_parnum_for_page_int
\l__cis_fpfep_parnum_int
\int_set_eq:NN \l__cis_fpfep_last_page_seen_int
\l__cis_fpfep_page_in_ref_int
\int_incr:N \l__cis_fpfep_parnum_int
}
% Store info for the last page containing a labelled parnum
\__cis_store_parnums_if_real_page:VVV
\l__cis_fpfep_last_page_seen_int
\l__cis_fpfep_first_parnum_for_page_int
\l__cis_fpfep_last_parnum_for_page_int
}
% #1: page number or sentinel value (-1000) meaning “do nothing”
% #2: first parnum on this page
% #3: last parnum on this page
\cs_new_protected:Npn \__cis_store_parnums_if_real_page:nnn #1#2#3
{
\int_compare:nNnF {#1} = { -1000 }
{
\prop_gput:Nnn \g_cis_parnums_for_page_prop {#1} { {#2} {#3} }
}
}
\cs_generate_variant:Nn \__cis_store_parnums_if_real_page:nnn { VVV }
\cs_generate_variant:Nn \__cis_output_parnum_range:nn { VV }
\tl_new:N \g__cis_oprfp_first_parnum_tl
\tl_new:N \g__cis_oprfp_last_parnum_tl
\cs_new_protected:Npn \cis_output_parnums_range_for_page:n #1
{
\prop_get:NnNTF \g_cis_parnums_for_page_prop {#1} \l_tmpa_tl
{
\seq_set_split:NnV \l_tmpa_seq { } \l_tmpa_tl
\seq_pop_left:NN \l_tmpa_seq \l_tmpa_tl
\seq_pop_left:NN \l_tmpa_seq \l_tmpb_tl
\tl_gset_eq:NN \g__cis_oprfp_first_parnum_tl \l_tmpa_tl
\tl_gset_eq:NN \g__cis_oprfp_last_parnum_tl \l_tmpb_tl
\__cis_output_parnum_range:VV \g__cis_oprfp_first_parnum_tl
\g__cis_oprfp_last_parnum_tl
}
{
% In case there is no parnum at all on a page, the OP wants the page
% header to hold only the last parnum seen (not the last parnum info,
% i.e.: he wants only a number, not a range). Hence "last, last"
% instead of "first, last" here:
\__cis_output_parnum_range:VV \g__cis_oprfp_last_parnum_tl
\g__cis_oprfp_last_parnum_tl
}
}
% Write formatted information for the specified parnum range.
%
% #1: first parnum of range
% #2: last parnum of range
\cs_new_protected:Npn \__cis_output_parnum_range:nn #1#2
{
\tl_if_eq:nnTF {#1} {#2}
{
\tl_if_blank:nF {#1} { (#1) }
}
{
(#1--#2)
}
}
\cs_generate_variant:Nn \cis_output_parnums_range_for_page:n { x }
% Fully expands the argument (which should be a page number)
\NewDocumentCommand \parnumrangeinpage { m }
{
\cis_output_parnums_range_for_page:x {#1}
}
% 1 is the number of the first parnum to consider as possibly existing in the
% document. \__cis_find_parnums_for_each_page:n looks for refs corresponding
% to parnums 1, 2, ... The smallest integer in this scanning process for which
% no ref is found in the .aux file is considered to be one past the last
% parnum.
\AtBeginDocument { \__cis_find_parnums_for_each_page:n { 1 } }
\ExplSyntaxOff
\makeatletter
\zref@newlist{cisparnumlist}
\zref@addprop{cisparnumlist}{page}
% Paragraph numbers. Must be strictly increasing, and the numbering should
% have no holes.
\newcounter{parnumber}
\newcommand*\parnum[1][]{%
\leavevmode
\refstepcounter{parnumber}%
\ifblank{#1}{}{\label{#1}}% regular LaTeX label for the numbered paragraph
\marginnote{%
\theparnumber
% Set our special zref label for parnums. From the set of all such labels,
% we can deduce in the \AtBeginDocument hook the parnum range for each
% page.
\zref@labelbylist{cis-parnum-label-\the\value{parnumber}}%
{cisparnumlist}}%
}
\makeatother
% Allow easy on/off switching of parnum info in headers
\newtoggle{parnumsinheader}
\newcommand*{\parnumsinheaderon}{\toggletrue{parnumsinheader}}
\newcommand*{\parnumsinheaderoff}{\togglefalse{parnumsinheader}}
\parnumsinheaderon % Show parnum info in headers by default
% Set up the page headers
\usepackage[automark]{scrlayer-scrpage}
\ohead*{%
\iftoggle{parnumsinheader}{%
\marginnote{\parnumrangeinpage{\thepage}}% range of parnums
}{}%
\ifstr{\headmark}{}{\rightbotmark}{\headmark}% chapter or section title, etc.
}
\begin{document}
\chapter{Three parnums here}
\parnum[TPy]
Theorem of Pythagoras \par
\parnum
\blindtext \par
Text without parnum.
\parnum Text.
The theorem of Pythagoras corresponds to parnum~\ref{TPy} on
page~\pageref{TPy}.
\chapter{Two parnums here}
\parnum Text.
\parnum[mylabel] Text.
\chapter{Only one parnum here}
\parnum Text.
\newpage % Test repeating of last parnum info when there is no parnum on the
% current page.
\chapter{Test with parnums deeply embedded in \TeX\ lists}
\noindent
{\centering
\begin{minipage}{\linewidth}
\begin{multicols}{2}
\parnum Text.
\lipsum[1-3]
\parnum Text.
\end{multicols}
\end{minipage}
}
\newpage
\lipsum[1-2]
\end{document}