检测空的 PGFKEYS

检测空的 PGFKEYS

我碰到 ”为变量赋值并检索以供日后使用的推荐方法是什么?“同时尝试弄清楚如何使用 PGFKEYS。但是,我在弄清楚如何让它检测未设置的键时遇到了麻烦。

梅威瑟:

\documentclass{minimal}
\usepackage{pgfkeys}

\newcommand{\setValue}[1]{\pgfkeys{/variables/#1}}
\newcommand{\getValue}[1]{\pgfkeysvalueof{/variables/#1}}
\newcommand{\declare}[1]{%
 \pgfkeys{
  /variables/#1.is family,
  /variables/#1.unknown/.style = {\pgfkeyscurrentpath/\pgfkeyscurrentname/.initial = ##1}
 }%
}

\declare{}

\newcommand{\leftTailA}[1]{%
  \declare{@mLT/} 
  \setValue{@mLT, Label = #1 } 
  \ifx\getValue{@mLT/Label}\empty
  \else
    $>$\getValue{@mLT/Label}$<$
  \fi
}

\newcommand{\leftTailB}[1]{%
  \ifx#1\empty
  \else
    $>$#1$<$
  \fi
}

\pgfkeys{
  /distMarkup/.is family, /distMarkup,
  default/.style = { leftTailLabel = {} },
  leftTailLabel/.estore in = \myLeftTailLabel,
}

\newcommand\distMarkup[1][]{% Note, don't put a space between the , and the #1, why? I don't know.
  \pgfkeys{/distMarkup, default,#1}
  \ifx\myLeftTailLabel\empty
  \else 
    $>$\myLeftTailLabel$<$
  \fi
}

\begin{document}

A: This has a label: \leftTailA{ label number 1 }

A: This has no label: \leftTailA{}

B: This has a label: \leftTailB{ label number 1 }

B: This has no label: \leftTailB{}

MA: This has a label: \distMarkup[leftTailLabel=label number 1]

MA: This has no label: \distMarkup[]

\end{document}

此代码示例的输出为:

答:这有一个标签:> 标签编号 1<

答:这个没有标签:><

B:这有一个标签:> 标签编号 1 <

B:这个没有标签:

MA:这有一个标签:>标签编号 1<

MA:这没有标签:

特别是,我不明白为什么“A:这没有标签”显示的是“><”而不是什么都没有。

额外积分: \declare 声明中的 ##1 起什么作用?

答案1

我发现您的代码的主要问题是 行\ifx\getValue{@mLT/Label}\empty。 的行为\ifx是比较紧随其后的两个标记\ifx并检查它们是否相同。 在这种情况下,这两个标记是\getValue{。 这两个标记永远不会相同,因此始终会采用错误分支。

解决方法是将\pgfkeysgetvalue值存储到宏中,然后进行比较:

\newcommand{\leftTailA}[1]{%
  \declare{@mLT/}%
  \setValue{@mLT, Label = #1 }%
  \pgfkeysgetvalue{@mLT/Label}{\temp}
  \ifx\getValue\temp\empty
  \else
    $>$\getValue{@mLT/Label}$<$%
  \fi
}

同样,中的比较\leftTailB也是错误的。一种解决方法是将的参数存储\leftTailB到宏中,然后将该宏与 进行比较,\empty如下\ifx所示:

\newcommand{\leftTailB}[1]{%
  \def\temp{#1}%
  \ifx\temp\empty
  \else
    $>$#1$<$%
  \fi
}

如果要进行多次比较,可以定义一个名为的命令\ifempty

\makeatletter
\def\ifempty#1{%
    \def\temp{#1}%
    \ifx\temp\empty
       \expandafter\@firstoftwo
    \else
       \expandafter\@secondoftwo
    \fi
}

\def\ifpgfkeyempty#1{%
    \pgfkeysgetvalue{#1}{\temp}%
    \ifx\temp\empty
       \expandafter\@firstoftwo
    \else
       \ifx\temp\relax
           \expandafter\expandafter\expandafter\@firstoftwo
       \else
           \expandafter\expandafter\expandafter\@secondoftwo
       \fi
    \fi
}
\makeatother

in是未定义键的参数。您定义一个未定义键处理程序,它将任何未定义的键变成一个新键并存储传递给它##1\declare值。如果您直接说:

/variables/.unknown/.style = {\pgfkeyscurrentpath/\pgfkeyscurrentname/.initial = #1}

然后\pgfkeys{/variables/some new key=some value}将其some new key变成一个新变量 key 并存储some value到其中。在宏内部,#1指的是宏的第一个参数。 doubled##用于转义#1,以便它指的是未定义 key 的参数,而不是 的参数\declare

#1为了表明和之间的关系##1,请考虑以下代码:

 \def\test#1{\def\testinner##1{(#1/##1)}}
 \test{a} % This defines \testinner as #1->(a/#1)
 \testinner{b} % expands to (a/b)

完整代码(顺便说一下,这仍然不是好的代码):

\documentclass{minimal}
\usepackage{etoolbox}
\usepackage{pgfkeys}

\newcommand{\setValue}[1]{\pgfkeys{/variables/#1}}
\newcommand{\getValue}[1]{\pgfkeysvalueof{/variables/#1}}
\newcommand{\declare}[1]{%
 \pgfkeys{
  /variables/#1.is family,
  /variables/#1.unknown/.style = {\pgfkeyscurrentpath/\pgfkeyscurrentname/.initial = ##1}
 }%
}

\declare{}

\makeatletter
\def\ifempty#1{%
    \def\temp{#1}%
    \ifx\temp\empty
       \expandafter\@firstoftwo
    \else
       \expandafter\@secondoftwo
    \fi
}

\def\ifpgfkeyempty#1{%
    \pgfkeysgetvalue{#1}{\temp}%
    \ifx\temp\empty
       \expandafter\@firstoftwo
    \else
       \expandafter\@secondoftwo
    \fi
}
\makeatother

\newcommand{\leftTailA}[1]{%
  \declare{@mLT/}%
  \setValue{@mLT/Label = #1 }%
  \ifpgfkeyempty{/variables/@mLT/Label}{}{%
      $>$\getValue{@mLT/Label}$<$%
  }
}

\newcommand{\leftTailB}[1]{%
  \ifempty{#1}{}{%
    $>$#1$<$%
  }
}

\pgfkeys{
  /distMarkup/.is family, /distMarkup,
  default/.style = { leftTailLabel = {} },
  leftTailLabel/.estore in = \myLeftTailLabel,
}

\newcommand\distMarkup[1][]{%
  \pgfkeys{/distMarkup, default,#1}%
  \ifx\myLeftTailLabel\empty
  \else
    $>$\myLeftTailLabel$<$%
  \fi
}

\begin{document}

A: This has a label: \leftTailA{ label number 1 }

A: This has no label: \leftTailA{}

B: This has a label: \leftTailB{ label number 1 }

B: This has no label: \leftTailB{}

MA: This has a label: \distMarkup[leftTailLabel=label number 1]

MA: This has no label: \distMarkup[]

\end{document} 

答案2

像这样吗?

\documentclass{article}
\usepackage{etoolbox}
\usepackage{pgfkeys}

\newcommand{\setValue}[1]{\pgfkeys{/variables/#1}}
\newcommand{\getValue}[1]{\pgfkeysvalueof{/variables/#1}}
\newcommand{\declare}[1]{%
 \pgfkeys{
  /variables/#1.is family,
  /variables/#1.unknown/.style = {\pgfkeyscurrentpath/\pgfkeyscurrentname/.initial = ##1}
 }%
}

\declare{}

\newcommand{\leftTailA}[1]{%
  \declare{@mLT/}% 
  \setValue{@mLT, Label = #1 }%
  \edef\tmp{\getValue{@mLT/Label}}%
  \ifx\tmp\empty
  \else
    $>$\getValue{@mLT/Label}$<$%
  \fi
}

\newcommand{\leftTailB}[1]{%
  \ifx#1\empty
  \else
    $>$#1$<$%
  \fi
}

\pgfkeys{
  /distMarkup/.is family, /distMarkup,
  default/.style = { leftTailLabel = {} },
  leftTailLabel/.estore in = \myLeftTailLabel,
}

\newcommand\distMarkup[1][]{% Note, don't put a space between the , and the #1, why? I don't know.
  \pgfkeys{/distMarkup, default,#1}%
  \ifx\myLeftTailLabel\empty
  \else 
    $>$\myLeftTailLabel$<$%
  \fi
}

\begin{document}

A: This has a label: \leftTailA{ label number 1 }

A: This has no label: \leftTailA{}

B: This has a label: \leftTailB{ label number 1 }

B: This has no label: \leftTailB{}

MA: This has a label: \distMarkup[leftTailLabel=label number 1]

MA: This has no label: \distMarkup[]

\end{document}

在此处输入图片描述

答案3

这是一个完全可扩展的解决方案。\pgfkeysvalueof必须扩展三次才能获得键的实际值,所以我们需要 2*3+1 \expandafters。

\documentclass[varwidth]{standalone}
\usepackage{pgfkeys}

\makeatletter

\def\pgfkeys@firstoftwo#1#2{#1}
\def\pgfkeys@secondoftwo#1#2{#2}

\def\ifpgfkeysempty#1{%
  \if\relax\detokenize\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{\pgfkeysvalueof{#1}}\relax
    \expandafter\pgfkeys@firstoftwo
  \else
    \expandafter\pgfkeys@secondoftwo
  \fi}

\def\pgfkeysmeaning#1{%
  {\ttfamily #1->|\detokenize\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{\pgfkeysvalueof{#1}}|}}

\makeatother

\pgfkeys{%
  /test1/.initial = {},
  /test2/.initial = \relax,
  /test3/.initial = {Foo},
  /test4/.initial = {\def#1\bar{bar}},
}

\begin{document}
\begin{itemize}
\item \pgfkeysmeaning{/test1}

  \ifpgfkeysempty{/test1}{Key is empty}{Key is not empty}
\item \pgfkeysmeaning{/test2}

  \ifpgfkeysempty{/test2}{Key is empty}{Key is not empty}
\item \pgfkeysmeaning{/test3}

  \ifpgfkeysempty{/test3}{Key is empty}{Key is not empty}
\item \pgfkeysmeaning{/test4}

  \ifpgfkeysempty{/test4}{Key is empty}{Key is not empty}
\end{itemize}
\end{document}

在此处输入图片描述

相关内容