这个问题的答案与通过宏捕获宏的下标/上标通过 egreg。
我正在尝试使用 xparser 包来创建一些宏,并且当我想要有下标和上标(或同时有两者)时我宁愿不必使用不同的宏!
我想要一个这样的宏:
\F
\F{m}
\F{m}_b
\F{m}^a
\F{m}_b^a
\F{m}^a_b
产生与此等同的输出:
$F$
$F[m]$
$F_b[m]$
$F^a[m]$
$F_b^a[m]$
$F^a_b[m]$
根据上述链接的问题,我可以捕捉到其中一个,但不能同时捕捉到两个。我尝试过几次,但现在的@ifnextchar
作品中一定有一些非常基本(或微妙)的东西超出了我的理解范围。
此代码采用两个可选参数,而不是一个,但问题仍然存在:下标和上标总是出现在行末,而不是定义的第一个字符上。
\documentclass{article}
\usepackage{xparse}
\makeatletter
\newcommand{\DFcmd}{\ensuremath{F}}
\NewDocumentCommand\DFhelp{ g g g g }
{
\IfValueT{#3}{ \def\@DFcmdsub{\DFcmd^{#3}} }{ \def\@DFcmdsub{\DFcmd} }
\IfValueT{#4}{ \def\@DFcmdsuper{\@DFcmdsub_{#4}} }{ \def\@DFcmdsuper{\@DFcmdsub} }
\@DFcmdsuper
\IfNoValueF{#1}{#1}{}
\IfNoValueF{#2}{#2}{}
}
\NewDocumentCommand\DF{ o o }
{%
\def\firstarg{}%
\def\secondarg{}%
\IfNoValueF{#1}{ \def\firstarg{[#1]} }{ \def\firstarg{} }%
\IfNoValueF{#2}{ \def\secondarg{#2} }{ \def\secondarg{} }%
\def\superopt{}%
\def\subopt{}%
\@ifnextchar^%
{%
\assign@superopt%
\@ifnextchar_%
{%
\assign@subopt%
}%
{%
\def\subopt{}%
}%
}%
{%
\@ifnextchar_%
{%
\assign@subopt%
\@ifnextchar^%
{%
\assign@superopt%
}%
{%
\def\superopt{}%
}%
}
{%
\def\subopt{}%
}%
}
\DFhelp{\firstarg}{\secondarg}{\superopt}{\subopt}%
}
\def\assign@superopt^#1{ \def\superopt{#1} }
\def\assign@subopt_#1{ \def\subopt{#1} }
\makeatother
答案1
以下抓取多个下标和上标。
括号中的参数(显然是可选的)最好放在 中[ ]
。
代码
\documentclass{article}
\makeatletter
\def\F{%
\let\f@sub\@empty
\let\f@super\@empty
\let\f@main\@empty
\@ifnextchar\bgroup\f@catch@main\f@test
}
\def\f@catch@main#1{\def\f@main{#1}\f@test}
\def\f@test{%
\@ifnextchar_\f@catch@sub{\@ifnextchar^\f@catch@super\f@finalize}%
}
\def\f@catch@sub_#1{\expandafter\def\expandafter\f@sub\expandafter{\f@sub#1}\f@test}
\def\f@catch@super^#1{\expandafter\def\expandafter\f@super\expandafter{\f@super#1}\f@test}
\def\f@finalize{%
F
\ifx\f@sub\@empty\else_{\f@sub}\fi
\ifx\f@super\@empty\else^{\f@super}\fi
\ifx\f@main\@empty\else[\f@main]\fi
}
\makeatother
\begin{document}
$ \F $ \par
$ \F{m} $ \par
$ \F{m}_b $ \par
$ \F{m}^a $ \par
$ \F{m}_b^a $ \par
$ \F{m}^a_b $ \par
$ \F{m}^a_b_a^b $ \par
\end{document}
输出
答案2
由于您只有一个强制参数(并且您正在寻找^
and _
),我认为不会xparse
给您带来很多好处,所以我\@ifnextchar
直接在这里使用。此外,由于您有m
一个强制{}
参数,因此应该始终给出它,因此我将其更改\F
为并添加了一个测试,以确保该参数为空。(另一种方法是使参数可选,但随后应将其用not\F{}
分隔。[]
{}
\documentclass{article}
\makeatletter
\def\F#1{\def\F@{\ifx\relax#1\relax\else[#1]\fi}\def\F@@{F}\@ifnextchar^\@Fsp\@Fnsp}
\def\@Fsp^#1{\def\F@@{F^{#1}}\@ifnextchar_\@Fspsb{\F@@\F@}}
\def\@Fspsb_#1{\F@@_{#1}\F@}
\def\@Fnsp{\@ifnextchar_{\@Fsb}{\F@@\F@}}
\def\@Fsb_#1{\def\F@@{F_{#1}}\@ifnextchar^\@Fsbsp{\F@@\F@}}
\def\@Fsbsp^#1{\F@@^{#1}\F@}
\begin{document}
$\F{}$
$\F{m}$
$\F{m}_b$
$\F{m}^a$
$\F{m}_b^a$
$\F{m}^a_b$
\end{document}
答案3
下面的似乎运行得相当好,但(至少)有一个限制,即它需要在宏后有一个空格才能运行。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\F}{}{
\peek_charcode:NTF \c_group_begin_token
{\renstar_F:w}
{$F$}
}
\cs_new:Npn \renstar_F:w #1#2~ {
\ensuremath{F#2[#1]}~
}
\ExplSyntaxOff
\begin{document}
\F
\F{m}
\F{m}_b
\F{m}^a
\F{m}_b^a
\F{m}^a_b
\end{document}
答案4
我会选择完全不同的方向。就你的情况而言,定义一个复杂的宏比更自然地打字没有任何好处
$F_{a}^{b}[m]$
如果这只是一个更复杂情况的例子,我建议你使用键值语法,这样可以避免追逐 token 和区分不同情况。这也更灵活。
这是示例。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\DF}{O{}}
{
\group_begin:
\keys_set:nn { renstar/DF } { #1 }
\renstar_DF:
\group_end:
}
\keys_define:nn { renstar/DF }
{
arg .tl_set:N = \l_renstar_arg_tl,
sub .tl_set:N = \l_renstar_sub_tl,
sup .tl_set:N = \l_renstar_sup_tl,
symbol .tl_set:N = \l_renstar_symbol_tl,
symbol .initial:n = F,
}
\cs_new:Npn \renstar_DF:
{
\l_renstar_symbol_tl
\tl_if_empty:NF \l_renstar_sub_tl
{ \c_math_subscript_token { \l_renstar_sub_tl } }
\tl_if_empty:NF \l_renstar_sup_tl
{ \c_math_superscript_token { \l_renstar_sup_tl } }
\tl_if_empty:NF \l_renstar_arg_tl
{ [ \l_renstar_arg_tl ] }
}
\ExplSyntaxOff
\begin{document}
$\DF$
$\DF[arg=m]$
$\DF[arg=m,sub=a]$
$\DF[sup=b,arg=m]$
$\DF[arg=m,sup=b,sub=a]$
$\DF[symbol=M,sup=x,arg=f]$
\end{document}