我有一个带有一些参数的自定义环境。目标是基本上布局环境的一些参数。我的简化文档如下:
\documentclass[11pt, a4paper]{article}
\usepackage[table,xcdraw]{xcolor}
\usepackage{booktabs}
\usepackage{graphicx}
\usepackage{framed}
\usepackage{enumitem}
\usepackage{hyperref}
\usepackage{etoolbox}
\usepackage[yyyymmdd,hhmmss]{datetime}
\usepackage{fancyhdr}
\usepackage{array}
\usepackage[top=1in, bottom=1.25in, left=1.25in, right=1.25in]{geometry}
% External definitions
\newenvironment{testcase}
{
\newcommand{\caseid}[1]{\renewcommand{\givenid}{##1}\label{case:##1}}
\newcommand{\casetitle}[1]{\renewcommand{\giventitle}{##1}}
\newcommand{\caseresult}[1]{\renewcommand{\givencaseresult}{##1}}
\newcommand{\casesteps}[1]{\renewcommand{\givencasesteps}{##1}}
\newcommand{\givenid}{Required!}
\newcommand{\giventitle}{Required!}
\newcommand{\givencaseresult}{Required!}
\newcommand{\givencasesteps}{Required!}
}
{
\begin{framed}
\textbf{\givenid \ : \giventitle }
\end{framed}
\addcontentsline{toc}{subsubsection}{\givenid \ : \giventitle }
\if\relax\givencasesteps\relax
\else
\begin{tabular}{p{4cm}p{10cm} }
\textbf{Steps:} & \ \\
\end{tabular}
\begin{enumerate}
\givencasesteps
\end{enumerate}
\fi
\if\relax\givencaseresult\relax
\else
\begin{tabular}{p{4cm}p{10cm} }
\textbf{Result:} & \ \\
\end{tabular}
\begin{enumerate}
\givencaseresult
\end{enumerate}
\fi
\newpage
}
\sloppy
\begin{document}
\begin{testcase}
\caseid{CaseNumber}
\casetitle{Case Title}
\caseresult{\item Sorry, it failed.}
\casesteps{
\item This is the first step
\item This is the second step
}
\end{testcase}
\end{document}
这不会编译并出现错误!不完整 \iffalse;所有文本被忽略。如果我省略第二个 if 块,它确实可以编译并按预期工作,即使我只是第二次复制第一个 if 块。所以这确实有效。
\documentclass[11pt, a4paper]{article}
\usepackage[table,xcdraw]{xcolor}
\usepackage{booktabs}
\usepackage{graphicx}
\usepackage{framed}
\usepackage{enumitem}
\usepackage{hyperref}
\usepackage{etoolbox}
\usepackage[yyyymmdd,hhmmss]{datetime}
\usepackage{fancyhdr}
\usepackage{array}
\usepackage[top=1in, bottom=1.25in, left=1.25in, right=1.25in]{geometry}
% External definitions
\newenvironment{testcase}
{
\newcommand{\caseid}[1]{\renewcommand{\givenid}{##1}\label{case:##1}}
\newcommand{\casetitle}[1]{\renewcommand{\giventitle}{##1}}
\newcommand{\caseresult}[1]{\renewcommand{\givencaseresult}{##1}}
\newcommand{\casesteps}[1]{\renewcommand{\givencasesteps}{##1}}
\newcommand{\givenid}{Required!}
\newcommand{\giventitle}{Required!}
\newcommand{\givencaseresult}{Required!}
\newcommand{\givencasesteps}{Required!}
}
{
\begin{framed}
\textbf{\givenid \ : \giventitle }
\end{framed}
\addcontentsline{toc}{subsubsection}{\givenid \ : \giventitle }
\if\relax\givencasesteps\relax
\else
\begin{tabular}{p{4cm}p{10cm} }
\textbf{Steps:} & \ \\
\end{tabular}
\begin{enumerate}
\givencasesteps
\end{enumerate}
\fi
\if\relax\givencasesteps\relax
\else
\begin{tabular}{p{4cm}p{10cm} }
\textbf{Steps:} & \ \\
\end{tabular}
\begin{enumerate}
\givencasesteps
\end{enumerate}
\fi
\newpage
}
\sloppy
\begin{document}
\begin{testcase}
\caseid{CaseNumber}
\casetitle{Case Title}
\caseresult{\item Sorry, it failed.}
\casesteps{
\item This is the first step
\item This is the second step
}
\end{testcase}
\end{document}
这可能非常愚蠢,但我真的不明白为什么我的第一个片段是错误的而第二个片段是正确的。
谢谢你的帮助,Y。
答案1
当你这样做
\if\relax\givencasesteps\relax
第一次,宏\givencasesteps
扩展为
\item This ...
(...
表示此处不相关的其他标记),但\if
会继续扩展,直到剩下另一个不可扩展的标记(已经有\relax
)。因此\item
被扩展,其扩展从开始\@hyper@itemfalse
,进而扩展为
\let\if@hyper@item\iffalse
嗯,\let
是不可展开的,并且它与 进行比较\relax
,因此测试返回 false。但是,\if@hyper@item
和\iffalse
已经进入场景,并且第一个\else
与 匹配\if@hyper@item
,留下一个悬空的\iffalse
。
测试应该是
\if\relax\detokenize\expandafter{\givencasesteps}\relax
当的扩展为\givencasesteps
空时将返回 true。
但请注意,仅指定\casesteps{}
(参数中没有任何内容)将使测试为真。
可能更简单
\ifx\givencasesteps\longempty
随着
\newcommand\longempty{}
在序言中就可以了。