xdef 定义中的参数为空

xdef 定义中的参数为空

考虑一下乳胶宏的这个定义:

\newcommand\createCMDMANUV[4]{%
  \expandafter\@ifdefinable\csname #3#2\endcsname{%
    \expandafter\xdef\csname #3#2\endcsname##1{%
      \noexpand\vcenteredhbox{%
      \noexpand\includegraphics[width=##1,trim=0 0 1 -1]{BD_CATIA/#4/#1.png}}%
    }%
  }%
}

我尝试处理空(非可选)参数。因此我尝试了这个定义,但它不起作用:

\newcommand\createCMDMANUV[4]{%
  \expandafter\@ifdefinable\csname #3#2\endcsname{%
    \expandafter\xdef\csname #3#2\endcsname##1{%
      \noexpand\vcenteredhbox{%
      \ifdefempty{##1}{\def\widthCATIA{3cm}}{\def\widthCATIA{##1}}%
      \includegraphics[width=\widthCATIA,trim=0 0 1 -1]{BD_CATIA/#4/#1.png}}%
    }%
  }%
}

我认为这是由于定义\widthCATIA不明确,但正确的语法是什么......

我将该命令称为\createCMDMANUV{\tA}{\tB}{\tC}{\tD}包含字符串\tA的命令\tD

例如,如果\tC包含AVV\tB包含test宏,则构建命令\AVVtest

MWE(基于相同的想法):

\documentclass{standalone}
\RequirePackage{xstring}
\RequirePackage{etoolbox}

\makeatletter
\newcommand\createCMDMANUV[2]{%
  \expandafter\@ifdefinable\csname #1#2\endcsname{%
    \expandafter\xdef\csname #1#2\endcsname##1{%    
      \noexpand\textbf{##1}%
    }%
  }%
}
\makeatother

\begin{document}
\def\tA {AA}
\def\tB {BB}    
\createCMDMANUV{\tA}{\tB}

\AABB{coucou}   
\end{document}

MNWE(最小不工作示例:-)):

\documentclass{standalone}
\RequirePackage{xstring}
\RequirePackage{etoolbox}

\makeatletter
\newcommand\createCMDMANUV[2]{%
  \expandafter\@ifdefinable\csname #1#2\endcsname{%
    \expandafter\xdef\csname #1#2\endcsname##1{%    
    \ifcsempty{##1}{ \expandafter\xdef\csname ttMANU\endcsname{Ahah}}{ \expandafter\xdef\csname ttMANU\endcsname{ohoh}}%
      \noexpand\textbf{\csname ttMANU\endcsname}%
    }%
  }%
}
\makeatother

\begin{document}
\def\tA {AA}
\def\tB {BB}    
\createCMDMANUV{\tA}{\tB}

\AABB{}    
\AABB{aa}
\end{document}

\ifcsempty空测好像没做好。

我的 MNWE 解决方案:

\documentclass{standalone}
\RequirePackage{xstring}
\RequirePackage{etoolbox}

\makeatletter
\newcommand\createCMDMANUV[2]{%
\ifdefempty{##1}{\def\ttMANU{ahah}}{\def\ttMANU{ohoh}}%
  \expandafter\@ifdefinable\csname #1#2\endcsname{%
    \expandafter\xdef\csname #1#2\endcsname##1{%    
    \noexpand\ifblank{##1}{\def\noexpand\ttMANU{ahah}}{\def\noexpand\ttMANU{##1}}%%
      \noexpand\textbf{\noexpand\ttMANU}%
    }%
  }%
}
\makeatother

\begin{document}    
\def\tA {AA}
\def\tB {BB}    
\createCMDMANUV{\tA}{\tB}

\AABB{}    
\AABB{aa}      
\end{document}

答案1

\ifdefempty您正在尝试在定义时进行扩展;但您应该使用\ifblank

\newcommand\createCMDMANUV[4]{%
  \expandafter\@ifdefinable\csname #3#2\endcsname{%
    \expandafter\xdef\csname #3#2\endcsname##1{%
      \noexpand\vcenteredhbox{%
      \noexpand\ifblank{##1}{\def\noexpand\widthCATIA{3cm}}{\def\noexpand\widthCATIA{##1}}%
      \noexpand\includegraphics[width=\noexpand\widthCATIA,trim=0 0 1 -1]{BD_CATIA/#4/#1.png}}%
    }%
  }%
}

如果我打电话

\def\tA{AA}\def\tB{test}\def\tC{AVV}\def\tD{DD}

\createCMDMANUV{\tA}{\tB}{\tC}{\tD}

\show\AVVtest

我收到以下回复:

> \AVVtest=macro:
#1->\vcenteredhbox {\ifblank {#1}{\def \widthCATIA {3cm}}{\def \widthCATIA {#1}
}\includegraphics [width=\widthCATIA ,trim=0 0 1 -1]{BD_CATIA/DD/AA.png}}.

