我希望\fn
在字符串中使用以前缀开头的命令时自动定义新命令和键值定义。
第一部分下面是需要更改的存根,以便当我输入第二部分(输入文件),第三部分使用适当的代码生成以fn-something-text = "the text"
将的文本路由fnSomething
为脚注文本。
希望这足以清楚地解释我所追求的内容,但下面示例文档中的评论更为详尽。
\documentclass{article}
\usepackage{keyval}
\begin{document}
% PART I (the part that makes it all happen):
% My main doc should establish a routine to test a string (arg #2) for any
% commands that begin with \fn. This procedure would be in place of `\testmystring` in:
\newcommand{\mycommand}[2]{%
\testmystring{#2}% look for and generate \fn commands, and generate key defs
\setkeys{mykeys}{#1}% set the values for those keys
{#2}% now expand the string
}
% PART II
% This is all that is in my input file, myinput.tex:
\mycommand{%
fn-foo-text = {This is my foo footnote.}}
}
{This is\fnFoo my new message.}
% PART III (what \testmystring should do)
% When \fn*suffix* is used, the use of `\fn` should trigger/generate the
% following definitions, which will insert *suffix* into the correct spots.
% In my example, both `Foo` and `Bar` and `BuzBee` are new suffixes.
\makeatletter
\define@key{mykeycollection}{fn-foo-text}{\def\fnfootext{#1}}
\makeatother
\def\fnFoo{\footnote{\fnfootext}}
Hopefully this is possible.
\end{document}
这个问题有点棘手,所以非常感谢你的帮助!如果我能找到任何答案,我会跟进的。
奖金:我没有在文档注释中指定这一点,但该函数也应该响应驼峰式命名法,以便fnBuzBee
将fn-buz-bee-text
(和自然\fnbuzbeetext
)发送到生成的 keyval 定义中的相应位置。这并不是这个问题的主要挑战,但如果在解决方案中也能实现这一点就好了。
答案1
这是你想要的?
\documentclass{scrartcl}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand \command { m m }
{
\group_begin:
\keyval_parse:NNn \use_none:n \jshivers_command:nn { #1 }
#2
\group_end:
}
\cs_generate_variant:Nn \seq_set_split:Nnn { NnV }
\cs_new_protected:Npn \jshivers_command:nn #1 #2
{
\tl_set:Nn \l_tmpa_tl { #1 }
\tl_remove_all:Nn \l_tmpa_tl { fn- }
\tl_remove_all:Nn \l_tmpa_tl { -text }
\seq_set_split:NnV \l_tmpa_seq { - } \l_tmpa_tl
\tl_clear:N \l_tmpa_tl
\seq_map_inline:Nn \l_tmpa_seq
{ \tl_put_right:Nx \l_tmpa_tl { \tl_upper_case:n ##1 } }
\tl_set:cn { fn \l_tmpa_tl } { #2 }
}
\ExplSyntaxOff
\begin{document}
\command{
fn-foo-text = {This is my foo footnote.},
fn-bar-text = {This is my bar footnote.},
fn-buz-bee-text = {This is my buzbee footnote.}
}
{This is\fnFoo my\fnBar new\fnBuzBee message.}
\end{document}
通过此代码,我们将每个部分传递fn-foo-bar-text = {This is my foobar footnote.}
到类似的命令中\process{fn-foo-bar-text}{This is my foobar footnote.}
。
然后从第一个参数中fn-foo-bar-text
我们删除fn-
仅离开foo-bar-text
。然后我们删除-text
离开foo-bar
。
然后我们将剩下的内容拆分为-
两个项目foo
和bar
。然后我们迭代它们,并在其前面添加一个命令,该命令将其参数中的内容大写,但是,由于没有括号,它只将第一个字母大写:like\MakeUppercase foo
将导致Foo
。
因此我们以FooBar
. 结尾,最后我们定义宏\fnFooBar
来包含第二个参数的内容。
该定义不是全局的,因此不能\fnFooBar
在第二个参数之外使用,即在\command{..=..,..=..}{\fnFooBar}\fnFooBar
第二个\fnFooBar
参数之外,第二个参数将不会被定义并且会引发错误。
答案2
这(几乎)回答了整个问题。我将使用FN
此解决方案作为新触发器,而不是\fn
。它不太优雅,但目前有效。
本文档列出了将采用 的过程\mymessage
,其中包含FN...
,使用该名称创建一个新命令,并用该新命令替换原始命令FN...
;此外,它还生成一个具有该唯一名称的新键命令,该命令最终放入放入字符串中的新命令中(并从命令 完全扩展processedMess
)。
\documentclass{article}
\usepackage{xstring}
\usepackage{keyval}
\begin{document}
\def\mymessage{My message hasFNsome a new command in it.}% <<< sent from the INPUT file
\StrCut{\mymessage}{FN}\partA\partB% take unique name after "FN"
\StrCut{\partB}{ }\partC\partD% stop at the first space
% GENERATE THE KEY NAME, using the syntax fn-(uniquename)-text
\makeatletter
\define@key{mykeys}{fn-\partC-text}{\expandafter\def\csname fn\partC text\endcsname{#1}}
\makeatother
% THE VALUE OF THE KEY (this is actually from input.tex as well)
\setkeys{mykeys}{fn-some-text={my type here}}% <<< sent from the INPUT file
\expandafter\def\csname FN\partC\endcsname{\expandarg\footnote{\expandafter\csname fn\partC text\endcsname}}
\edef\expandthis{FN\partC}
\expandarg\def\processedMess{
\StrSubstitute[0]{\mymessage}{\expandthis}
{\csname FN\partC\endcsname}
}
Result:
\processedMess
\end{document}
因此,到目前为止,上面的代码满足了我的需要。每当我使用时FN*anything*
,它都会在那里添加一个新的脚注。这个过程将在我的代码中加上一个计数器,该计数器首先搜索使用 FN 的次数,以便该过程可以应用于不止第一次出现的情况。真正有趣的部分是将所有这些包装成一个命令。我会在另一个回复中发布完成此操作的完整答案。希望这个部分答案以后能为其他人阐明一些事情,所以我现在就保持原样!
还我应该说,\csname
这是此解决方案中非常重要的一部分。特别是将 扩展\command
为新命令的名称,就像我在这里所做的那样。