我正在尝试定义一个 pgf 密钥处理程序, name/.unquote and store in=\command
以便{name="quoted string"}
或{name=unquotedstring}
两者都能工作。也就是说,的最终效果.unquote and store in
是从参数中删除可选的外部字符串标记。
到目前为止,我还没能做到。从我尝试的情况来看,\@ifnextchar
在下面的 MWE 中使用时,一切都会崩溃 [我也尝试了\expandafter
几个阶段,但都无济于事]。
你能帮我吗?
\documentclass{article}
\usepackage{pgfkeys}
\usepackage{fontawesome5}
\begin{document}
\makeatletter
\def\remove@quotes@eov"#1"#2\pgfeov{#1}
\def\remove@eov#1\pgfeov{#1}
\def\maybe@remove@quotes#1\pgfeov{\@ifnextchar"%
{\let\@next=\remove@quotes@eov}{\let\@next=\remove@eov}%
\@next#1\pgfeov}
\pgfkeys{/handlers/.unquote and store in/.code=%
{%
\pgfkeysalso{%
\pgfkeyscurrentpath/.code=%
{%
\edef#1{\maybe@remove@quotes##1\pgfeov}%
}%
}%
}%
}%
\pgfkeys{/faicon/.is family, /faicon/.cd,
name/.unquote and store in=\shtcIconName,
style/.unquote and store in=\shtcIconStyle,
}
\newcommand\shortcodefaicon[1][]{\pgfkeys{/faicon/.cd,#1}\faIcon[\shtcIconStyle]{\shtcIconName}}
\shortcodefaicon[name="apple", style=regular]
\end{document}
答案1
使用 expl3 会更简单一些。假设将输入转换为字符串没有问题,并且如果第一个字符是,"
那么最后一个字符也是。
%! TEX program = lualatex
\documentclass{article}
\usepackage{pgfkeys}
\usepackage{fontawesome5}
\begin{document}
\makeatletter
\ExplSyntaxOn
\cs_generate_variant:Nn \str_if_eq:nnTF {x}
\cs_new_protected:Npn \assignRemoveQuotes #1 #2 {
\str_if_eq:xnTF {\str_head:n {#2}} {"} {
\str_set:Nx #1 {\str_range:nnn {#2} {2} {-2}}
} {
\str_set:Nn #1 {#2}
}
}
\ExplSyntaxOff
\pgfkeys{/handlers/.unquote and store in/.code=%
{%
\pgfkeysalso{%
\pgfkeyscurrentpath/.code=%
{%
\assignRemoveQuotes{#1}{##1}%
}%
}%
}%
}%
\pgfkeys{/faicon/.is family, /faicon/.cd,
name/.unquote and store in=\shtcIconName,
style/.unquote and store in=\shtcIconStyle,
}
\newcommand\shortcodefaicon[1][]{\pgfkeys{/faicon/.cd,#1}\faIcon[\shtcIconStyle]{\shtcIconName}}
\shortcodefaicon[name="apple", style=regular]
\end{document}
出于教育目的,采用 LaTeX2e 编程风格的解决方案。
%! TEX program = lualatex
\documentclass{article}
\usepackage{pgfkeys}
\usepackage{fontawesome5}
\begin{document}
\makeatletter
\errorcontextlines=5
\def\remove@quotes@eov"#1"\myeov#2{\def#2{#1}}
\def\remove@eov#1\myeov#2{\def#2{#1}}
\def\maybe@remove@quotes{\@ifnextchar"%
\remove@quotes@eov \remove@eov%
}
\pgfkeys{/handlers/.unquote and store in/.code=%
{%
\pgfkeysalso{%
\pgfkeyscurrentpath/.code=%
{%
\maybe@remove@quotes##1\myeov#1%
}%
}%
}%
}%
\pgfkeys{/faicon/.is family, /faicon/.cd,
name/.unquote and store in=\shtcIconName,
style/.unquote and store in=\shtcIconStyle,
}
\newcommand\shortcodefaicon[1][]{\pgfkeys{/faicon/.cd,#1}\faIcon[\shtcIconStyle]{\shtcIconName}}
\shortcodefaicon[name="apple", style=regular]
\end{document}
虽然它只有当你正确研究宏扩展规则并手动跟踪执行过程时才真正具有“教育目的”。(大多数人没有真的想学这个。
顺便说一句,重用\pgfeov
被证明是一个非常糟糕的主意。(当“神秘错误”出现时,我应该猜到的。)所以\myeov
在代码中将其重命名为。
答案2
这是一个 PGFkeys 解决方案,它使用一些辅助宏(存储为其他键),从其参数中剥离正常"
或活动"
,以及一个仅抓取整个参数的简单宏。
无需\pgfeov
使用多个支架保护,原来的\pgfkeysdef
宏被用来(本来会被使用)来向 PGFKeys 解析器.code
隐藏该对象。\pgfeov
否则,我们将需要三个括号(或另一个辅助宏,如\@firstofone
):
\pgfkeys{
/handlers/.unquote and store in/.style={
\pgfkeyscurrentpath/.code={{{% Eugh!
\@ifnextchar"{\pgfkeysvalueof{/handlers/helper/unquote/.@cmd}}{%
\expandafter\@ifnextchar\@activedblquote
{\pgfkeysvalueof{/handlers/helper/unquote active/.@cmd}}
{\pgfkeysvalueof{/handlers/helper/store in/.@cmd}}}##1\pgfeov
\let#1\pgfkeys@temp}}}}}
\pgfeov
当然,如果你使用自己的解包器,那么首先就不需要在这里使用:
\def\removeNormalDblQuote"#1"\myeov{…}
\def\removeActiveDblQuote"#1"\myeof{…} % with active " of course
\def\donotremoveaDblQuote#1\myeov{…}
您只需要确保实际上“看到” /\@ifnextchar
的第一个字符...所以不要在那里使用该宏,那是行不通的。#1
##1
\@next
顺便说一句,您的定义不会存储未加引号的参数,#1
而是会存储整个\maybe@remove@quotes
说辞。这也不行,因为\faIcon
那里需要一个完全可扩展的参数。
代码
\documentclass{article}
\usepackage{pgfkeys}
\usepackage[ngerman]{babel}
\makeatletter
\pgfkeys{/handlers/helper/.cd,
unquote/.code args={"#1"}{\def\pgfkeys@temp{#1}},
store in/.code={\def\pgfkeys@temp{#1}}}
\begingroup % active " for babel user
\catcode`\"\active
\gdef\@activedblquote{"}%
\expandafter
\endgroup\@firstofone{%
\pgfkeys{/handlers/helper/unquote active/.code args=%
{"#1"}{\def\pgfkeys@temp{#1}}}}
\pgfkeys{
/handlers/.unquote and store in/.code=%
\pgfkeysdef{\pgfkeyscurrentpath}{% \pgfkeysdef is what .code actually does
\@ifnextchar"{\pgfkeysvalueof{/handlers/helper/unquote/.@cmd}}{%
\expandafter\@ifnextchar\@activedblquote
{\pgfkeysvalueof{/handlers/helper/unquote active/.@cmd}}
{\pgfkeysvalueof{/handlers/helper/store in/.@cmd}}}##1\pgfeov
\let#1\pgfkeys@temp}}
\makeatother
\usepackage{fontawesome5}
\begin{document}
\pgfkeys{/faicon/.is family, /faicon/.cd,
name/.unquote and store in=\shtcIconName,
style/.unquote and store in=\shtcIconStyle}
\newcommand\shortcodefaicon[1][]{%
\pgfkeys{/faicon/.cd,#1}\faIcon[\shtcIconStyle]{\shtcIconName}}
\shortcodefaicon[name="apple", style=regular]
\end{document}