我有以下设置将宏应用于命令的某些数据:
\makeatletter
\def\myqu@rck{\myqu@rck}
\pgfkeys{/mykeys/macro/.code=\mykeys@defmacro{#1}}
\def\mykeys@defmacro#1{\mykeys@@defmacro#1\myqu@rck}
%the user macros are maintained in a separate folder
\def\mykeys@@defmacro#1=#2\myqu@rck{\pgfkeys{/mykeys/user macros/#1/.code=#2}}
\makeatother
用法如下:
\mycomplicatedcmd[macro={bold=\textbf {#1}},temperature=bold,pressure,density]{<data>}
当发现温度时<data>
,会以粗体打印。
为了集中宏的定义,我需要另一个命令来定义所有这些宏。
工作设置
\def\mymacros#1{\pgfkeys{/mykeys/.cd,#1}}
\mymacros{macro={bold=\textbf{#1}}}
结果是: \pgfkeys{mykeys/macro={bold=\textbf{#1}}}
然后:\pgfkeys{mykeys/user macros/bold=\textbf{#1}}}
并且有效:
\pgfkeys{/mykeys/user macros/bold=test}
印刷测试
可以一次定义多个宏:
\mymacros{%
macro={italic=\textit{#1}},
macro={math=$#1$},
macro={small caps=\textsc{#1}}
}
\pgfkeys{/mykeys/user macros/italic=test};
\pgfkeys{/mykeys/user macros/math=\tau};
\pgfkeys{/mykeys/user macros/small caps=test}
修改设置(不工作)
\def\mymacros#1{\pgfkeys{/mykeys/.cd,macro={#1}}}
\mymacros{upper case=\MakeUppercase{#1}}
\pgfkeys{/mykeys/user macros/upper case=test}
有效,但现在我无法插入列表:
\mymacros{%
italic=\textit{#1},
% math=$#1$,
% small caps=\textsc{#1}
}
% yields: \pgfkeys{mykeys/macro=<list>}} which is wrong
因此,\mymacros
应该循环遍历列表。但pgfkeys
这样不行:
\pgfkeys{mykeys/macro/.list={upper case=\MakeUppercase{#1}}}
%! Illegal parameter number in definition of \pgffor@values
使用\@for
循环它也无法工作。
\makeatletter
\def\mymacros#1{%
\@for\my@temp:=#1\do{%
\pgfkeys{/mykeys/macro=\my@temp}
}}
\makeatother
\mymacros{upper case=\MakeUppercase{#1}}}
%! Illegal parameter number in definition of \@fortmp
完整的 MWE:
\documentclass{article}
\usepackage{pgfkeys}
\setlength{\parindent}{0pt}
\begin{document}
\makeatletter
\def\myqu@rck{\myqu@rck}
\pgfkeys{/mykeys/macro/.code=\mykeys@defmacro{#1}}
\def\mykeys@defmacro#1{\mykeys@@defmacro#1\myqu@rck}
% the user macros are maintained in a separate folder
\def\mykeys@@defmacro#1=#2\myqu@rck{\pgfkeys{/mykeys/user macros/#1/.code=#2}}
\makeatother
\subsection*{working setup}
\def\mymacros#1{\pgfkeys{/mykeys/.cd,#1}}
\mymacros{macro={bold=\textbf{#1}}}
% yields: \pgfkeys{mykeys/macro={bold=\textbf{#1}}}
% and then: \pgfkeys{mykeys/user macros/bold=\textbf{#1}}}
% and it works:
\pgfkeys{/mykeys/user macros/bold=test}
multiple macros can be defined at once:
\mymacros{%
macro={italic=\textit{#1}},
macro={math=$#1$},
macro={small caps=\textsc{#1}}
}
\pgfkeys{/mykeys/user macros/italic=test};
\pgfkeys{/mykeys/user macros/math=\tau};
\pgfkeys{/mykeys/user macros/small caps=test}
\subsection*{modified setup (non working)}
%I would like to avoid to write \verb|{macro={<macro>=<code>}}| every time.
It works for one:
\def\mymacros#1{\pgfkeys{/mykeys/.cd,macro={#1}}}
\mymacros{upper case=\MakeUppercase{#1}}
%
\pgfkeys{/mykeys/user macros/upper case=test}
but now I can not insert a list.
%%%pgfkeys does not work
%\pgfkeys{mykeys/macro/.list={upper case=\MakeUppercase{#1}}}
%%%! Illegal parameter number in definition of \pgffor@values
%%% this does not work either
\makeatletter
\def\mymacros#1{%
\@for\my@temp:=#1\do{%
\pgfkeys{/mykeys/macro=\my@temp}
}}
\makeatother
%\mymacros{bold=\textbf{#1}} %! Illegal parameter number in definition of \@fortmp
\end{document}
答案1
您可以使用另一个宏来循环遍历逗号分隔的列表。下面使用函数expl3
代替\clist_map_inline:nn
LaTeX2e 的\@for
。
\documentclass{article}
\usepackage{pgfkeys}
\setlength{\parindent}{0pt}
\begin{document}
\makeatletter
\def\myqu@rck{\myqu@rck}
\pgfkeys{/mykeys/macro/.code=\mykeys@defmacro{#1}}
\def\mykeys@defmacro#1{\mykeys@@defmacro#1\myqu@rck}
% the user macros are maintained in a separate folder
\def\mykeys@@defmacro#1=#2\myqu@rck{\pgfkeys{/mykeys/user macros/#1/.code=#2}}
\ExplSyntaxOn
\cs_new_eq:NN \clist@map@inline@@nn \clist_map_inline:nn
\ExplSyntaxOff
\def\mymacros#1{\clist@map@inline@@nn{#1}{\pgfkeys{/mykeys/macro={##1}}}}
\makeatother
\subsection*{working setup}
Multiple macros can be defined at once:
\mymacros{%
italic=\textit{#1},
math=$#1$,
small caps=\textsc{#1}
}
\pgfkeys{/mykeys/user macros/italic=test};
\pgfkeys{/mykeys/user macros/math=\tau};
\pgfkeys{/mykeys/user macros/small caps=test}
\end{document}
答案2
通过搜索\clist_map_inline:nn
,我找到了一篇由 Enrico Gregorio 撰写的文章,其中写道:
通过将每个项目传递给第二个参数来映射给定的列表,其中当前项目称为
#1
;这里需要将井号加倍,因为我们在定义主体中。将其与标准\@for
循环进行比较,其中当前项目存储在宏中,通常需要扩展,而且通常方式很尴尬(TUGboat,第 39 卷(2018 年),第 1 期,第 51-59 页)。
因此,要不使用expl3
,只需找到正确的笨拙方法并将哈希值加倍即可。必须注意的是,本文作者鼓励使用expl3
,以避免使用 的复杂用法\expandafter
。
\makeatletter
\def\mykeysmacro{/mykeys/macro=}
\def\mymacros#1{%
\@for\my@temp:=#1\do{%
\expandafter\expandafter\expandafter
\pgfkeys
\expandafter\expandafter\expandafter
{\expandafter\mykeysmacro\expandafter{\my@temp}}
}}
\makeatother
小心:双重哈希!
\mymacros{
italic=\textit{##1},
math=$##1$,
small caps=\textsc{##1}
}
\pgfkeys{/mykeys/user macros/italic=test};
\pgfkeys{/mykeys/user macros/math=\tau};
\pgfkeys{/mykeys/user macros/small caps=test}
这可行,但必须使用双重哈希值对用户来说不太舒服。我还找到了一种自动将其加倍的方法,请点击此处 @wipet
使用\scantokes
:
\documentclass{article}
\usepackage{pgfkeys}
\usepackage{verbatim}
\setlength{\parindent}{0pt}
\begin{document}
\makeatletter
\def\myqu@rck{\myqu@rck}
\pgfkeys{/mykeys/macro/.code=\mykeys@defmacro{#1}}
\def\mykeys@defmacro#1{\mykeys@@defmacro#1\myqu@rck}
% the user macros are maintained in a separate folder
\def\mykeys@@defmacro#1=#2\myqu@rck{\pgfkeys{/.
mykeys/user macros/#1/.code=#2}}
\def\my@keysmacro{/mykeys/macro=}
\def\mymacros#1{%
%%%
%%% https://tex.stackexchange.com/a/553015
%%%
\scantokens{\toks0{#1}}
\edef\my@tempb{\the\toks0}
%%%
\@for\my@tempa:=\my@tempb\do{%
\expandafter\expandafter\expandafter
\pgfkeys
\expandafter\expandafter\expandafter
{\expandafter\my@keysmacro\expandafter{\my@tempa}}
}}
\makeatother
\subsection*{this works}
\mymacros{
italic=\textit{#1},
math=$#1$,
small caps=\textsc{#1} }
\pgfkeys{/mykeys/user macros/italic=test};
\pgfkeys{/mykeys/user macros/math=\tau};
\pgfkeys{/mykeys/user macros/small caps=test}
\end{document}