自动生成新命令和键值定义

自动生成新命令和键值定义

我希望\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}

这个问题有点棘手,所以非常感谢你的帮助!如果我能找到任何答案,我会跟进的。


奖金:我没有在文档注释中指定这一点,但该函数也应该响应驼峰式命名法,以便fnBuzBeefn-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

然后我们将剩下的内容拆分为-两个项目foobar。然后我们迭代它们,并在其前面添加一个命令,该命令将其参数中的内容大写,但是,由于没有括号,它只将第一个字母大写: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为新命令的名称,就像我在这里所做的那样。

相关内容