嵌套 xparse 宏

嵌套 xparse 宏

我经常定义一个带有各种可选参数的宏,例如

\NewDocumentCommand{\GenericWebSite}{s O{blue} o m e_}{<code>}

并希望定义此宏的一个小变体,而不重复所有<code>\GenericWebSite。因此,例如,我想要定义

\NewDocumentCommand{\ImportantWebSite}{s o o m e_}{%
    \fcolorbox{red}{gray!20}{<code>}%
}

蛮力方法(如下面的 MWE 所示)效果很好,但肯定有更简单的方法来做到这一点。

第一行是 的各种用途的输出\GenericWebSite,第二行是传入\ImportantWebSite相同参数的 的调用。

在此处输入图片描述

笔记:

  • \GenericWebSite这个问题不是关于测试用例中定义的具体功能,而是一般的在 MWE 中定义一个新的xparse宏,\ImportantWebSite以便它可以利用现有的宏(\GenericWebSite在本例中,该宏已经定义)。
  • 一个选项是传递键值标志,\GenericWebSite以便单身的宏可以提供所有功能。虽然在这个特定示例中,这当然是可行的,但我更愿意保留单独的宏,因为在实际用例中,我需要许多变体。

参考:

代码:

\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}

答案1

您应该根据内部命令来定义这两个命令:

\documentclass{article}
\usepackage{amsmath}
\usepackage{xcolor}
\usepackage{xparse}
\usepackage{hyperref}

\ExplSyntaxOn
\NewDocumentCommand{\GenericWebSite}{sO{blue}mO{\c_grill_website_default_tl}e{+}}
 {
  \grill_website:nnnnnN
   { #1 }
   { #2 }
   { #3 }
   { #4 }
   { #5 }
   \grill_website_generic:nn
 }
\NewDocumentCommand{\ImportantWebSite}{sO{}mO{\c_grill_website_default_tl}e{+}}
 {
  \grill_website:nnnnnN
   { #1 }
   { #2 }
   { #3 }
   { #4 }
   { #5 }
   \grill_website_important:nn
 }

\tl_const:Nn \c_grill_website_default_tl { http://tex.stackexchange.com }

\cs_new_protected:Nn \grill_website_generic:nn
 {
  \group_begin:
  \leavevmode
  \color{#1}
  #2
  \group_end:
 }
\cs_new_protected:Nn \grill_website_important:nn
 {
  \fcolorbox{red}{gray!20}
   {
    \tl_if_empty:nF { #1 } { \color{#1} }
    #2
   }
 }

\cs_new_protected:Nn \grill_website:nnnnnN
 {
  % #1 = *
  % #2 = optional color (for generic)
  % #3 = text to display
  % #4 = web site to link 
  % #5 = subscript
  % #6 = wrapper
  #6 { #2 }
   {
    \bool_if:nTF { #1 }
     {% no need to link web site as it is already a link
      \textnormal{#3}
     }
     {
      \href{#4}{\textnormal{#3}}
     }
    \tl_if_novalue:nF { #5 }
     {
      \mode_if_math:TF { \sb } { \textsubscript } {\textnormal{Note: #5}}
     }
   }
 }
\ExplSyntaxOff

\begin{document}

%% Testing various uses of \GenericWebSite
\GenericWebSite{TeX.SE}
\GenericWebSite[red]{TeX.SE}
\GenericWebSite*[black]{\href{http://www.google.com}{The Google}}+4
$\GenericWebSite*[black]{\href{http://www.google.com}{The Google}}+4$

\medskip

%% Testing various uses of \ImportantWebSite
\ImportantWebSite{TeX.SE}
\ImportantWebSite[red]{TeX.SE}
\ImportantWebSite*[black]{\href{http://www.google.com}{The Google}}+4
$\ImportantWebSite*[black]{\href{http://www.google.com}{The Google}}+4$

\end{document}

我改变了第二个可选参数的位置,因为两个连续的参数应该相互依赖,而你的参数是独立的。

注释+仅出于技术原因。我会使用键值语法。

在此处输入图片描述

相关内容