为什么即使经过扩展之后, \notblank 仍然认为其参数不为空?

为什么即使经过扩展之后, \notblank 仍然认为其参数不为空?

在以下 MWE 中:

\documentclass{article}

\usepackage{etoolbox}
\usepackage{xparse}

\makeatletter
\NewDocumentCommand{\@mkCommands}{mm}{%
  \expandafter\NewDocumentCommand\csname @#1\endcsname{}{%
    \notblank{#2}{%
      NO \MakeUppercase{#2} PROVIDED,
      USE \textbackslash #1 COMMAND%
    }{}%
  }
  \expandafter\NewDocumentCommand\csname #1\endcsname{m}{%
    \expandafter\RenewDocumentCommand\csname @#1\endcsname{}{##1}%
  }
}

\@mkCommands{testCmdA}{TEST-COMMAND-A}
\@mkCommands{testCmdB}{}

\NewDocumentCommand{\makePage}{}{%
  A: \@testCmdA

  \protected@edef\@tempa{\@testCmdB}%
  \expandafter\notblank\expandafter{\@tempa}{%
    B: \@testCmdB
  }{}%
}
\makeatother

\begin{document}

\makePage

\end{document}

预期输出应为:

A: NO TEST COMMAND A PROVIDED, USE \testCmdA COMMAND

但实际的输出是:

A: NO TEST COMMAND A PROVIDED, USE \testCmdA COMMAND
B:

换句话说,\notblank相信\@tempa不是空白,尽管它应该充分\@testCmdB扩展应该为空白。

我在这里遗漏了什么?

答案1

如果您\@testcmdB用定义\NewDocumentCommand,它是一个宏,因此它在(和)\protected中保持不变。\edef\protected@edef

我认为采用不同的方法更好,而且这种\NewDocumentCommand方法带来的阻碍比帮助更大。

\documentclass{article}
\usepackage{etoolbox}

\makeatletter

\newcommand{\@mkCommands}[2]{%
  \ifblank{#2}
    {\@namedef{@#1}{}}
    {%
     \@namedef{@#1}{%
       NO \MakeUppercase{#2} PROVIDED,
       USE \texttt{\symbol{`\\}#1} COMMAND%
     }%
    }%
  \@namedef{#1}##1{%
    \global\@namedef{@#1}{##1}%
  }%
}


\@mkCommands{testcmdA}{test-command-A}
\@mkCommands{testcmdB}{}

\newcommand{\makePage}{%
  A: \@testcmdA
  \expandafter\notblank\expandafter{\@testcmdB}{%
    \\
    B: \@testcmdB
  }%
}
\makeatother

\begin{document}

\section{No commands given}

\makePage

\section{Command A}

\testcmdA{Here is a test}

\makePage

\section{Command B}

\testcmdB{Here is b test}

\makePage

\end{document}

在此处输入图片描述

这是一种相当不同的方法。我提供的不是几个命令,而是一个\@useCommand带有两个参数的接口:命令名称(例如testcmdA)和要使用相关标记列表的内容执行的操作,用#1(或者##1如果在定义内,当然是)表示。

如果\@mkCommands与尾随可选参数一起使用,则定义的命令将被视为对用户强制执行,因此在\makePage执行时会出现关于在文档中提供该命令的警告。否则,\@useCommand如果相关内容仍为空,它将不被视为强制执行,并且不会对规范执行任何操作。

\documentclass{article}
\usepackage{xparse}

\makeatletter
\ExplSyntaxOn

\clist_new:N \g_gablin_makepage_commands_clist

\NewDocumentCommand{\@mkCommands}{mo}
 {
  \tl_new:c { g_gablin_makepage_#1_tl }
  \IfValueT { #2 }
   {
    \clist_gput_right:Nn \g_gablin_makepage_commands_clist { #1 }
    \tl_gset:cn { g_gablin_makepage_#1_tl }
     {
      NO ~ \tl_upper_case:n { #2 } ~ PROVIDED, ~
      USE ~ \texttt{\symbol{`\\}#1} ~ COMMAND
     }
   }
  \exp_args:Nc \NewDocumentCommand { #1 } { m }
   {
    \tl_gset:cn { g_gablin_makepage_#1_tl } { ##1 }
   }
 }
\NewDocumentCommand{\@useCommand}{mm}
 {
  \cs_set:Nn \__gablin_makepage_do:n { #2 }
  \clist_if_in:NnTF \g_gablin_makepage_commands_clist { #1 }
   {
    \__gablin_makepage_do:v { g_gablin_makepage_#1_tl }
   }
   {
    \tl_if_blank:vF { g_gablin_makepage_#1_tl }
     {
      \__gablin_makepage_do:v { g_gablin_makepage_#1_tl }
     }
   }
 }

\cs_new:Nn \__gablin_makepage_do:n {}
\cs_generate_variant:Nn \__gablin_makepage_do:n { v }
\cs_generate_variant:Nn \tl_if_blank:nF { v }

\ExplSyntaxOff


\@mkCommands{testcmdA}[test-command-A]
\@mkCommands{testcmdB}

\newcommand{\makePage}{%
  \@useCommand{testcmdA}{%
    A: ##1
  }%
  \@useCommand{testcmdB}{
    \\
    B: ##1
  }%
}
\makeatother

\begin{document}

\section{No commands given}

\makePage

\section{Command A}

\testcmdA{Here is a test}

\makePage

\section{Command B}

\testcmdB{Here is b test}

\makePage

\end{document}

输出与以前相同。

答案2

也许是这个?

问题是\NewDocumentCommand不会扩展为简单文本。如果你想测试某些内容是否为空白,你必须确保它扩展为简单文本,即本例中的空白文本。因此,对于你想要测试的情况,你需要使用 而\def不是\NewDocumentCommand

我将 放在的定义中 的定义之外\@mkCommands。如果是空白,我使用 简单定义为。这样,在后面的测试中,就会检测到空白。\notblank{#2}\@#1\def\@#1{}\@tempa\notblank\@testCmdB

\documentclass{article}

\usepackage{etoolbox}
\usepackage{xparse}

\makeatletter
\NewDocumentCommand{\@mkCommands}{mm}{%
  \notblank{#2}{%
  \expandafter\NewDocumentCommand\csname @#1\endcsname{}{%
      NO \MakeUppercase{#2} PROVIDED,
      USE \textbackslash #1 COMMAND%
    }}%
  {\expandafter\def\csname @#1\endcsname{}}%
  \expandafter\NewDocumentCommand\csname #1\endcsname{m}{%
    \expandafter\RenewDocumentCommand\csname @#1\endcsname{}{##1}%
  }
}

\@mkCommands{testCmdA}{TEST-COMMAND-A}
\@mkCommands{testCmdB}{}

\NewDocumentCommand{\makePage}{}{%
  A: \@testCmdA

  \protected@edef\@tempa{\@testCmdB}%
  \expandafter\notblank\expandafter{\@tempa}{%
    B: \@testCmdB
  }{}%
}
\makeatother

\begin{document}

\makePage

\end{document}

相关内容