我期望用户写类似这样的内容:
\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}
如果你知道更好的解决方案,请告诉我^^