以下範例中的版本 A 部分是header/footer
透過套件中的巨集定義的fancyhdr
。
雖然這個版本是可行的,但這是一個尷尬的成就,因為 code() 的同一部分\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
or之一。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}