3

I am writing my master's thesis on Formal Concept Analysis and I want to create a custom command for the derivation operators. They are superscript arrows with some optional argument, and would look like this:

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

So, my first try was to define these commands as:

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

However, there are instances where these operators will be applied one after the other, and

\[ x\up\down \]

creates a "double superscript" error. This has a simple fix, just add brackets around the expression like so:

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

This has been my command for the whole time I've been writing the thesis, but recently I found an instance where this doesn't work as I want it to.

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

This code doesn't place the arrow as high as it should be, like in this code

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

Basically I want to define a command that satisfies these two requisites: I have to be able to write them one after another and they should place at the correct height when next to big symbols.

Here is a MWE with what I have:

\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}

My try: I have been looking all over the internet and this forum in order to find a solution, and I have come up with something (though I haven't been able to make it work). Using the \@ifnextchar command I can tell whether there is a \down command after \up (or \up after \down) and proceed accordingly. What I have is the following:

  • I create a toggle for when I am writing the operators, say writing (for example using the package etoolbox), and set it to false.
  • I create an environment superscriptenv to write its contents in superscript.
  • When I start \up or \down, if writing was set to false, I start the superscript environment, write the corresponding arrow and toggle writing to true.
  • If the next command is down or up, then don't do anything else. Otherwise, end the superscript environment and toggle writing false.

Below is the code I have written, only with the up operator.

\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}

However, this doesn't compile because "\begin{superscriptenv} ended by \end{document}". Would appreciate it if anyone got any ideas. Thanks in advance!

2 Answers 2

2

You have almost the right idea.

Instead of using a toggle and an Environ, it is easier to use the following logic:

  • Everytime \up or \down starts, push the symbol that it would add to a queue.
  • Check if the next token is an \up or a \down. If so, do nothing.
  • If the next token is neither \up nor \down, bring the whole queue, and reset the queue.
\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}
1
2

You can try following macros:

\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] $$

The main idea is that the superscript is opened by ^\bgroup and then the text is scanned and printed until the superscript is finished by something else than \up or \down. Then it is closed by \egroup

1
  • Thank you for your answer. I accepted the one given by @Willie because I find it easier to understand. Commented Apr 12 at 10:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .