我有这个小例子来检查键是否为空:
\documentclass[]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\makeatletter
\newcount\cnt\cnt=0\relax
\tikzset{dir/.is family}
\tikzset{dir/t0/.initial={}}
\begin{document}
% \tikzset{dir/t0={\small SMALL}}
Key \the\cnt is: \pgfkeysvalueof{/tikz/dir/t\the\cnt}
\edef\mykey{x\pgfkeysvalueof{/tikz/dir/t\the\cnt}}
\edef\plainx{x}
\ifx\plainx\mykey
key t\the\cnt{} is empty
\else
key t\the\cnt{} is not empty
\fi
\end{document}
并且它有效,除非我在键本身中放置一个字体更改命令(取消注释tikzset
):
! TeX capacity exceeded, sorry [input stack size=5000].
\@setfontsize #1#2#3->\@nomath #1
\ifx \protect \@typeset@protect \let \@curr...
l.18 ...ykey{x\pgfkeysvalueof{/tikz/dir/t\the\cnt}
}
! ==> Fatal error occurred, no output PDF file produced!
我如何才能安全地检查密钥是否已设置为{}
?我需要使用核心包来执行此操作,代码必须与 LaTeX 和 ConTeXt 兼容...
答案1
字体更改命令(现在)很强大,因此如果您使用\protected@edef
而不是普通的\edef
,则 LaTeX 的保护机制将启动并阻止 的扩展\small
。但是,这仅在键包含强大或可扩展的命令时才有效(通常情况并非如此)。
更可靠的方法是利用 的实现细节\pgfkeysvalueof
,也就是\csname pgfk@<full path to key>\endcsname
(经过一次扩展)。\csname
扩展路径中的所有内容并生成控制序列(经过第二次扩展),然后再进行一次扩展(第三次)会产生密钥的内容,因此您可以使用:
\def\unexpandedvalueof#1{%
\unexpanded
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter{\pgfkeysvalueof{#1}}}
扩大\pgfkeysvalueof
3 倍并将结果留在里面\unexpanded
,这样它就不会进一步扩大\edef
。
请注意,由于\pgfkeysvalueof
直接使用\csname
,如果键之前不存在,TeX 将\relax
在扩展后退出,并且空性测试将返回 false。如果您希望它对未定义的键返回 true,则需要在\relax
扩展存储键的实际控制序列之前检查:
\def\unexpandedvalueof#1{%
\unexpanded\expandafter\expandafter
\expandafter\rmano@valueof@chk\pgfkeysvalueof{#1}}
\def\rmano@valueof@chk#1{%
\ifx\relax#1%
\expandafter\pgfutil@firstoftwo
\else
\expandafter\pgfutil@secondoftwo
\fi
{{}}%
{\expandafter{#1}}}
这是一个可编译的示例:
\documentclass[]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage{unravel}
\makeatletter
\newcount\cnt\cnt=0\relax
\tikzset{dir/.is family}
\tikzset{dir/t0/.initial={}}
\begin{document}
\tikzset{dir/t0={\small SMALL}}
Key \the\cnt is: \pgfkeysvalueof{/tikz/dir/t\the\cnt}
\makeatletter
\newcommand\unexpandedvalueof[1]{%
\unexpanded\expandafter\expandafter
\expandafter\rmano@valueof@chk\pgfkeysvalueof{#1}}
\def\rmano@valueof@chk#1{%
\ifx\relax#1%
\expandafter\pgfutil@firstoftwo
\else
\expandafter\pgfutil@secondoftwo
\fi
{{}}% #1 is \relax, so consider empty
{\expandafter{#1}}}% otherwise, leave the key after one more expansion
\makeatletter
\edef\mykey{x\unexpandedvalueof{/tikz/dir/t\the\cnt}}
\edef\plainx{x}
\ifx\plainx\mykey
key t\the\cnt{} is empty
\else
key t\the\cnt{} is not empty
\fi
\edef\mykey{x\unexpandedvalueof{/tikz/dir/tBOO}}
\edef\plainx{x}
\ifx\plainx\mykey
key t\the\cnt{} is empty
\else
key t\the\cnt{} is not empty
\fi
\end{document}
ConTeXt 重命名了\unexpanded
原语,因此您需要改用\normalunexpanded
。您可以使用此代码定义泛型\pgfutil@unexpanded
:
\ifcsname normalunexpanded\endcsname
\let\pgfutil@unexpanded\normalunexpanded
\else
\let\pgfutil@unexpanded\unexpanded
\fi