自定义 LaTeX 命令,用于大符号后正确对齐连续上标

自定义 LaTeX 命令,用于大符号后正确对齐连续上标

我正在撰写关于形式概念分析的硕士论文,我想为派生运算符创建一个自定义命令。它们是带有一些可选参数的上标箭头,看起来像这样:

\[ x^{\uparrow_i}, \quad a^{\downarrow^i} \]

因此,我第一次尝试将这些命令定义为:

\newcommand{\up}[1][]{^{\uparrow_{#1}}}
\newcommand{\down}[1][]{^{\downarrow^{#1}}}

然而,有些情况下这些操作符会一个接一个地被应用,并且

\[ x\up\down \]

会产生“双上标”错误。这有一个简单的解决方法,只需在表达式周围添加括号,如下所示:

\newcommand{\up}[1][]{{^{\uparrow_{#1}}}}
\newcommand{\down}[1][]{{^{\downarrow^{#1}}}}

这是我撰写论文时一直遵循的命令,但最近我发现,这个命令并不像我希望的那样有效。

\[ \Big( \bigvee p_i \Big)\up \]

此代码没有将箭头放置在应有的高度,就像此代码中一样

\[ \Big( \bigvee p_i \Big)^{\uparrow} \]

基本上,我想定义一个满足这两个要求的命令:我必须能够一个接一个地写入它们,并且它们应该在大符号旁边放置在正确的高度。

以下是我所拥有的 MWE:

\documentclass{article}
\newcommand{\up}[1][]{{^{\uparrow_{#1}}}}
\newcommand{\down}[1][]{{^{\downarrow^{#1}}}}

\begin{document}

Expected output:
\[
  x^{\uparrow_i}, \quad x^{\uparrow_i\downarrow_j}, \quad \Big( \bigcup S \Big)^{\uparrow_i}
\]

How I want to write it:
\[
  x\up[i], \quad x\up[i]\down[j], \quad \Big( \bigcup S \Big)\up[i]
\]

\end{document}

我的尝试:为了找到解决方案,我一直在互联网和论坛上寻找,并想出了一些办法(尽管我还没能让它发挥作用)。使用命令,我可以判断后面\@ifnextchar是否有命令(或后面是否有命令),并据此进行操作。我得到的是以下内容:\down\up\up\down

  • 我在编写操作符时创建一个切换按钮writing(比如使用包etoolbox),并将其设置为 false。
  • 我创建了一个环境,superscriptenv以上面标的方式书写其内容。
  • 当我启动\up或时\down,如果writing设置为false,我会启动上标环境,写下相应的箭头并切换writing为true。
  • 如果下一个命令是downup,则不执行任何其他操作。否则,结束上标环境并切换为writingfalse。

下面是我编写的代码,仅带有up运算符。

\documentclass{article}
\usepackage{etoolbox, environ}

\newtoggle{writing}
\togglefalse{writing}

\makeatletter
\NewEnviron{superscriptenv}{^{\BODY}}

\newcommand{\up}[1][]{
  \iftoggle{writing}{}{%
    \toggletrue{writing}%
    \begin{superscriptenv}%
  }%
  \uparrow_{#1}
  \@ifnextchar\up{}{%
    \end{superscriptenv}%
    \togglefalse{writingup}%
  }
}

\begin{document}

\[
  x\up[i], \quad x\up[I]\up[j], \quad \Big( \bigcup S \Big)\up[i]
\]

\end{document}

但是,由于“\begin{superscriptenv} 以 \end{document} 结尾”,因此无法编译。如果有人有任何想法,我将不胜感激。提前致谢!

答案1

您的想法几乎正确。

与使用切换和 Environ 相比,使用以下逻辑更容易:

  • 每次\up\down启动时,按下它将添加到队列中的符号。
  • 检查下一个标记是否是\up\down。 如果是,则不执行任何操作。
  • 如果下一个标记既不是\up也不是\down,则将整个队列带入,并重置队列。
\documentclass{article}

\makeatletter
\def\@sjmr@temp{}
\newcommand\up[1][]{%
        \expandafter\def\expandafter\@sjmr@temp\expandafter{\@sjmr@temp\uparrow_{#1}}
\@ifnextchar\up{}{\@ifnextchar\down{}{^{\@sjmr@temp}\def\@sjmr@temp{}}}}
\newcommand\down[1][]{%
        \expandafter\def\expandafter\@sjmr@temp\expandafter{\@sjmr@temp\downarrow_{#1}}
\@ifnextchar\up{}{\@ifnextchar\down{}{^{\@sjmr@temp}\def\@sjmr@temp{}}}}
\makeatother

\begin{document}
\[
        x\up[i], \quad x\up[i]\down[j], \quad \Big( \bigcup S \Big)\up[i]\up[j]\down[k]
\]
\end{document}

答案2

您可以尝试以下宏:

\def\isnextchar#1#2#3{\def\tmp{#1{#2}{#3}}\futurelet\next\isnextcharA}
\def\isnextcharA{\expandafter\isnextcharB\tmp}
\def\isnextcharB#1#2#3{\ifx\next#1\afterfi{#2}\else\afterfi{#3}\fi}
\def\afterfi#1#2\fi{\fi#1}
\def\up{^\bgroup\upA.}
\def\upA#1{\isnextchar[{\updown\uparrow_}{\updown\uparrow_[]}}
\def\updown#1#2[#3]{#1#2{#3}\isnextchar\down{\downA}{\isnextchar\up{\upA}{\egroup}}}
\def\down{^\brgroup\downA.}
\def\downA#1{\isnextchar[{\updown\downarrow^}{\updown\downarrow^[]}}

Test:
$$ x\up[i]\down[j], \Bigr)\up[i]\down[j]\down[k] $$

主要思想是上标以 开头,然后扫描并打印文本,直到上标以或^\bgroup以外的其他内容结束。然后以 结尾\up\down\egroup

相关内容