使用起来更简单expl3

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand\createCMDMANUV { mmmm }
 {
  \guuk_create_cmd_manuv:xxxx { #1 } { #2 } { #3 } { #4 }
 }

\tl_new:N \l__guuk_width_catia_tl

\cs_new_protected:Nn \guuk_create_cmd_manuv:nnnn
 {
  \cs_new_protected:cpn { #3#2 } ##1
   {
    \vcenteredhbox
     {
      \tl_if_empty:nTF { ##1 }
       { \tl_set:Nn \l__guuk_width_catia_tl { 3cm } }
       { \tl_set:Nn \l__guuk_width_catia_tl { ##1 } }
      \includegraphics[width=\l__guuk_width_catia_tl,trim=0 ~ 0 ~ 1 ~ -1]{BD_CATIA/#4/#1.png}
     }
   }
 }

\cs_generate_variant:Nn \guuk_create_cmd_manuv:nnnn { xxxx }
\ExplSyntaxOff
\def\tA{AA}\def\tB{test}\def\tC{AVV}\def\tD{DD}

\createCMDMANUV{\tA}{\tB}{\tC}{\tD}

\show\AVVtest

答案是

> \AVVtest=\protected\long macro:
#1->\vcenteredhbox {\tl_if_empty:nTF {#1}{\tl_set:Nn \l__guuk_width_catia_tl {3
cm}}{\tl_set:Nn \l__guuk_width_catia_tl {#1}}\includegraphics [width=\l__guuk_w
idth_catia_tl ,trim=0 0 1 -1]{BD_CATIA/DD/AA.png}}.

怎么运行的

  1. 我定义了一个带有四个参数的“用户级命令” \createCMDMANUV。它的任务只是将参数传递给\guuk_create_cmd_manuv:xxxx

  2. 我定义了该\guuk_create_cmd_manuv:nnnn函数;“4”n表示它是一个具有四个“正常”参数的宏。

  3. 此函数反过来根据传递的参数定义一个新的宏;它的作用\cs_new_protected:cpn是类似于\expandafter\def\csname ...\endcsname,但添加了“未定义性测试”,因此

    \cs_new_protected:cpn { <tokens> } #1 { ... }
    

    你在做什么

    \expandafter\def\csname <tokens>\endcsname##1{...}
    
  4. 根据要求,构造的宏有一个参数,用 测试该参数是否为空,\tl_if_blank:nTF如果参数为空则返回第二个参数,否则返回第三个参数。此测试与 相同etoolbox \ifblank;代码只是将内部标记列表设置为参数,如果不是空则设置为3cm

  5. 构建函数的内部代码与使用传统方法构建的完全相同,但是没有任何\noexpand

  6. 最后的技巧:

    \cs_generate_variant:Nn \guuk_create_cmd_manuv:nnnn { xxxx }
    

    我们从所述函数中定义另一个名为的函数\guuk_create_cmd_manuv:xxxx,当调用时,首先对其四个参数进行完全扩展,然后将扩展的参数作为普通参数传递给\guuk_create_cmd_manuv:nnnn

  7. 请注意,在编程环境中,\ExplSyntaxOn和之间\ExplSyntaxOff,空格和空行会被忽略,因此无需担心保护行尾。唯一的小麻烦是想要的空间必须明确地插入上述键~的值中trim

答案2

我删除了我的第一个答案,因为看起来你的代码太复杂了(对于许多用户来说通常都是这样:)。首先,你必须问为什么我需要使用\xdef普通的\gdef?我不明白为什么。因此,您的示例可以适用于\gdef

\def\createCMDMANUV#1#2#3#4{%
  \expandafter\@ifdefinable\csname #3#2\endcsname{%
    \expandafter\gdef\csname #3#2\endcsname##1{%
      \vcenteredhbox{%
      \includegraphics[width=\widthCATIA{##1},trim=0 0 1 -1]{BD_CATIA/#4/#1.png}}%
    }%
  }%
}
\def\withCATIA#1{\ifx^#1^3cm\else#1\fi}

编辑(回应关于声明期间参数扩展的评论)。如果您需要在代码中使用扩展参数\declaremacro,那么您可以考虑以下代码:

\def\delcleremacro#1#2#3#4{\edef\tmp{\noexpand\declaremacroA{#1}{#2}{#3}{#4}\tmp}
\def\declaremacroA#1#2#3#4{%
    \expandafter\gdef\csname #3#2\endcsname##1{%
        ... here is my complicated macro, which uses declared
            and {\bf expanded} parameters #1, #2, #3, #4 and one real parameter ##1.
            I need not to use fifty times \noexpand here.
            The test of empty parameter ##1 can be done by
            \ifx^##1^empty\else nonempty\fi or (more robust but nonexpandable)
            \def\tmp{##1}\ifx\tmp\empty \def\tmp{3cm}\else\def\tmp{##1}\fi
            and you can use \tmp in your meaning of \widthCATIA.
            Here is no \noexpand problem.
}}

相关内容