\documentclass{article}
\usepackage{amsmath,amssymb}
\usepackage[margin=3cm]{geometry}
\usepackage{parskip}
\usepackage[hidelinks]{hyperref}
\usepackage{substnote}

\newcommand\pkg{\textsf{substnote}}
\newcommand\demorun[1]{\begingroup\endlinechar=-1 \scantokens{#1}\endgroup}
\newcommand\demoshow[1]{%
  \par\noindent
  \begin{minipage}[c]{0.56\linewidth}\ttfamily\small #1\end{minipage}%
  \hfill
  \begin{minipage}[c]{0.40\linewidth}\raggedleft
    $\displaystyle\demorun{#1}$%
  \end{minipage}\par\medskip}
\NewDocumentCommand\demoline{v}{\demoshow{#1}}

\title{The \pkg\ package\\[1ex]
  \large Substitution notation with a switchable convention}
\author{Vseslav Sekorin\\\texttt{vssekorin@gmail.com}}
\date{2026/07/30 \quad v0.1.0\\[1ex]
  \small\url{https://github.com/vssekorin/substnote}}

\begin{document}
\maketitle

\section{Introduction}

There is no agreement on how to write ``the result of substituting $t$
for $x$ in $\varphi$''. Textbooks variously write
\[
  \subst{\varphi}{x}{t} \quad
  \subst[style=slashrev]{\varphi}{x}{t} \quad
  \subst[style=assign]{\varphi}{x}{t} \quad
  \subst[style=arrow]{\varphi}{x}{t} \quad
  \subst[style=mapsto]{\varphi}{x}{t} \quad
  \subst[style=updown,fences=parens]{\varphi}{x}{t}
\]
and the choice is a matter of house style rather than of mathematics.
The two slash conventions are moreover mirror images of one another:
some authors read $\varphi[t/x]$ as ``$t$ replaces $x$'', others read
$\varphi[x/t]$ in the same sense. A convention fixed throughout a
manuscript therefore has to be revised in full when the text is prepared
for a different journal or series.

The \pkg\ package provides a single command and lets the convention be
chosen once, in the preamble.

\section{Usage}

\begin{verbatim}
\usepackage{substnote}          % or [style=updown], etc.
...
\subst{\varphi}{x}{t}
\end{verbatim}

\demoline|\subst{\varphi}{x}{t}|

Simultaneous substitutions are written as two comma-separated lists, and
the package pairs them up:

\demoline|\subst{\varphi}{x,y}{s,t}|

If the lists have different lengths, \pkg\ reports an error rather than
discarding the surplus entries.

Because the two arguments are read as comma lists, a term that itself
contains a top-level comma must be braced, or it will be taken for two
terms:
\begin{verbatim}
\subst{\varphi}{x}{{f(a,b)}}     % one term
\subst{\varphi}{x}{f(a,b)}       % error: 1 variable but 2 terms
\end{verbatim}

\subsection{The mark alone}

\verb|\substmark| sets the substitution mark on its own, for attaching to
something already typeset:

\demoline|\psi\substmark{x}{t}|

\noindent Since there is no expression to enclose, the up--down styles
set the scripts alone rather than a pair of empty delimiters:

\demoline|\psi\substmark[style=updown]{x}{t}|

\subsection{Auto-scaling}

The starred forms scale the delimiters to their contents:

\demoline|\subst*{\varphi}{x}{\frac{a}{b}}|

\noindent against the unstarred

\demoline|\subst{\varphi}{x}{\frac{a}{b}}|

\section{Styles}

The \texttt{style} key selects the convention. It can be given as a
package option, for the whole document, or per use.

\demoline|\subst[style=slash]{\varphi}{x}{t}|
\demoline|\subst[style=slashrev]{\varphi}{x}{t}|
\demoline|\subst[style=assign]{\varphi}{x}{t}|
\demoline|\subst[style=arrow]{\varphi}{x}{t}|
\demoline|\subst[style=mapsto]{\varphi}{x}{t}|
\demoline|\subst[style=updown]{\varphi}{x}{t}|
\demoline|\subst[style=updownrev]{\varphi}{x}{t}|

In the \texttt{updown} styles the variable is set above and the term
below, as in Kleene and much of the older literature;
\texttt{updownrev} swaps them. Simultaneous substitutions stack as
comma-separated lists:

\demoline|\subst[style=updown]{\varphi}{x,y}{s,t}|

\noindent The delimiters around the expression follow \texttt{fences},
so the traditional parenthesised form is:

\demoline|\subst[style=updown,fences=parens]{\varphi}{x}{t}|

\section{Delimiters}

The \texttt{fences} key chooses the delimiters. In the five
\emph{delimited} styles---\texttt{slash}, \texttt{slashrev},
\texttt{assign}, \texttt{arrow} and \texttt{mapsto}---they enclose the
substitution mark set beside the expression:

\demoline|\subst[fences=parens]{\varphi}{x}{t}|
\demoline|\subst[fences=braces]{\varphi}{x}{t}|
\demoline|\subst[fences=none]{\varphi}{x}{t}|

The styles fall into two families, and \texttt{fences} applies to both,
though it governs different material in each:

\begin{center}
\begin{tabular}{@{}lll@{}}
\emph{Delimited} & \texttt{slash}, \texttt{slashrev}, \texttt{assign},
  & fences enclose the mark\\
 & \texttt{arrow}, \texttt{mapsto} & \\[2pt]
\emph{Up--down} & \texttt{updown}, \texttt{updownrev}
  & fences enclose the expression\\
\end{tabular}
\end{center}

\noindent An unknown value for \texttt{style} or \texttt{fences} is
reported at once, together with the list of what is allowed.

\section{Options and keys}

The same names work as package options (for the document-wide
convention) and in the optional argument of each command (per use).

\begin{description}
\item[\texttt{style=$\langle$name$\rangle$}] One of \texttt{slash}
  (default), \texttt{slashrev}, \texttt{assign}, \texttt{arrow},
  \texttt{mapsto}, \texttt{updown}, \texttt{updownrev}. In
  \texttt{assign} the colon is centred on the math axis and set close to
  the equals sign; the symbol is taken from the font under
  \textsf{unicode-math}, or from \textsf{mathtools} when that is loaded,
  and is otherwise assembled by the package, so no further package is
  required.
\item[\texttt{fences=$\langle$name$\rangle$}] Delimiters:
  \texttt{brackets} (default), \texttt{parens}, \texttt{braces} or
  \texttt{none}. In the delimited styles they enclose the substitution
  mark, in the up--down styles the expression. The up--down styles are
  never left undelimited, since a bare superscript would attach to the
  last symbol of a compound expression only; there \texttt{none} is read
  as \texttt{parens}.
\item[\texttt{pairsep=$\langle$code$\rangle$}] What separates
  simultaneous substitutions. Default \verb|,\,|.
\item[\texttt{synonym=$\langle$name$\rangle$}] Additionally define
  copies of \verb|\subst| and \verb|\substmark| under the given name;
  see the following section. Load-time option only.
\end{description}

\section{If a name is already taken}

Some packages define their own \verb|\subst|. In that case \pkg\
\emph{never} overwrites the existing command. Instead, load it with a
synonym:
\begin{verbatim}
\usepackage[synonym=mysubst]{substnote}
\end{verbatim}
This defines \verb|\mysubst| as a full copy of \verb|\subst| --- the
starred form and the optional argument included --- together with
\verb|\mysubstmark| for the mark. The synonym is created whether or not
\verb|\subst| itself was free, so it may also serve as a shorter or a
more descriptive name.

The same holds for \verb|\substmark|, which is reported and left alone
in the same way. If a name is taken and no synonym was requested, the
package issues a warning to that effect and the document still
compiles. Requesting a synonym whose name is itself taken produces an error.

\section{Requirements}

Only a \LaTeX{} kernel from 2022-06-01 or newer; the package uses the
kernel's key--value interface and \textsf{expl3} list handling, and loads
nothing else.

\section{Implementation notes}

The variables and terms are read as comma lists and paired by index, so
one code path serves both the single and the simultaneous case. The
style is applied to each pair separately, so that the mirror-image
conventions (\texttt{slash} and \texttt{slashrev}) differ only in the
order of the two arguments. The \texttt{updown} styles are constructed
differently: the delimiters enclose the expression rather than a body,
and the variables and the terms are joined into a superscript and a
subscript. Since \verb|\substmark| carries no expression, it omits
those delimiters, which would otherwise come out empty. The starred forms set a flag that switches the fences to
\verb|\left| and \verb|\right|. The values of \texttt{style} and
\texttt{fences} are checked as the key is set, so that a mistyped value
is reported at the point where it was given rather than affecting the
output silently. Writing \texttt{:=} directly would be
incorrect, since the colon is a relation atom and TeX would both space it
away from the equals sign and leave it on the baseline; the package
therefore defers to a properly built symbol when the document provides
one and otherwise centres the colon with \verb|\mathop|, which follows
the current math style, closing the remaining gap with a negative kern.

\section{Changes}

\begin{description}
\item[v0.1.0 (2026-07-30)] First public version.
\end{description}

\end{document}
