从样式中删除键

从样式中删除键

是否可以使用pgfkeys从样式中删除键的包来创建键处理程序?

这是一个最小的工作示例:

\documentclass[preview,margin=10pt,convert]{standalone}
\usepackage{pgfkeys}
\pgfkeys{/a/.code={a#1},
    /b/.code={b#1},
    /c/.code={c#1}}
\pgfkeys{/my style/.style = {/a=1, /b=2, /c=3}}
\begin{document}
\pgfkeys{/my style}\par
%\pgfkeys{/my style/.remove from style = {b}}
\pgfkeys{/my style}
\end{document}

输出为

a1b2c3a1b2c3

如果取消注释注释行,则所需的输出将是

a1b2c3
a1c3

这里有几个密切相关的问题。它们不是这个问题的重复,但第二个问题的答案可能有助于设计这个问题的答案。

取消设置 PGF/TikZ 密钥

如何从 pgfkeys 样式元素中提取值

答案1

下面在的帮助下实现了这一点expkv(因为它可扩展并且速度快,所以我可以更轻松地设置键过滤)。

它利用 的内部结构.style,解析存储的键列表,并过滤该键列表内的值。

警告:您必须提供与样式中定义完全一致的关键路径,此解决方案不进行广泛的路径解析。

\documentclass[preview,margin=10pt]{standalone}
\usepackage{pgfkeys}

% how a style is defined (current code 2023-06-17)
\iffalse
\pgfkeys{/handlers/.style/.code=\pgfkeys{\pgfkeyscurrentpath/.code=\pgfkeysalso{#1}}}
\pgfkeysdef{/handlers/.code}{\pgfkeysdef{\pgfkeyscurrentpath}{#1}}
\long\def\pgfkeysdef#1#2{%
  \long\def\pgfkeys@temp##1\pgfeov{#2}%
  \pgfkeyslet{#1/.@cmd}{\pgfkeys@temp}%
  \pgfkeyssetvalue{#1/.@body}{#2}%
}
\long\def\pgfkeyslet#1#2{%
  \expandafter\let\csname pgfk@#1\endcsname#2%
}
\fi

\pgfkeys
  {
     /a/.code={a#1}
    ,/b/.code={b#1}
    ,/c/.code={c#1}
    ,/my style/.style = {/a=1, /b=2, /c=3}
  }

\usepackage{expkv} % yes, I use expkv to filter pgfkeys...

\makeatletter
\ExplSyntaxOn
\cs_new:Npn \mypgfkeys@checkstyle #1
  {
    \bool_lazy_and:nnF
      { \tl_if_head_eq_meaning_p:nN {#1} \pgfkeysalso }
      { \exp_args:No \tl_if_single_p:n { \use_none:n #1 } }
  }
\ExplSyntaxOff
\protected\def\mypgfkeys@not@a@style
  {%
    \PackageError{mypgfkeys}{Not a style: \pgfkeyscurrentpath}{}
    \mypgfkeys@break
  }
\def\mypgfkeys@breakpoint#1{}
\def\mypgfkeys@break#1\mypgfkeys@breakpoint#2{#2}
\pgfkeys{/handlers/.remove from style/.code=\mypgfkeysrmfromstyle{#1}}
\def\mypgfkeysrmfromstyle@mark{\mypgfkeysrmfromstyle@mark}
\protected\def\mypgfkeysrmfromstyle#1%
  {%
    \begingroup
      \ekvcsvloop\mypgfkeysrmfromstyle@makemark{#1}%
      \expandafter\let\csname mypgfkeys@@#1\endcsname\mypgfkeysrmfromstyle@mark
      \pgfkeysgetvalue{\pgfkeyscurrentpath/.@body}\mypgfkeysrmfromstyle@body
      \ifx\mypgfkeysrmfromstyle@body\relax
        \mypgfkeys@not@a@style
      \fi
      \expandafter\mypgfkeys@checkstyle\expandafter
        {\mypgfkeysrmfromstyle@body}%
        \mypgfkeys@not@a@style
      \edef\mypgfkeysrmfromstyle@body
        {%
          \expanded
            {%
              \expandafter\mypgfkeysrmfromstyle@do\expandafter
                {\mypgfkeysrmfromstyle@body}%
            }%
        }%
    \expanded{%
    \endgroup
    \unexpanded{\pgfkeys}%
      {%
        \pgfkeyscurrentpath/.style=
          {%
            \unexpanded\expandafter\expandafter\expandafter
              {\expandafter\@gobble\mypgfkeysrmfromstyle@body}%
          }%
      }%
    }%
    \mypgfkeys@breakpoint\endgroup
  }
\protected\def\mypgfkeysrmfromstyle@makemark#1%
  {\expandafter\let\csname mypgfkeys@@#1\endcsname\mypgfkeysrmfromstyle@mark}
\def\mypgfkeysrmfromstyle@do#1%
  {\expandafter\mypgfkeysrmfromstyle@do@\expandafter{\@secondoftwo#1}}
\def\mypgfkeysrmfromstyle@do@
  {\ekvparse\mypgfkeysrmfromstyle@do@k\mypgfkeysrmfromstyle@do@kv}
\def\mypgfkeysrmfromstyle@do@k#1%
  {%
    \expandafter\ifx\csname mypgfkeys@@#1\endcsname\mypgfkeysrmfromstyle@mark
      \expandafter\@gobbletwo
    \fi
    \unexpanded{,#1}%
  }
\long\def\mypgfkeysrmfromstyle@do@kv#1#2%
  {%
    \expandafter\ifx\csname mypgfkeys@@#1\endcsname\mypgfkeysrmfromstyle@mark
      \expandafter\@gobbletwo
    \fi
    \unexpanded{,#1= {#2}}%
  }
\makeatother

%\expandafter\show\csname pgfk@/my style/.@body\endcsname

\begin{document}
\pgfkeys{/my style}\par
\pgfkeys{/my style/.remove from style={/b,/c}}
\pgfkeys{/my style}
\end{document}

在此处输入图片描述

答案2

根据您的使用情况,您可以安装密钥过滤器

这不会/b从中删除,只是在使用它时/my style禁用样式(或任何其他样式) 。/b/my style\pgfkeysfiltered

代码

\documentclass{article}
\usepackage{pgfkeys}
\pgfkeys{
  /a/.code={a#1},
  /b/.code={b#1},
  /c/.code={c#1},
  /my style/.style = {/a=1, /b=2, /c=3},
  /x/.style={/b=3, /c=4},
}
\begin{document}
normal: \pgfkeys{/my style}\par
\pgfkeys{
  /pgf/key filters/not/.install key filter={
    /pgf/key filters/equals=/b
  }
}
filtered: \pgfkeysfiltered{/my style}\par
Add /x \pgfkeys{/my style/.append style=/x}
and filter: \pgfkeysfiltered{/my style}\par
\end{document}

输出

正常:a1b2c3
过滤:a1c3
添加/x 并过滤:a1c3c4

相关内容