\documentclass{article}
\usepackage{amssymb}
\usepackage[synonym=Setb]{setbuilder}
\usepackage[margin=3cm]{geometry}
\usepackage{parskip}
\usepackage[hidelinks]{hyperref}

\newcommand\pkg{\textsf{setbuilder}}
\makeatletter
\NewDocumentCommand\demo{v}{%
  \par\noindent
  \begin{minipage}[c]{0.56\linewidth}\ttfamily\small #1\end{minipage}%
  \hfill
  \begin{minipage}[c]{0.40\linewidth}\raggedleft
    $\displaystyle\demo@run{#1}$%
  \end{minipage}\par\medskip}
\newcommand\demo@run[1]{\begingroup\endlinechar=-1 \scantokens{#1}\endgroup}
\makeatother

\title{The \pkg\ package\\[1ex]
  \large Smart set-builder notation\\with correctly scaled braces and separator}
\author{Vseslav Sekorin\\\texttt{vssekorin@gmail.com}}
\date{2026/07/28 \quad v0.2.0\\[1ex]
  \small\url{https://github.com/vssekorin/setbuilder}}

\begin{document}
\maketitle

\section{Introduction}

Typesetting set-builder notation correctly in \LaTeX{} requires a
number of manual adjustments. The naive markup
\begin{center}\verb|\{\,x \mid x > 0\,\}|\end{center}
already carries two thin spaces inserted by hand, and it still breaks
down as soon as the contents grow: the braces stay small. The robust
alternative,
\begin{center}\verb|\left\{\,x \,\middle\vert\, x > 0\,\right\}|\end{center}
scales the braces, but now four occurrences of \verb|\,| are needed,
and they obscure the structure of the formula. In a subscript the same
spaces are too wide and have to be removed again by hand.

The \pkg\ package reduces all of this to one command:
\demo{\set{x \in \mathbb{R} \given x^2 < 2}}
with correct spacing around the separator, automatic or fixed scaling of
\emph{both} the braces and the bar, spaces that vanish in sub- and
superscripts, and a permitted line break after the bar in inline formulas.

\section{Usage}

\begin{verbatim}
\usepackage{setbuilder}
\end{verbatim}

\subsection{The \texttt{\string\set} command}

\demo{\set{1, 2, 3, \dots}}
\demo{\set{x \in \mathbb{R} \given x^2 < 2}}

The separator is written \verb|\given| (or its synonym \verb|\suchthat|).
Both raise a descriptive error when used outside \verb|\set|.

Note the difference between the two examples above: the second one is
padded with a thin space just inside the braces, the first one is not.
Knuth (\emph{The \TeX book}) prescribes the space for a set
given by a condition, \verb|{\,x \mid x>0\,}|, but not for a plain
enumeration, \verb|{1, 2, \dots, n}|. Since \verb|\set| serves both,
it inserts the space only when the body contains a separator.
The amount is the \texttt{pad} option (see below).

\subsection{Auto-scaling: \texttt{\string\set*}}

The starred form wraps the contents in
\verb|\left|\dots\verb|\middle|\dots\verb|\right|, so the braces
\emph{and} the bar grow together:

\demo{\set*{\frac{n}{n+1} \given n \in \mathbb{N}}}
\demo{\set*{A \subseteq \mathbb{N} \given \sum_{a \in A} \frac{1}{a} < \infty}}

\subsection{Fixed size: \texttt{\string\set[\string\Big]}}

When auto-scaling overshoots, a well-known limitation of
\verb|\left|\dots\verb|\right|, the size can be fixed explicitly:

\demo{\set[\Big]{x \given f(x) = \max_{y} f(y)}}

\subsection{Correct spacing in scripts}

The thin spaces around the separator are inserted with
\verb|\nonscript\:|, so they disappear in sub- and superscripts, where
they would be disproportionately wide:
\[
  \bigcup_{i \in \set{n \given n \ge 1}} A_i
  \qquad\text{compare hand-made:}\qquad
  \bigcup_{i \in \{\,n \,\mid\, n \ge 1\,\}} A_i
\]

\subsection{Nesting}

\demo{\set*{\set{x \given x \sim y} \given y \in Y}}

\section{Package options}

Options use the key--value syntax of the modern \LaTeX{} kernel.

\begin{description}
\item[\texttt{bar} (default)] The separator is a vertical bar:
  $\set{x \given x > 0}$.
\item[\texttt{colon}] The separator is a colon throughout the document,
  as preferred in some traditions: $\{\,x : x > 0\,\}$.
\item[\texttt{pad=$\langle$mu glue$\rangle$}] The space inserted just
  inside the braces of a set given by a condition. The default is
  \verb|\,| (that is, \texttt{3mu}); \texttt{pad=none} disables it, so
  that the body abuts the braces: $\{x \mid x > 0\}$. Any mu glue is
  accepted, e.g.\ \verb|pad=2mu plus 1mu|. The option has no effect on
  a set written as an enumeration, which is never padded.
\item[\texttt{synonym=$\langle$name$\rangle$}] Additionally defines
  \verb|\|$\langle$name$\rangle$ as a full copy of \verb|\set|,
  including the starred and fixed-size variants. This document, for
  instance, is compiled with \verb|synonym=Setb|:
  \demo|\Setb*{\frac{1}{n} \given n \ge 1}|
\end{description}

\subsection{Conflict with an existing \texttt{\string\set}}

Some packages define their own \verb|\set|. In that case \pkg\ never
overwrites the existing command. Instead:

\begin{itemize}
\item if a synonym was requested, the synonym silently becomes the way
  to access the functionality:
\begin{verbatim}
\usepackage[synonym=mkset]{setbuilder}
\end{verbatim}
\item if no synonym was requested, the package issues a warning with
  exactly this advice, and the document still compiles.
\end{itemize}

Requesting a synonym whose name is itself already defined
(\verb|synonym=section|) produces an explicit error message.

\section{Requirements}

The package loads \textsf{mathtools} and requires a \LaTeX{} kernel from
2022-06-01 or newer (for key--value package options and
\verb|\NewCommandCopy|).

\section{Implementation notes}

The command is built with \verb|\DeclarePairedDelimiterX| from
\textsf{mathtools}, which provides the plain, starred and sized variants
uniformly. Inside the delimiter body, \verb|\given| is redefined locally
to typeset the separator at the current delimiter size
(\verb|\delimsize|). The separator itself is
\begin{verbatim}
\nonscript\: <bar> \allowbreak \nonscript\: \mathopen{}
\end{verbatim}
where the trailing \verb|\mathopen{}| makes a following unary minus
space correctly, and \verb|\allowbreak| permits a line break after the
bar in inline material.

The padding is emitted only if \verb|\in@| finds \verb|\given| or
\verb|\suchthat| in the body at brace level~0. The test is run twice,
once before and once after the body, rather than cached in a flag: a
nested \verb|\set| inside the body would overwrite \verb|\ifin@| in
between. Like the spaces around the separator, the padding is prefixed
with \verb|\nonscript|, so it disappears in scripts.

\section{Changes}

\begin{description}
\item[v0.2.0 (2026-07-28)] New \texttt{pad} option: a thin space inside
  the braces for sets given by a condition, none for enumerations.
\item[v0.1.1 (2026-07-25)] Bug fix: \verb|\given| and \verb|\suchthat|
  are now robust, so they survive expansion in moving arguments
  (section titles, captions) unbroken.
\item[v0.1.0 (2026-07-19)] First public version.
\end{description}

\end{document}
