以下代码尝试plain text
从格式化的参数(这里是\bfseries
)中提取但失败。
\x
用于存储的扩展结果\pgfkeysvalueof
。
\edef
是为了充分展开,\pgfkeysvalueof
得到后面可能会用到的键的值。
为什么第二次尝试还是错误呢?
如何在第二次尝试中ABC
从键的值中提取纯文本(此示例中未用粗体显示) ?\pgfkeys
代码:
\documentclass{article}
\usepackage{tikz,etoolbox}%
\begin{document}
%(1)
\pgfkeys{title/.initial,title=ABC}
\edef\x{\pgfkeysvalueof{/title}}\x %This works all right
%(2)
\pgfkeys{title=\bfseries ABC}
\edef\x{\pgfkeysvalueof{/title}}\x %This can not pass compile
\end{document}
答案1
我能想到三种方法。前两种方法忽略使用任何键。相反,我只使用命令结构。
第一个例子说明了基本思想。这和你用钥匙举的例子类似。
\documentclass{article}
\newcommand\lyimarkup{\bfseries}
\makeatletter
\newcommand\lyititle{\@ifstar{\lyititle@starred}{\lyititle@nostar}}
\newcommand\lyititle@starred[2]{\providecommand#1{}\renewcommand#1{#2}}
\newcommand\lyititle@nostar[2]{\providecommand#1{}\renewcommand#1{{\bfseries#2}}}
\makeatother
\begin{document}
\lyititle\x{Hello World}\x
\lyititle*\x{Hello World}\x
\end{document}
第二个例子说明了如何按照您在评论中所建议的内容来处理更具动态的内容。
\documentclass{article}
\usepackage{xcolor}
\newcommand\lyicolor[1]{\color{#1}}
\makeatletter
\newcommand\lyitext{\@ifstar{\lyitext@starred}{\lyitext@nostar}}
\newcommand\lyitext@starred[2]{%%
\providecommand#1{}%%
\renewcommand#1{{\renewcommand\lyicolor[1]{}#2}}}
\newcommand\lyitext@nostar[2]{\providecommand#1{}\renewcommand#1{#2}}
\makeatother
\begin{document}
\lyitext\x{ab{\lyicolor{red}cd}ef}\x
\lyitext*\x{ab{\lyicolor{red}cd}ef}\x%% no mark up
\lyitext\x{ab{\lyicolor{red}cd}ef}\x%% mark up restored
\end{document}
我会让你自己想办法如何使用 来实现这一点pgfkeys
。
上面给出的例子之所以这样写,是因为我想严格遵循 OP 在 MWE 中的做法。也许 OP 想使用\x
在整个文档的不同位置使用。但是,如果情况并非如此,并且如果原作者只想要渲染选项未标记文本,那么上述答案就显得比必要的更为笨重。
我不想假设 OP(或任何其他偶然发现此答案的人)对 LaTeX 的了解足以使这些示例更简单一些。因此,我在这里提供了简化版本。
第一个例子可以重写为:
\documentclass{article}
\newcommand\lyimarkup{\bfseries}
\makeatletter
\newcommand\lyititle{\@ifstar{\lyititle@starred}{\lyititle@nostar}}
\newcommand\lyititle@starred[1]{#1}
\newcommand\lyititle@nostar[1]{\textbf{#1}}
\makeatother
\begin{document}
\lyititle{Hello World}
\lyititle*{Hello World}
\end{document}
第二个示例可以重写为:
\documentclass{article}
\usepackage{xcolor}
\newcommand\lyicolor[1]{\color{#1}}
\makeatletter
\newcommand\lyitext{\@ifstar{\lyitext@starred}{\lyitext@nostar}}
\newcommand\lyitext@starred[1]{%%
{\renewcommand\lyicolor[1]{}%%
#1}}
\newcommand\lyitext@nostar[1]{#1}
\makeatother
\begin{document}
\lyitext{ab{\lyicolor{red}cd}ef}
\lyitext*{ab{\lyicolor{red}cd}ef}
\lyitext{ab{\lyicolor{red}cd}ef}
\end{document}
如果您尝试遵守内容和标记应明确分离的原则,那么这种情况相对容易处理。如果您不习惯这样做,而只考虑最终产品的外观,那么这将需要一些努力来学习。因此,例如,在数学教科书中,您可能会大胆的第一次介绍文本中的一个词时。
而不是写作
\textbf{new fangled word}
你可以写类似
\vocab{new fangled word}
你定义的地方
\newcommand\vocab[1]{\textbf{#1}}
您需要考虑如何构建文档。但是一旦您开始这样思考,LaTeX 的强大功能就会真正显现出来。
答案2
您可以使用\text_purify:n
中的函数expl3
。这不是一种万无一失的方法,因为解析 TeX 需要 TeX,但至少它可以在大多数简单情况下(例如您的 MWE)工作。
\documentclass{article}
\usepackage{tikz,etoolbox}%
\ExplSyntaxOn
\NewExpandableDocumentCommand \PurifiedPgfkeysvalueof { m }
{ \text_purify:n { \pgfkeysvalueof {#1} } }
\NewDocumentCommand \GetPurifiedPgfkey { m m }
{ \tl_set:Nx #1 { \text_purify:n { \pgfkeysvalueof {#2} } } }
\ExplSyntaxOff
\begin{document}
%(1)
\pgfkeys{title/.initial,title=ABC}
\edef\x{\pgfkeysvalueof{/title}}\x %This works all right
%(2)
\pgfkeys{title=\bfseries ABC}
\GetPurifiedPgfkey\mytitle{/title}\mytitle %This can not pass compile
or without an assignment: \PurifiedPgfkeysvalueof{/title}
\end{document}
答案3
如果您知道提取的文本中使用了哪些宏,那么您可以\let
将它们\relax
临时放在一个组中:
\pgfkeys{title=\bfseries ABC}
{\let\bfseries=\relax \xdef\x{\pgfkeysvalueof{/title}}}\meaning\x
如果你不知道文中用到的宏,那么必须使用正确数量的宏\expandafter
来连接\unexpanded
才能展开\pgfkeysvalueof
宏的正确级别:
\def\threeexa{\expandafter\expandafter\expandafter}
\def\pgfkeyprotect#1#2{\unexpanded\expandafter\threeexa\expandafter{#1{#2}}}
\pgfkeys{title=\bfseries ABC}
\edef\x{\pgfkeyprotect\pgfkeysvalueof{/title}}\meaning\x