没有参数的 pgf 密钥样式,或者如何避免转义哈希

没有参数的 pgf 密钥样式,或者如何避免转义哈希

我期望用户写类似这样的内容:

\pgfkeys{
  latex/.append style={
    add to preamble={
      \def\sayhello#1{Hello #1.}
    }
  },
}

但这不起作用,因为它#1被理解为 latex 样式的第一个参数,而我期望它只是符号#。所以我需要将哈希值的数量加倍,例如:

\pgfkeys{
  latex/.append style={
    add to preamble={
      \def\sayhello##1{Hello ##1.}
    }
  },
}

但是,没有理由定义#1,因为latex无论如何都不需要参数。

是否可以说不add to preamble应该尝试将内部哈希解释为参数?我想也许可以使用 catcode,但重要的是这些 catcode 应该在定义中一次性添加,add to preamble但这不是我希望最终用户输入的代码(基本上他们应该或多或少地输入我在第一个代码中写的内容)。

平均能量损失

\documentclass[]{article}
\usepackage{tikz}
\begin{document}

\ExplSyntaxOn

%% See also https://tex.stackexchange.com/questions/695432/latex3-latex-doubles-the-number-of-hashes-when-storing-them-in-string/695460#695460
\cs_generate_variant:Nn \str_replace_all:Nnn { Nnx }
\cs_set:Nn \str_set_hash_robust:Nn {
  \str_set:Nn {#1} {#2}
  \str_replace_all:Nnx {#1} { ## } { \c_hash_str }
}

\NewDocumentCommand{\defineString}{m}{
  \str_set_hash_robust:Nn \l_test_str {#1} 
}

\NewDocumentCommand{\showString}{}{
  \show \l_test_str
}

\ExplSyntaxOff

% To show that in a normal setting hashes are not doubled
\defineString{Hey \notexistingbutnoproblem #}
\showString

%%% Code of the library: feel free to do anything here
\pgfkeys{
  latex/.style={
    add to preamble/.code={\defineString{##1}},
    show string/.code={\showString},
  },
  add to style/.style 2 args={
    #1/.append style={
      #2
    },
  },
}



%%% Code of the user: ideally modify as little as possible, especially no catcode stuff.
%%% I’m fine with defining "my append to style={latex}{add to preamble={...}}" but no catcode stuff here.
\pgfkeys{
  %% I don't want the user to use ##, a single # should be enough.
  %%
  add to style={latex}{
    %% This should contain only # instead of ##
    % Works:
    add to preamble={\def\sayhello##1{Hello ##1}}
    % Fails:
    % add to preamble={\def\sayhello#1{Hello #1}}
  },
  latex,
  show string
}


\end{document}

编辑

我发现 (编辑2实际上它不能完美地工作,就好像代码包含占位符一样,它们也被替换了,并且会破坏系统,我需要一个更具体的替换函数)通过​​替换latex/.append style={…}我创建的自定义内容来解决问题add to style={latex}{…}。这会将第二个参数转换为字符串,然后将其转换###,将其放入字符串中,创建(使用我的库 robustExternalize 中的占位符,在展开后我会{…}在字符串周围得到额外的内容,不知道为什么,肯定是 catcode 魔法)。然后我添加\pgfkeys-stuff,然后重新扫描这个字符串(再次使用 robustExternalize)...我想有一个更好的解决方案,但这是我现在找到的唯一解决方案。

\documentclass[]{article}
\usepackage{tikz}
\usepackage{robust-externalize} % Allows manipulation with placeholder, not even sure how to do it efficiently without. Copy .sty from https://github.com/leo-colisson/robust-externalize (freshly added in CTAN)
\begin{document}

\ExplSyntaxOn

%% See also https://tex.stackexchange.com/questions/695432/latex3-latex-doubles-the-number-of-hashes-when-storing-them-in-string/695460#695460
\cs_generate_variant:Nn \str_replace_all:Nnn { Nnx }
\cs_set:Nn \str_set_hash_robust:Nn {
  \str_set:Nn {#1} {#2}
  \str_replace_all:Nnx {#1} { ## } { \c_hash_str }
}
\cs_generate_variant:Nn \str_set_hash_robust:Nn { cn }
% Double the number of hashes... quite dirty but cannot find any solution or the user need to double it itself
% 
\cs_set:Nn \str_set_hash_double:Nn {
  \str_set:Nn {#1} {#2}
  \str_replace_all:Nnx {#1} { ## } { \c_hash_str \c_hash_str }
}

\NewDocumentCommand{\defineString}{m}{
  \str_set_hash_robust:Nn \l_test_str {#1} 
}

\NewDocumentCommand{\strSetDoubleHash}{mm}{
  \str_set:Nn {#1} {#2}
  \str_replace_all:Nnx {#1} { ## } { \c_hash_str \c_hash_str }
}

\NewDocumentCommand{\showString}{}{
  \show \l_test_str
}

\ExplSyntaxOff

% To show that in a normal setting hashes are not doubled
\defineString{Hey \notexistingbutnoproblem #}
\showString

%%% Code of the library: feel free to do anything here
\pgfkeys{
  latex/.style={
    add to preamble/.code={\defineString{##1}},
    show string/.code={\showString},
  },
  add to style/.code 2 args={%
    \strSetDoubleHash{\robExtTmpStr}{#2}
    % Sadly, \expanded{\noexpand } does not work, as I get extra {} around the def, creating a group
    % so the simpler seems to use this library ^^
    \robExtPlaceholderFromString{__ROBEXT_TMP__}{\robExtTmpStr}%
    \robExtEvalPlaceholder{%
      \pgfkeys{%
        #1/.append style={__ROBEXT_TMP__},%
      }%
    }%
    \robExtRemovePlaceholder{__ROBEXT_TMP__}% let us clean our variables
  },
}



%%% Code of the user: ideally modify as little as possible, especially no catcode stuff.
%%% I’m fine with defining "my append to style={latex}{add to preamble={...}}" but no catcode stuff here.
\pgfkeys{
  %% I don't want the user to use ##, a single # should be enough.
  %%  
  add to style={latex}{
    add to preamble={\def\sayhello#1{Hello #1}\foo},
  },
  latex,
  show string
}


\end{document}

如果你知道更好的解决方案,请告诉我^^

相关内容