
最近、 のキー値インターフェイスとハンドラー インターフェイスの使用の違いに関する投稿をたくさん読んでいますpgfkeys
。私の理解では、どちらの方法でも同じ値を保存および取得できます。例:
\documentclass{article}
\usepackage{tikz}
\pgfkeys{
/testa/.initial,
/testb/.store in=\testbvalue,
}
\begin{document}
\def\foo{bar}
\pgfkeys{/testa=\foo,/testb=\foo}
\pgfkeysvalueof{/testa}
\testbvalue
\pgfkeysgetvalue{/testa}\testavalue
\meaning\testavalue
\meaning\testbvalue
\end{document}
\pgfkeysvalueof{/testa}
ここで、とを通じて同じ値を取得できます\testbvalue
。実際、\testavalue
との意味\testbvalue
は同じです(驚くことではありません)。しかし、次のコードはなぜ機能するのでしょうか?
\documentclass{article}
\usepackage{tikz}
\usepackage{etoolbox}
\usepackage{overpic}
\pgfkeys{
/icon/.cd,
width/.initial,
overlay/.store in=\iconoverlay,
set defaults/.unknown/.code={\pgfkeys{/icon/\pgfkeyscurrentname/.default=#1}}
}
\newcommand\icondefaults[1]{%
\pgfkeys{/icon/set defaults/.cd, #1}%
}
\newcommand\ifkeyempty[3]{%
\pgfkeysgetvalue{#1}{\keyvalue}%
\ifempty{\keyvalue}{#2}{#3}%
}
\newcommand\ifempty[3]{%
\def\novalue{\pgfkeysnovalue}%
\def\empty{}%
\ifboolexpr{test {\ifdefequal{#1}{\empty}} or test {\ifdefequal{#1}{\novalue}}}{#2}{#3}%
}
\newcommand{\icon}[2][]{%
{%
\pgfkeys{/icon/.cd,width,overlay,#1}% Reset to default values
\def\options{}%
\ifkeyempty{/icon/width}{}{\edef\options{width=\pgfkeysvalueof{/icon/width},\options}}%
\ifempty{\iconoverlay}{%
\edef\graphic{\noexpand\includegraphics[\options]{#2}}%
}{%
\edef\overlay{\noexpand\begin{overpic}[\options]{#2}}%
\def\graphic{\overlay\put(0,0){\iconoverlay}\end{overpic}}%
}%
\graphic%
}%
}%
\begin{document}
\icondefaults{width=6cm}
\icon{example-image} % Image gets default width 6cm
\icon[width=2cm,overlay={\icon{example-image-overlay}}]{example-image} % Image gets width 2cm, while the overlaid image gets default width 6cm
\icon{example-image} % Image gets default width 6cm
\end{document}
次のコード セクションは機能しません。唯一の違いは、 が/.store in
キーに使用されずoverlay
、したがって が\pgfkeysvalueof
キーの値にアクセスするために使用されることです。その結果、エラーが発生しますTeX capacity exceeded
。
\documentclass{article}
\usepackage{tikz}
\usepackage{etoolbox}
\usepackage{overpic}
\pgfkeys{
/icon/.cd,
width/.initial,
overlay/.initial,
set defaults/.unknown/.code={\pgfkeys{/icon/\pgfkeyscurrentname/.default=#1}}
}
\newcommand\icondefaults[1]{%
\pgfkeys{/icon/set defaults/.cd, #1}%
}
\newcommand\ifkeyempty[3]{%
\pgfkeysgetvalue{#1}{\keyvalue}%
\ifempty{\keyvalue}{#2}{#3}%
}
\newcommand\ifempty[3]{%
\def\novalue{\pgfkeysnovalue}%
\def\empty{}%
\ifboolexpr{test {\ifdefequal{#1}{\empty}} or test {\ifdefequal{#1}{\novalue}}}{#2}{#3}%
}
\newcommand{\icon}[2][]{%
{%
\pgfkeys{/icon/.cd,width,overlay,#1}% Reset to default values
\def\options{}%
\ifkeyempty{/icon/width}{}{\edef\options{width=\pgfkeysvalueof{/icon/width},\options}}%
\ifkeyempty{/icon/overlay}{%
\edef\graphic{\noexpand\includegraphics[\options]{#2}}%
}{%
\edef\overlay{\noexpand\begin{overpic}[\options]{#2}}%
\def\graphic{\overlay\put(0,0){\pgfkeysvalueof{/icon/overlay}}\end{overpic}}%
}%
\graphic%
}%
}%
\begin{document}
\icondefaults{width=6cm}
\icon{example-image} % Image gets default width 6cm
\icon[width=2cm,overlay={\icon{example-image-overlay}}]{example-image} % Image gets width 2cm, while the overlaid image gets default width 6cm
\icon{example-image} % Image gets default width 6cm
\end{document}
この動作を説明できる人はいますか? どちらの場合も同じ値が保存され、取得されるが、方法が異なるだけ、という私の理解は間違っていますか?
答え1
これらは同等ではありません。/.store in
ハンドラーは単に\def
操作を実行し、値を保持しません。ただし、キーを設定すると、そのスコープに設定されている値を取得できます。そのため、2 番目のケースではキーを設定する必要があります。
最初の方法は、デフォルトの動作への設定が再帰の両方のレベルでローカルに使用できるため機能します。ただし、2 番目の方法ではキーの値が変更されません。
そのためには、次の行でオーバーレイキーを明示的に何も設定しない必要があります。
\pgfkeys{/icon/.cd,width,overlay=,#1}% Notice the equal sign for the overlay key