是或不是 - 巨集定義中的可選參數

是或不是 - 巨集定義中的可選參數

以下範例中的版本 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>,
}

在 的呼叫中只能使用heador之一。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}

相關內容