将 #1 传递给 \pgfkeys

将 #1 传递给 \pgfkeys

我有以下设置将宏应用于命令的某些数据:

\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:nnLaTeX2e 的\@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}

在此处输入图片描述

相关内容