%% setbuilder.sty %% Smart set-builder notation for LaTeX. %% %% \set{x \in \mathbb{R} \given x^2 < 2} %% %% produces { x ∈ ℝ | x² < 2 } with correctly spaced and, on demand, %% correctly scaled braces and separator bar. No more %% \left\{ ... \,\middle|\, ... \right\}. %% %% Commands: %% \set{...} canonical command: braces and bar at normal size %% \set*{...} braces and bar auto-scale (\left/\middle/\right) %% \set[\Big]{...} braces and bar at a fixed size %% \given the separator, usable only inside \set %% \suchthat alias for \given %% %% Package options (key-value): %% bar (default) separator is a vertical bar { x | ... } %% colon separator is a colon { x : ... } %% synonym= additionally define \ as a full copy of %% \set (with all its * and [\Big] variants). %% If \set is already taken by another package, %% setbuilder leaves it untouched, and the synonym %% becomes the way to access the functionality: %% \usepackage[synonym=mkset]{setbuilder} %% %% Requires LaTeX kernel 2022-06-01 or newer (for key-value options). %% %% Copyright (c) 2026 Vseslav Sekorin %% License: MIT (see LICENSE file or https://opensource.org/licenses/MIT) %% \NeedsTeXFormat{LaTeX2e}[2022/06/01] \ProvidesPackage{setbuilder}[2026/07/19 v0.1 Smart set-builder notation] \RequirePackage{mathtools} %% --------------------------------------------------------------- %% Key-value options %% --------------------------------------------------------------- \newif\ifsetbuilder@colon \newcommand*\setbuilder@synonym{} \DeclareKeys[setbuilder]{ bar.code = {\setbuilder@colonfalse}, colon.code = {\setbuilder@colontrue}, synonym.store = \setbuilder@synonym, synonym.usage = load, } \ProcessKeyOptions[setbuilder] %% --------------------------------------------------------------- %% The separator %% --------------------------------------------------------------- %% \setbuilder@sep[] typesets the separator with correct spacing: %% - \nonscript\: adds a medium-thin space that vanishes in sub/superscripts; %% - \allowbreak permits a line break after the bar in inline formulas; %% - \mathopen{} makes what follows behave as if freshly opened, so %% unary minus etc. after the bar are spaced correctly. %% The bar scales with the braces (it receives \delimsize / \middle); %% a colon never needs to scale, so the size argument is ignored there. \ifsetbuilder@colon \newcommand\setbuilder@sep[1][]{% \nonscript\:{\mathord{:}}\allowbreak\nonscript\:\mathopen{}} \else \newcommand\setbuilder@sep[1][]{% \nonscript\:#1\vert\allowbreak\nonscript\:\mathopen{}} \fi %% Outside \set the separator commands raise a friendly error. \newcommand\given{% \PackageError{setbuilder}% {\string\given\space may only be used inside \string\set}% {Write e.g. \string\set{x \string\given\space x>0}.}} \newcommand\suchthat{% \PackageError{setbuilder}% {\string\suchthat\space may only be used inside \string\set}% {Write e.g. \string\set{x \string\suchthat\space x>0}.}} %% --------------------------------------------------------------- %% The command itself (internal master copy) %% --------------------------------------------------------------- %% \DeclarePairedDelimiterX gives us the *, [\Big] and plain variants %% for free; inside the body we locally redefine \given so that it %% knows the current delimiter size (\delimsize is \middle in the %% starred version and the chosen \big/\Big/... otherwise). \DeclarePairedDelimiterX\setbuilder@cmd[1]\{\}{% \renewcommand\given{\setbuilder@sep[\delimsize]}% \let\suchthat\given #1} %% --------------------------------------------------------------- %% Canonical name \set + optional synonym %% --------------------------------------------------------------- %% \NewCommandCopy makes a faithful copy of the robust paired-delimiter %% command, so the copy supports \set, \set* and \set[\Big] alike. \ifdefined\set \ifx\setbuilder@synonym\@empty \PackageWarning{setbuilder}{% \string\set\space is already defined by another package and is\MessageBreak left untouched. Load setbuilder with a synonym to access\MessageBreak its functionality, e.g.\MessageBreak \space\space\string\usepackage[synonym=mkset]{setbuilder}}% \else \PackageInfo{setbuilder}{% \string\set\space is already defined elsewhere and is left\MessageBreak untouched; using the requested synonym instead}% \fi \else \NewCommandCopy\set\setbuilder@cmd \fi \ifx\setbuilder@synonym\@empty\else \ifcsname \setbuilder@synonym\endcsname \PackageError{setbuilder}% {Cannot create synonym \expandafter\string \csname\setbuilder@synonym\endcsname: this name is already defined}% {Choose another name in the synonym=... option.}% \else \expandafter\NewCommandCopy \csname\setbuilder@synonym\endcsname \setbuilder@cmd \fi \fi \endinput