以下示例中的版本 A 部分是header/footer
通过包中的宏来定义的fancyhdr
。
虽然这个版本是可行的,但是这是一个令人尴尬的成就,因为同一部分代码(\ifnum...
)被写了两次。
除了可选参数 #2 之外,其他代码完全相同。为了改进它,我尝试了下面的版本 B,但它根本不起作用。
尤其是当同一部分代码很大时,这将是可怕的。
因此,总而言之,是否有更好的方法来处理可选参数(存在或不存在)以避免大量重复代码。
\documentclass{article}
\usepackage{geometry,fancyhdr,xparse}
\geometry{showframe}
\begin{document}
first page\par\vspace{80em} second page
\pagestyle{fancy}
\fancyhf{}
%Version A: workable %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\NewDocumentCommand{\firstpage}{momm}{%
\IfNoValueTF{#2}
{#1{%
\ifnum\value{page}=1
#3% content of header/footer only at the first page
\else
#4% content of header/footer at the rest pages
\fi
}
}
{#1[#2]% the only diferrence between the two branches of \IfNoValueTF is, whether introducing the optional argument #2
{%
\ifnum\value{page}=1
#3% content of header/footer only at the first page
\else
#4% content of header/footer at the rest pages
\fi
}
}
}%\firstpage
% Test
\firstpage{\fancyhead}[c]{only at the first page}{at rest pages}
\firstpage{\rhead}{r first}{r rest}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Version B: not workable %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\NewDocumentCommand{\firstpageA}{momm}{%
#1 \IfNoValueTF{#2}{}{[#2]}
\ifnum\value{page}=1
#3% content of header/footer only at the first page
\else
#4% content of header/footer at the rest pages
\fi
}%\firstpageA
% Test
\firstpageA{\fancyhead}[c]{only at the first page}{at rest pages}
\firstpageA{\rhead}{r first}{r rest}
\end{document}
答案1
我认为尝试将不合适的语法融入这样的命令是没有用的。
花点时间设计一个更友好的语法会更有价值。我建议
\sethf{
head = <contents of all headers, except possibly the first>,
foot = <contents of all footers, except possibly the first>,
pos = <l|c|r>,
first = <possible exception for first header/footer>,
}
在 的调用中,只能使用head
或中的一个。foot
\sethf
\documentclass{article}
\usepackage{fancyhdr,xparse}
\usepackage[paper=a6paper]{geometry} % smaller pictures
\usepackage{lipsum} % mock text
\pagestyle{fancy}
\fancyhf{}
\ExplSyntaxOn
\NewDocumentCommand{\sethf}{m}
{
\tl_clear:N \l__lyl_hf_pos_tl
\tl_clear:N \l__lyl_hf_first_tl
\tl_clear:N \l__lyl_hf_headfoot_tl
\keys_set:nn { lyl/hf } { #1 }
\lyl_hf_set:
}
\keys_define:nn { lyl/hf }
{
head .code:n = \__lyl_hf_aux:Nn \fancyhead { #1 },
foot .code:n = \__lyl_hf_aux:Nn \fancyfoot { #1 },
pos .tl_set:N = \l__lyl_hf_pos_tl,
first .tl_set:N = \l__lyl_hf_first_tl,
}
\tl_new:N \l__lyl_hf_headfoot_tl
\cs_new_protected:Nn \__lyl_hf_aux:Nn
{
\cs_set_eq:NN \__lyl_hf_temp:w #1
\tl_set:Nn \l__lyl_hf_headfoot_tl { #2 }
}
\cs_new_protected:Nn \lyl_hf_set:
{
\tl_if_empty:NT \l__lyl_hf_first_tl
{
\tl_set_eq:NN \l__lyl_hf_first_tl \l__lyl_hf_headfoot_tl
}
\__lyl_hf_set:NVVV
\__lyl_hf_temp:w % \fancyhead or \fancyfoot
\l__lyl_hf_pos_tl % position
\l__lyl_hf_first_tl % first page
\l__lyl_hf_headfoot_tl % other pages
}
\cs_new_protected:Nn \__lyl_hf_set:Nnnn
{
#1 [ #2 ] { \int_compare:nTF { \value{page} = 1 } { #3 } { #4 } }
}
\cs_generate_variant:Nn \__lyl_hf_set:Nnnn { NVVV }
\ExplSyntaxOff
\sethf{
head = other pages,
first = first page,
pos = c,
}
\sethf{pos = r, foot=\thepage}
\begin{document}
\lipsum[1-2]
\end{document}
回答您的问题:使用宏来获取重复的代码。
\documentclass{article}
\usepackage{fancyhdr,xparse}
\usepackage[paper=a6paper]{geometry} % smaller pictures
\usepackage{lipsum} % mock text
\pagestyle{fancy}
\fancyhf{}
\NewDocumentCommand{\firstpage}{momm}{%
\IfNoValueTF{#2}
{\setfirstpage{#1}{#3}{#4}}
{\setfirstpage{#1[#2]}{#3}{#4}}%
}
\NewDocumentCommand{\setfirstpage}{mmm}
{
#1{\ifnum\value{page}=1 #2\else #3\fi}
}
\firstpage{\fancyhead}[c]{first page}{other pages}
% can also be \firstpage{\chead}{first page}{other pages}
\begin{document}
\lipsum[1-2]
\end{document}
你可能用以下定义替换此处
\ExplSyntaxOn
\NewDocumentCommand{\firstpage}{momm}
{
\exp_last_unbraced:Nf #1 \IfNoValueTF{#2}{}{[#2]}
{
\int_compare:nTF { \value{page}=1 } { #3 } { #4 }
}
}
\ExplSyntaxOff
但这不是我自己会做的事情。代码\IfNoValueTF{#2}{}{[#2]}
可以更简单地替换为\IfValueT{#2}{[#2]}
。
答案2
对于具体的例子,\thispagestyle
在第一页简单地使用可能会更好,但对于一般的问题,你可以避免预扫描参数,直到可选参数的测试之后,而辅助宏可以避免代码重复:
\documentclass{article}
\usepackage{geometry,fancyhdr,xparse}
\geometry{showframe}
\begin{document}
first page\par\vspace{80em} second page
\pagestyle{fancy}
\fancyhf{}
\def\fpageTF#1#2#3{#1{\ifnum\value{page}=1 #2\else #3\fi}}
\NewDocumentCommand{\firstpage}{mo}{%
\IfNoValueTF{#2}{\fpageTF{#1}}{\fpageTF{#1[#2]}}}
% Test
\firstpage{\fancyhead}[c]{only at the first page}{at rest pages}
\firstpage{\rhead}{r first}{r rest}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{document}