
我花了大約五個小時(!)學習如何建立帶有鍵值的命令?(和其他資源)並試圖了解如何實現關鍵值,這非常令人困惑。我寫了一個本質上微不足道的測試案例(無論如何,對於這裡的大多數人來說),並且存在一些我無法解釋的不一致之處。
這是一個使用 的 MWE keyval
。
% !TEX TS-program = lualatexmk
% !TEX encoding = UTF-8 Unicode
\documentclass{article}
\usepackage{keyval}
\makeatletter
% Key definitions
\define@key{sayhello}{towhom}{\def\sh@towhom{#1}}
% Key defaults
\setkeys{sayhello}{towhom=Michael}
% Define the command that uses the key
\newcommand{\sayhello}[2][]{%
%\begingroup% localizes the new settings w/o calling the defaults
\setkeys{sayhello}{towhom=Michael} % Reset defaults w/o localizing
\setkeys{sayhello}{#1} % Set new keys
Say hello to \sh@towhom\ #2.
%\endgroup%
}%
\makeatother
\begin{document}
\sayhello{tomorrow}
%\sayhello[towhom]{today} % throws no value specified for towhom
\sayhello[towhom=Jill]{tomorrow}
%\sayhello[towhom]{today} % throws no value specified for towhom
\sayhello[towhom=Joe]{tomorrow}
%\sayhello[towhom]{tomorrow} % throws no value specified for towhom
\sayhello{today}
\end{document}
這是一個使用 的 MWE pgfkeys
。
% !TEX TS-program = lualatexmk
% !TEX encoding = UTF-8 Unicode
\documentclass{article}
\usepackage{pgfkeys}
\pgfkeys{%
/sayhello/.is family, /sayhello,
towhom/.default=Michael,
towhom/.store in=\sayto
}%
\newcommand*{\sayhello}[2][]{%
\pgfkeys{/sayhello,#1}
Say hello to \sayto\ #2.
}%
\begin{document}
%\sayhello{tomorrow} % throws undefined control sequence
\sayhello[towhom]{today}
\sayhello[towhom=Jill]{tomorrow}
\sayhello[towhom]{today}
\sayhello[towhom=Joe]{tomorrow}
\sayhello[towhom]{tomorrow}
\sayhello{today} % works perfectly
\end{document}
我希望兩種實作都能給出相同的結果。他們不。keyval
似乎不喜歡指定沒有值的鍵。pgfkeys
當根本沒有給出任何選項時,行為不一致,但在keyval
沒有給出選項的情況下,行為完美。我的範例編碼不正確嗎?不一致的行為是預期的嗎?我徹底糊塗了。
答案1
您混淆了初始值和預設值。如果您使用鍵而不給出值,請使用第二個。除此之外,如果您使用命令來儲存鍵值,最好先使用 定義它\newcommand
,因為這將避免您覆蓋現有命令。
就我個人而言,我確實發現pgfkeys
更令人困惑,因為使用相同的命令來定義和設定鍵,並且理解某些處理程序的行為並不總是容易的,請參見例如pgfkeys 金鑰處理程序 .get 和 .store 的作用是什麼?。
\documentclass{article}
\usepackage{keyval}
\makeatletter
\newcommand\sh@towhom{}
\define@key{sayhello}{towhom}[Default]{\def\sh@towhom{#1}}
\setkeys{sayhello}{towhom=Initial}
\newcommand{\sayhello}[2][]{%
\begingroup
\setkeys{sayhello}{#1} % Set new keys
keyval, say hello to \sh@towhom\ #2.
\endgroup%
}%
\makeatother
\usepackage{pgfkeys}
\newcommand\sayto{}
\pgfkeys{%
/sayhello/.is family, /sayhello,
towhom/.store in=\sayto,
towhom/.default=Default,
towhom = Initial,
}%
\newcommand*{\sayhellopgf}[2][]{%
\begingroup
\pgfkeys{/sayhello,#1}%
pgfkeys, say hello to \sayto\ #2.
\endgroup
}%
\ExplSyntaxOn
\tl_new:N \l_sayhello_towhom_tl
\keys_define:nn {sayhello}
{
towhom .tl_set:N = \l_sayhello_towhom_tl,
towhom .initial:n = Initial,
towhom .default:n = Default
}
\NewDocumentCommand\sayhelloexpl{O{}m}
{
\group_begin:
\keys_set:nn{sayhello}{#1}
l3keys,~say~hello~to~\l_sayhello_towhom_tl\c_space_tl#2
\group_end:
}
\ExplSyntaxOff
\begin{document}
\sayhello{tomorrow}
\sayhello[towhom]{today}
\sayhello[towhom=Jill]{tomorrow}
\sayhello[towhom]{today}
\sayhello[towhom=Joe]{tomorrow}
\sayhello[towhom]{tomorrow}
\sayhello{today}
\sayhellopgf{tomorrow}
\sayhellopgf[towhom]{today}
\sayhellopgf[towhom=Jill]{tomorrow}
\sayhellopgf[towhom]{today}
\sayhellopgf[towhom=Joe]{tomorrow}
\sayhellopgf[towhom]{tomorrow}
\sayhellopgf{today}
\sayhelloexpl{tomorrow}
\sayhelloexpl[towhom]{today}
\sayhelloexpl[towhom=Jill]{tomorrow}
\sayhelloexpl[towhom]{today}
\sayhelloexpl[towhom=Joe]{tomorrow}
\sayhelloexpl[towhom]{tomorrow}
\sayhelloexpl{today}
\end{document}