带有 if 情况的 NewDocumentCommand 的可选参数

带有 if 情况的 NewDocumentCommand 的可选参数

我有这个命令,我想采用两个可选参数:\pubtitle[title][symbol]{custom}

这是命令(MWE):

\documentclass{article}

\usepackage{xcolor}
\usepackage{fontawesome}

\definecolor{icons}{HTML}{46A247}

\ExplSyntaxOn

\cs_new_protected:Nn \pubtitle_symbolheading:nn
 {
  \group_begin:
  {\large\textcolor{icons}{#1}\hspace{10pt}\textbf{#2}}
  \group_end:
 }

\NewDocumentCommand{\pubtitle}{m}
 {
  \pubtitle_pubtitle:n { #1 }
 }

\cs_new_protected:Nn \pubtitle_pubtitle:n
 {
  \str_case:nnF { #1 }
   {
    {book}{\pubtitle_symbolheading:nn{\faBook}{Book}}
    {article}{\pubtitle_symbolheading:nn{\faFileText}{Article}}
    % other cases
   }
   {% none of the above
    \PackageError{pubtitle}
     {
      Unsupported ~ entry ~ field ~ '#1' ~ \MessageBreak for bibliography}
     {
      Perhaps ~ you ~ meant ~ '\string\pubtitle{custom}'
     }
   }
 }

\ExplSyntaxOff

\begin{document}

\pubtitle{book}

\pubtitle{article}

\pubtitle{invalidArgument}

\end{document}

这将返回“不支持”强制参数的错误。我希望能够在给出\pubtitle_symbolheading:nn强制参数时提供两个可选参数(命令中每个参数一个)custom。MWE 的输出为:

在此处输入图片描述

我想要的是能够使用可选参数更改输出中的粗体文本和符号(但只有当custom作为强制参数给出时才有效)。

我希望能够更改不带符号的标题,即\pubtitle[title]{custom}

答案1

下面提供了两个内部相同的解决方案,但文档界面不同。第一个解决方案,名为 called,\pubtitle使用两个可选参数,后跟一个强制参数。第二个解决方案,名为 called,\Pubtitle使用您在问题中展示的界面,带有一个可选参数,其中两个参数用逗号分隔。

此外,第三个参数将被标准化\str_foldcase:n

\documentclass{article}

\usepackage{xcolor}
\usepackage{fontawesome}

\definecolor{icons}{HTML}{46A247}

\ExplSyntaxOn
\msg_new:nnn { pubtitle } { extraneous-optional }
  {
    \exp_not:N \pubtitle
    only~ accepts~ optional~ arguments~ if~ you~ use~ `custom'~ as~ a~
    mandatory~ argument.
  }
\msg_new:nnn { pubtitle } { missing-optional }
  {
    \exp_not:N \pubtitle
    requires~ two~ optional~ arguments~ if~ you~ use~ `custom'~ as~ a~
    mandatory~ argument.
  }
\msg_new:nnnn { pubtitle } { unsupported-argument }
  { Unsupported~ entry~ field~ `#1'~ for~ bibliography. }
  { Perhaps~ you~ meant~ `\token_to_str:N \pubtitle[<icon>][<text>]{custom}'. }

% document interfaces
\NewDocumentCommand \pubtitle { o o m }
  { \pubtitle_pubtitle:nne {#1} {#2} { \str_foldcase:n {#3} } }
\NewDocumentCommand \Pubtitle { >{\SplitArgument{1}{,}}o m }
  {
    % design decision of ltcmd: unused o-args are not processed by argument
    % processors, so we need to add this processing here
    \IfNoValueTF {#1}
      { \pubtitle_pubtitle:nne {#1} {#1} }
      { \pubtitle_pubtitle:nne #1 }
        { \str_foldcase:n {#2} }
  }

% internal code
\cs_new_protected:Npn \pubtitle_pubtitle:nnn #1#2#3
  {
    \str_case:nnTF {#3}
      {
        { book }    { \pubtitle_symbolheading:nn \faBook     { Book } }
        { article } { \pubtitle_symbolheading:nn \faFileText { Article } }
      }
      {
        \bool_lazy_and:nnF
          { \tl_if_novalue_p:n {#1} }
          { \tl_if_novalue_p:n {#2} }
          { \msg_error:nn { pubtitle } { extraneous-optional } }
      }
      {
        \str_if_eq:nnTF {#3} { custom }
          {
            \bool_lazy_or:nnTF
              { \tl_if_novalue_p:n {#1} }
              { \tl_if_novalue_p:n {#2} }
              { \msg_error:nn { pubtitle } { missing-optional } }
              { \pubtitle_symbolheading:nn {#1} {#2} }
          }
          { \msg_error:nnn { pubtitle } { unsupported-argument } {#3} }
      }
  }
\cs_generate_variant:Nn \pubtitle_pubtitle:nnn { nne }
\cs_new_protected:Npn \pubtitle_symbolheading:nn #1#2
  {
    \group_begin:
      \large
      \textcolor { icons } {#1}
      \skip_horizontal:n { 10pt }
      \textbf {#2}
    \group_end:
  }

% just for tests
\NewDocumentCommand \showtest { v }
  {
    \noindent\texttt{#1}:\\
    \tl_rescan:nn {} {#1}
    \par
    \medskip
  }
\ExplSyntaxOff

\begin{document}
\section{Interface \texttt{\protect\string\pubtitle}}
\showtest{\pubtitle{book}}
\showtest{\pubtitle{ArTiClE}}
\showtest{\pubtitle[\faBeer][Beer]{custom}} % thanks Ulrich for the beer

% error cases
%\pubtitle{invalidArgument} % throws an error
%\pubtitle[\faBook]{article} % throws an error
%\pubtitle[\faBook]{custom} % throws an error

\section{Interface \texttt{\protect\string\Pubtitle}}
\showtest{\Pubtitle{book}}
\showtest{\Pubtitle{ArTiClE}}
\showtest{\Pubtitle[\faBeer,Beer]{custom}} % thanks Ulrich for the beer

%\Pubtitle{invalidArgument} % throws an error
%\Pubtitle[\faBook]{article} % throws an error
%\Pubtitle[\faBook]{custom} % throws an error
%\Pubtitle[\faBeer,Beer, and more]{custom} % throws an error
\end{document}

在此处输入图片描述


如果使用了,以下将使用标题和图标的默认值custom。如果您指定两个可选参数(或在变体中用逗号分隔变体),则第一个将是标题,第二个将是图标。如果您只指定一个可选参数,如果它只包含一个将用作图标的标记/括号组,则标题将是默认的。如果您只指定一个可选参数并且它包含多个标记/组,它将是标题并使用默认图标。

\documentclass{article}

\usepackage{xcolor}
\usepackage{fontawesome}

\definecolor{icons}{HTML}{46A247}

\ExplSyntaxOn
\msg_new:nnn { pubtitle } { extraneous-optional }
  {
    \exp_not:N \pubtitle
    only~ accepts~ optional~ arguments~ if~ you~ use~ `custom'~ as~ a~
    mandatory~ argument.
  }
\msg_new:nnnn { pubtitle } { unsupported-argument }
  { Unsupported~ entry~ field~ `#1'~ for~ bibliography. }
  { Perhaps~ you~ meant~ `\token_to_str:N \pubtitle[<icon>][<text>]{custom}'. }

% document interfaces
\NewDocumentCommand \pubtitle { o o m }
  { \pubtitle_pubtitle:nne {#1} {#2} { \str_foldcase:n {#3} } }
\NewDocumentCommand \Pubtitle { >{\SplitArgument{1}{,}}o m }
  {
    % design decision of ltcmd: unused o-args are not processed by argument
    % processors, so we need to add this processing here
    \IfNoValueTF {#1}
      { \pubtitle_pubtitle:nne {#1} {#1} }
      { \pubtitle_pubtitle:nne #1 }
        { \str_foldcase:n {#2} }
  }

\tl_new:N \l__pubtitle_default_custom_icon_tl
\tl_new:N \l__pubtitle_default_custom_title_tl
\tl_set:Nn \l__pubtitle_default_custom_icon_tl { \faFileTextO }
\tl_set:Nn \l__pubtitle_default_custom_title_tl { Publication }

% internal code
\cs_new_protected:Npn \pubtitle_pubtitle:nnn #1#2#3
  {
    \str_case:nnTF {#3}
      {
        { book }    { \pubtitle_symbolheading:nn \faBook     { Book } }
        { article } { \pubtitle_symbolheading:nn \faFileText { Article } }
      }
      {
        \tl_if_novalue:nF {#1}
          { \msg_error:nn { pubtitle } { extraneous-optional } }
      }
      {
        \str_if_eq:nnTF {#3} { custom }
          {
            \tl_if_novalue:nTF {#2}
              {
                \tl_if_novalue:nTF {#1}
                  {
                    \pubtitle_symbolheading:nn
                      \l__pubtitle_default_custom_icon_tl
                      \l__pubtitle_default_custom_title_tl
                  }
                  {
                    \tl_if_single:nTF {#1}
                      {
                        \pubtitle_symbolheading:nn
                          #1
                          \l__pubtitle_default_custom_title_tl
                      }
                      {
                        \pubtitle_symbolheading:nn
                          \l__pubtitle_default_custom_icon_tl
                          {#1}
                      }
                  }
              }
              { \pubtitle_symbolheading:nn {#2} {#1} }
          }
          { \msg_error:nnn { pubtitle } { unsupported-argument } {#3} }
      }
  }
\cs_generate_variant:Nn \pubtitle_pubtitle:nnn { nne }
\cs_new_protected:Npn \pubtitle_symbolheading:nn #1#2
  {
    \group_begin:
      \large
      \textcolor { icons } {#1}
      \skip_horizontal:n { 10pt }
      \textbf {#2}
    \group_end:
  }

% just for tests
\NewDocumentCommand \showtest { v }
  {
    \noindent\texttt{#1}:\\
    \tl_rescan:nn {} {#1}
    \par
    \medskip
  }
\ExplSyntaxOff

\begin{document}
\section{Interface \texttt{\protect\string\pubtitle}}
\showtest{\pubtitle{book}}
\showtest{\pubtitle{ArTiClE}}
\showtest{\pubtitle[Beer][\faBeer]{custom}} % thanks Ulrich for the beer
\showtest{\pubtitle[\faBeer]{custom}}
\showtest{\pubtitle[Beer]{custom}}

% error cases
%\pubtitle{invalidArgument} % throws an error
%\pubtitle[\faBook]{article} % throws an error
%\pubtitle[\faBook]{custom} % throws an error

\section{Interface \texttt{\protect\string\Pubtitle}}
\showtest{\Pubtitle{book}}
\showtest{\Pubtitle{ArTiClE}}
\showtest{\Pubtitle[Beer,\faBeer]{custom}} % thanks Ulrich for the beer
\showtest{\Pubtitle[\faBeer]{custom}}
\showtest{\Pubtitle[Beer]{custom}}

%\Pubtitle{invalidArgument} % throws an error
%\Pubtitle[\faBook]{article} % throws an error
%\Pubtitle[\faBook]{custom} % throws an error
%\Pubtitle[\faBeer,Beer, and more]{custom} % throws an error
\end{document}

在此处输入图片描述

答案2

您可以使用一个命令\pubtitle,该命令通常只处理一个强制参数,但如果第一个参数等于“自定义”,则处理三个强制参数,在这种情况下,第二个强制参数表示 fontawesome 符号,第三个参数表示文本短语:

\documentclass{article}

\usepackage{xcolor}
\usepackage{fontawesome}

\definecolor{icons}{HTML}{46A247}

\ExplSyntaxOn

\cs_new_protected:Nn \pubtitle_symbolheading:nn
 {
  \group_begin:
  {\large\textcolor{icons}{#1}\hspace{10pt}\textbf{#2}}
  \group_end:
 }

\NewDocumentCommand{\pubtitle}{m}
 {
  \pubtitle_pubtitle:n { #1 }
 }

\cs_new_protected:Nn \pubtitle_pubtitle:n
 {
  \str_case:nnF { #1 }
   {
    {book}{\pubtitle_symbolheading:nn{\faBook}{Book}}
    {article}{\pubtitle_symbolheading:nn{\faFileText}{Article}}
    % other cases
    % ...
    {custom}{\pubtitle_symbolheading:nn}% In cae of "custom" don't provide \pubtitle_symbolheading:nn's
                                        % arguments but let the user do it.
   }
   {% none of the above
    \PackageError{pubtitle}
     {
      Unsupported ~ entry ~ field ~ '#1' ~ \MessageBreak for bibliography}
     {
      Perhaps ~ you ~ meant ~ '\string\pubtitle{custom}'
     }
   }
 }

\ExplSyntaxOff

\begin{document}

\pubtitle{book}

\pubtitle{article}

\pubtitle{custom}{\faBeer}{Beer!}

%\pubtitle{invalidArgument}

\end{document}

在此处输入图片描述



\pubtitle或者,我可以提供通常的 where 语法的变体 ,但以防万一
\pubtitle{⟨mandatory⟩}
⟨强制的⟩持有短语“自定义”的语法是。
\pubtitle[⟨symbol⟩]{custom}[⟨text-phrase⟩]

在后一种情况下

  • 默认为⟨象征⟩\faFileTextO
  • 默认为⟨文本短语⟩Publication

在进一步的情况下,指定可选参数会产生一条警告消息,提示它们会被忽略。

这样,您就有了两个可选参数,它们由一个强制参数分隔,因此可以轻松地分别指定符号/文本短语,而无需让您的宏解析可选参数来检测用户可能提供的内容。

要点是:

首先检查强制参数是否等于“custom”。
然后在两种情况下检查可选参数是否存在。

如果强制参数等于短语“自定义”,则只有用户实际提供的可选参数才会传递给处理具有默认值的可选参数的宏并执行\pubtitle_symbolheading:nn

如果强制参数不等于短语“自定义”,则可选参数的存在会导致有关可选参数被忽略的警告消息。
然后\pubtitle_pubtitle:n执行分叉以生成强制参数的不同非“自定义”案例。

\documentclass{article}

\usepackage{xcolor}
\usepackage{fontawesome}

\definecolor{icons}{HTML}{46A247}

\ExplSyntaxOn

\cs_new_protected:Nn \pubtitle_symbolheading:nn
 {
  \group_begin:
  {\large\textcolor{icons}{#1}\hspace{10pt}\textbf{#2}}
  \group_end:
 }
\cs_new:Nn \pubtitle_optional_args_present_fork:nnnnnn 
  {
    \IfNoValueTF{#1}{\IfNoValueTF{#2}{#3}{#4}}
                    {\IfNoValueTF{#2}{#5}{#6}}
  }
\NewDocumentCommand{\pubtitle}{omo}
  {
    \str_case:nnF { #2 }
     {
        {custom}{
                  \pubtitle_optional_args_present_fork:nnnnnn{#1}{#3}
                  {\pubtitle_custom{}}
                  {\pubtitle_custom{}[{#3}]}
                  {\pubtitle_custom[{#1}]{}}
                  {\pubtitle_custom[{#1}]{}[{#3}]}
                }
     }
     {
        \pubtitle_optional_args_present_fork:nnnnnn{#1}{#3}
           {}
           {\pubtitle_superfluous_opt_args_warning{\pubtitle}{[#3]}}
           {\pubtitle_superfluous_opt_args_warning{\pubtitle}{[#1]}}
           {\pubtitle_superfluous_opt_args_warning{\pubtitle}{[#1]/[#3]}}
        \pubtitle_pubtitle:n{#2}
     }
   }
\NewDocumentCommand{\pubtitle_custom}{O{\faFileTextO}mO{Publication}}
  {
    \pubtitle_symbolheading:nn{#1}{#3}
  }
\cs_new_protected:Nn \pubtitle_pubtitle:n
 {
  \str_case:nnF { #1 }
   {
    {book}{\pubtitle_symbolheading:nn{\faBook}{Book}}
    {article}{\pubtitle_symbolheading:nn{\faFileText}{Article}}
    %
    % other non-custom-cases
    %
   }
   {\pubtitle_unsupported_entry_field_error{\pubtitle}{#1} }
 }
\prop_gput:Nnn \g_msg_module_type_prop { pubtitle } {}
\prop_gput:Nnn \g_msg_module_name_prop { pubtitle } {Macro-Defined-In-Preamble:}
\msg_new:nnnn {pubtitle} 
              {superfluous optional arguments}
              {Macro~#1:~Ignoring~superfluous~optional~argument(s)~#2~as~it~is/they~are~provided~while~not~doing~a~"custom"-thingie~\msg_line_context: .}
              {With~macro~#1~specifying~optional~arguments~only~makes~sense~if~the~mandatory~argument~equals~"custom".}
\cs_new:Npn \pubtitle_superfluous_opt_args_warning #1 #2 {
  \exp_args:Nne \use:n  {
    \msg_warning:nnnn {pubtitle} {superfluous optional arguments}
  }{\iow_char:N \\\cs_to_str:N #1}{#2}
}
\msg_new:nnnn {pubtitle} 
              {unsupported entry field}
              {Macro~#1:~Unsupported~ entry~field~'#2'~for~bibliography~\msg_line_context: .}
              {Perhaps~you~meant~'#1\pubtitle{custom}'.}
\cs_new:Npn \pubtitle_unsupported_entry_field_error #1 #2 {
  \exp_args:Nne \use:n  {
    \msg_error:nnnn {pubtitle} {unsupported entry field}
  }{\iow_char:N \\\cs_to_str:N #1}{#2}
}

\ExplSyntaxOff

\begin{document}

\noindent\verb|\pubtitle{book}|\\
\pubtitle{book}

\medskip

\noindent\verb|\pubtitle{article}|\\
\noindent\pubtitle{article}

\medskip

\noindent\verb|\pubtitle{custom}|\\
\pubtitle{custom}

\medskip

\noindent\verb|\pubtitle[\faBeer]{custom}|\\
\pubtitle[\faBeer]{custom}


\medskip

\noindent\verb|\pubtitle{custom}[Beer!]|\\
\pubtitle{custom}[Beer!]


\medskip

\noindent\verb|\pubtitle[\faBeer]{custom}[Beer!]|\\
\pubtitle[\faBeer]{custom}[Beer!]

% Switch to \iftrue to see warning-messages in case optional arguments are provided with non-custom-thingie:

\iffalse
%\iftrue

\medskip

\noindent\verb|\pubtitle[\faBeer]{book}|\\
\pubtitle[\faBeer]{book}

\medskip

\noindent\verb|\pubtitle{book}[Beer!]|\\
\pubtitle{book}[Beer!]

\medskip

\noindent\verb|\pubtitle[\faBeer]{book}[Beer!]|\\
\pubtitle[\faBeer]{book}[Beer!]

\fi

% Switch to \iftrue to see error-messages in case an undefined-custom-thingie is provided as
% mandatory argument:

\iffalse
%\iftrue


\medskip

\noindent\verb|\pubtitle{invalidArgument}|\\
\pubtitle{invalidArgument}

\medskip

\noindent\verb|\pubtitle[\faBeer]{invalidArgument}|\\
\pubtitle[\faBeer]{invalidArgument}

\medskip

\noindent\verb|\pubtitle{invalidArgument}[Beer!]|\\
\pubtitle{invalidArgument}[Beer!]

\medskip

\noindent\verb|\pubtitle[\faBeer]{invalidArgument}[Beer!]|\\
\pubtitle[\faBeer]{invalidArgument}[Beer!]

\fi

\end{document}

在此处输入图片描述



您可以使用像 expl3 的 l3keys 这样的键值系统,并使用一个键(我们称之为“符号”)表示 fontawesome 符号,另一个键(我们称之为“文本”)表示文本短语,并定义元键“book”/“article”,进而提供模式的预定义键值列表symbol=..., text=...

\documentclass{article}

\usepackage{xcolor}
\usepackage{fontawesome}

\definecolor{icons}{HTML}{46A247}

\ExplSyntaxOn
\cs_new:Npn \__pubtitle_symbol: {}
\cs_new:Npn \__pubtitle_text: {}
\keys_define:nn { pubtitle }
{
   symbol.cs_set:Np = \__pubtitle_symbol: ,
   symbol.value_required:n = true ,
   symbol.initial:n = \q_no_value ,
   text.cs_set:Np = \__pubtitle_text: ,
   text.value_required:n = true ,
   text.initial:n = \q_no_value ,
   %% meta-keys denoting presets of symbol=..., text=...
   book.meta:n = {symbol=\faBook, text=Book,}, book.value_forbidden:n = true,
   article.meta:n = {symbol=\faFileText, text=Article,}, article.value_forbidden:n = true,
}
\cs_new_protected:Npn \pubtitle #1 
 {
  \group_begin:
  \keys_set:nn { pubtitle } { #1 } 
  \exp_args:No \quark_if_no_value:nTF {\__pubtitle_symbol:}{
      \pubtitle_missing_value_error{\pubtitle}{symbol}
      \exp_args:No \quark_if_no_value:nT {\__pubtitle_text:}{
          \pubtitle_missing_value_error{\pubtitle}{text}
      }
  }{
      \exp_args:No \quark_if_no_value:nTF {\__pubtitle_text:}{
          \pubtitle_missing_value_error{\pubtitle}{text}
      }{
          {\large\textcolor{icons}{\__pubtitle_symbol:}\hspace{10pt}\textbf{\__pubtitle_text:}}
      }
  }
  \group_end:
 }
\prop_gput:Nnn \g_msg_module_type_prop { pubtitle } {}
\prop_gput:Nnn \g_msg_module_name_prop { pubtitle } {Macro-Defined-In-Preamble:}
\msg_new:nnnn {pubtitle} 
              {missing value}
              {Macro~#1:~No~value~for~key~'#2'~provided~\msg_line_context: .}
              {Provide~a~value~for~key~'#2'!}
\cs_new:Npn \pubtitle_missing_value_error #1 #2 {
  % \msg_error:... etc turn their arguments into strings, but let's make sure
  % the control-sequence whose name is to be displayed is stringified with a
  % leading backslash regardless the current value of the \escapechar parameter:
  \exp_args:Nne \use:n  {
    \msg_error:nnnn {pubtitle} {missing value}
  }{\iow_char:N \\\cs_to_str:N #1}{#2}
}
\ExplSyntaxOff

\begin{document}

\noindent\verb|\pubtitle{book}|:\\
\pubtitle{book}

\medskip

\noindent\verb|\pubtitle{article}|:\\
\pubtitle{article}

\medskip

\noindent Customizing by providing keys \verb|symbol|/\verb|text| additionally to or instead
of meta-keys like \verb|book|/\verb|article|:

\medskip

\noindent\verb|\pubtitle{symbol=\faBeer, text=Beer!}|:\\
\pubtitle{symbol=\faBeer, text=Beer!}

\medskip

\noindent\verb|\pubtitle{book, text=Beer!}|:\\
\pubtitle{book, text=Beer!}

\medskip

\noindent\verb|\pubtitle{book, symbol=\faBeer}|:\\
\pubtitle{book, symbol=\faBeer}

% Test error-messages:
%\pubtitle{invalidArgument}
\end{document}

在此处输入图片描述

相关内容