I often have a macro defined with with various optional parameters such as
\NewDocumentCommand{\GenericWebSite}{s O{blue} o m e_}{<code>}
and want to define a small variant of this macro, without duplicating all the <code> of the \GenericWebSite macro. So, for instance, I want to define
\NewDocumentCommand{\ImportantWebSite}{s o o m e_}{%
\fcolorbox{red}{gray!20}{<code>}%
}
The brute force method (illustrated in the MWE below) works fine, but there must be an easier way to do this.
The first line is the output of various uses of \GenericWebSite and the second line is the invocation of \ImportantWebSite passed in with the same parameters.
Notes:
- This question isn't about the specific functionality of the
\GenericWebSitedefined in the test case, but how, in general, to define a newxparsemacro,\ImportantWebSitein the MWE, so that it can take advantage of an existing macro,\GenericWebSitein this case, that is already defined. - One option would be to pass in key-value flags to
\GenericWebSiteso that the single macro can provide all the functionality. While in this particular example, this is certainly doable, I would prefer to keep separate macros as in may actual use case I need many variants.
References:
- How to \let an xparse defined command?,
- Optional Parameters in xparse: \IfBooleanTF vs \IfNoValueTF
- Xparse's new e-type argument (replacement for k-type argument)
- How to create internet link in PDF?
Code:
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\usepackage{xcolor}
\usepackage{hyperref}
\makeatletter
\newcommand{@DefaultWebLink}{http://tex.stackexchange.com}
\NewDocumentCommand{\GenericWebSite}{
s% = text in #4 is already a link
O{blue}% #2 = color to use for text
o% #3 = web site to link to (Defaults to @DefaultWebLink)
m% #4 = text to display
e_% #5 = optional subscript
}{%
\begingroup%% Keep \color{} change local
\color{#2}%
\IfBooleanTF{#1}{% no need to link web site as it is already a link
\textnormal{#4}
}{%
\IfNoValueTF{#3}{% web site to link to not provided, so use default
\href{@DefaultWebLink}{\textnormal{#4}}%
}{% web site to link to provided
\href{#3}{\textnormal{#4}}%
}%
}%
\IfNoValueTF{#5}{}{% Include subscript since it was given
_{Note:,#5}
}%
\endgroup
}
%% Want to make use of \GenericWebSite with some slight modifications
\NewDocumentCommand{\ImportantWebSite}{
s% * = text in #4 is already a link
o% #2 = color to use for text <--- NOTE that this does NOT have a default
o% #3 = web site to link to (Defaults to @DefaultWebLink)
m% #4 = text to display
e_% #5 = optional subscript
}{%
\fcolorbox{red}{gray!20}{$
\IfBooleanTF{#1}{%
\IfValueTF{#2}{% #2 given so needs to be passed on
\IfValueTF{#3}{
\IfValueTF{#5}{
\GenericWebSite[#2][#3]{#4}_{#5}
}{
\GenericWebSite[#2][#3]{#4}
}
}{
\IfValueTF{#5}{
\GenericWebSite[#2]{#4}_{#5}
}{
\GenericWebSite[#2]{#4}
}
}
}{% No #2 given, so same as true case above but without the #2
\IfValueTF{#3}{
\IfValueTF{#5}{
\GenericWebSite[#3]{#4}_{#5}
}{
\GenericWebSite[#3]{#4}
}
}{% No #2 and #3 given, so same as true case above but without the #2 and #3
\IfValueTF{#5}{
\GenericWebSite{#4}_{#5}
}{
\GenericWebSite{#4}
}
}
}
}{% same as above but without the * option
\IfValueTF{#2}{% #2 given so needs to be passed on
\IfValueTF{#3}{
\IfValueTF{#5}{
\GenericWebSite[#2][#3]{#4}{#5}
}{
\GenericWebSite[#2][#3]{#4}
}
}{
\IfValueTF{#5}{
\GenericWebSite[#2]{#4}{#5}
}{
\GenericWebSite[#2]{#4}
}
}
}{% No #2 given, so same as true case above but without the #2
\IfValueTF{#3}{
\IfValueTF{#5}{
\GenericWebSite[#3]{#4}{#5}
}{
\GenericWebSite[#3]{#4}
}
}{% No #2 and #3 given, so same as true case above but without the #2 and #3
\IfValueTF{#5}{
\GenericWebSite{#4}{#5}
}{
\GenericWebSite{#4}
}
}
}
}%
$}%
}
\makeatother
\begin{document}
%% Testing various uses of \GenericWebSite
$\GenericWebSite{TeX.SE}$
$\GenericWebSite[red]{TeX.SE}$
$\GenericWebSite*[black]{\href{http://www.google.com}{The Google}}_4$
%% Testing various uses of \ImportantWebSite
\par\medskip
$\ImportantWebSite{TeX.SE}$
$\ImportantWebSite[red]{TeX.SE}$
$\ImportantWebSite*[black]{\href{http://www.google.com}{The Google}}_4$
\end{document}


\letor\patchcmndreplacement for xparse declared commands, but what I mean is that you should not have hudreds of places, just one. you make have lots of \DeclareDocumentcommand\doo{sooomo}{..} but they should be calling as single macro with mandatory argumentspg_core_code_layout_thing{1}{b}{c}{d}{e}and if you decide to redefine that to use\fcolorboxthen all your variants will use the new code. ... – David Carlisle Aug 16 '18 at 20:39s,o,O{},e_etc... – Peter Grill Aug 16 '18 at 20:41*forms and[]optional argument syntax for this reason – David Carlisle Aug 16 '18 at 20:42\makebox[<dimen>][<alignment>]{<text>}. In your case they're completely independent, so the syntax is bad. – egreg Aug 16 '18 at 21:45