La parte de la versión A en el siguiente ejemplo se define header/footer
mediante macros del paquete fancyhdr
.
Aunque esta versión es viable, es un logro incómodo porque la misma parte del código ( \ifnum...
) se escribe dos veces.
Excepto el argumento opcional n.º 2, todo el resto del código es exactamente igual. Para mejorarlo, probé la versión B a continuación, pero no funciona en absoluto.
Será terrible, especialmente cuando la misma parte del código sea grande.
Entonces, para resumir, ¿existe una mejor manera de manejar argumentos opcionales (estar allí o no) para evitar código duplicado pesado?
\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}
Respuesta1
Creo que no es útil intentar encajar una sintaxis incómoda en un comando como ese.
Es más gratificante dedicar un poco más de tiempo a idear una sintaxis más amigable. aqui te propongo
\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>,
}
Solo se debe utilizar uno entre head
o en una llamada de .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}
Para responder a su pregunta: use una macro para el código duplicado.
\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}
Túpodríareemplace la definición aquí con
\ExplSyntaxOn
\NewDocumentCommand{\firstpage}{momm}
{
\exp_last_unbraced:Nf #1 \IfNoValueTF{#2}{}{[#2]}
{
\int_compare:nTF { \value{page}=1 } { #3 } { #4 }
}
}
\ExplSyntaxOff
pero no es algo que haría yo mismo. El código \IfNoValueTF{#2}{}{[#2]}
se puede reemplazar de manera más sencilla con \IfValueT{#2}{[#2]}
.
Respuesta2
Para el ejemplo específico, \thispagestyle
probablemente sería mejor simplemente usarlo en la primera página, pero para la pregunta general, puede evitar el escaneo previo de los argumentos hasta después de las pruebas de argumentos opcionales, y una macro auxiliar puede evitar la duplicación de código:
\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}